Example #1
0
def test_build_provider_raises_for_missing_singleton_parameter():
    container = Container()

    container.add_exact_singleton(CatsController)

    with raises(CannotResolveParameterException):
        container.build_provider()
Example #2
0
def test_scoped_services_exact():
    container = Container()

    class A:
        def __init__(self, b):
            self.b = b

    class B:
        def __init__(self, c):
            self.c = c

    class C:
        def __init__(self):
            pass

    container.add_exact_scoped(A)
    container.add_exact_scoped(B)
    container.add_exact_scoped(C)

    provider = container.build_provider()
    context = GetServiceContext(provider)

    a = provider.get(A, context)
    assert isinstance(a, A)
    assert isinstance(a.b, B)
    assert isinstance(a.b.c, C)

    a2 = provider.get(A, context)
    assert a is a2
    assert a.b is a2.b
    assert a.b.c is a2.b.c
Example #3
0
def test_add_alias_requires_configured_type():
    container = Container()

    container.add_alias('something', Cat)

    with raises(AliasConfigurationError):
        container.build_provider()
Example #4
0
def test_add_singleton_by_factory_given_type(method_name):
    container = Container()

    def factory(a):
        return Cat('Celine')

    method = getattr(container, method_name)

    method(factory, Cat)

    provider = container.build_provider()

    cat = provider.get(Cat)

    assert cat is not None
    assert cat.name == 'Celine'

    if method_name == 'add_singleton_by_factory':
        cat_2 = provider.get(Cat)
        assert cat_2 is cat

    if method_name == 'add_transient_by_factory':
        assert provider.get(Cat) is not cat
        assert provider.get(Cat) is not cat
        assert provider.get(Cat) is not cat

    if method_name == 'add_scoped_by_factory':
        with GetServiceContext() as context:
            cat_2 = provider.get(Cat, context)
            assert cat_2 is not cat

            assert provider.get(Cat, context) is cat_2
            assert provider.get(Cat, context) is cat_2
            assert provider.get(Cat, context) is cat_2
Example #5
0
def test_executor_with_given_scoped_services():
    called = False

    @inject()
    def fn(example, context: Context):
        nonlocal called
        called = True
        assert isinstance(example, Example)
        assert isinstance(example.repository, Repository)
        assert isinstance(context, Context)
        # scoped parameter:
        assert context is example.repository.context
        return context

    container = Container()

    container.add_transient(Example)
    container.add_transient(Repository)
    container.add_scoped(Context)

    provider = container.build_provider()

    executor = provider.get_executor(fn)

    given_context = Context()
    result = executor({Context: given_context})

    assert called
    assert result is given_context
Example #6
0
    def __init__(
        self,
        *,
        router: Optional[Router] = None,
        services: Optional[Container] = None,
        debug: bool = False,
        show_error_details: Optional[bool] = None,
    ):
        if router is None:
            router = Router()
        if services is None:
            services = Container()
        if show_error_details is None:
            show_error_details = bool(
                os.environ.get("APP_SHOW_ERROR_DETAILS", False))
        super().__init__(show_error_details, router)

        self.services: Container = services
        self._service_provider: Optional[Services] = None
        self.debug = debug
        self.middlewares: List[Callable[..., Awaitable[Response]]] = []
        self._default_headers: Optional[Tuple[Tuple[str, str], ...]] = None
        self._middlewares_configured = False
        self._cors_strategy: Optional[CORSStrategy] = None
        self._authentication_strategy: Optional[AuthenticationStrategy] = None
        self._authorization_strategy: Optional[AuthorizationStrategy] = None
        self.on_start = ApplicationEvent(self)
        self.after_start = ApplicationEvent(self)
        self.on_stop = ApplicationEvent(self)
        self.started = False
        self.controllers_router: RoutesRegistry = controllers_router
        self.files_handler = FilesHandler()
        self.server_error_details_handler = ServerErrorDetailsHandler()
        self._session_middleware: Optional[SessionMiddleware] = None
