Skip to content

Commit

Permalink
Merge 032af3f into 4733aad
Browse files Browse the repository at this point in the history
  • Loading branch information
rmk135 committed Sep 28, 2021
2 parents 4733aad + 032af3f commit 1712c26
Show file tree
Hide file tree
Showing 7 changed files with 3,862 additions and 2,697 deletions.
4 changes: 1 addition & 3 deletions examples/wiring/example.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
"""Wiring example."""

import sys

from dependency_injector import containers, providers
from dependency_injector.wiring import inject, Provide

Expand All @@ -22,6 +20,6 @@ def main(service: Service = Provide[Container.service]) -> None:

if __name__ == '__main__':
container = Container()
container.wire(modules=[sys.modules[__name__]])
container.wire(modules=[__name__])

main()
6,449 changes: 3,763 additions & 2,686 deletions src/dependency_injector/containers.c

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/dependency_injector/containers.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class Container:
def override_providers(self, **overriding_providers: Union[Provider, Any]) -> None: ...
def reset_last_overriding(self) -> None: ...
def reset_override(self) -> None: ...
def wire(self, modules: Optional[Iterable[Any]] = None, packages: Optional[Iterable[Any]] = None) -> None: ...
def wire(self, modules: Optional[Iterable[Any]] = None, packages: Optional[Iterable[Any]] = None, from_package: Optional[str] = None) -> None: ...
def unwire(self) -> None: ...
def init_resources(self) -> Optional[Awaitable]: ...
def shutdown_resources(self) -> Optional[Awaitable]: ...
Expand Down
41 changes: 39 additions & 2 deletions src/dependency_injector/containers.pyx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
"""Containers module."""

import contextlib
import json
import sys
import importlib
import inspect

try:
import asyncio
Expand Down Expand Up @@ -248,11 +251,22 @@ class DynamicContainer(Container):
for provider in six.itervalues(self.providers):
provider.reset_override()

def wire(self, modules=None, packages=None):
def wire(self, modules=None, packages=None, from_package=None):
"""Wire container providers with provided packages and modules.
:rtype: None
"""
modules = [*modules] if modules else []
packages = [*packages] if packages else []

if _any_relative_string_imports_in(modules) or _any_relative_string_imports_in(packages):
if from_package is None:
with contextlib.suppress(Exception):
from_package = _resolve_calling_package_name()

modules = _resolve_string_imports(modules, from_package)
packages = _resolve_string_imports(packages, from_package)

wire(
container=self,
modules=modules,
Expand All @@ -261,7 +275,6 @@ class DynamicContainer(Container):

if modules:
self.wired_to_modules.extend(modules)

if packages:
self.wired_to_packages.extend(packages)

Expand Down Expand Up @@ -789,3 +802,27 @@ cpdef object _check_provider_type(object container, object provider):
if not isinstance(provider, container.provider_type):
raise errors.Error('{0} can contain only {1} '
'instances'.format(container, container.provider_type))


cpdef bint _any_relative_string_imports_in(object modules):
for module in modules:
if not isinstance(module, str):
continue
if module.startswith("."):
return True
else:
return False


cpdef list _resolve_string_imports(object modules, object from_package):
return [
importlib.import_module(module, from_package) if isinstance(module, str) else module
for module in modules
]


cpdef object _resolve_calling_package_name():
stack = inspect.stack()
pre_last_frame = stack[0]
module = inspect.getmodule(pre_last_frame[0])
return module.__package__
6 changes: 2 additions & 4 deletions src/dependency_injector/wiring.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,7 @@ def wire( # noqa: C901
packages: Optional[Iterable[ModuleType]] = None,
) -> None:
"""Wire container providers with provided packages and modules."""
if not modules:
modules = []
modules = [*modules] if modules else []

if packages:
for package in packages:
Expand Down Expand Up @@ -367,8 +366,7 @@ def unwire( # noqa: C901
packages: Optional[Iterable[ModuleType]] = None,
) -> None:
"""Wire provided packages and modules with previous wired providers."""
if not modules:
modules = []
modules = [*modules] if modules else []

if packages:
for package in packages:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""Wiring sample package."""


def wire_with_relative_string_names(container):
container.wire(
modules=[".module"],
packages=[".package"],
)
49 changes: 48 additions & 1 deletion tests/unit/wiring/test_wiring_py36.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from wiringsamples import module, package
from wiringsamples.service import Service
from wiringsamples.container import Container, SubContainer
from wiringsamples.wire_relative_string_names import wire_with_relative_string_names


class WiringTest(unittest.TestCase):
Expand Down Expand Up @@ -314,7 +315,53 @@ def test_container(self):
self.assertIsInstance(service, Service)


class ModuleAsPackagingTest(unittest.TestCase):
class WiringWithStringModuleAndPackageNamesTest(unittest.TestCase):

container: Container

def setUp(self) -> None:
self.container = Container()
self.addCleanup(self.container.unwire)

def test_absolute_names(self):
self.container.wire(
modules=["wiringsamples.module"],
packages=["wiringsamples.package"],
)

service = module.test_function()
self.assertIsInstance(service, Service)

from wiringsamples.package.subpackage.submodule import test_function
service = test_function()
self.assertIsInstance(service, Service)

def test_relative_names_with_explicit_package(self):
self.container.wire(
modules=[".module"],
packages=[".package"],
from_package="wiringsamples",
)

service = module.test_function()
self.assertIsInstance(service, Service)

from wiringsamples.package.subpackage.submodule import test_function
service = test_function()
self.assertIsInstance(service, Service)

def test_relative_names_with_auto_package(self):
wire_with_relative_string_names(self.container)

service = module.test_function()
self.assertIsInstance(service, Service)

from wiringsamples.package.subpackage.submodule import test_function
service = test_function()
self.assertIsInstance(service, Service)


class ModuleAsPackageTest(unittest.TestCase):

def setUp(self):
self.container = Container(config={'a': {'b': {'c': 10}}})
Expand Down

0 comments on commit 1712c26

Please sign in to comment.