Skip to content

Commit

Permalink
Move get_dependencies into Inspector
Browse files Browse the repository at this point in the history
  • Loading branch information
GabrielCappelli committed Jul 30, 2023
1 parent 7f2b028 commit d4c75dc
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 70 deletions.
12 changes: 4 additions & 8 deletions meta_di/__init__.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
from .builder import ContainerBuilder
from .container_proto import ContainerProto
from .dependency_resolver import (
ArgNameServiceResolver,
ServiceResolverProto,
TypeHintServiceResolver,
)
from .exceptions import MetaDIException
from .inspector import ArgNameInspector, InspectorProto, TypeHintInspector

__all__ = [
"ContainerBuilder",
"ContainerProto",
"MetaDIException",
"ServiceResolverProto",
"TypeHintServiceResolver",
"ArgNameServiceResolver",
"InspectorProto",
"TypeHintInspector",
"ArgNameInspector",
]
10 changes: 4 additions & 6 deletions meta_di/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

from meta_di.code_generator import CodeGenerator
from meta_di.container_proto import ContainerProto
from meta_di.dependency_resolver import ServiceResolverProto, TypeHintServiceResolver
from meta_di.exceptions import CannotInferProvider
from meta_di.inspector import InspectorProto, TypeHintInspector
from meta_di.service_descriptor import ServiceDescriptor, ServiceLifecycle
from meta_di.typing import Provider_T, ServiceId_T

Expand All @@ -15,15 +15,13 @@ class ContainerBuilder(Generic[ServiceId_T]):

def __init__(
self,
dependency_resolver: ServiceResolverProto[
ServiceId_T
] = TypeHintServiceResolver(),
inspector: InspectorProto[ServiceId_T] = TypeHintInspector(),
code_generator: Optional[CodeGenerator] = None,
) -> None:
self._service_descriptors_map: Dict[
ServiceId_T, ServiceDescriptor[ServiceId_T]
] = {}
self._dependency_resolver = dependency_resolver
self._inspector = inspector
self._code_generator = code_generator or CodeGenerator()

def _add_service(
Expand All @@ -38,7 +36,7 @@ def _add_service(

provider = service_id

dependency_kwargs = self._dependency_resolver.get_dependencies(provider)
dependency_kwargs = self._inspector.get_dependencies(provider)
self._service_descriptors_map[service_id] = ServiceDescriptor(
service_id=service_id,
provider=provider,
Expand Down
4 changes: 2 additions & 2 deletions meta_di/code_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meta_di.code_formatter import DEFAULT_CODE_FORMATTER, CodeFormatterProto
from meta_di.container_proto import ContainerProto
from meta_di.exceptions import MissingServiceError
from meta_di.inspector import DEFAULT_INSPECTOR, InspectorProto
from meta_di.inspector import InspectorProto, TypeHintInspector
from meta_di.service_descriptor import ServiceDescriptor
from meta_di.typing import ServiceId_T

Expand All @@ -21,7 +21,7 @@ class CodeGenerator:
def __init__(
self,
code_formatter: CodeFormatterProto = DEFAULT_CODE_FORMATTER,
inspector: InspectorProto = DEFAULT_INSPECTOR,
inspector: InspectorProto[Any] = TypeHintInspector(),
preload_singleton_instances: bool = True,
container_svc_ids: Optional[Set[Any]] = None,
) -> None:
Expand Down
50 changes: 0 additions & 50 deletions meta_di/dependency_resolver.py

This file was deleted.

47 changes: 43 additions & 4 deletions meta_di/inspector.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import inspect
from typing import Any, Protocol
from typing import Any, Dict, Protocol

from meta_di.exceptions import CannotReferenceError
from meta_di.typing import Provider_T, ServiceId_T


class InspectorProto(Protocol):
class InspectorProto(Protocol[ServiceId_T]):
"""
Inspects objects to get required information for code generation
"""
Expand Down Expand Up @@ -41,8 +42,16 @@ def get_full_name(self, obj: Any) -> str:
"""
...

def get_dependencies(self, provider: Provider_T) -> Dict[str, ServiceId_T]:
"""
Extracts dependencies from a provider and returns them as a dict
where the keys are the name of the func arguments
and the values are the ServiceId_T of the dependencies
"""
...


class Inspector(InspectorProto):
class BaseInspector(InspectorProto[ServiceId_T]):
def requires_import(self, obj: Any) -> bool:
if isinstance(obj, type):
return True
Expand All @@ -64,5 +73,35 @@ def get_module_name(self, obj: Any) -> str:
def get_full_name(self, obj: Any) -> str:
return f"{self.get_module_name(obj)}.{obj.__qualname__}"

def get_dependencies(self, provider: Provider_T) -> Dict[str, ServiceId_T]:
raise NotImplementedError()


class TypeHintInspector(BaseInspector[type]):
"""
DependencyResolver that uses the types extracted from type hints as ServiceId_T
"""

def get_dependencies(self, provider: Provider_T) -> Dict[str, type]:
return {
arg_name: arg_type
for arg_name, arg_type in inspect.getfullargspec(
provider
).annotations.items()
if arg_name != "self" and arg_type
}


class ArgNameInspector(BaseInspector[str]):
"""
DependencyResolver that uses the names of args as ServiceId_T
"""

DEFAULT_INSPECTOR = Inspector()
def get_dependencies(self, provider: Provider_T) -> Dict[str, str]:
return {
arg_name: arg_name
for arg_name, arg in inspect.signature(provider).parameters.items()
if arg_name != "self"
and arg.kind
not in (inspect.Parameter.VAR_KEYWORD, inspect.Parameter.VAR_POSITIONAL)
}

0 comments on commit d4c75dc

Please sign in to comment.