Example #7
0
    def __init__(
        self,
        *,
        router: Optional[Router] = None,
        resources: Optional[Resources] = None,
        services: Optional[Container] = None,
        debug: bool = False,
        show_error_details: bool = False,
    ):
        if router is None:
            router = Router()
        if services is None:
            services = Container()
        super().__init__(show_error_details, router)

        if resources is None:
            resources = Resources(get_resource_file_content("error.html"))
        self.services: Container = services
        self._service_provider: Optional[Services] = None
        self.debug = debug
        self.middlewares: List[Callable[..., Awaitable[Response]]] = []
        self.access_logger = None
        self.logger = None
        self._default_headers: Optional[Tuple[Tuple[str, str], ...]] = None
        self._middlewares_configured = False
        self.resources = resources
        self._authentication_strategy: Optional[AuthenticationStrategy] = None
        self._authorization_strategy: Optional[AuthorizationStrategy] = None
        self.on_start = ApplicationEvent(self)
        self.after_start = ApplicationEvent(self)
        self.on_stop = ApplicationEvent(self)
        self.started = False
        self.controllers_router: RoutesRegistry = controllers_router
        self.files_handler = FilesHandler()
Example #8
0
def test_add_alias_raises_if_alias_is_defined():
    container = Container()

    container.add_alias('something', Cat)

    with raises(AliasAlreadyDefined):
        container.add_alias('something', Foo)
Example #9
0
    def __init__(self,
                 router: Optional[Router] = None,
                 middlewares: Optional[List[Callable]] = None,
                 resources: Optional[Resources] = None,
                 services: Optional[ServicesType] = None,
                 debug: bool = False,
                 show_error_details: bool = False):
        if router is None:
            router = Router()
        if services is None:
            services = Container()
        super().__init__(get_show_error_details(debug or show_error_details), router)

        if middlewares is None:
            middlewares = []
        if resources is None:
            resources = Resources(get_resource_file_content('error.html'))
        self.services = services  # type: ServicesType
        self.debug = debug
        self.middlewares = middlewares
        self.access_logger = None
        self.logger = None
        self._default_headers = None
        self._use_sync_logging = False
        self._middlewares_configured = False
        self.resources = resources
        self._serve_files = None
        self._authentication_strategy = None  # type: Optional[AuthenticationStrategy]
        self._authorization_strategy = None  # type: Optional[AuthorizationStrategy]
        self.on_start = ApplicationEvent(self)
        self.on_stop = ApplicationEvent(self)
        self.started = False
        self.controllers_router: RoutesRegistry = controllers_router
Example #10
0
def test_add_instance_with_declared_type():
    container = Container()
    container.add_instance(Circle(Circle(None)), declared_class=ICircle)
    provider = container.build_provider()

    icircle = provider.get(ICircle)
    assert isinstance(icircle, Circle)
Example #11
0
async def test_async_executor():
    called = False

    @inject()
    async def fn(example, context: Context):
        nonlocal called
        called = True
        assert isinstance(example, Example)
        assert isinstance(example.repository, Repository)
        assert isinstance(context, Context)
        # scoped parameter:
        assert context is example.repository.context
        return context.trace_id

    container = Container()

    container.add_transient(Example)
    container.add_transient(Repository)
    container.add_scoped(Context)

    provider = container.build_provider()

    executor = provider.get_executor(fn)

    result = await executor()

    assert called
    assert result == Context().trace_id
Example #12
0
def test_factories_activating_singleton_type_consistency(method_name):
    container = Container()

    class ABase(ABC):
        pass

    class BBase(ABC):
        pass

    class A(ABase):
        def __init__(self, b: BBase):
            self.b = b

    class B(BBase):
        def __init__(self):
            pass

    def bbase_factory(context: Services, activating_type: Type) -> BBase:
        assert isinstance(context, Services)
        assert activating_type is A
        return B()

    container.add_singleton(ABase, A)

    method = getattr(container, method_name)
    method(bbase_factory)

    provider = container.build_provider()
    context = GetServiceContext(provider)

    a = provider.get(ABase, context)
    assert isinstance(a, A)
    assert isinstance(a.b, B)
