python-injection 0.9.5__tar.gz → 0.9.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of python-injection might be problematic. Click here for more details.

Files changed (21) hide show
  1. {python_injection-0.9.5 → python_injection-0.9.7}/PKG-INFO +28 -1
  2. {python_injection-0.9.5 → python_injection-0.9.7}/documentation/basic-usage.md +27 -0
  3. {python_injection-0.9.5 → python_injection-0.9.7}/injection/__init__.py +5 -3
  4. {python_injection-0.9.5 → python_injection-0.9.7}/injection/__init__.pyi +34 -17
  5. {python_injection-0.9.5/injection → python_injection-0.9.7/injection/_core}/common/lazy.py +1 -1
  6. {python_injection-0.9.5/injection/common/tools → python_injection-0.9.7/injection/_core/common}/threading.py +2 -1
  7. {python_injection-0.9.5/injection/common/tools → python_injection-0.9.7/injection/_core/common}/type.py +7 -2
  8. {python_injection-0.9.5/injection/core → python_injection-0.9.7/injection/_core}/module.py +77 -42
  9. {python_injection-0.9.5 → python_injection-0.9.7}/injection/testing/__init__.py +5 -2
  10. {python_injection-0.9.5 → python_injection-0.9.7}/injection/testing/__init__.pyi +1 -0
  11. {python_injection-0.9.5 → python_injection-0.9.7}/injection/utils.py +8 -8
  12. {python_injection-0.9.5 → python_injection-0.9.7}/pyproject.toml +1 -1
  13. python_injection-0.9.5/injection/integrations/__init__.py +0 -0
  14. {python_injection-0.9.5/injection/core → python_injection-0.9.7/injection/_core}/__init__.py +0 -0
  15. {python_injection-0.9.5/injection → python_injection-0.9.7/injection/_core}/common/__init__.py +0 -0
  16. {python_injection-0.9.5/injection → python_injection-0.9.7/injection/_core}/common/event.py +0 -0
  17. {python_injection-0.9.5/injection → python_injection-0.9.7/injection/_core}/common/invertible.py +0 -0
  18. {python_injection-0.9.5 → python_injection-0.9.7}/injection/exceptions.py +0 -0
  19. {python_injection-0.9.5/injection/common/tools → python_injection-0.9.7/injection/integrations}/__init__.py +0 -0
  20. {python_injection-0.9.5 → python_injection-0.9.7}/injection/integrations/blacksheep.py +0 -0
  21. {python_injection-0.9.5 → python_injection-0.9.7}/injection/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-injection
3
- Version: 0.9.5
3
+ Version: 0.9.7
4
4
  Summary: Fast and easy dependency injection framework.
5
5
  Home-page: https://github.com/100nm/python-injection
6
6
  License: MIT
@@ -63,6 +63,18 @@ service_c = ServiceC()
63
63
  set_constant(service_c)
64
64
  ```
65
65
 
66
+ Or here is the decorator `constant` which is equivalent:
67
+
68
+ > Unlike `@singleton`, dependencies will not be resolved.
69
+
70
+ ```python
71
+ from injection import constant
72
+
73
+ @constant
74
+ class ServiceC:
75
+ """ class implementation """
76
+ ```
77
+
66
78
  ## Inject an instance
67
79
 
68
80
  To inject one or several instances, use `inject` decorator.
@@ -173,3 +185,18 @@ def service_d_recipe() -> ServiceD:
173
185
  """ recipe implementation """
174
186
  ```
175
187
 
188
+ ## Working with type aliases
189
+
190
+ ```python
191
+ from injection import injectable, set_constant
192
+
193
+ type APIKey = str
194
+
195
+ set_constant("<secret_api_key>", APIKey, alias=True)
196
+
197
+ @injectable
198
+ class Client:
199
+ def __init__(self, api_key: APIKey):
200
+ ...
201
+ ```
202
+
@@ -37,6 +37,18 @@ service_c = ServiceC()
37
37
  set_constant(service_c)
