mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-10-31 16:07:51 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			1176 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1176 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import asyncio
 | |
| import random
 | |
| import unittest
 | |
| 
 | |
| from dependency_injector import containers, providers, errors
 | |
| 
 | |
| # Runtime import to get asyncutils module
 | |
| import os
 | |
| _TOP_DIR = os.path.abspath(
 | |
|     os.path.sep.join((
 | |
|         os.path.dirname(__file__),
 | |
|         '../',
 | |
|     )),
 | |
| )
 | |
| import sys
 | |
| sys.path.append(_TOP_DIR)
 | |
| 
 | |
| from asyncutils import AsyncTestCase
 | |
| 
 | |
| 
 | |
| RESOURCE1 = object()
 | |
| RESOURCE2 = object()
 | |
| 
 | |
| 
 | |
| async def init_resource(resource):
 | |
|     await asyncio.sleep(random.randint(1, 10) / 1000)
 | |
|     yield resource
 | |
|     await asyncio.sleep(random.randint(1, 10) / 1000)
 | |
| 
 | |
| 
 | |
| class Client:
 | |
|     def __init__(self, resource1: object, resource2: object) -> None:
 | |
|         self.resource1 = resource1
 | |
|         self.resource2 = resource2
 | |
| 
 | |
| 
 | |
| class Service:
 | |
|     def __init__(self, client: Client) -> None:
 | |
|         self.client = client
 | |
| 
 | |
| 
 | |
| class Container(containers.DeclarativeContainer):
 | |
|     resource1 = providers.Resource(init_resource, providers.Object(RESOURCE1))
 | |
|     resource2 = providers.Resource(init_resource, providers.Object(RESOURCE2))
 | |
| 
 | |
|     client = providers.Factory(
 | |
|         Client,
 | |
|         resource1=resource1,
 | |
|         resource2=resource2,
 | |
|     )
 | |
| 
 | |
|     service = providers.Factory(
 | |
|         Service,
 | |
|         client=client,
 | |
|     )
 | |
| 
 | |
| 
 | |
| class FactoryTests(AsyncTestCase):
 | |
| 
 | |
|     def test_args_injection(self):
 | |
|         class ContainerWithArgs(containers.DeclarativeContainer):
 | |
|             resource1 = providers.Resource(init_resource, providers.Object(RESOURCE1))
 | |
|             resource2 = providers.Resource(init_resource, providers.Object(RESOURCE2))
 | |
| 
 | |
|             client = providers.Factory(
 | |
|                 Client,
 | |
|                 resource1,
 | |
|                 resource2,
 | |
|             )
 | |
| 
 | |
|             service = providers.Factory(
 | |
|                 Service,
 | |
|                 client,
 | |
|             )
 | |
| 
 | |
|         container = ContainerWithArgs()
 | |
| 
 | |
|         client1 = self._run(container.client())
 | |
|         client2 = self._run(container.client())
 | |
| 
 | |
|         self.assertIsInstance(client1, Client)
 | |
|         self.assertIs(client1.resource1, RESOURCE1)
 | |
