diff --git a/src/dependency_injector/wiring.py b/src/dependency_injector/wiring.py index 18042c1b..49a0cdd7 100644 --- a/src/dependency_injector/wiring.py +++ b/src/dependency_injector/wiring.py @@ -2,10 +2,18 @@ import functools import inspect +import sys import pkgutil from types import ModuleType from typing import Optional, Iterable, Callable, Any, Type, Dict, Generic, TypeVar +# Spike for Python 3.6 +if sys.version_info < (3, 7): + from typing import GenericMeta +else: + class GenericMeta(type): + ... + from . import providers AnyContainer = Any @@ -73,25 +81,12 @@ def _resolve_injections(fn: Callable[..., Any], container: AnyContainer) -> Dict continue marker = parameter.default - provider = None - provider_name = container.resolve_provider_name(marker.provider) if provider_name: provider = container.providers[provider_name] - - if config and isinstance(marker.provider, providers.ConfigurationOption): - full_option_name = marker.provider.get_name() - _, *parts = full_option_name.split('.') - relative_option_name = '.'.join(parts) - provider = config.get_option_provider(relative_option_name) - if parameter.annotation is int: - provider = provider.as_int() - elif parameter.annotation is float: - provider = provider.as_float() - elif parameter.annotation is not inspect.Parameter.empty: - provider = provider.as_(parameter.annotation) - - if provider is None: + elif config and isinstance(marker.provider, providers.ConfigurationOption): + provider = _prepare_config_injection(marker.provider, parameter, config) + else: continue if isinstance(marker, Provide): @@ -102,6 +97,24 @@ def _resolve_injections(fn: Callable[..., Any], container: AnyContainer) -> Dict return injections +def _prepare_config_injection( + option: providers.ConfigurationOption, + parameter: inspect.Parameter, + config: providers.Configuration, +) -> providers.Provider: + full_option_name = option.get_name() + _, *parts = full_option_name.split('.') + relative_option_name = '.'.join(parts) + provider = config.get_option_provider(relative_option_name) + if parameter.annotation is int: + provider = provider.as_int() + elif parameter.annotation is float: + provider = provider.as_float() + elif parameter.annotation is not inspect.Parameter.empty: + provider = provider.as_(parameter.annotation) + return provider + + def _resolve_container_config(container: AnyContainer) -> Optional[providers.Configuration]: for provider in container.providers.values(): if isinstance(provider, providers.Configuration): @@ -141,7 +154,11 @@ class ClassGetItemMeta(type): return cls(item) -class _Marker(Generic[T], metaclass=ClassGetItemMeta): +class GenericClassGetItemMeta(GenericMeta, ClassGetItemMeta): + pass + + +class _Marker(Generic[T], metaclass=GenericClassGetItemMeta): def __init__(self, provider: providers.Provider) -> None: self.provider = provider