self.one = one class Container(Injector): class SubContainer(Injector): foo = Foo one = 1 foo = this.SubContainer.foo.one assert Container.foo == 1 # Item access. item_access = CodeCollector() @item_access.parametrize def test_item_getter(code): """We can describe item access in the `Injector` in the declarative manner.""" result = code() assert result == 1 @item_access def ce642f492941(): """Get item with string key."""
"""Tests related to Injector classes written inside other Injector classes.""" from dependencies import Injector from dependencies import Package from dependencies import this from helpers import CodeCollector parent_attr = CodeCollector() subcontainer = CodeCollector("sub") @parent_attr.parametrize @subcontainer.parametrize def test_attribute_getter_parent_access(code, sub): """We can access attribute of outer container.""" Container = code(sub()) assert Container.SubContainer.bar == 1 @parent_attr def _ac7814095628(sub): class Container(Injector): foo = 1 SubContainer = sub return Container @parent_attr def _f607abc82079(sub): return Injector(foo=1, SubContainer=sub)
# -*- coding: utf-8 -*- """Tests related to the circle detection in the injector definitions.""" import pytest from dependencies import Injector from dependencies import operation from dependencies import Package from dependencies import value from dependencies.exceptions import DependencyError from helpers import CodeCollector # Simple circle. circle_deps = CodeCollector() circle_defs = CodeCollector("foo") @circle_deps.parametrize @circle_defs.parametrize def test_circle_dependencies(code, foo): """Throw `DependencyError` if class needs a dependency named same as class. `Summator.foo` will fail with maximum recursion depth. So we need to raise exception before this attribute access. """ with pytest.raises(DependencyError) as exc_info: code(foo()) message = str(exc_info.value)
"""Tests related to descriptor objects.""" import pytest from dependencies import Injector from dependencies import Package from dependencies.exceptions import DependencyError from helpers import CodeCollector deny_descriptors = CodeCollector() define_descriptors = CodeCollector("foo") @deny_descriptors.parametrize @define_descriptors.parametrize def test_deny_descriptors(code, foo): """Descriptors passed to the injector have confusing expectations. If users pass method descriptor to the injector, they probably expect access to the Injector itself. """ with pytest.raises(DependencyError) as exc_info: code(foo()) expected = """ Attribute 'foo' contains descriptor. Descriptors usage will be confusing inside Injector subclasses. Use @value decorator instead, if you really need inject descriptor instance somewhere. """.strip()
from dependencies.exceptions import DependencyError from helpers import CodeCollector def test_protect_against_classes(): """Deny to decorate classes with @value proxy.""" with pytest.raises(DependencyError) as exc_info: @value class Foo: pass # pragma: no cover assert str(exc_info.value) == "'value' decorator can not be used on classes" deny_method = CodeCollector() @deny_method.parametrize def test_protect_against_self(code): """Deny to define a value with argument called `self`.""" @value def method(self, foo, bar): pass # pragma: no cover with pytest.raises(DependencyError) as exc_info: code(method) assert str(exc_info.value) == "'value' decorator can not be used on methods"
def test_keyword_arguments(): class Container(Injector): foo = 1 bar = 2 @value def result(foo, bar, baz=3): return foo + bar + baz assert Container.result == 6 deny_method = CodeCollector() @deny_method.parametrize def test_protect_against_self(code): """Deny to define a value with argument called `self`.""" @value def method(self, foo, bar): pass # pragma: no cover with pytest.raises(DependencyError) as exc_info: code(method) assert str(exc_info.value) == "'value' decorator can not be used on methods"
# -*- coding: utf-8 -*- """Tests related to the loops detection in the injector definition.""" import pytest from dependencies import Injector from dependencies import Package from dependencies import this from dependencies.exceptions import DependencyError from helpers import CodeCollector # Flat injector. flat_injector = CodeCollector() @flat_injector.parametrize def test_circle_links(code): """We can detect link loops in the same container without hierarchy.""" with pytest.raises(DependencyError) as exc_info: code() assert str(exc_info.value) in { "'foo' is a circle link in the 'Container' injector", "'foo' is a circle link in the 'Injector' injector", "'bar' is a circle link in the 'Container' injector", "'bar' is a circle link in the 'Injector' injector", "'baz' is a circle link in the 'Container' injector", "'baz' is a circle link in the 'Injector' injector", }
"""Tests related to the Package object.""" import inspect import pytest from dependencies import Injector from dependencies import Package from helpers import CodeCollector package_definitions = CodeCollector() @package_definitions.parametrize def test_provide_module(code): """Package instance itself should refer to the module.""" Container = code() assert inspect.ismodule(Container.itself) assert inspect.ismodule(Container.submodule) @package_definitions.parametrize def test_provide_an_instance(code): """Package attribute access should provide an instance when refer to a class.""" Container = code() from examples.submodule import Foo, Bar assert isinstance(Container.instance, Foo) or isinstance( Container.instance, Bar) assert hasattr(Container.instance, "do")
assert "x" in dir(Foo.let(x=1)) def test_omit_parent_link_in_dir_listing(): """ Don't show `__parent__` link in the `dir` output. It is an implementation detail. """ class Foo(Injector): class Bar(Injector): pass assert "__parent__" not in dir(Foo.Bar) attribute_assignment = CodeCollector() @attribute_assignment.parametrize def test_deny_injector_changes(code): """Explicitly deny change of any kind on `Injector` and its subclasses.""" with pytest.raises(DependencyError) as exc_info: code() assert str(exc_info.value) == "'Injector' modification is not allowed" @attribute_assignment def mvT9oyJdXhzh(): """Attribute assignment."""
from dependencies import Injector from dependencies.exceptions import DependencyError from helpers import CodeCollector @unique class Choices(Enum): """Enumeration class.""" one = auto() two = auto() three = auto() deny_enums = CodeCollector() @deny_enums.parametrize def test_deny_enums(code): """Deny inject enum classes. We should suggest to inject a specific enum member instead. """ with pytest.raises(DependencyError) as exc_info: code() expected = """ Attribute 'foo' contains Enum.
"""Tests related to injectable objects.""" import pytest from dependencies import Injector from dependencies import value from dependencies.exceptions import DependencyError from helpers import CodeCollector deny_varargs = CodeCollector() varargs_defs = CodeCollector("foo") @deny_varargs.parametrize @varargs_defs.parametrize def test_deny_arbitrary_argument_list(code, foo): """Raise `DependencyError` if constructor have *args argument.""" with pytest.raises(DependencyError) as exc_info: code(foo()) message = str(exc_info.value) assert message in { "'Foo.__init__' have variable-length positional arguments", "'func' have variable-length positional arguments", } @deny_varargs def _dfe1c22c641e(Foo): class Container(Injector): foo = Foo args = (1, 2, 3)
app.tasks.clear() return app class Run(object): def __init__(self, args, kwargs): self.args = args self.kwargs = kwargs def __call__(self): assert self.args == ("foo",) assert self.kwargs == {"bar": "baz"} return 1 containers = CodeCollector() @containers def bAMWkT3WSTN1(_app): """Task decorator.""" @contrib.task class Container(Injector): app = _app name = "foo.bar.baz" run = Run return Container
def __init__(self, one): self.one = one class Container(Injector): class SubContainer(Injector): foo = Foo one = 1 foo = this.SubContainer.foo.one assert Container.foo == 1 parent_attr = CodeCollector() @parent_attr.parametrize def test_attribute_getter_parent_access(code): """We can access attribute of outer container.""" Container = code() assert Container.SubContainer.bar == 1 @parent_attr def ac7814095628(): """Declarative injector.""" class Container(Injector):
def test_omit_parent_link_in_dir_listing(): """Don't show `__parent__` link in the `dir` output. It is an implementation detail. """ class Foo(Injector): class Bar(Injector): x = 1 assert "__parent__" not in dir(Foo.Bar) attribute_assignment = CodeCollector() @attribute_assignment.parametrize def test_deny_injector_changes(code): """Explicitly deny change of any kind on `Injector` and its subclasses.""" with pytest.raises(DependencyError) as exc_info: code() assert str(exc_info.value) == "'Injector' modification is not allowed" @attribute_assignment def _mvT9oyJdXhzh(): class Container(Injector): x = 1
"""Tests related to the Injector subclasses checks.""" import pytest from dependencies import Injector from dependencies.exceptions import DependencyError from helpers import CodeCollector subclasses_only = CodeCollector() @subclasses_only.parametrize def test_multiple_inheritance_deny_regular_classes(code): """Only `Injector` subclasses are allowed to be used in the inheritance.""" class Foo: pass with pytest.raises(DependencyError) as exc_info: code(Foo) message = str(exc_info.value) assert message == "Multiple inheritance is allowed for Injector subclasses only" @subclasses_only def _f1583394f1a6(Foo): class Bar(Injector, Foo): pass @subclasses_only def _b51814725d07(Foo):
import inspect import pytest from dependencies import Injector, Package from helpers import CodeCollector package_definitions = CodeCollector() @package_definitions.parametrize def test_provide_module(code): """Package instance itself should refer to the module.""" Container = code() assert inspect.ismodule(Container.itself) assert inspect.ismodule(Container.submodule) @package_definitions.parametrize def test_provide_an_instance(code): """ Package instance attribute access should provide injectable spec when refer to a class. """ Container = code() from pkg.submodule import Foo, Bar assert isinstance(Container.instance, Foo) or isinstance(Container.instance, Bar)