mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-10-31 07:57:43 +03:00 
			
		
		
		
	Use cache in _fetch_reference_injections()
This commit is contained in:
		
							parent
							
								
									16f444b230
								
							
						
					
					
						commit
						4b3476cb48
					
				|  | @ -30,12 +30,14 @@ class WiringConfiguration: | ||||||
|     packages: List[Any] |     packages: List[Any] | ||||||
|     from_package: Optional[str] |     from_package: Optional[str] | ||||||
|     auto_wire: bool |     auto_wire: bool | ||||||
|  |     keep_cache: bool | ||||||
|     def __init__( |     def __init__( | ||||||
|         self, |         self, | ||||||
|         modules: Optional[Iterable[Any]] = None, |         modules: Optional[Iterable[Any]] = None, | ||||||
|         packages: Optional[Iterable[Any]] = None, |         packages: Optional[Iterable[Any]] = None, | ||||||
|         from_package: Optional[str] = None, |         from_package: Optional[str] = None, | ||||||
|         auto_wire: bool = True, |         auto_wire: bool = True, | ||||||
|  |         keep_cache: bool = False, | ||||||
|     ) -> None: ... |     ) -> None: ... | ||||||
| 
 | 
 | ||||||
| class Container: | class Container: | ||||||
|  |  | ||||||
|  | @ -20,14 +20,15 @@ from .wiring import wire, unwire | ||||||
| class WiringConfiguration: | class WiringConfiguration: | ||||||
|     """Container wiring configuration.""" |     """Container wiring configuration.""" | ||||||
| 
 | 
 | ||||||
|     def __init__(self, modules=None, packages=None, from_package=None, auto_wire=True): |     def __init__(self, modules=None, packages=None, from_package=None, auto_wire=True, keep_cache=False): | ||||||
|         self.modules = [*modules] if modules else [] |         self.modules = [*modules] if modules else [] | ||||||
|         self.packages = [*packages] if packages else [] |         self.packages = [*packages] if packages else [] | ||||||
|         self.from_package = from_package |         self.from_package = from_package | ||||||
|         self.auto_wire = auto_wire |         self.auto_wire = auto_wire | ||||||
|  |         self.keep_cache = keep_cache | ||||||
| 
 | 
 | ||||||
|     def __deepcopy__(self, memo=None): |     def __deepcopy__(self, memo=None): | ||||||
|         return self.__class__(self.modules, self.packages, self.from_package, self.auto_wire) |         return self.__class__(self.modules, self.packages, self.from_package, self.auto_wire, self.keep_cache) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Container: | class Container: | ||||||
|  | @ -258,7 +259,7 @@ class DynamicContainer(Container): | ||||||
|         """Check if auto wiring is needed.""" |         """Check if auto wiring is needed.""" | ||||||
|         return self.wiring_config.auto_wire is True |         return self.wiring_config.auto_wire is True | ||||||
| 
 | 
 | ||||||
|     def wire(self, modules=None, packages=None, from_package=None): |     def wire(self, modules=None, packages=None, from_package=None, keep_cache=None): | ||||||
|         """Wire container providers with provided packages and modules. |         """Wire container providers with provided packages and modules. | ||||||
| 
 | 
 | ||||||
|         :rtype: None |         :rtype: None | ||||||
|  | @ -289,10 +290,14 @@ class DynamicContainer(Container): | ||||||
|         if not modules and not packages: |         if not modules and not packages: | ||||||
|             return |             return | ||||||
| 
 | 
 | ||||||
|  |         if keep_cache is None: | ||||||
|  |             keep_cache = self.wiring_config.keep_cache | ||||||
|  | 
 | ||||||
