mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-10-31 07:57:43 +03:00 
			
		
		
		
	Merge branch 'release/4.10.2' into master
This commit is contained in:
		
						commit
						9f7dbe89f6
					
				|  | @ -7,6 +7,20 @@ that were made in every particular version. | ||||||
| From version 0.7.6 *Dependency Injector* framework strictly  | From version 0.7.6 *Dependency Injector* framework strictly  | ||||||
| follows `Semantic versioning`_ | follows `Semantic versioning`_ | ||||||
| 
 | 
 | ||||||
|  | Development version | ||||||
|  | ------------------- | ||||||
|  | - Fix a bug in the ``Configuration`` provider: strict mode didn't work when provider | ||||||
|  |   is overridden by ``None``. | ||||||
|  |   See issue: `#358#issuecomment-761607432 <https://github.com/ets-labs/python-dependency-injector/issues/358#issuecomment-761607432>`_. | ||||||
|  |   Many thanks to `Stefano Frazzetto <https://github.com/StefanoFrazzetto>`_ for reporting the issue. | ||||||
|  | 
 | ||||||
|  | 4.10.2 | ||||||
|  | ------ | ||||||
|  | - Fix a bug in ``Resource`` that cause failure when async resource depends on | ||||||
|  |   another async resource. | ||||||
|  |   See issue `#361 <https://github.com/ets-labs/python-dependency-injector/issues/361>`_. | ||||||
|  |   Thanks `@kolypto <https://github.com/kolypto>`_ for the bug report. | ||||||
|  | 
 | ||||||
| 4.10.1 | 4.10.1 | ||||||
| ------ | ------ | ||||||
| - Fix a Python 3.9 specific bug in ``wiring`` module: introspection doesn't work for | - Fix a Python 3.9 specific bug in ``wiring`` module: introspection doesn't work for | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| """Top-level package.""" | """Top-level package.""" | ||||||
| 
 | 
 | ||||||
| __version__ = '4.10.1' | __version__ = '4.10.2' | ||||||
| """Version number. | """Version number. | ||||||
| 
 | 
 | ||||||
| :type: str | :type: str | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1471,12 +1471,14 @@ cdef class Configuration(Object): | ||||||
|         :return: Option value. |         :return: Option value. | ||||||
|         :rtype: Any |         :rtype: Any | ||||||
|         """ |         """ | ||||||
|         keys = selector.split('.') |  | ||||||
|         value = self.__call__() |         value = self.__call__() | ||||||
| 
 | 
 | ||||||
|         if value is None: |         if value is None: | ||||||
|  |             if self.__strict or required: | ||||||
|  |                 raise Error('Undefined configuration option "{0}.{1}"'.format(self.__name, selector)) | ||||||
|             return None |             return None | ||||||
| 
 | 
 | ||||||
|  |         keys = selector.split('.') | ||||||
|         while len(keys) > 0: |         while len(keys) > 0: | ||||||
|             key = keys.pop(0) |             key = keys.pop(0) | ||||||
|             value = value.get(key, self.UNDEFINED) |             value = value.get(key, self.UNDEFINED) | ||||||
|  | @ -1500,9 +1502,9 @@ cdef class Configuration(Object): | ||||||
|         :return: Overriding context. |         :return: Overriding context. | ||||||
|         :rtype: :py:class:`OverridingContext` |         :rtype: :py:class:`OverridingContext` | ||||||
|         """ |         """ | ||||||
|         keys = selector.split('.') |  | ||||||
|         original_value = current_value = deepcopy(self.__call__()) |         original_value = current_value = deepcopy(self.__call__()) | ||||||
| 
 | 
 | ||||||