Example #13
0
def test_raises_for_circular_dependency_with_dynamic_resolver():
    container = Container()
    container.add_exact_transient(Jing)
    container.add_exact_transient(Jang)

    with pytest.raises(CircularDependencyException):
        container.build_provider()
Example #14
0
def test_factory_can_receive_activating_type_as_parameter_nested_resolution_many(
):
    # NB: this scenario can only work when a class is registered as transient service

    class Logger:
        def __init__(self, name):
            self.name = name

    class HelpRepo:
        def __init__(self, db_context: FooDBContext, logger: Logger):
            self.db_context = db_context
            self.logger = logger

    class HelpHandler:
        def __init__(self, help_repo: HelpRepo):
            self.repo = help_repo

    class AnotherPathTwo:
        def __init__(self, logger: Logger):
            self.logger = logger

    class AnotherPath:
        def __init__(self, another_path_2: AnotherPathTwo):
            self.child = another_path_2

    class HelpController:
        def __init__(self, handler: HelpHandler, another_path: AnotherPath,
                     logger: Logger):
            self.logger = logger
            self.handler = handler
            self.other = another_path

    container = Container()

    def factory(_, activating_type) -> Logger:
        # NB: this scenario is tested for rolog library
        return Logger(activating_type.__module__ + '.' +
                      activating_type.__name__)

    container.add_transient_by_factory(factory)

    container.add_instance(ServiceSettings('foo:foo'))

    for service_type in {
            HelpRepo, HelpHandler, HelpController, AnotherPath, AnotherPathTwo,
            Foo, FooDBContext
    }:
        container.add_exact_transient(service_type)

    provider = container.build_provider()

    help_controller = provider.get(HelpController)

    assert help_controller is not None
    assert help_controller.logger is not None
    assert help_controller.logger.name == 'tests.test_services.HelpController'
    assert help_controller.handler.repo.logger.name == 'tests.test_services.HelpRepo'
    assert help_controller.other.child.logger.name == 'tests.test_services.' \
                                                      'AnotherPathTwo'
Example #15
0
def test_service_provider_contains():
    container = Container()
    container.add_exact_transient(IdGetter)

    provider = container.build_provider()

    assert Foo not in provider
    assert IdGetter in provider
Example #16
0
def test_raises_for_circular_dependency():
    container = Container()
    container.add_transient(ICircle, Circle)

    with pytest.raises(CircularDependencyException) as context:
        container.build_provider()

    assert 'Circle' in str(context.value)
Example #17
0
def test_raises_for_optional_parameter():
    container = Container()
    container.add_exact_transient(Foo)
    container.add_exact_transient(TypeWithOptional)

    with pytest.raises(UnsupportedUnionTypeException) as context:
        container.build_provider()

    assert 'foo' in str(context.value)
Example #18
0
def arrange_cats_example():
    container = Container()
    container.add_transient(ICatsRepository, FooDBCatsRepository)
    container.add_scoped(IRequestContext, RequestContext)
    container.add_exact_transient(GetCatRequestHandler)
    container.add_exact_transient(CatsController)
    container.add_instance(ServiceSettings('foodb:example;something;'))
    container.add_exact_transient(FooDBContext)
    return container
Example #19
0
def test_singleton_by_instance():
    container = Container()
    container.add_instance(Cat('Celine'))
    provider = container.build_provider()

    cat = provider.get(Cat)

    assert cat is not None
    assert cat.name == "Celine"
Example #20
0
def configure_services(configuration: Configuration) \
        -> Tuple[Container, ServicesRegistrationContext, Configuration]:
    container = Container()

    context = ServicesRegistrationContext()

    container.add_instance(configuration)

    return container, context, configuration
Example #21
0
def test_container_raises_for_class_without_init():
    container = Container()

    class WithoutInit:
        pass

    container.add_exact_singleton(WithoutInit)

    with raises(ClassNotDefiningInitMethod):
        container.build_provider()
