A function that returns a decorator (or acts like a decorator)
    that marks class or function as a source of `base`.

    If a class is decorated, it should inherit after from `base` type.

    If a function is decorated, it declared return type should inherit after
    some `base` type, or it should be the `base` type.

    .. code-block:: python

        @egg
        class DepImpl(DepType):
            pass

        @egg(profile='test')
        class TestDepImpl(DepType):
            pass

        @egg(qualifier='special_dep')
        def dep_factory() -> DepType:
            return SomeDepImpl()

    :param qualifier: extra qualifier for dependency. Can be used to\
            register more than one type for one base. If non-string argument\
            is passed, it'll act like a decorator.
    :param profile: An optional profile within this dependency should be used
    :return: decorator

def egg(qualifier: Union[str, Type] = '', profile: str = None):
    """
    A function that returns a decorator (or acts like a decorator)
    that marks class or function as a source of `base`.

    If a class is decorated, it should inherit after from `base` type.

    If a function is decorated, it declared return type should inherit after
    some `base` type, or it should be the `base` type.

    .. code-block:: python

        @egg
        class DepImpl(DepType):
            pass

        @egg(profile='test')
        class TestDepImpl(DepType):
            pass

        @egg(qualifier='special_dep')
        def dep_factory() -> DepType:
            return SomeDepImpl()

    :param qualifier: extra qualifier for dependency. Can be used to\
            register more than one type for one base. If non-string argument\
            is passed, it'll act like a decorator.
    :param profile: An optional profile within this dependency should be used
    :return: decorator
    """
    first_arg = qualifier

    def egg_dec(obj: Union[FunctionType, type]) -> T:
        if isinstance(obj, FunctionType):
            spec = inspect.signature(obj)
            return_annotation = spec.return_annotation
            if return_annotation is Signature.empty:
                raise ConfigurationError('No return type annotation')
            egg.factories.append(
                Egg(
                    type_=spec.return_annotation,
                    qualifier=qualifier,
                    egg_=obj,
                    base_=None,
                    profile=profile
                ))
            return obj
        elif isinstance(obj, type):
            egg.factories.append(
                Egg(type_=obj, qualifier=qualifier, egg_=obj, base_=None,
                    profile=profile))
            return obj
        else:
            raise AttributeError('Wrong egg obj type')

    if isinstance(qualifier, str):
        qualifier = qualifier or None
        return egg_dec
    else:
        qualifier = None
        return egg_dec(first_arg)