docs: def SynchronizedClassMethod(*locks_attr_names, **kwargs):
      # pylint: disable=C1801
      """
      A synchronizer decorator for class methods. An AttributeError can be raised
      at runtime if the given lock attribute doesn't exist or if it is None.
  
      If a parameter ``sorted`` is found in ``kwargs`` and its value is True,
      then the list of locks names will be sorted before locking.
  
      :param locks_attr_names: A list of the lock(s) attribute(s) name(s) to be
                               used for synchronization
      :return: The decorator method, surrounded with the lock
      """
      # Filter the names (remove empty ones)
      locks_attr_names = [
          lock_name for lock_name in locks_attr_names if lock_name
      ]
  
      if not locks_attr_names:
          raise ValueError("The lock names list can't be empty")
  
      if "sorted" not in kwargs or kwargs["sorted"]:
          # Sort the lock names if requested
          # (locking always in the same order reduces the risk of dead lock)
          locks_attr_names = list(locks_attr_names)
          locks_attr_names.sort()
  
      def wrapped(method):
          """
          The wrapping method
  
          :param method: The wrapped method
          :return: The wrapped method
          :raise AttributeError: The given attribute name doesn't exist
          """
  
          @functools.wraps(method)
          def synchronized(self, *args, **kwargs):
              """
              Calls the wrapped method with a lock
              """
              # Raises an AttributeError if needed
              locks = [getattr(self, attr_name) for attr_name in locks_attr_names]
              locked = collections.deque()
              i = 0
  
              try:
                  # Lock
                  for lock in locks:
                      if lock is None:
                          # No lock...
                          raise AttributeError(
                              "Lock '{0}' can't be None in class {1}".format(
                                  locks_attr_names[i], type(self).__name__
                              )
                          )
  
                      # Get the lock
                      i += 1
                      lock.acquire()
                      locked.appendleft(lock)
  
                  # Use the method
                  return method(self, *args, **kwargs)
  
              finally:
                  # Unlock what has been locked in all cases
                  for lock in locked:
                      lock.release()
  
                  locked.clear()
                  del locks[:]
  
          return synchronized
  
      # Return the wrapped method
      return wrapped