38
38
  ```
39
39
 
40
+ Or here is the decorator `constant` which is equivalent:
41
+
42
+ > Unlike `@singleton`, dependencies will not be resolved.
43
+
44
+ ```python
45
+ from injection import constant
46
+
47
+ @constant
48
+ class ServiceC:
49
+ """ class implementation """
50
+ ```
51
+
40
52
  ## Inject an instance
41
53
 
42
54
  To inject one or several instances, use `inject` decorator.
@@ -146,3 +158,18 @@ from injection import injectable
146
158
  def service_d_recipe() -> ServiceD:
147
159
  """ recipe implementation """
148
160
  ```
161
+
162
+ ## Working with type aliases
163
+
164
+ ```python
165
+ from injection import injectable, set_constant
166
+
167
+ type APIKey = str
168
+
169
+ set_constant("<secret_api_key>", APIKey, alias=True)
170
+
171
+ @injectable
172
+ class Client:
173
+ def __init__(self, api_key: APIKey):
174
+ ...
175
+ ```
@@ -1,12 +1,13 @@
1
- from .core import Injectable, Module
2
- from .core import Mode as InjectableMode
3
- from .core import Priority as ModulePriority
1
+ from ._core import Injectable, Module
2
+ from ._core import Mode as InjectableMode
3
+ from ._core import Priority as ModulePriority
4
4
 