|  |         keys = selector.split('.') | ||||||
|         while len(keys) > 0: |         while len(keys) > 0: | ||||||
|             key = keys.pop(0) |             key = keys.pop(0) | ||||||
|             if len(keys) == 0: |             if len(keys) == 0: | ||||||
|  | @ -2967,7 +2969,7 @@ cdef class Resource(Provider): | ||||||
|                 self.__kwargs_len, |                 self.__kwargs_len, | ||||||
|             ) |             ) | ||||||
|             self.__initialized = True |             self.__initialized = True | ||||||
|             return self._create_init_future(initializer.__anext__(), initializer.asend) |             return self._create_async_gen_init_future(initializer) | ||||||
|         elif callable(self.__initializer): |         elif callable(self.__initializer): | ||||||
|             self.__resource = __call( |             self.__resource = __call( | ||||||
|                 self.__initializer, |                 self.__initializer, | ||||||
|  | @ -2995,6 +2997,18 @@ cdef class Resource(Provider): | ||||||
| 
 | 
 | ||||||
|         return future |         return future | ||||||
| 
 | 
 | ||||||
|  |     def _create_async_gen_init_future(self, initializer): | ||||||
|  |         if inspect.isasyncgen(initializer): | ||||||
|  |             return self._create_init_future(initializer.__anext__(), initializer.asend) | ||||||
|  | 
 | ||||||
|  |         future = asyncio.Future() | ||||||
|  | 
 | ||||||
|  |         create_initializer = asyncio.ensure_future(initializer) | ||||||
|  |         create_initializer.add_done_callback(functools.partial(self._async_create_gen_callback, future)) | ||||||
|  |         self.__resource = future | ||||||
|  | 
 | ||||||
|  |         return future | ||||||
|  | 
 | ||||||
|     def _async_init_callback(self, initializer, shutdowner=None): |     def _async_init_callback(self, initializer, shutdowner=None): | ||||||
|         try: |         try: | ||||||
|             resource = initializer.result() |             resource = initializer.result() | ||||||
|  | @ -3005,6 +3019,14 @@ cdef class Resource(Provider): | ||||||
|             self.__resource = resource |             self.__resource = resource | ||||||
|             self.__shutdowner = shutdowner |             self.__shutdowner = shutdowner | ||||||
| 
 | 
 | ||||||
|  |     def _async_create_gen_callback(self, future, initializer_future): | ||||||
|  |         initializer = initializer_future.result() | ||||||
|  |         init_future = self._create_init_future(initializer.__anext__(), initializer.asend) | ||||||
|  |         init_future.add_done_callback(functools.partial(self._async_trigger_result, future)) | ||||||
|  | 
 | ||||||
|  |     def _async_trigger_result(self, future, future_result): | ||||||
|  |         future.set_result(future_result.result()) | ||||||
|  | 
 | ||||||
|     def _create_shutdown_future(self, shutdown_future): |     def _create_shutdown_future(self, shutdown_future): | ||||||
|         future = asyncio.Future() |         future = asyncio.Future() | ||||||
|         shutdown_future = asyncio.ensure_future(shutdown_future) |         shutdown_future = asyncio.ensure_future(shutdown_future) | ||||||
|  |  | ||||||
|  | @ -214,6 +214,12 @@ class ConfigTests(unittest.TestCase): | ||||||
|         with self.assertRaisesRegex(errors.Error, 'Undefined configuration option "config.a"'): |         with self.assertRaisesRegex(errors.Error, 'Undefined configuration option "config.a"'): | ||||||
|             self.config.a() |             self.config.a() | ||||||
| 
 | 
 | ||||||
|  |     def test_value_of_undefined_option_with_root_none_in_strict_mode(self): | ||||||
|  |         self.config = providers.Configuration(strict=True) | ||||||
|  |         self.config.override(None) | ||||||
|  |         with self.assertRaisesRegex(errors.Error, 'Undefined configuration option "config.a"'): | ||||||
|  |             self.config.a() | ||||||
|  | 
 | ||||||
|     def test_value_of_defined_none_option_in_strict_mode(self): |     def test_value_of_defined_none_option_in_strict_mode(self): | ||||||
|         self.config = providers.Configuration(strict=True) |         self.config = providers.Configuration(strict=True) | ||||||
|         self.config.from_dict({'a': None}) |         self.config.from_dict({'a': None}) | ||||||
|  |  | ||||||
|  | @ -461,6 +461,43 @@ class AsyncResourceTest(AsyncTestCase): | ||||||
|         self.assertFalse(provider.initialized) |         self.assertFalse(provider.initialized) | ||||||
|         self.assertTrue(provider.is_async_mode_enabled()) |         self.assertTrue(provider.is_async_mode_enabled()) | ||||||
| 
 | 
 | ||||||
|  |     def test_init_with_dependency_to_other_resource(self): | ||||||
|  |         # See: https://github.com/ets-labs/python-dependency-injector/issues/361 | ||||||
|  |         async def init_db_connection(db_url: str): | ||||||
|  |             await asyncio.sleep(0.001) | ||||||
|  |             yield {'connection': 'ok', 'url': db_url} | ||||||
|  | 
 | ||||||
|  |         async def init_user_session(db): | ||||||
|  |             await asyncio.sleep(0.001) | ||||||
|  |             yield {'session': 'ok', 'db': db} | ||||||
|  | 
 | ||||||
|  |         class Container(containers.DeclarativeContainer): | ||||||
|  |             config = providers.Configuration() | ||||||
|  | 
 | ||||||
|  |             db_connection = providers.Resource( | ||||||
|  |                 init_db_connection, | ||||||
|  |                 db_url=config.db_url, | ||||||
|  |             ) | ||||||
|  | 
 | ||||||
|  |             user_session = providers.Resource( | ||||||
|  |                 init_user_session, | ||||||
|  |                 db=db_connection | ||||||
|  |             ) | ||||||
|  | 
 | ||||||
|  |         async def main(): | ||||||
|  |             container = Container(config={'db_url': 'postgres://...'}) | ||||||
|  |             try: | ||||||
|  |                 return await container.user_session() | ||||||
|  |             finally: | ||||||
|  |                 await container.shutdown_resources() | ||||||
|  | 
 | ||||||
|  |         result = self._run(main()) | ||||||
|  | 
 | ||||||
|  |         self.assertEqual( | ||||||
|  |             result, | ||||||
|  |             {'session': 'ok', 'db': {'connection': 'ok', 'url': 'postgres://...'}}, | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|     def test_init_and_shutdown_methods(self): |     def test_init_and_shutdown_methods(self): | ||||||
|         async def _init(): |         async def _init(): | ||||||
|             await asyncio.sleep(0.001) |             await asyncio.sleep(0.001) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user