class_docstr: An extension for the scheduler to manage Events
  
  This adds the following routes to the scheduler
  
  *  event_wait
  *  event_set
  *  event_clear
  *  event_is_set
  
  In principle, the implementation logic is quite simple
  as we can reuse the asyncio.Event as much as possible:
  we keep a mapping from name to an asyncio.Event and call
  every function (wait, set, clear, is_set) directly on these
  events.
  
  However, this would cause a memory leak: created events in the
  dictionary are never removed.
  For this, we also keep a counter for the number of waiters on
  a specific event.
  If an event is set, we need to keep track of this state so
  we can not remove it (the default flag is false).
  If it is unset but there are waiters, we can also not remove
  it, as those waiters would then have dangling futures.
  Therefore the only time we can remove the event from our dict
  is when the number of waiters is 0 and the event flag is cleared.
class_docstr_tok: ["An","extension","for","the","scheduler","to","manage","Events","This","adds","the","following","routes","to","the","scheduler","*","event_wait","*","event_set","*","event_clear","*","event_is_set","In","principle",",","the","implementation","logic","is","quite","simple","as","we","can","reuse","the","asyncio.Event","as","much","as","possible",":","we","keep","a","mapping","from","name","to","an","asyncio.Event","and","call","every","function","(","wait",",","set",",","clear",",","is_set",")","directly","on","these","events",".","However",",","this","would","cause","a","memory","leak",":","created","events","in","the","dictionary","are","never","removed",".","For","this",",","we","also","keep","a","counter","for","the","number","of","waiters","on","a","specific","event",".","If","an","event","is","set",",","we","need","to","keep","track","of","this","state","so","we","can","not","remove","it","(","the","default","flag","is","false",")",".","If","it","is","unset","but","there","are","waiters",",","we","can","also","not","remove","it",",","as","those","waiters","would","then","have","dangling","futures",".","Therefore","the","only","time","we","can","remove","the","event","from","our","dict","is","when","the","number","of","waiters","is","0","and","the","event","flag","is","cleared","."]
docstr: Helper function to normalize an event name
docstr_tok: ["Helper","function","to","normalize","an","event","name"]
code: def _normalize_name(self, name):
      """Helper function to normalize an event name"""
      if isinstance(name, list):
          name = tuple(name)
  
      return name
  
imports: from __future__ import annotations
  import asyncio
  import logging
  import uuid
  from collections import defaultdict
  from contextlib import suppress
  from dask.utils import parse_timedelta
  from distributed.utils import TimeoutError, log_errors, wait_for
  from distributed.worker import get_client
label_desc: Use image node_id 5 for calling the EventExtension obj's underlying member method code with example usage: obj._normalize_name(name) and returns: name