tests.test_context_based_executions   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 179
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 122
dl 0
loc 179
rs 10
c 0
b 0
f 0
wmc 28

13 Functions

Rating   Name   Duplication   Size   Complexity  
A test_it_works_with_actual_context_managers() 0 12 2
A test_a_partial_function_cleans_up_the_loaded_contexts_after_execution() 0 11 1
A test_context_instances_are_not_singletons() 0 5 2
A test_context_instance_singletons_only_have_a_lifespan_of_the_with() 0 10 3
A test_clean_up_of_loaded_contexts_happens_on_container_exit() 0 7 2
A test_clean_up_of_loaded_contexts_happens_recursively_on_container_exit() 0 13 2
A test_the_container_can_be_reused() 0 7 3
A test_a_magic_partial_function_cleans_up_the_loaded_contexts_after_execution() 0 11 1
A test_the_container_can_be_nested_though_this_has_no_meaning() 0 7 3
A _load_a_some_dep_then_clean() 0 7 1
A test_it_fails_if_the_dependencies_arent_defined_correctly() 0 8 3
A _load_a_some_wrapper_dep_then_clean() 0 6 1
A test_context_instances_can_be_made_singletons() 0 9 2

2 Methods

Rating   Name   Duplication   Size   Complexity  
A Thing.__init__() 0 2 1
A SomeWrapperDep.__init__() 0 2 1
1
from contextlib import contextmanager
2
from typing import Iterator, Generator, ContextManager
3
4
import pytest
5
6
from lagom import (
7
    Container,
8
    dependency_definition,
9
    ContextContainer,
10
    injectable,
11
)
12
from lagom.decorators import context_dependency_definition
13
from lagom.exceptions import InvalidDependencyDefinition
14
15
16
class SomeDep:
17
    global_clean_up_has_happened = False
18
19
20
class SomeWrapperDep:
21
    global_clean_up_has_happened = False
22
23
    def __init__(self, dep: SomeDep):
24
        pass
25
26
27
class SomeNotProperlySetupDef:
28
    pass
29
30
31
class Thing:
32
    contents: str
33
34
    def __init__(self, contents: str):
35
        self.contents = contents
36
37
38
container = Container()
39
40
41
@dependency_definition(container)
42
@contextmanager
43
def _load_a_some_dep_then_clean() -> Generator[SomeDep, None, None]:
44
    try:
45
        yield SomeDep()
46
    finally:
47
        SomeDep.global_clean_up_has_happened = True
48
49
50
@context_dependency_definition(container)
51
def _load_a_some_wrapper_dep_then_clean(c) -> Iterator[SomeWrapperDep]:
52
    try:
53
        yield SomeWrapperDep(c[SomeDep])
54
    finally:
55
        SomeWrapperDep.global_clean_up_has_happened = True
56
57
58
def test_clean_up_of_loaded_contexts_happens_on_container_exit():
59
    SomeDep.global_clean_up_has_happened = False
60
61
    with ContextContainer(container, context_types=[SomeDep]) as context_container:
62
        assert isinstance(context_container[SomeDep], SomeDep)
63
        assert not SomeDep.global_clean_up_has_happened
64
    assert SomeDep.global_clean_up_has_happened
65
66
67
def test_context_instances_are_not_singletons():
68
    with ContextContainer(container, context_types=[SomeDep]) as context_container:
69
        one = context_container[SomeDep]
70
        two = context_container[SomeDep]
71
        assert one is not two
72
73
74
def test_context_instances_can_be_made_singletons():
75
    SomeDep.global_clean_up_has_happened = False
76
    with ContextContainer(
77
        container, context_types=[], context_singletons=[SomeDep]
78
    ) as context_container:
79
        one = context_container[SomeDep]
80
        two = context_container[SomeDep]
81
        assert one is two
82
    assert SomeDep.global_clean_up_has_happened
83
84
85
def test_context_instance_singletons_only_have_a_lifespan_of_the_with():
86
    SomeDep.global_clean_up_has_happened = False
87
    context_container = ContextContainer(
88
        container, context_types=[], context_singletons=[SomeDep]
89
    )
90
    with context_container as c:
91
        one = c[SomeDep]
92
    with context_container as c:
93
        two = c[SomeDep]
94
    assert one is not two
95
96
97
def test_clean_up_of_loaded_contexts_happens_recursively_on_container_exit():
98
    SomeDep.global_clean_up_has_happened = False
99
    SomeWrapperDep.global_clean_up_has_happened = False
100
101
    with ContextContainer(
102
        container, context_types=[SomeDep, SomeWrapperDep]
103
    ) as context_container:
104
        assert isinstance(context_container[SomeWrapperDep], SomeWrapperDep)
105
        assert not SomeDep.global_clean_up_has_happened
106
        assert not SomeWrapperDep.global_clean_up_has_happened
107
108
    assert SomeDep.global_clean_up_has_happened
109
    assert SomeWrapperDep.global_clean_up_has_happened
110
111
112
def test_it_fails_if_the_dependencies_arent_defined_correctly():
113
    with pytest.raises(InvalidDependencyDefinition) as failure:
114
        with ContextContainer(
115
            container, context_types=[SomeNotProperlySetupDef]
116
        ) as context_container:
117
            context_container.resolve(SomeNotProperlySetupDef)
118
    assert f"A ContextManager[{SomeNotProperlySetupDef}] should be defined" in str(
119
        failure.value
120
    )
121
122
123
def test_it_works_with_actual_context_managers():
124
    class ThingManager:
125
        def __enter__(self):
126
            return Thing("managed thing")
127
128
        def __exit__(self, exc_type, exc_val, exc_tb):
129
            pass
130
131
    container[ContextManager[Thing]] = ThingManager  # type: ignore
132
133
    with ContextContainer(container, context_types=[Thing]) as context_container:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable container does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable Thing does not seem to be defined.
Loading history...
134
        assert context_container.resolve(Thing).contents == "managed thing"
135
136
137
def test_the_container_can_be_reused():
138
    original = ContextContainer(container, context_types=[SomeDep])
139
    with original as context_container_1:
140
        a = context_container_1.resolve(SomeDep)
141
    with original as context_container_2:
142
        b = context_container_2.resolve(SomeDep)
143
    assert a != b
144
145
146
def test_the_container_can_be_nested_though_this_has_no_meaning():
147
    original = ContextContainer(container, context_types=[SomeDep])
148
    with original as context_container_1:
149
        a = context_container_1.resolve(SomeDep)
150
        with context_container_1 as context_container_2:
151
            b = context_container_2.resolve(SomeDep)
152
    assert a != b
153
154
155
def test_a_partial_function_cleans_up_the_loaded_contexts_after_execution():
156
    SomeDep.global_clean_up_has_happened = False
157
    context_container = ContextContainer(container, context_types=[SomeDep])
158
159
    def _some_func(dep: SomeDep = injectable):
160
        return dep
161
162
    wrapped_func = context_container.partial(_some_func)
163
164
    assert isinstance(wrapped_func(), SomeDep)
165
    assert SomeDep.global_clean_up_has_happened
166
167
168
def test_a_magic_partial_function_cleans_up_the_loaded_contexts_after_execution():
169
    SomeDep.global_clean_up_has_happened = False
170
    context_container = ContextContainer(container, context_types=[SomeDep])
171
172
    def _some_func(dep: SomeDep):
173
        return dep
174
175
    wrapped_func = context_container.magic_partial(_some_func)
176
177
    assert isinstance(wrapped_func(), SomeDep)
178
    assert SomeDep.global_clean_up_has_happened
179