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])
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