docs: def register(self, source, attributes=None, allow_class=False, allow_subclasses=True,
                   propagate_attributes=True, inherit_attributes=True):
          """Register a source class with its attributes.
  
          Arguments
          ---------
          source : type
              Must be a class for which we want to allow access to only the given attributes.
          attributes : iterable[str] / Attributes, optional
              A list (or other iterable) of string representing the names of the allowed
              attributes from the source.
              Can also be an ``Attributes`` instance.
              To allow all attributes, you must pass an ``Attributes`` instance with
              ``allow_all=True``.
          allow_class : boolean, default ``False``
              If set to ``True``, the source apply not only to instances of the source class, but
              also to the class itself.
          allow_subclasses : boolean, default ``True``
                  When ``True``, if an instance of a subclass is used without defined source, this
                  source will be used.
          propagate_attributes : boolean, default ``True``
              When ``True``, all the attributes of this source will be propagated to subclasses of
              this source (except if the subclass has ``inherit_attributes`` set to ``False``.
              When ``False``, subclasses will have to declare their own attributes.
          inherit_attributes : boolean, default ``True``
              When ``True``, if the source class has a parent class in the registry, it will inherits
              its attributes if it has ``propagate_attributes`` set to ``True``.
              When ``False``, it has to declare its own attributes
  
          Raises
          ------
          dataql.solvers.exception.AlreadyRegistered
              If the source class is already registered.
  
          Example
          -------
  
          >>> from datetime import date
          >>> d = date(2015, 6, 1)
          >>> registry = Registry()
          >>> registry.register(date, ['day', 'today'])
          >>> registry.register(date, ['day']) # doctest: +ELLIPSIS
          Traceback (most recent call last):
          dataql.solvers.exceptions.AlreadyRegistered: The `datetime.date` source is already...
          >>> registry[date].solve(d, 'day')
          1
          >>> registry[date].solve(date, 'today') # doctest: +ELLIPSIS
          Traceback (most recent call last):
          dataql.solvers.exceptions.NotSolvable: The `datetime.date` source can only...
          >>> registry = Registry()
          >>> registry.register(date, ['day', 'today'], True)
          >>> s = Source(date, ['day', 'today'], allow_class=True)
          >>> registry[date].solve(d, 'day')
          1
          >>> registry[date].solve(date, 'today') == date.today()
          True
  
          """
  
          if source in self.sources:
              raise AlreadyRegistered(self, source)
  
          # Inherit attributes from parent classes
          parent_sources = set()
          if inherit_attributes:
              bases = source.__bases__ if isinstance(source, type) else source.__class__.__bases__
              for klass in bases:
                  if klass in self.sources and self.sources[klass].propagate_attributes:
                      parent_sources.add(self.sources[klass])
  
          self.sources[source] = self.Source(
              source, attributes, allow_class, allow_subclasses,
              propagate_attributes, inherit_attributes, parent_sources
          )
  
          # Propagate attributes to existing subclasses
          if propagate_attributes:
              for src in self.sources.values():
                  if src.source != source and src.inherit_attributes\
                          and issubclass(src.source, source):
                      src.parent_source.add(self.sources[source])