|
10 | 10 |
|
11 | 11 | """Functional tests for the "Injector" dependency injection framework.""" |
12 | 12 |
|
13 | | -from contextlib import contextmanager |
14 | | -from dataclasses import dataclass |
15 | | -from typing import Any, NewType, Optional, Union |
16 | 13 | import abc |
17 | 14 | import sys |
18 | 15 | import threading |
19 | 16 | import traceback |
20 | 17 | import warnings |
| 18 | +from contextlib import contextmanager |
| 19 | +from dataclasses import dataclass |
| 20 | +from typing import Any, NewType, Optional, Union |
21 | 21 |
|
22 | 22 | if sys.version_info >= (3, 9): |
23 | 23 | from typing import Annotated |
|
29 | 29 | import pytest |
30 | 30 |
|
31 | 31 | from injector import ( |
| 32 | + AssistedBuilder, |
32 | 33 | Binder, |
33 | 34 | CallError, |
| 35 | + CircularDependency, |
| 36 | + ClassAssistedBuilder, |
| 37 | + ClassProvider, |
| 38 | + Error, |
34 | 39 | Inject, |
35 | 40 | Injector, |
| 41 | + InstanceProvider, |
| 42 | + InvalidInterface, |
| 43 | + Module, |
36 | 44 | NoInject, |
| 45 | + ProviderOf, |
37 | 46 | Scope, |
38 | | - InstanceProvider, |
39 | | - ClassProvider, |
| 47 | + ScopeDecorator, |
| 48 | + SingletonScope, |
| 49 | + UnknownArgument, |
| 50 | + UnsatisfiedRequirement, |
40 | 51 | get_bindings, |
41 | 52 | inject, |
42 | 53 | multiprovider, |
43 | 54 | noninjectable, |
| 55 | + provider, |
44 | 56 | singleton, |
45 | 57 | threadlocal, |
46 | | - UnsatisfiedRequirement, |
47 | | - CircularDependency, |
48 | | - Module, |
49 | | - SingletonScope, |
50 | | - ScopeDecorator, |
51 | | - AssistedBuilder, |
52 | | - provider, |
53 | | - ProviderOf, |
54 | | - ClassAssistedBuilder, |
55 | | - Error, |
56 | | - UnknownArgument, |
57 | | - InvalidInterface, |
58 | 58 | ) |
59 | 59 |
|
60 | 60 |
|
@@ -723,6 +723,46 @@ def configure_dict(binder: Binder): |
723 | 723 | Injector([configure_dict]) |
724 | 724 |
|
725 | 725 |
|
| 726 | +def test_multibind_types_respect_the_bound_type_scope() -> None: |
| 727 | + def configure(binder: Binder) -> None: |
| 728 | + binder.bind(PluginA, to=PluginA, scope=singleton) |
| 729 | + binder.multibind(List[Plugin], to=PluginA) |
| 730 | + |
| 731 | + injector = Injector([configure]) |
| 732 | + first_list = injector.get(List[Plugin]) |
| 733 | + second_list = injector.get(List[Plugin]) |
| 734 | + |
| 735 | + assert first_list[0] is second_list[0] |
| 736 | + |
| 737 | + |
| 738 | +def test_multibind_scopes_applies_to_the_bound_items() -> None: |
| 739 | + def configure(binder: Binder) -> None: |
| 740 | + binder.multibind(List[Plugin], to=PluginA, scope=singleton) |
| 741 | + binder.multibind(List[Plugin], to=PluginB) |
| 742 | + binder.multibind(List[Plugin], to=PluginC, scope=singleton) |
| 743 | + |
| 744 | + injector = Injector([configure]) |
| 745 | + first_list = injector.get(List[Plugin]) |
| 746 | + second_list = injector.get(List[Plugin]) |
| 747 | + |
| 748 | + assert first_list is not second_list |
| 749 | + assert first_list[0] is second_list[0] |
| 750 | + assert first_list[1] is not second_list[1] |
| 751 | + assert first_list[2] is second_list[2] |
| 752 | + |
| 753 | + |
| 754 | +def test_multibind_scopes_does_not_apply_to_the_type_globally() -> None: |
| 755 | + def configure(binder: Binder) -> None: |
| 756 | + binder.multibind(List[Plugin], to=PluginA, scope=singleton) |
| 757 | + |
| 758 | + injector = Injector([configure]) |
| 759 | + plugins = injector.get(List[Plugin]) |
| 760 | + |
| 761 | + assert plugins[0] is not injector.get(PluginA) |
| 762 | + assert plugins[0] is not injector.get(Plugin) |
| 763 | + assert injector.get(PluginA) is not injector.get(PluginA) |
| 764 | + |
| 765 | + |
726 | 766 | def test_regular_bind_and_provider_dont_work_with_multibind(): |
727 | 767 | # We only want multibind and multiprovider to work to avoid confusion |
728 | 768 |
|
|
0 commit comments