|         self.assertIs(client1.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsInstance(client2, Client)
 | |
|         self.assertIs(client2.resource1, RESOURCE1)
 | |
|         self.assertIs(client2.resource2, RESOURCE2)
 | |
| 
 | |
|         service1 = self._run(container.service())
 | |
|         service2 = self._run(container.service())
 | |
| 
 | |
|         self.assertIsInstance(service1, Service)
 | |
|         self.assertIsInstance(service1.client, Client)
 | |
|         self.assertIs(service1.client.resource1, RESOURCE1)
 | |
|         self.assertIs(service1.client.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsInstance(service2, Service)
 | |
|         self.assertIsInstance(service2.client, Client)
 | |
|         self.assertIs(service2.client.resource1, RESOURCE1)
 | |
|         self.assertIs(service2.client.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsNot(service1.client, service2.client)
 | |
| 
 | |
|     def test_kwargs_injection(self):
 | |
|         container = Container()
 | |
| 
 | |
|         client1 = self._run(container.client())
 | |
|         client2 = self._run(container.client())
 | |
| 
 | |
|         self.assertIsInstance(client1, Client)
 | |
|         self.assertIs(client1.resource1, RESOURCE1)
 | |
|         self.assertIs(client1.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsInstance(client2, Client)
 | |
|         self.assertIs(client2.resource1, RESOURCE1)
 | |
|         self.assertIs(client2.resource2, RESOURCE2)
 | |
| 
 | |
|         service1 = self._run(container.service())
 | |
|         service2 = self._run(container.service())
 | |
| 
 | |
|         self.assertIsInstance(service1, Service)
 | |
|         self.assertIsInstance(service1.client, Client)
 | |
|         self.assertIs(service1.client.resource1, RESOURCE1)
 | |
|         self.assertIs(service1.client.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsInstance(service2, Service)
 | |
|         self.assertIsInstance(service2.client, Client)
 | |
|         self.assertIs(service2.client.resource1, RESOURCE1)
 | |
|         self.assertIs(service2.client.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsNot(service1.client, service2.client)
 | |
| 
 | |
|     def test_context_kwargs_injection(self):
 | |
|         resource2_extra = object()
 | |
| 
 | |
|         container = Container()
 | |
| 
 | |
|         client1 = self._run(container.client(resource2=resource2_extra))
 | |
|         client2 = self._run(container.client(resource2=resource2_extra))
 | |
| 
 | |
|         self.assertIsInstance(client1, Client)
 | |
|         self.assertIs(client1.resource1, RESOURCE1)
 | |
|         self.assertIs(client1.resource2, resource2_extra)
 | |
| 
 | |
|         self.assertIsInstance(client2, Client)
 | |
|         self.assertIs(client2.resource1, RESOURCE1)
 | |
|         self.assertIs(client2.resource2, resource2_extra)
 | |
| 
 | |
|     def test_args_kwargs_injection(self):
 | |
|         class ContainerWithArgsAndKwArgs(containers.DeclarativeContainer):
 | |
|             resource1 = providers.Resource(init_resource, providers.Object(RESOURCE1))
 | |
|             resource2 = providers.Resource(init_resource, providers.Object(RESOURCE2))
 | |
| 
 | |
|             client = providers.Factory(
 | |
|                 Client,
 | |
|                 resource1,
 | |
|                 resource2=resource2,
 | |
|             )
 | |
| 
 | |
|             service = providers.Factory(
 | |
|                 Service,
 | |
|                 client=client,
 | |
|             )
 | |
| 
 | |
|         container = ContainerWithArgsAndKwArgs()
 | |
| 
 | |
|         client1 = self._run(container.client())
 | |
|         client2 = self._run(container.client())
 | |
| 
 | |
|         self.assertIsInstance(client1, Client)
 | |
|         self.assertIs(client1.resource1, RESOURCE1)
 | |
|         self.assertIs(client1.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsInstance(client2, Client)
 | |
|         self.assertIs(client2.resource1, RESOURCE1)
 | |
|         self.assertIs(client2.resource2, RESOURCE2)
 | |
| 
 | |
|         service1 = self._run(container.service())
 | |
|         service2 = self._run(container.service())
 | |
| 
 | |
|         self.assertIsInstance(service1, Service)
 | |
|         self.assertIsInstance(service1.client, Client)
 | |
|         self.assertIs(service1.client.resource1, RESOURCE1)
 | |
|         self.assertIs(service1.client.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsInstance(service2, Service)
 | |
|         self.assertIsInstance(service2.client, Client)
 | |
|         self.assertIs(service2.client.resource1, RESOURCE1)
 | |
|         self.assertIs(service2.client.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsNot(service1.client, service2.client)
 | |
| 
 | |
|     def test_injection_error(self):
 | |
|         async def init_resource():
 | |
|             raise Exception('Something went wrong')
 | |
| 
 | |
|         class Container(containers.DeclarativeContainer):
 | |
|             resource_with_error = providers.Resource(init_resource)
 | |
| 
 | |
|             client = providers.Factory(
 | |
|                 Client,
 | |
|                 resource1=resource_with_error,
 | |
|                 resource2=None,
 | |
|             )
 | |
| 
 | |
|         container = Container()
 | |
| 
 | |
|         with self.assertRaises(Exception) as context:
 | |
|             self._run(container.client())
 | |
|         self.assertEqual(str(context.exception), 'Something went wrong')
 | |
| 
 | |
|     def test_injection_runtime_error_async_provides(self):
 | |
|         async def create_client(*args,  **kwargs):
 | |
|             raise Exception('Something went wrong')
 | |
| 
 | |
|         class Container(containers.DeclarativeContainer):
 | |
|             resource = providers.Resource(init_resource, providers.Object(RESOURCE1))
 | |
| 
 | |
|             client = providers.Factory(
 | |
|                 create_client,
 | |
|                 resource1=resource,
 | |
|                 resource2=None,
 | |
|             )
 | |
| 
 | |
|         container = Container()
 | |
| 
 | |
|         with self.assertRaises(Exception) as context:
 | |
|             self._run(container.client())
 | |
|         self.assertEqual(str(context.exception), 'Something went wrong')
 | |
| 
 | |
|     def test_injection_call_error_async_provides(self):
 | |
|         async def create_client():  # <-- no args defined
 | |
|             ...
 | |
| 
 | |
|         class Container(containers.DeclarativeContainer):
 | |
|             resource = providers.Resource(init_resource, providers.Object(RESOURCE1))
 | |
| 
 | |
|             client = providers.Factory(
 | |
|                 create_client,
 | |
|                 resource1=resource,
 | |
|                 resource2=None,
 | |
|             )
 | |
| 
 | |
|         container = Container()
 | |
| 
 | |
|         with self.assertRaises(TypeError) as context:
 | |
|             self._run(container.client())
 | |
|         self.assertIn("create_client() got", str(context.exception))
 | |
|         self.assertIn("unexpected keyword argument", str(context.exception))
 | |
| 
 | |
|     def test_attributes_injection(self):
 | |
|         class ContainerWithAttributes(containers.DeclarativeContainer):
 | |
|             resource1 = providers.Resource(init_resource, providers.Object(RESOURCE1))
 | |
|             resource2 = providers.Resource(init_resource, providers.Object(RESOURCE2))
 | |
| 
 | |
|             client = providers.Factory(
 | |
|                 Client,
 | |
|                 resource1,
 | |
|                 resource2=None,
 | |
|             )
 | |
|             client.add_attributes(resource2=resource2)
 | |
| 
 | |
|             service = providers.Factory(
 | |
|                 Service,
 | |
|                 client=None,
 | |
|             )
 | |
|             service.add_attributes(client=client)
 | |
| 
 | |
|         container = ContainerWithAttributes()
 | |
| 
 | |
|         client1 = self._run(container.client())
 | |
|         client2 = self._run(container.client())
 | |
| 
 | |
|         self.assertIsInstance(client1, Client)
 | |
|         self.assertIs(client1.resource1, RESOURCE1)
 | |
|         self.assertIs(client1.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsInstance(client2, Client)
 | |
|         self.assertIs(client2.resource1, RESOURCE1)
 | |
|         self.assertIs(client2.resource2, RESOURCE2)
 | |
| 
 | |
|         service1 = self._run(container.service())
 | |
|         service2 = self._run(container.service())
 | |
| 
 | |
|         self.assertIsInstance(service1, Service)
 | |
|         self.assertIsInstance(service1.client, Client)
 | |
|         self.assertIs(service1.client.resource1, RESOURCE1)
 | |
|         self.assertIs(service1.client.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsInstance(service2, Service)
 | |
|         self.assertIsInstance(service2.client, Client)
 | |
|         self.assertIs(service2.client.resource1, RESOURCE1)
 | |
|         self.assertIs(service2.client.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsNot(service1.client, service2.client)
 | |
| 
 | |
|     def test_attributes_injection_attribute_error(self):
 | |
|         class ClientWithException(Client):
 | |
|             @property
 | |
|             def attribute_set_error(self):
 | |
|                 return None
 | |
| 
 | |
|             @attribute_set_error.setter
 | |
|             def attribute_set_error(self, value):
 | |
|                 raise Exception('Something went wrong')
 | |
| 
 | |
|         class Container(containers.DeclarativeContainer):
 | |
|             resource = providers.Resource(init_resource, providers.Object(RESOURCE1))
 | |
| 
 | |
|             client = providers.Factory(
 | |
|                 ClientWithException,
 | |
|                 resource1=resource,
 | |
|                 resource2=resource,
 | |
|             )
 | |
|             client.add_attributes(attribute_set_error=123)
 | |
| 
 | |
|         container = Container()
 | |
| 
 | |
|         with self.assertRaises(Exception) as context:
 | |
|             self._run(container.client())
 | |
|         self.assertEqual(str(context.exception), 'Something went wrong')
 | |
| 
 | |
|     def test_attributes_injection_runtime_error(self):
 | |
|         async def init_resource():
 | |
|             raise Exception('Something went wrong')
 | |
| 
 | |
|         class Container(containers.DeclarativeContainer):
 | |
|             resource = providers.Resource(init_resource)
 | |
| 
 | |
|             client = providers.Factory(
 | |
|                 Client,
 | |
|                 resource1=None,
 | |
|                 resource2=None,
 | |
|             )
 | |
|             client.add_attributes(resource1=resource)
 | |
|             client.add_attributes(resource2=resource)
 | |
| 
 | |
|         container = Container()
 | |
| 
 | |
|         with self.assertRaises(Exception) as context:
 | |
|             self._run(container.client())
 | |
|         self.assertEqual(str(context.exception), 'Something went wrong')
 | |
| 
 | |
|     def test_async_instance_and_sync_attributes_injection(self):
 | |
|         class ContainerWithAttributes(containers.DeclarativeContainer):
 | |
|             resource1 = providers.Resource(init_resource, providers.Object(RESOURCE1))
 | |
| 
 | |
|             client = providers.Factory(
 | |
|                 Client,
 | |
|                 resource1,
 | |
|                 resource2=None,
 | |
|             )
 | |
|             client.add_attributes(resource2=providers.Object(RESOURCE2))
 | |
| 
 | |
|             service = providers.Factory(
 | |
|                 Service,
 | |
|                 client=None,
 | |
|             )
 | |
|             service.add_attributes(client=client)
 | |
| 
 | |
|         container = ContainerWithAttributes()
 | |
| 
 | |
|         client1 = self._run(container.client())
 | |
|         client2 = self._run(container.client())
 | |
| 
 | |
|         self.assertIsInstance(client1, Client)
 | |
|         self.assertIs(client1.resource1, RESOURCE1)
 | |
|         self.assertIs(client1.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsInstance(client2, Client)
 | |
|         self.assertIs(client2.resource1, RESOURCE1)
 | |
|         self.assertIs(client2.resource2, RESOURCE2)
 | |
| 
 | |
|         service1 = self._run(container.service())
 | |
|         service2 = self._run(container.service())
 | |
| 
 | |
|         self.assertIsInstance(service1, Service)
 | |
|         self.assertIsInstance(service1.client, Client)
 | |
|         self.assertIs(service1.client.resource1, RESOURCE1)
 | |
|         self.assertIs(service1.client.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsInstance(service2, Service)
 | |
|         self.assertIsInstance(service2.client, Client)
 | |
|         self.assertIs(service2.client.resource1, RESOURCE1)
 | |
|         self.assertIs(service2.client.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsNot(service1.client, service2.client)
 | |
| 
 | |
| 
 | |
| class FactoryAggregateTests(AsyncTestCase):
 | |
| 
 | |
|     def test_async_mode(self):
 | |
|         object1 = object()
 | |
|         object2 = object()
 | |
| 
 | |
|         async def _get_object1():
 | |
|             return object1
 | |
| 
 | |
|         def _get_object2():
 | |
|             return object2
 | |
| 
 | |
|         provider = providers.FactoryAggregate(
 | |
|             object1=providers.Factory(_get_object1),
 | |
|             object2=providers.Factory(_get_object2),
 | |
|         )
 | |
| 
 | |
|         self.assertTrue(provider.is_async_mode_undefined())
 | |
| 
 | |
|         created_object1 = self._run(provider('object1'))
 | |
|         self.assertIs(created_object1, object1)
 | |
|         self.assertTrue(provider.is_async_mode_enabled())
 | |
| 
 | |
|         created_object2 = self._run(provider('object2'))
 | |
|         self.assertIs(created_object2, object2)
 | |
| 
 | |
| 
 | |
| class SingletonTests(AsyncTestCase):
 | |
| 
 | |
|     def test_injections(self):
 | |
|         class ContainerWithSingletons(containers.DeclarativeContainer):
 | |
|             resource1 = providers.Resource(init_resource, providers.Object(RESOURCE1))
 | |
|             resource2 = providers.Resource(init_resource, providers.Object(RESOURCE2))
 | |
| 
 | |
|             client = providers.Singleton(
 | |
|                 Client,
 | |
|                 resource1=resource1,
 | |
|                 resource2=resource2,
 | |
|             )
 | |
| 
 | |
|             service = providers.Singleton(
 | |
|                 Service,
 | |
|                 client=client,
 | |
|             )
 | |
| 
 | |
|         container = ContainerWithSingletons()
 | |
| 
 | |
|         client1 = self._run(container.client())
 | |
|         client2 = self._run(container.client())
 | |
| 
 | |
|         self.assertIsInstance(client1, Client)
 | |
|         self.assertIs(client1.resource1, RESOURCE1)
 | |
|         self.assertIs(client1.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsInstance(client2, Client)
 | |
|         self.assertIs(client2.resource1, RESOURCE1)
 | |
|         self.assertIs(client2.resource2, RESOURCE2)
 | |
| 
 | |
|         service1 = self._run(container.service())
 | |
|         service2 = self._run(container.service())
 | |
| 
 | |
|         self.assertIsInstance(service1, Service)
 | |
|         self.assertIsInstance(service1.client, Client)
 | |
|         self.assertIs(service1.client.resource1, RESOURCE1)
 | |
|         self.assertIs(service1.client.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsInstance(service2, Service)
 | |
|         self.assertIsInstance(service2.client, Client)
 | |
|         self.assertIs(service2.client.resource1, RESOURCE1)
 | |
|         self.assertIs(service2.client.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIs(service1, service2)
 | |
|         self.assertIs(service1.client, service2.client)
 | |
|         self.assertIs(service1.client, client1)
 | |
| 
 | |
|         self.assertIs(service2.client, client2)
 | |
|         self.assertIs(client1, client2)
 | |
| 
 | |
|     def test_async_mode(self):
 | |
|         instance = object()
 | |
| 
 | |
|         async def create_instance():
 | |
|             return instance
 | |
| 
 | |
|         provider = providers.Singleton(create_instance)
 | |
| 
 | |
|         instance1 = self._run(provider())
 | |
|         instance2 = self._run(provider())
 | |
| 
 | |
|         self.assertIs(instance1, instance2)
 | |
|         self.assertIs(instance, instance)
 | |
| 
 | |
|     def test_async_init_with_error(self):
 | |
|         # Disable default exception handling to prevent output
 | |
|         asyncio.get_event_loop().set_exception_handler(lambda loop, context: ...)
 | |
| 
 | |
|         async def create_instance():
 | |
|             create_instance.counter += 1
 | |
|             raise RuntimeError()
 | |
| 
 | |
|         create_instance.counter = 0
 | |
| 
 | |
|         provider = providers.Singleton(create_instance)
 | |
| 
 | |
| 
 | |
|         future = provider()
 | |
|         self.assertTrue(provider.is_async_mode_enabled())
 | |
| 
 | |
|         with self.assertRaises(RuntimeError):
 | |
|             self._run(future)
 | |
| 
 | |
|         self.assertEqual(create_instance.counter, 1)
 | |
|         self.assertTrue(provider.is_async_mode_enabled())
 | |
| 
 | |
|         with self.assertRaises(RuntimeError):
 | |
|             self._run(provider())
 | |
| 
 | |
|         self.assertEqual(create_instance.counter, 2)
 | |
|         self.assertTrue(provider.is_async_mode_enabled())
 | |
| 
 | |
|         # Restore default exception handling
 | |
|         asyncio.get_event_loop().set_exception_handler(None)
 | |
| 
 | |
| 
 | |
| class DelegatedSingletonTests(AsyncTestCase):
 | |
| 
 | |
|     def test_async_mode(self):
 | |
|         instance = object()
 | |
| 
 | |
|         async def create_instance():
 | |
|             return instance
 | |
| 
 | |
|         provider = providers.DelegatedSingleton(create_instance)
 | |
| 
 | |
|         instance1 = self._run(provider())
 | |
|         instance2 = self._run(provider())
 | |
| 
 | |
|         self.assertIs(instance1, instance2)
 | |
|         self.assertIs(instance, instance)
 | |
| 
 | |
| 
 | |
| class ThreadSafeSingletonTests(AsyncTestCase):
 | |
| 
 | |
|     def test_async_mode(self):
 | |
|         instance = object()
 | |
| 
 | |
|         async def create_instance():
 | |
|             return instance
 | |
| 
 | |
|         provider = providers.ThreadSafeSingleton(create_instance)
 | |
| 
 | |
|         instance1 = self._run(provider())
 | |
|         instance2 = self._run(provider())
 | |
| 
 | |
|         self.assertIs(instance1, instance2)
 | |
|         self.assertIs(instance, instance)
 | |
| 
 | |
| 
 | |
| class DelegatedThreadSafeSingletonTests(AsyncTestCase):
 | |
| 
 | |
|     def test_async_mode(self):
 | |
|         instance = object()
 | |
| 
 | |
|         async def create_instance():
 | |
|             return instance
 | |
| 
 | |
|         provider = providers.DelegatedThreadSafeSingleton(create_instance)
 | |
| 
 | |
|         instance1 = self._run(provider())
 | |
|         instance2 = self._run(provider())
 | |
| 
 | |
|         self.assertIs(instance1, instance2)
 | |
|         self.assertIs(instance, instance)
 | |
| 
 | |
| 
 | |
| class ThreadLocalSingletonTests(AsyncTestCase):
 | |
| 
 | |
|     def test_async_mode(self):
 | |
|         instance = object()
 | |
| 
 | |
|         async def create_instance():
 | |
|             return instance
 | |
| 
 | |
|         provider = providers.ThreadLocalSingleton(create_instance)
 | |
| 
 | |
|         instance1 = self._run(provider())
 | |
|         instance2 = self._run(provider())
 | |
| 
 | |
|         self.assertIs(instance1, instance2)
 | |
|         self.assertIs(instance, instance)
 | |
| 
 | |
| 
 | |
|     def test_async_init_with_error(self):
 | |
|         # Disable default exception handling to prevent output
 | |
|         asyncio.get_event_loop().set_exception_handler(lambda loop, context: ...)
 | |
| 
 | |
|         async def create_instance():
 | |
|             create_instance.counter += 1
 | |
|             raise RuntimeError()
 | |
|         create_instance.counter = 0
 | |
| 
 | |
|         provider = providers.ThreadLocalSingleton(create_instance)
 | |
| 
 | |
|         future = provider()
 | |
|         self.assertTrue(provider.is_async_mode_enabled())
 | |
| 
 | |
|         with self.assertRaises(RuntimeError):
 | |
|             self._run(future)
 | |
| 
 | |
|         self.assertEqual(create_instance.counter, 1)
 | |
|         self.assertTrue(provider.is_async_mode_enabled())
 | |
| 
 | |
|         with self.assertRaises(RuntimeError):
 | |
|             self._run(provider())
 | |
| 
 | |
|         self.assertEqual(create_instance.counter, 2)
 | |
|         self.assertTrue(provider.is_async_mode_enabled())
 | |
| 
 | |
|         # Restore default exception handling
 | |
|         asyncio.get_event_loop().set_exception_handler(None)
 | |
| 
 | |
| 
 | |
| class DelegatedThreadLocalSingletonTests(AsyncTestCase):
 | |
| 
 | |
|     def test_async_mode(self):
 | |
|         instance = object()
 | |
| 
 | |
|         async def create_instance():
 | |
|             return instance
 | |
| 
 | |
|         provider = providers.DelegatedThreadLocalSingleton(create_instance)
 | |
| 
 | |
|         instance1 = self._run(provider())
 | |
|         instance2 = self._run(provider())
 | |
| 
 | |
|         self.assertIs(instance1, instance2)
 | |
|         self.assertIs(instance, instance)
 | |
| 
 | |
| 
 | |
| class ProvidedInstanceTests(AsyncTestCase):
 | |
| 
 | |
|     def test_provided_attribute(self):
 | |
|         class TestClient:
 | |
|             def __init__(self, resource):
 | |
|                 self.resource = resource
 | |
| 
 | |
|         class TestService:
 | |
|             def __init__(self, resource):
 | |
|                 self.resource = resource
 | |
| 
 | |
|         class TestContainer(containers.DeclarativeContainer):
 | |
|             resource = providers.Resource(init_resource, providers.Object(RESOURCE1))
 | |
|             client = providers.Factory(TestClient, resource=resource)
 | |
|             service = providers.Factory(TestService, resource=client.provided.resource)
 | |
| 
 | |
|         container = TestContainer()
 | |
| 
 | |
|         instance1, instance2 = self._run(
 | |
|             asyncio.gather(
 | |
|                 container.service(),
 | |
|                 container.service(),
 | |
|             ),
 | |
|         )
 | |
| 
 | |
|         self.assertIs(instance1.resource, RESOURCE1)
 | |
|         self.assertIs(instance2.resource, RESOURCE1)
 | |
|         self.assertIs(instance1.resource, instance2.resource)
 | |
| 
 | |
|     def test_provided_attribute_error(self):
 | |
|         async def raise_exception():
 | |
|             raise RuntimeError()
 | |
| 
 | |
|         class TestContainer(containers.DeclarativeContainer):
 | |
|             client = providers.Factory(raise_exception)
 | |
| 
 | |
|         container = TestContainer()
 | |
| 
 | |
|         with self.assertRaises(RuntimeError):
 | |
|             self._run(container.client.provided.attr())
 | |
| 
 | |
|     def test_provided_attribute_undefined_attribute(self):
 | |
|         class TestClient:
 | |
|             def __init__(self, resource):
 | |
|                 self.resource = resource
 | |
| 
 | |
|         class TestContainer(containers.DeclarativeContainer):
 | |
|             resource = providers.Resource(init_resource, providers.Object(RESOURCE1))
 | |
|             client = providers.Factory(TestClient, resource=resource)
 | |
| 
 | |
|         container = TestContainer()
 | |
| 
 | |
|         with self.assertRaises(AttributeError):
 | |
|             self._run(container.client.provided.attr())
 | |
| 
 | |
|     def test_provided_item(self):
 | |
|         class TestClient:
 | |
|             def __init__(self, resource):
 | |
|                 self.resource = resource
 | |
| 
 | |
|             def __getitem__(self, item):
 | |
|                 return getattr(self, item)
 | |
| 
 | |
|         class TestService:
 | |
|             def __init__(self, resource):
 | |
|                 self.resource = resource
 | |
| 
 | |
|         class TestContainer(containers.DeclarativeContainer):
 | |
|             resource = providers.Resource(init_resource, providers.Object(RESOURCE1))
 | |
|             client = providers.Factory(TestClient, resource=resource)
 | |
|             service = providers.Factory(TestService, resource=client.provided['resource'])
 | |
| 
 | |
|         container = TestContainer()
 | |
| 
 | |
|         instance1, instance2 = self._run(
 | |
|             asyncio.gather(
 | |
|                 container.service(),
 | |
|                 container.service(),
 | |
|             ),
 | |
|         )
 | |
| 
 | |
|         self.assertIs(instance1.resource, RESOURCE1)
 | |
|         self.assertIs(instance2.resource, RESOURCE1)
 | |
|         self.assertIs(instance1.resource, instance2.resource)
 | |
| 
 | |
|     def test_provided_item_error(self):
 | |
|         async def raise_exception():
 | |
|             raise RuntimeError()
 | |
| 
 | |
|         class TestContainer(containers.DeclarativeContainer):
 | |
|             client = providers.Factory(raise_exception)
 | |
| 
 | |
|         container = TestContainer()
 | |
| 
 | |
|         with self.assertRaises(RuntimeError):
 | |
|             self._run(container.client.provided['item']())
 | |
| 
 | |
|     def test_provided_item_undefined_item(self):
 | |
|         class TestContainer(containers.DeclarativeContainer):
 | |
|             resource = providers.Resource(init_resource, providers.Object(RESOURCE1))
 | |
|             client = providers.Factory(dict, resource=resource)
 | |
| 
 | |
|         container = TestContainer()
 | |
| 
 | |
|         with self.assertRaises(KeyError):
 | |
|             self._run(container.client.provided['item']())
 | |
| 
 | |
|     def test_provided_method_call(self):
 | |
|         class TestClient:
 | |
|             def __init__(self, resource):
 | |
|                 self.resource = resource
 | |
| 
 | |
|             def get_resource(self):
 | |
|                 return self.resource
 | |
| 
 | |
|         class TestService:
 | |
|             def __init__(self, resource):
 | |
|                 self.resource = resource
 | |
| 
 | |
|         class TestContainer(containers.DeclarativeContainer):
 | |
|             resource = providers.Resource(init_resource, providers.Object(RESOURCE1))
 | |
|             client = providers.Factory(TestClient, resource=resource)
 | |
|             service = providers.Factory(TestService, resource=client.provided.get_resource.call())
 | |
| 
 | |
|         container = TestContainer()
 | |
| 
 | |
|         instance1, instance2 = self._run(
 | |
|             asyncio.gather(
 | |
|                 container.service(),
 | |
|                 container.service(),
 | |
|             ),
 | |
|         )
 | |
| 
 | |
|         self.assertIs(instance1.resource, RESOURCE1)
 | |
|         self.assertIs(instance2.resource, RESOURCE1)
 | |
|         self.assertIs(instance1.resource, instance2.resource)
 | |
| 
 | |
|     def test_provided_method_call_parent_error(self):
 | |
|         async def raise_exception():
 | |
|             raise RuntimeError()
 | |
| 
 | |
|         class TestContainer(containers.DeclarativeContainer):
 | |
|             client = providers.Factory(raise_exception)
 | |
| 
 | |
|         container = TestContainer()
 | |
| 
 | |
|         with self.assertRaises(RuntimeError):
 | |
|             self._run(container.client.provided.method.call()())
 | |
| 
 | |
|     def test_provided_method_call_error(self):
 | |
|         class TestClient:
 | |
|             def method(self):
 | |
|                 raise RuntimeError()
 | |
| 
 | |
|         class TestContainer(containers.DeclarativeContainer):
 | |
|             client = providers.Factory(TestClient)
 | |
| 
 | |
|         container = TestContainer()
 | |
| 
 | |
|         with self.assertRaises(RuntimeError):
 | |
|             self._run(container.client.provided.method.call()())
 | |
| 
 | |
| 
 | |
| class DependencyTests(AsyncTestCase):
 | |
| 
 | |
|     def test_provide_error(self):
 | |
|         async def get_async():
 | |
|             raise Exception
 | |
| 
 | |
|         provider = providers.Dependency()
 | |
|         provider.override(providers.Callable(get_async))
 | |
| 
 | |
|         with self.assertRaises(Exception):
 | |
|             self._run(provider())
 | |
| 
 | |
|     def test_isinstance(self):
 | |
|         dependency = 1.0
 | |
| 
 | |
|         async def get_async():
 | |
|             return dependency
 | |
| 
 | |
|         provider = providers.Dependency(instance_of=float)
 | |
|         provider.override(providers.Callable(get_async))
 | |
| 
 | |
|         self.assertTrue(provider.is_async_mode_undefined())
 | |
| 
 | |
|         dependency1 = self._run(provider())
 | |
| 
 | |
|         self.assertTrue(provider.is_async_mode_enabled())
 | |
| 
 | |
|         dependency2 = self._run(provider())
 | |
| 
 | |
|         self.assertEqual(dependency1, dependency)
 | |
|         self.assertEqual(dependency2, dependency)
 | |
| 
 | |
|     def test_isinstance_invalid(self):
 | |
|         async def get_async():
 | |
|             return {}
 | |
| 
 | |
|         provider = providers.Dependency(instance_of=float)
 | |
|         provider.override(providers.Callable(get_async))
 | |
| 
 | |
|         self.assertTrue(provider.is_async_mode_undefined())
 | |
| 
 | |
|         with self.assertRaises(errors.Error):
 | |
|             self._run(provider())
 | |
| 
 | |
|         self.assertTrue(provider.is_async_mode_enabled())
 | |
| 
 | |
|     def test_async_mode(self):
 | |
|         dependency = 123
 | |
| 
 | |
|         async def get_async():
 | |
|             return dependency
 | |
| 
 | |
|         def get_sync():
 | |
|             return dependency
 | |
| 
 | |
|         provider = providers.Dependency(instance_of=int)
 | |
|         provider.override(providers.Factory(get_async))
 | |
| 
 | |
|         self.assertTrue(provider.is_async_mode_undefined())
 | |
| 
 | |
|         dependency1 = self._run(provider())
 | |
| 
 | |
|         self.assertTrue(provider.is_async_mode_enabled())
 | |
| 
 | |
|         dependency2 = self._run(provider())
 | |
|         self.assertEqual(dependency1, dependency)
 | |
|         self.assertEqual(dependency2, dependency)
 | |
| 
 | |
|         provider.override(providers.Factory(get_sync))
 | |
| 
 | |
|         dependency3 = self._run(provider())
 | |
| 
 | |
|         self.assertTrue(provider.is_async_mode_enabled())
 | |
| 
 | |
|         dependency4 = self._run(provider())
 | |
|         self.assertEqual(dependency3, dependency)
 | |
|         self.assertEqual(dependency4, dependency)
 | |
| 
 | |
| 
 | |
| class ListTests(AsyncTestCase):
 | |
| 
 | |
|     def test_provide(self):
 | |
|         # See issue: https://github.com/ets-labs/python-dependency-injector/issues/450
 | |
|         async def create_resource(param: str):
 | |
|             return param
 | |
| 
 | |
|         class Container(containers.DeclarativeContainer):
 | |
| 
 | |
|             resources = providers.List(
 | |
|                 providers.Resource(create_resource, 'foo'),
 | |
|                 providers.Resource(create_resource, 'bar')
 | |
|             )
 | |
| 
 | |
|         container = Container()
 | |
|         resources = self._run(container.resources())
 | |
| 
 | |
|         self.assertEqual(resources[0], 'foo')
 | |
|         self.assertEqual(resources[1], 'bar')
 | |
| 
 | |
| 
 | |
| class DictTests(AsyncTestCase):
 | |
| 
 | |
|     def test_provide(self):
 | |
|         async def create_resource(param: str):
 | |
|             return param
 | |
| 
 | |
|         class Container(containers.DeclarativeContainer):
 | |
| 
 | |
|             resources = providers.Dict(
 | |
|                 foo=providers.Resource(create_resource, 'foo'),
 | |
|                 bar=providers.Resource(create_resource, 'bar')
 | |
|             )
 | |
| 
 | |
|         container = Container()
 | |
|         resources = self._run(container.resources())
 | |
| 
 | |
|         self.assertEqual(resources['foo'], 'foo')
 | |
|         self.assertEqual(resources['bar'], 'bar')
 | |
| 
 | |
| 
 | |
| class OverrideTests(AsyncTestCase):
 | |
| 
 | |
|     def test_provider(self):
 | |
|         dependency = object()
 | |
| 
 | |
|         async def _get_dependency_async():
 | |
|             return dependency
 | |
| 
 | |
|         def _get_dependency_sync():
 | |
|             return dependency
 | |
| 
 | |
|         provider = providers.Provider()
 | |
| 
 | |
|         provider.override(providers.Callable(_get_dependency_async))
 | |
|         dependency1 = self._run(provider())
 | |
| 
 | |
|         provider.override(providers.Callable(_get_dependency_sync))
 | |
|         dependency2 = self._run(provider())
 | |
| 
 | |
|         self.assertIs(dependency1, dependency)
 | |
|         self.assertIs(dependency2, dependency)
 | |
| 
 | |
|     def test_callable(self):
 | |
|         dependency = object()
 | |
| 
 | |
|         async def _get_dependency_async():
 | |
|             return dependency
 | |
| 
 | |
|         def _get_dependency_sync():
 | |
|             return dependency
 | |
| 
 | |
|         provider = providers.Callable(_get_dependency_async)
 | |
|         dependency1 = self._run(provider())
 | |
| 
 | |
|         provider.override(providers.Callable(_get_dependency_sync))
 | |
|         dependency2 = self._run(provider())
 | |
| 
 | |
|         self.assertIs(dependency1, dependency)
 | |
|         self.assertIs(dependency2, dependency)
 | |
| 
 | |
|     def test_factory(self):
 | |
|         dependency = object()
 | |
| 
 | |
|         async def _get_dependency_async():
 | |
|             return dependency
 | |
| 
 | |
|         def _get_dependency_sync():
 | |
|             return dependency
 | |
| 
 | |
|         provider = providers.Factory(_get_dependency_async)
 | |
|         dependency1 = self._run(provider())
 | |
| 
 | |
|         provider.override(providers.Callable(_get_dependency_sync))
 | |
|         dependency2 = self._run(provider())
 | |
| 
 | |
|         self.assertIs(dependency1, dependency)
 | |
|         self.assertIs(dependency2, dependency)
 | |
| 
 | |
|     def test_async_mode_enabling(self):
 | |
|         dependency = object()
 | |
| 
 | |
|         async def _get_dependency_async():
 | |
|             return dependency
 | |
| 
 | |
|         provider = providers.Callable(_get_dependency_async)
 | |
|         self.assertTrue(provider.is_async_mode_undefined())
 | |
| 
 | |
|         self._run(provider())
 | |
| 
 | |
|         self.assertTrue(provider.is_async_mode_enabled())
 | |
| 
 | |
|     def test_async_mode_disabling(self):
 | |
|         dependency = object()
 | |
| 
 | |
|         def _get_dependency():
 | |
|             return dependency
 | |
| 
 | |
|         provider = providers.Callable(_get_dependency)
 | |
|         self.assertTrue(provider.is_async_mode_undefined())
 | |
| 
 | |
|         provider()
 | |
| 
 | |
|         self.assertTrue(provider.is_async_mode_disabled())
 | |
| 
 | |
|     def test_async_mode_enabling_on_overriding(self):
 | |
|         dependency = object()
 | |
| 
 | |
|         async def _get_dependency_async():
 | |
|             return dependency
 | |
| 
 | |
|         provider = providers.Provider()
 | |
|         provider.override(providers.Callable(_get_dependency_async))
 | |
|         self.assertTrue(provider.is_async_mode_undefined())
 | |
| 
 | |
|         self._run(provider())
 | |
| 
 | |
|         self.assertTrue(provider.is_async_mode_enabled())
 | |
| 
 | |
|     def test_async_mode_disabling_on_overriding(self):
 | |
|         dependency = object()
 | |
| 
 | |
|         def _get_dependency():
 | |
|             return dependency
 | |
| 
 | |
|         provider = providers.Provider()
 | |
|         provider.override(providers.Callable(_get_dependency))
 | |
|         self.assertTrue(provider.is_async_mode_undefined())
 | |
| 
 | |
|         provider()
 | |
| 
 | |
|         self.assertTrue(provider.is_async_mode_disabled())
 | |
| 
 | |
| 
 | |
| class TestAsyncModeApi(unittest.TestCase):
 | |
| 
 | |
|     def setUp(self):
 | |
|         self.provider = providers.Provider()
 | |
| 
 | |
|     def test_default_mode(self):
 | |
|         self.assertFalse(self.provider.is_async_mode_enabled())
 | |
|         self.assertFalse(self.provider.is_async_mode_disabled())
 | |
|         self.assertTrue(self.provider.is_async_mode_undefined())
 | |
| 
 | |
|     def test_enable(self):
 | |
|         self.provider.enable_async_mode()
 | |
| 
 | |
|         self.assertTrue(self.provider.is_async_mode_enabled())
 | |
|         self.assertFalse(self.provider.is_async_mode_disabled())
 | |
|         self.assertFalse(self.provider.is_async_mode_undefined())
 | |
| 
 | |
|     def test_disable(self):
 | |
|         self.provider.disable_async_mode()
 | |
| 
 | |
|         self.assertFalse(self.provider.is_async_mode_enabled())
 | |
|         self.assertTrue(self.provider.is_async_mode_disabled())
 | |
|         self.assertFalse(self.provider.is_async_mode_undefined())
 | |
| 
 | |
|     def test_reset(self):
 | |
|         self.provider.enable_async_mode()
 | |
| 
 | |
|         self.assertTrue(self.provider.is_async_mode_enabled())
 | |
|         self.assertFalse(self.provider.is_async_mode_disabled())
 | |
|         self.assertFalse(self.provider.is_async_mode_undefined())
 | |
| 
 | |
|         self.provider.reset_async_mode()
 | |
| 
 | |
|         self.assertFalse(self.provider.is_async_mode_enabled())
 | |
|         self.assertFalse(self.provider.is_async_mode_disabled())
 | |
|         self.assertTrue(self.provider.is_async_mode_undefined())
 | |
| 
 | |
| 
 | |
| class AsyncTypingStubTests(AsyncTestCase):
 | |
| 
 | |
|     def test_async_(self):
 | |
|         container = Container()
 | |
| 
 | |
|         client1 = self._run(container.client.async_())
 | |
|         client2 = self._run(container.client.async_())
 | |
| 
 | |
|         self.assertIsInstance(client1, Client)
 | |
|         self.assertIs(client1.resource1, RESOURCE1)
 | |
|         self.assertIs(client1.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsInstance(client2, Client)
 | |
|         self.assertIs(client2.resource1, RESOURCE1)
 | |
|         self.assertIs(client2.resource2, RESOURCE2)
 | |
| 
 | |
|         service1 = self._run(container.service.async_())
 | |
|         service2 = self._run(container.service.async_())
 | |
| 
 | |
|         self.assertIsInstance(service1, Service)
 | |
|         self.assertIsInstance(service1.client, Client)
 | |
|         self.assertIs(service1.client.resource1, RESOURCE1)
 | |
|         self.assertIs(service1.client.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsInstance(service2, Service)
 | |
|         self.assertIsInstance(service2.client, Client)
 | |
|         self.assertIs(service2.client.resource1, RESOURCE1)
 | |
|         self.assertIs(service2.client.resource2, RESOURCE2)
 | |
| 
 | |
|         self.assertIsNot(service1.client, service2.client)
 | |
| 
 | |
| 
 | |
| class AsyncProvidersWithAsyncDependenciesTests(AsyncTestCase):
 | |
| 
 | |
|     def test_injections(self):
 | |
|         # See: https://github.com/ets-labs/python-dependency-injector/issues/368
 | |
|         async def async_db_provider():
 | |
|             return {'db': 'ok'}
 | |
| 
 | |
|         async def async_service(db=None):
 | |
|             return {'service': 'ok', 'db': db}
 | |
| 
 | |
|         class Container(containers.DeclarativeContainer):
 | |
| 
 | |
|             db = providers.Factory(async_db_provider)
 | |
|             service = providers.Singleton(async_service, db=db)
 | |
| 
 | |
|         container = Container()
 | |
|         service = self._run(container.service())
 | |
| 
 | |
|         self.assertEqual(service, {'service': 'ok', 'db': {'db': 'ok'}})
 | |
| 
 | |
| 
 | |
| class AsyncProviderWithAwaitableObjectTests(AsyncTestCase):
 | |
| 
 | |
|     def test(self):
 | |
|         class SomeResource:
 | |
|             def __await__(self):
 | |
|                 raise RuntimeError('Should never happen')
 | |
| 
 | |
|         async def init_resource():
 | |
|             pool = SomeResource()
 | |
|             yield pool
 | |
| 
 | |
|         class Service:
 | |
|             def __init__(self, resource) -> None:
 | |
|                 self.resource = resource
 | |
| 
 | |
|         class Container(containers.DeclarativeContainer):
 | |
|             resource = providers.Resource(init_resource)
 | |
|             service = providers.Singleton(Service, resource=resource)
 | |
| 
 | |
|         container = Container()
 | |
| 
 | |
|         self._run(container.init_resources())
 | |
|         self.assertIsInstance(container.service(), asyncio.Future)
 | |
|         self.assertIsInstance(container.resource(), asyncio.Future)
 | |
| 
 | |
|         resource = self._run(container.resource())
 | |
|         service = self._run(container.service())
 | |
| 
 | |
|         self.assertIsInstance(resource, SomeResource)
 | |
|         self.assertIsInstance(service.resource, SomeResource)
 | |
|         self.assertIs(service.resource, resource)
 | |
| 
 | |
|     def test_without_init_resources(self):
 | |
|         class SomeResource:
 | |
|             def __await__(self):
 | |
|                 raise RuntimeError('Should never happen')
 | |
| 
 | |
|         async def init_resource():
 | |
|             pool = SomeResource()
 | |
|             yield pool
 | |
| 
 | |
|         class Service:
 | |
|             def __init__(self, resource) -> None:
 | |
|                 self.resource = resource
 | |
| 
 | |
|         class Container(containers.DeclarativeContainer):
 | |
|             resource = providers.Resource(init_resource)
 | |
|             service = providers.Singleton(Service, resource=resource)
 | |
| 
 | |
|         container = Container()
 | |
| 
 | |
|         self.assertIsInstance(container.service(), asyncio.Future)
 | |
|         self.assertIsInstance(container.resource(), asyncio.Future)
 | |
| 
 | |
|         resource = self._run(container.resource())
 | |
|         service = self._run(container.service())
 | |
| 
 | |
|         self.assertIsInstance(resource, SomeResource)
 | |
|         self.assertIsInstance(service.resource, SomeResource)
 | |
|         self.assertIs(service.resource, resource)
 |