Marks the decorated class as an abstract interface.

    Injects following classmethods:

        .. py:method:: .all(context) 

            Returns a list of instances of each component in the ``context`` implementing this ``@interface``

            :param context: context to look in
            :type context: :class:`Context`
            :returns: list(``cls``)

        .. py:method:: .any(context)

            Returns the first suitable instance implementing this ``@interface`` or raises :exc:`NoImplementationError` if none is available.

            :param context: context to look in
            :type context: :class:`Context`
            :returns: ``cls``

        .. py:method:: .classes()

            Returns a list of classes implementing this ``@interface``

            :returns: list(class)

def interface(cls):
    '''
    Marks the decorated class as an abstract interface.

    Injects following classmethods:

        .. py:method:: .all(context) 

            Returns a list of instances of each component in the ``context`` implementing this ``@interface``

            :param context: context to look in
            :type context: :class:`Context`
            :returns: list(``cls``)

        .. py:method:: .any(context)

            Returns the first suitable instance implementing this ``@interface`` or raises :exc:`NoImplementationError` if none is available.

            :param context: context to look in
            :type context: :class:`Context`
            :returns: ``cls``

        .. py:method:: .classes()

            Returns a list of classes implementing this ``@interface``

            :returns: list(class)
    '''

    if not cls:
        return None

    cls.implementations = []

    # Inject methods
    def _all(cls, context, ignore_exceptions=False):
        return list(context.get_components(cls, ignore_exceptions=ignore_exceptions))
    cls.all = _all.__get__(cls)

    def _any(cls, context):
        instances = cls.all(context)
        if instances:
            return instances[0]
        raise NoImplementationError(cls)
    cls.any = _any.__get__(cls)

    def _classes(cls):
        return list(cls.implementations)
    cls.classes = _classes.__get__(cls)

    log.debug('Registering [%s] (interface)', get_fqdn(cls))

    return cls