class_docstr: An extension for the scheduler to manage Semaphores
  
  This adds the following routes to the scheduler
  
  * semaphore_acquire
  * semaphore_release
  * semaphore_close
  * semaphore_refresh_leases
  * semaphore_register
class_docstr_tok: ["An","extension","for","the","scheduler","to","manage","Semaphores","This","adds","the","following","routes","to","the","scheduler","*","semaphore_acquire","*","semaphore_release","*","semaphore_close","*","semaphore_refresh_leases","*","semaphore_register"]
code: def release(self, name=None, lease_id=None):
      if not self._semaphore_exists(name):
          logger.warning(
              f"Tried to release semaphore `{name}` but it is not known or already closed."
          )
          return
      if isinstance(name, list):
          name = tuple(name)
      if name in self.leases and lease_id in self.leases[name]:
          self._release_value(name, lease_id)
      else:
          logger.warning(
              "Tried to release semaphore but it was already released: "
              f"{name=}, {lease_id=}. "
              "This can happen if the semaphore timed out before."
          )
  
imports: from __future__ import annotations
  import asyncio
  import logging
  import uuid
  import warnings
  from asyncio import TimeoutError
  from collections import defaultdict, deque
  import dask
  from dask.utils import parse_timedelta
  from distributed.compatibility import PeriodicCallback
  from distributed.metrics import time
  from distributed.utils import Deadline, SyncMethodMixin, log_errors, wait_for
  from distributed.utils_comm import retry_operation
  from distributed.worker import get_client, get_worker
label_desc: Use image node_id 7 for calling the SemaphoreExtension obj's underlying member method code with example usage: obj.release(name, lease_id) without return types