Example #22
0
def test_transient_service():
    container = Container()
    container.add_transient(ICatsRepository, InMemoryCatsRepository)
    provider = container.build_provider()

    cats_repo = provider.get(ICatsRepository)
    assert isinstance(cats_repo, InMemoryCatsRepository)

    other_cats_repo = provider.get(ICatsRepository)
    assert cats_repo is not other_cats_repo
Example #23
0
def test_scoped_services_context_used_more_than_once_manual_dispose():
    container = Container()

    container.add_instance('value')

    provider = container.build_provider()
    context = GetServiceContext(provider)

    context.dispose()
    assert context.provider is None
Example #24
0
def test_add_singleton_by_factory_raises_for_missing_type(method_name):
    container = Container()

    def factory(_):
        return Cat('Celine')

    method = getattr(container, method_name)

    with pytest.raises(MissingTypeException):
        method(factory)
Example #25
0
async def test_from_services():
    request = Request("GET", b"/", [])

    service_instance = ExampleOne(1, 2)
    container = Container()
    container.add_instance(service_instance)

    parameter = ServiceBinder(ExampleOne, "service", False, container.build_provider())
    value = await parameter.get_value(request)

    assert value is service_instance
Example #26
0
def test_transient_by_type_without_parameters():
    container = Container()
    container.add_transient(ICatsRepository, InMemoryCatsRepository)
    provider = container.build_provider()
    cats_repo = provider.get(ICatsRepository)

    assert isinstance(cats_repo, InMemoryCatsRepository)
    other_cats_repo = provider.get(ICatsRepository)

    assert isinstance(other_cats_repo, InMemoryCatsRepository)
    assert cats_repo is not other_cats_repo
Example #27
0
def test_resolution_by_parameter_name():
    container = Container()
    container.add_transient(ICatsRepository, InMemoryCatsRepository)
    container.add_exact_transient(ResolveThisByParameterName)

    provider = container.build_provider()
    resolved = provider.get(ResolveThisByParameterName)

    assert resolved is not None

    assert isinstance(resolved, ResolveThisByParameterName)
    assert isinstance(resolved.cats_repository, InMemoryCatsRepository)
Example #28
0
def test_factory_can_receive_activating_type_as_parameter(method_name):
    class Logger:
        def __init__(self, name):
            self.name = name

    class HelpController:
        def __init__(self, logger: Logger):
            self.logger = logger

    class HomeController:
        def __init__(self, logger: Logger):
            self.logger = logger

    class FooController:
        def __init__(self, foo: Foo, logger: Logger):
            self.foo = foo
            self.logger = logger

    container = Container()
    container.add_exact_transient(Foo)

    def factory(_, activating_type) -> Logger:
        return Logger(activating_type.__module__ + '.' +
                      activating_type.__name__)

    method = getattr(container, method_name)
    method(factory)

    container\
        .add_exact_transient(HelpController)\
        .add_exact_transient(HomeController)\
        .add_exact_transient(FooController)

    provider = container.build_provider()

    help_controller = provider.get(HelpController)

    assert help_controller is not None
    assert help_controller.logger is not None
    assert help_controller.logger.name == 'tests.test_services.HelpController'

    home_controller = provider.get(HomeController)

    assert home_controller is not None
    assert home_controller.logger is not None
    assert home_controller.logger.name == 'tests.test_services.HomeController'

    foo_controller = provider.get(FooController)

    assert foo_controller is not None
    assert foo_controller.logger is not None
    assert foo_controller.logger.name == 'tests.test_services.FooController'
Example #29
0
def test_by_factory_with_different_parameters(method_name, factory):
    container = Container()

    method = getattr(container, method_name)
    method(factory)

    provider = container.build_provider()

    # ??? why not?
    cat = provider.get(Cat)

    assert cat is not None
    assert cat.name == 'Celine'
Example #30
0
def test_singleton_by_provider_with_shortcut():
    container = Container()
    container.add_singleton(P)
    container.add_transient(R)

    provider = container.build_provider()

    p = provider.get(P)
    r = provider.get(R)

    assert p is not None
    assert r is not None
    assert r.p is p