5
5
  __all__ = (
6
6
  "Injectable",
7
7
  "InjectableMode",
8
8
  "Module",
9
9
  "ModulePriority",
10
+ "constant",
10
11
  "find_instance",
11
12
  "get_instance",
12
13
  "get_lazy_instance",
@@ -26,6 +27,7 @@ def mod(name: str = None, /) -> Module:
26
27
  return Module.from_name(name)
27
28
 
28
29
 
30
+ constant = mod().constant
29
31
  find_instance = mod().find_instance
30
32
  get_instance = mod().get_instance
31
33
  get_lazy_instance = mod().get_lazy_instance
@@ -1,7 +1,7 @@
1
1
  from abc import abstractmethod
2
2
  from collections.abc import Callable
3
3
  from contextlib import ContextDecorator
4
- from enum import StrEnum
4
+ from enum import Enum
5
5
  from logging import Logger
6
6
  from types import UnionType
7
7
  from typing import (
@@ -9,18 +9,20 @@ from typing import (
9
9
  ContextManager,
10
10
  Protocol,
11
11
  Self,
12
+ TypeAliasType,
12
13
  final,
13
14
  runtime_checkable,
14
15
  )
15
16
 
16
- from .common.invertible import Invertible
17
- from .common.tools.type import TypeInfo
18
- from .core import InjectableFactory
19
- from .core import ModeStr as InjectableModeStr
20
- from .core import PriorityStr as ModulePriorityStr
17
+ from ._core import InjectableFactory as _InjectableFactory
18
+ from ._core import ModeStr as InjectableModeStr
19
+ from ._core import PriorityStr as ModulePriorityStr
20
+ from ._core.common.invertible import Invertible as _Invertible
21
+ from ._core.common.type import TypeInfo as _TypeInfo
21
22
 
22
23
  _: Module = ...
23
24
 
25
+ constant = _.constant
24
26
  find_instance = _.find_instance
25
27
  get_instance = _.get_instance
26
28
  get_lazy_instance = _.get_lazy_instance
@@ -47,7 +49,7 @@ class Module:
47
49
  """
48
50
 
49
51
  def __init__(self, name: str = ...): ...
50
- def __contains__(self, cls: type | UnionType, /) -> bool: ...
52
+ def __contains__(self, cls: type | UnionType | TypeAliasType, /) -> bool: ...
51
53
  @property
52
54
  def is_locked(self) -> bool: ...
53
55
  def inject(self, wrapped: Callable[..., Any] = ..., /):
@@ -62,9 +64,9 @@ class Module:
62
64
  wrapped: Callable[..., T] = ...,
63
65
  /,
64
66
  *,
65
- cls: InjectableFactory[T] = ...,
67
+ cls: _InjectableFactory[T] = ...,
66
68
  inject: bool = ...,
67
- on: TypeInfo[T] = ...,
69
+ on: _TypeInfo[T] = ...,
68
70
  mode: InjectableMode | InjectableModeStr = ...,
69
71
  ):
70
72
  """
@@ -79,7 +81,7 @@ class Module:
79
81
  /,
80
82
  *,
81
83
  inject: bool = ...,
82
- on: TypeInfo[T] = ...,
84
+ on: _TypeInfo[T] = ...,
83
85
  mode: InjectableMode | InjectableModeStr = ...,
84
86
  ):
85
87
  """
@@ -95,11 +97,26 @@ class Module:
95
97
  registered.
96
98
  """
97
99
 
100
+ def constant[T](
101
+ self,
102
+ wrapped: Callable[..., T] = ...,
103
+ /,
104
+ *,
105
+ on: _TypeInfo[T] = ...,
106
+ mode: InjectableMode | InjectableModeStr = ...,
107
+ ):
108
+ """
109
+ Decorator applicable to a class or function. It is used to indicate how the
110
+ constant is constructed. At injection time, the injected instance will always
111
+ be the same. Unlike `@singleton`, dependencies will not be resolved.
112
+ """
113
+
98
114
  def set_constant[T](
99
115
  self,
100
116
  instance: T,
101
- on: TypeInfo[T] = ...,
117
+ on: _TypeInfo[T] = ...,
102
118
  *,
119
+ alias: bool = ...,
103
120
  mode: InjectableMode | InjectableModeStr = ...,
104
121
  ) -> Self:
105
122
  """
@@ -108,13 +125,13 @@ class Module:
108
125
  that no dependencies are resolved, so the module doesn't need to be locked.
109
126
  """
110
127
 
111
- def find_instance[T](self, cls: type[T]) -> T:
128
+ def find_instance[T](self, cls: type[T] | TypeAliasType) -> T:
112
129
  """
113
130
  Function used to retrieve an instance associated with the type passed in
114
131
  parameter or an exception will be raised.
115
132
  """
116
133
 
117
- def get_instance[T](self, cls: type[T]) -> T | None:
134
+ def get_instance[T](self, cls: type[T] | TypeAliasType) -> T | None:
118
135
  """
119
136
  Function used to retrieve an instance associated with the type passed in
120
137
  parameter or return `None`.
@@ -122,10 +139,10 @@ class Module:
122
139
 
123
140
  def get_lazy_instance[T](
124
141
  self,
125
- cls: type[T],
142
+ cls: type[T] | TypeAliasType,
126
143
  *,
127
144
  cache: bool = ...,
128
- ) -> Invertible[T | None]:
145
+ ) -> _Invertible[T | None]:
129
146
  """
130
147
  Function used to retrieve an instance associated with the type passed in
131
148
  parameter or `None`. Return a `Invertible` object. To access the instance
@@ -199,7 +216,7 @@ class Module:
199
216
  """
200
217
 
201
218
  @final
202
- class ModulePriority(StrEnum):
219
+ class ModulePriority(Enum):
203
220
  LOW = ...
204
221
  HIGH = ...
205
222
 
@@ -212,7 +229,7 @@ class Injectable[T](Protocol):
212
229
  def get_instance(self) -> T: ...
213
230
 
214
231
  @final
215
- class InjectableMode(StrEnum):
232
+ class InjectableMode(Enum):
216
233
  FALLBACK = ...
217
234
  NORMAL = ...
218
235
  OVERRIDE = ...
@@ -1,7 +1,7 @@
1
1
  from collections.abc import Callable, Iterator, Mapping
2
2
  from types import MappingProxyType
3
3
 
4
- from injection.common.invertible import Invertible
4
+ from injection._core.common.invertible import Invertible
5
5
 
6
6
  __all__ = ("Lazy", "LazyMapping")
7
7
 
@@ -1,3 +1,4 @@
1
+ from collections.abc import Iterator
1
2
  from contextlib import contextmanager
2
3
  from threading import RLock
3
4
 
@@ -5,7 +6,7 @@ __all__ = ("synchronized",)
5
6
 
6
7
 
7
8
  @contextmanager
8
- def synchronized():
9
+ def synchronized() -> Iterator[RLock]:
9
10
  lock = RLock()
10
11
 
11
12
  with lock:
@@ -6,6 +6,7 @@ from typing import (
6
6
  Any,
7
7
  NamedTuple,
8
8
  Self,
9
+ TypeAliasType,
9
10
  Union,
10
11
  get_args,
11
12
  get_origin,
@@ -13,7 +14,9 @@ from typing import (
13
14
 
14
15
  __all__ = ("TypeInfo", "TypeReport", "analyze_types", "get_return_types")
15
16
 
16
- type TypeInfo[T] = type[T] | Callable[..., T] | Iterable[TypeInfo[T]] | UnionType
17
+ type TypeInfo[T] = (
18
+ type[T] | Callable[..., T] | Iterable[TypeInfo[T]] | UnionType | TypeAliasType
19
+ )
17
20
 
18
21
 
19
22
  class TypeReport[T](NamedTuple):
@@ -57,7 +60,9 @@ def analyze_types(*types: type | Any) -> Iterator[TypeReport[Any]]:
57
60
  yield from analyze_types(*inner_types)
58
61
 
59
62
 
60
- def get_return_types(*args: TypeInfo[Any]) -> Iterator[type | UnionType]:
63
+ def get_return_types(
64
+ *args: TypeInfo[Any],
65
+ ) -> Iterator[type | UnionType | TypeAliasType]:
61
66
  for arg in args:
62
67
  if isinstance(arg, Iterable) and not (
63
68
  isinstance(arg, type | str) or isinstance(get_origin(arg), type)
@@ -28,14 +28,16 @@ from typing import (
28
28
  NoReturn,
29
29
  Protocol,
30
30
  Self,
31
+ TypeAliasType,
31
32
  runtime_checkable,
32
33
  )
34
+ from uuid import uuid4
33
35
 
34
- from injection.common.event import Event, EventChannel, EventListener
35
- from injection.common.invertible import Invertible, SimpleInvertible
36
- from injection.common.lazy import Lazy, LazyMapping
37
- from injection.common.tools.threading import synchronized
38
- from injection.common.tools.type import (
36
+ from injection._core.common.event import Event, EventChannel, EventListener
37
+ from injection._core.common.invertible import Invertible, SimpleInvertible
38
+ from injection._core.common.lazy import Lazy, LazyMapping
39
+ from injection._core.common.threading import synchronized
40
+ from injection._core.common.type import (
39
41
  TypeInfo,
40
42
  TypeReport,
41
43
  analyze_types,
@@ -65,12 +67,12 @@ Events
65
67
 
66
68
 
67
69
  @dataclass(frozen=True, slots=True)
68
- class ContainerEvent(Event, ABC):
69
- container: Container
70
+ class LocatorEvent(Event, ABC):
71
+ locator: Locator
70
72
 
71
73
 
72
74
  @dataclass(frozen=True, slots=True)
73
- class ContainerDependenciesUpdated(ContainerEvent):
75
+ class LocatorDependenciesUpdated(LocatorEvent):
74
76
  reports: Collection[TypeReport]
75
77
  mode: Mode
76
78
 
@@ -78,8 +80,8 @@ class ContainerDependenciesUpdated(ContainerEvent):
78
80
  length = len(self.reports)
79
81
  formatted_types = ", ".join(f"`{report.type}`" for report in self.reports)
80
82
  return (
81
- f"{length} container dependenc{'ies' if length > 1 else 'y'} have "
82
- f"been updated{f': {formatted_types}' if formatted_types else ''}."
83
+ f"{length} dependenc{"ies" if length > 1 else "y"} have been "
84
+ f"updated{f": {formatted_types}" if formatted_types else ""}."
83
85
  )
84
86
 
85
87
 
@@ -214,11 +216,15 @@ class Broker(Protocol):
214
216
  __slots__ = ()
215
217
 
216
218
  @abstractmethod
217
- def __getitem__[T](self, cls: type[T] | UnionType, /) -> Injectable[T]:
219
+ def __getitem__[T](
220
+ self,
221
+ cls: type[T] | UnionType | TypeAliasType,
222
+ /,
223
+ ) -> Injectable[T]:
218
224
  raise NotImplementedError
219
225
 
220
226
  @abstractmethod
221
- def __contains__(self, cls: type | UnionType, /) -> bool:
227
+ def __contains__(self, cls: type | UnionType | TypeAliasType, /) -> bool:
222
228
  raise NotImplementedError
223
229
 
224
230
  @property
@@ -232,7 +238,7 @@ class Broker(Protocol):
232
238
 
233
239
 
234
240
  """
235
- Container
241
+ Locator
236
242
  """
237
243
 
238
244
 
@@ -259,11 +265,15 @@ class Record[T](NamedTuple):
259
265
 
260
266
 
261
267
  @dataclass(repr=False, frozen=True, slots=True)
262
- class Container(Broker):
268
+ class Locator(Broker):
263
269
  __records: dict[TypeReport, Record] = field(default_factory=dict, init=False)
264
270
  __channel: EventChannel = field(default_factory=EventChannel, init=False)
265
271
 
266
- def __getitem__[T](self, cls: type[T] | UnionType, /) -> Injectable[T]:
272
+ def __getitem__[T](
273
+ self,
274
+ cls: type[T] | UnionType | TypeAliasType,
275
+ /,
276
+ ) -> Injectable[T]:
267
277
  for report in analyze_types(cls):
268
278
  for scoped_report in OrderedDict.fromkeys((report, report.no_args)):
269
279
  try:
@@ -275,7 +285,7 @@ class Container(Broker):
275
285
 
276
286
  raise NoInjectable(cls)
277
287
 
278
- def __contains__(self, cls: type | UnionType, /) -> bool:
288
+ def __contains__(self, cls: type | UnionType | TypeAliasType, /) -> bool:
279
289
  return any(report in self.__records for report in analyze_types(cls))
280
290
 
281
291
  @property
@@ -289,18 +299,19 @@ class Container(Broker):
289
299
  @synchronized()
290
300
  def update[T](
291
301
  self,
292
- classes: Iterable[type[T] | UnionType],
302
+ classes: Iterable[type[T] | UnionType | TypeAliasType],
293
303
  injectable: Injectable[T],
294
304
  mode: Mode | ModeStr,
295
305
  ) -> Self:
296
306
  mode = Mode(mode)
307
+ record = Record(injectable, mode)
297
308
  records = {
298
- report: Record(injectable, mode)
309
+ report: record
299
310
  for report in self.__prepare_reports_for_updating(classes, mode)
300
311
  }
301
312
 
302
313
  if records:
303
- event = ContainerDependenciesUpdated(self, records.keys(), mode)
314
+ event = LocatorDependenciesUpdated(self, records.keys(), mode)
304
315
 
305
316
  with self.dispatch(event):
306
317
  self.__records.update(records)
@@ -323,7 +334,7 @@ class Container(Broker):
323
334
 
324
335
  def __prepare_reports_for_updating(
325
336
  self,
326
- classes: Iterable[type | UnionType],
337
+ classes: Iterable[type | UnionType | TypeAliasType],
327
338
  mode: Mode,
328
339
  ) -> Iterator[TypeReport]:
329
340
  rank = mode.rank
@@ -367,25 +378,25 @@ type InjectableFactory[T] = Callable[[Callable[..., T]], Injectable[T]]
367
378
 
368
379
 
369
380
  @dataclass(eq=False, frozen=True, slots=True)
370
- class Module(EventListener, Broker):
371
- name: str | None = field(default=None)
381
+ class Module(Broker, EventListener):
382
+ name: str = field(default_factory=lambda: f"anonymous@{uuid4().hex[:7]}")
372
383
  __channel: EventChannel = field(
373
384
  default_factory=EventChannel,
374
385
  init=False,
375
386
  repr=False,
376
387
  )
377
- __container: Container = field(
378
- default_factory=Container,
388
+ __locator: Locator = field(
389
+ default_factory=Locator,
379
390
  init=False,
380
391
  repr=False,
381
392
  )
382
- __modules: OrderedDict[Module, None] = field(
383
- default_factory=OrderedDict,
393
+ __loggers: list[Logger] = field(
394
+ default_factory=lambda: [getLogger(__name__)],
384
395
  init=False,
385
396
  repr=False,
386
397
  )
387
- __loggers: list[Logger] = field(
388
- default_factory=lambda: [getLogger(__name__)],
398
+ __modules: OrderedDict[Module, None] = field(
399
+ default_factory=OrderedDict,
389
400
  init=False,
390
401
  repr=False,
391
402
  )
@@ -393,19 +404,20 @@ class Module(EventListener, Broker):
393
404
  __instances: ClassVar[dict[str, Module]] = {}
394
405
 
395
406
  def __post_init__(self):
396
- self.__container.add_listener(self)
407
+ self.__locator.add_listener(self)
397
408
 
398
- def __getitem__[T](self, cls: type[T] | UnionType, /) -> Injectable[T]:
409
+ def __getitem__[T](
410
+ self,
411
+ cls: type[T] | UnionType | TypeAliasType,
412
+ /,
413
+ ) -> Injectable[T]:
399
414
  for broker in self.__brokers:
400
415
  with suppress(KeyError):
401
416
  return broker[cls]
402
417
 
403
418
  raise NoInjectable(cls)
404
419
 
405
- def __setitem__[T](self, cls: type[T] | UnionType, injectable: Injectable[T], /):
406
- self.update((cls,), injectable)
407
-
408
- def __contains__(self, cls: type | UnionType, /) -> bool:
420
+ def __contains__(self, cls: type | UnionType | TypeAliasType, /) -> bool:
409
421
  return any(cls in broker for broker in self.__brokers)
410
422
 
411
423
  @property
@@ -415,7 +427,7 @@ class Module(EventListener, Broker):
415
427
  @property
416
428
  def __brokers(self) -> Iterator[Broker]:
417
429
  yield from tuple(self.__modules)
418
- yield self.__container
430
+ yield self.__locator
419
431
 
420
432
  def injectable[T](
421
433
  self,
@@ -449,18 +461,41 @@ class Module(EventListener, Broker):
449
461
 
450
462
  return decorator(wrapped) if wrapped else decorator
451
463
 
464
+ def constant[T](
465
+ self,
466
+ wrapped: Callable[..., T] = None,
467
+ /,
468
+ *,
469
+ on: TypeInfo[T] = (),
470
+ mode: Mode | ModeStr = Mode.get_default(),
471
+ ):
472
+ def decorator(wp):
473
+ instance = wp()
474
+ self.set_constant(
475
+ instance,
476
+ on=on,
477
+ mode=mode,
478
+ )
479
+ return wp
480
+
481
+ return decorator(wrapped) if wrapped else decorator
482
+
452
483
  def set_constant[T](
453
484
  self,
454
485
  instance: T,
455
486
  on: TypeInfo[T] = (),
456
487
  *,
488
+ alias: bool = False,
457
489
  mode: Mode | ModeStr = Mode.get_default(),
458
490
  ) -> Self:
459
- cls = type(instance)
491
+ if not alias:
492
+ cls = type(instance)
493
+ on = (cls, on)
494
+
460
495
  self.injectable(
461
496
  lambda: instance,
462
497
  inject=False,
463
- on=(cls, on),
498
+ on=on,
464
499
  mode=mode,
465
500
  )
466
501
  return self
@@ -488,11 +523,11 @@ class Module(EventListener, Broker):
488
523
 
489
524
  return decorator(wrapped) if wrapped else decorator
490
525
 
491
- def find_instance[T](self, cls: type[T]) -> T:
526
+ def find_instance[T](self, cls: type[T] | TypeAliasType) -> T:
492
527
  injectable = self[cls]
493
528
  return injectable.get_instance()
494
529
 
495
- def get_instance[T](self, cls: type[T]) -> T | None:
530
+ def get_instance[T](self, cls: type[T] | TypeAliasType) -> T | None:
496
531
  try:
497
532
  return self.find_instance(cls)
498
533
  except KeyError:
@@ -500,7 +535,7 @@ class Module(EventListener, Broker):
500
535
 
501
536
  def get_lazy_instance[T](
502
537
  self,
503
- cls: type[T],
538
+ cls: type[T] | TypeAliasType,
504
539
  *,
505
540
  cache: bool = False,
506
541
  ) -> Invertible[T | None]:
@@ -513,11 +548,11 @@ class Module(EventListener, Broker):
513
548
 
514
549
  def update[T](
515
550
  self,
516
- classes: Iterable[type[T] | UnionType],
551
+ classes: Iterable[type[T] | UnionType | TypeAliasType],
517
552
  injectable: Injectable[T],
518
553
  mode: Mode | ModeStr = Mode.get_default(),
519
554
  ) -> Self:
520
- self.__container.update(classes, injectable, mode)
555
+ self.__locator.update(classes, injectable, mode)
521
556
  return self
522
557
 
523
558
  def init_modules(self, *modules: Module) -> Self:
@@ -1,21 +1,24 @@
1
1
  from contextlib import contextmanager
2
- from functools import partial
3
2
 
4
3
  from injection import Module, ModulePriority, mod
5
4
 
6
5
  __all__ = (
7
6
  "set_test_constant",
8
7
  "should_be_test_injectable",
8
+ "test_constant",
9
9
  "test_injectable",
10
10
  "test_singleton",
11
11
  "use_test_injectables",
12
12
  )
13
13
 
14
14
 
15
- tmod = partial(mod, "testing")
15
+ def tmod() -> Module:
16
+ return mod("testing")
17
+
16
18
 
17
19
  set_test_constant = tmod().set_constant
18
20
  should_be_test_injectable = tmod().should_be_injectable
21
+ test_constant = tmod().constant
19
22
  test_injectable = tmod().injectable
20
23
  test_singleton = tmod().singleton
21
24
 
@@ -6,6 +6,7 @@ from injection import Module
6
6
 
7
7
  set_test_constant = _.set_constant
8
8
  should_be_test_injectable = _.should_be_injectable
9
+ test_constant = _.constant
9
10
  test_injectable = _.injectable
10
11
  test_singleton = _.singleton
11
12
 
@@ -1,15 +1,15 @@
1
1
  from collections.abc import Callable, Iterator
2
2
  from importlib import import_module
3
3
  from pkgutil import walk_packages
4
- from types import ModuleType
4
+ from types import ModuleType as PythonModule
5
5
 
6
6
  __all__ = ("load_package",)
7
7
 
8
8
 
9
9
  def load_package(
10
- package: ModuleType | str,
10
+ package: PythonModule | str,
11
11
  predicate: Callable[[str], bool] = lambda module_name: True,
12
- ) -> tuple[ModuleType, ...]:
12
+ ) -> dict[str, PythonModule]:
13
13
  """
14
14
  Function for importing all modules in a Python package.
15
15
  Pass the `predicate` parameter if you want to filter the modules to be imported.
@@ -18,13 +18,13 @@ def load_package(
18
18
  if isinstance(package, str):
19
19
  package = import_module(package)
20
20
 
21
- return tuple(__iter_modules(package, predicate))
21
+ return dict(__iter_modules_from(package, predicate))
22
22
 
23
23
 
24
- def __iter_modules(
25
- package: ModuleType,
24
+ def __iter_modules_from(
25
+ package: PythonModule,
26
26
  predicate: Callable[[str], bool],
27
- ) -> Iterator[ModuleType]:
27
+ ) -> Iterator[tuple[str, PythonModule]]:
28
28
  try:
29
29
  path = package.__path__
30
30
  except AttributeError as exc:
@@ -38,4 +38,4 @@ def __iter_modules(
38
38
  if info.ispkg or not predicate(name):
39
39
  continue
40
40
 
41
- yield import_module(name)
41
+ yield name, import_module(name)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-injection"
3
- version = "0.9.5"
3
+ version = "0.9.7"
4
4
  description = "Fast and easy dependency injection framework."
5
5
  license = "MIT"
6
6
  authors = ["remimd"]
File without changes