def test_build_provider_raises_for_missing_singleton_parameter(): container = Container() container.add_exact_singleton(CatsController) with raises(CannotResolveParameterException): container.build_provider()
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
def test_add_alias_requires_configured_type(): container = Container() container.add_alias('something', Cat) with raises(AliasConfigurationError): container.build_provider()
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
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
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
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()
def test_add_alias_raises_if_alias_is_defined(): container = Container() container.add_alias('something', Cat) with raises(AliasAlreadyDefined): container.add_alias('something', Foo)
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
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)
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
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)
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()
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'
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
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)
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)
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
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"
def configure_services(configuration: Configuration) \ -> Tuple[Container, ServicesRegistrationContext, Configuration]: container = Container() context = ServicesRegistrationContext() container.add_instance(configuration) return container, context, configuration
def test_container_raises_for_class_without_init(): container = Container() class WithoutInit: pass container.add_exact_singleton(WithoutInit) with raises(ClassNotDefiningInitMethod): container.build_provider()
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
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
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)
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
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
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)
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'
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'
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