|         wire( |         wire( | ||||||
|             container=self, |             container=self, | ||||||
|             modules=modules, |             modules=modules, | ||||||
|             packages=packages, |             packages=packages, | ||||||
|  |             keep_cache=keep_cache, | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         if modules: |         if modules: | ||||||
|  |  | ||||||
|  | @ -26,6 +26,13 @@ from typing import ( | ||||||
| 
 | 
 | ||||||
| from typing_extensions import Self | from typing_extensions import Self | ||||||
| 
 | 
 | ||||||
|  | try: | ||||||
|  |     from functools import cache | ||||||
|  | except ImportError: | ||||||
|  |     from functools import lru_cache | ||||||
|  | 
 | ||||||
|  |     cache = lru_cache(maxsize=None) | ||||||
|  | 
 | ||||||
| # Hotfix, see: https://github.com/ets-labs/python-dependency-injector/issues/362 | # Hotfix, see: https://github.com/ets-labs/python-dependency-injector/issues/362 | ||||||
| if sys.version_info >= (3, 9): | if sys.version_info >= (3, 9): | ||||||
|     from types import GenericAlias |     from types import GenericAlias | ||||||
|  | @ -409,6 +416,7 @@ def wire(  # noqa: C901 | ||||||
|     *, |     *, | ||||||
|     modules: Optional[Iterable[ModuleType]] = None, |     modules: Optional[Iterable[ModuleType]] = None, | ||||||
|     packages: Optional[Iterable[ModuleType]] = None, |     packages: Optional[Iterable[ModuleType]] = None, | ||||||
|  |     keep_cache: bool = False, | ||||||
| ) -> None: | ) -> None: | ||||||
|     """Wire container providers with provided packages and modules.""" |     """Wire container providers with provided packages and modules.""" | ||||||
|     modules = [*modules] if modules else [] |     modules = [*modules] if modules else [] | ||||||
|  | @ -449,6 +457,9 @@ def wire(  # noqa: C901 | ||||||
|         for patched in _patched_registry.get_callables_from_module(module): |         for patched in _patched_registry.get_callables_from_module(module): | ||||||
|             _bind_injections(patched, providers_map) |             _bind_injections(patched, providers_map) | ||||||
| 
 | 
 | ||||||
|  |     if not keep_cache: | ||||||
|  |         clear_cache() | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| def unwire(  # noqa: C901 | def unwire(  # noqa: C901 | ||||||
|     *, |     *, | ||||||
|  | @ -604,6 +615,7 @@ def _extract_marker(parameter: inspect.Parameter) -> Optional["_Marker"]: | ||||||
|     return marker |     return marker | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @cache | ||||||
| def _fetch_reference_injections(  # noqa: C901 | def _fetch_reference_injections(  # noqa: C901 | ||||||
|     fn: Callable[..., Any], |     fn: Callable[..., Any], | ||||||
| ) -> Tuple[Dict[str, Any], Dict[str, Any]]: | ) -> Tuple[Dict[str, Any], Dict[str, Any]]: | ||||||
|  | @ -1078,3 +1090,8 @@ def _get_members_and_annotated(obj: Any) -> Iterable[Tuple[str, Any]]: | ||||||
|                 member = args[1] |                 member = args[1] | ||||||
|                 members.append((annotation_name, member)) |                 members.append((annotation_name, member)) | ||||||
|     return members |     return members | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def clear_cache() -> None: | ||||||
|  |     """Clear all caches used by :func:`wire`.""" | ||||||
|  |     _fetch_reference_injections.cache_clear() | ||||||
|  |  | ||||||
							
								
								
									
										46
									
								
								tests/unit/wiring/test_cache.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								tests/unit/wiring/test_cache.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | ||||||
|  | """Tests for string module and package names.""" | ||||||
|  | 
 | ||||||
|  | from typing import Iterator, Optional | ||||||
|  | 
 | ||||||
|  | from pytest import fixture, mark | ||||||
|  | from samples.wiring.container import Container | ||||||
|  | 
 | ||||||
|  | from dependency_injector.wiring import _fetch_reference_injections | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @fixture | ||||||
|  | def container() -> Iterator[Container]: | ||||||
|  |     container = Container() | ||||||
|  |     yield container | ||||||
|  |     container.unwire() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @mark.parametrize( | ||||||
|  |     ["arg_value", "wc_value", "empty_cache"], | ||||||
|  |     [ | ||||||
|  |         (None, False, True), | ||||||
|  |         (False, True, True), | ||||||
|  |         (True, False, False), | ||||||
|  |         (None, True, False), | ||||||
|  |     ], | ||||||
|  | ) | ||||||
|  | def test_fetch_reference_injections_cache( | ||||||
|  |     container: Container, | ||||||
|  |     arg_value: Optional[bool], | ||||||
|  |     wc_value: bool, | ||||||
|  |     empty_cache: bool, | ||||||
|  | ) -> None: | ||||||
|  |     container.wiring_config.keep_cache = wc_value | ||||||
|  |     container.wire( | ||||||
|  |         modules=["samples.wiring.module"], | ||||||
|  |         packages=["samples.wiring.package"], | ||||||
|  |         keep_cache=arg_value, | ||||||
|  |     ) | ||||||
|  |     cache_info = _fetch_reference_injections.cache_info() | ||||||
|  | 
 | ||||||
|  |     if empty_cache: | ||||||
|  |         assert cache_info == (0, 0, None, 0) | ||||||
|  |     else: | ||||||
|  |         assert cache_info.hits > 0 | ||||||
|  |         assert cache_info.misses > 0 | ||||||
|  |         assert cache_info.currsize > 0 | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user