diff --git a/README.rst b/README.rst index 6be9665..80e2313 100644 --- a/README.rst +++ b/README.rst @@ -87,8 +87,8 @@ and designed for Humans. * - .. code:: python + from typing import Annotated, List from injectable import Autowired, autowired - from typing import List from models import Database from messaging import Broker @@ -96,8 +96,8 @@ and designed for Humans. @autowired def __init__( self, - database: Autowired(Database), - message_brokers: Autowired(List[Broker]), + database: Annotated[Database, Autowired], + message_brokers: Annotated[List[Broker], Autowired], ): pending = database.get_pending_messages() for broker in message_brokers: @@ -149,7 +149,8 @@ Features you'll love ❤️ * **Qualifier overloading**: declare as many injectables as you like for a single qualifier or extending the same base class. You can inject all of them just by - specifying a :python:`typing.List` to :python:`Autowired`: :python:`deps: Autowired(List["qualifier"])`. + specifying a :python:`typing.List` to :python:`Autowired`: + :python:`deps: Annotated[List["qualifier"], Autowired]`. * **Transparent lazy initialization**: passing the argument :python:`lazy=True` for :python:`Autowired` will make your dependency to be initialized only when actually used, all @@ -160,7 +161,7 @@ Features you'll love ❤️ * **Namespaces**: specify different namespaces for injectables as in :python:`@injectable(namespace="foo")` and then just use them when annotating your - parameters as in :python:`dep: Autowired(..., namespace="foo")`. + parameters as in :python:`dep: Annotated[..., Autowired(namespace="foo")]`. * **Linters friendly**: :python:`Autowired` is carefully designed to comply with static linter analysis such as PyCharm's to preserve the parameter original type hint. diff --git a/docs/.buildinfo b/docs/.buildinfo index 48e29d4..c1e15aa 100644 --- a/docs/.buildinfo +++ b/docs/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 927fa4b8772f27b8ef95b7056f132ebc +config: c23d413b855c1456020e10f46639280c tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/_modules/index.html b/docs/_modules/index.html index 2a8b015..8911aa8 100644 --- a/docs/_modules/index.html +++ b/docs/_modules/index.html @@ -4,7 +4,7 @@ - Overview: module code — injectable 4.0.0 documentation + Overview: module code — injectable 4.0.1 documentation @@ -28,7 +28,7 @@

Navigation

@@ -108,7 +108,7 @@

Navigation

diff --git a/docs/_modules/injectable/autowiring/autowired_decorator.html b/docs/_modules/injectable/autowiring/autowired_decorator.html index 7bb70ad..ccb16c6 100644 --- a/docs/_modules/injectable/autowiring/autowired_decorator.html +++ b/docs/_modules/injectable/autowiring/autowired_decorator.html @@ -4,7 +4,7 @@ - injectable.autowiring.autowired_decorator — injectable 4.0.0 documentation + injectable.autowiring.autowired_decorator — injectable 4.0.1 documentation @@ -28,7 +28,7 @@

Navigation

@@ -48,15 +48,15 @@

Navigation

Source code for injectable.autowiring.autowired_decorator

 import inspect
 from functools import wraps
-from typing import TypeVar, Callable, Any, get_args, _AnnotatedAlias, Union
+from typing import TypeVar, Callable, get_args, _AnnotatedAlias, Union
 
 from injectable.autowiring.autowired_type import _Autowired, Autowired
 from injectable.errors import AutowiringError
 
-T = TypeVar("T", bound=Callable[..., Any])
+R = TypeVar("R")
 
 
-
[docs]def autowired(func: T) -> T: +
[docs]def autowired(func: Callable[..., R]) -> Callable[..., R]: """ Function decorator to setup dependency injection autowiring. @@ -112,7 +112,7 @@

Source code for injectable.autowiring.autowired_decorator

raise AutowiringError("No parameter is typed with 'Autowired'") @wraps(func) - def wrapper(*args, **kwargs): + def wrapper(*args, **kwargs) -> R: bound_arguments = signature.bind_partial(*args, **kwargs).arguments args = list(args) for parameter in autowired_parameters: @@ -209,7 +209,7 @@

Navigation

diff --git a/docs/_sources/usage/namespaces.rst.txt b/docs/_sources/usage/namespaces.rst.txt index 9b31091..220edd4 100644 --- a/docs/_sources/usage/namespaces.rst.txt +++ b/docs/_sources/usage/namespaces.rst.txt @@ -10,6 +10,9 @@ Namespaces Example :caption: namespaces_example.py :start-after: sphinx-start +.. literalinclude:: ../../examples/namespaces/measuring_service_abc.py + :caption: measuring_service_abc.py + .. literalinclude:: ../../examples/namespaces/intl_measuring_service.py :caption: intl_measuring_service.py diff --git a/docs/_sources/usage/optional_injection.rst.txt b/docs/_sources/usage/optional_injection.rst.txt index 67a5a95..506572d 100644 --- a/docs/_sources/usage/optional_injection.rst.txt +++ b/docs/_sources/usage/optional_injection.rst.txt @@ -9,3 +9,6 @@ Optional Injection Example .. literalinclude:: ../../examples/optional_injection/optional_injection_example.py :caption: optional_injection_example.py :start-after: sphinx-start + +.. literalinclude:: ../../examples/optional_injection/service_xyz.py + :caption: service_xyz.py diff --git a/docs/_static/documentation_options.js b/docs/_static/documentation_options.js index 7440b26..d8e0e58 100644 --- a/docs/_static/documentation_options.js +++ b/docs/_static/documentation_options.js @@ -1,6 +1,6 @@ var DOCUMENTATION_OPTIONS = { URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), - VERSION: '4.0.0', + VERSION: '4.0.1', LANGUAGE: 'None', COLLAPSE_INDEX: false, BUILDER: 'html', diff --git a/docs/authors.html b/docs/authors.html index 1b50a45..697c79b 100644 --- a/docs/authors.html +++ b/docs/authors.html @@ -5,7 +5,7 @@ - Authors — injectable 4.0.0 documentation + Authors — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

Navigation

@@ -119,7 +119,7 @@

Navigation

diff --git a/docs/caveats.html b/docs/caveats.html index 71725ed..972571a 100644 --- a/docs/caveats.html +++ b/docs/caveats.html @@ -5,7 +5,7 @@ - Caveats — injectable 4.0.0 documentation + Caveats — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

Navigation

@@ -149,7 +149,7 @@

Navigation

diff --git a/docs/changelog.html b/docs/changelog.html index 895e982..4acc3c6 100644 --- a/docs/changelog.html +++ b/docs/changelog.html @@ -5,7 +5,7 @@ - Changelog — injectable 4.0.0 documentation + Changelog — injectable 4.0.1 documentation @@ -30,7 +30,7 @@

Navigation

@@ -49,57 +49,63 @@

Navigation

Changelog

-

4.0.0 (2024-07-12)

+

4.0.1 (2024-07-31)

+
    +
  • Fix @autowired decorator wrong type annotation causing issues with pyright, mypy, and other type checkers

  • +
+
+
+

4.0.0 (2024-07-12)

  • Drop support for Python versions 3.6, 3.7 and 3.8

  • Comply with PEP-593 and support typing.Annotated

-
-

3.4.7 (2021-08-15)

+
+

3.4.7 (2021-08-15)

  • Fix injectable crashing when relative imports are used in files containing injectables.

-
-

3.4.6 (2021-03-20)

+
+

3.4.6 (2021-03-20)

  • Fix testing.register_injectables not creating the namespace when it doesn’t exist yet

-
-

3.4.5 (2021-03-11)

+
+

3.4.5 (2021-03-11)

  • Fix opening of UTF-8 files & allow for user set encoding

-
-

3.4.4 (2020-07-29)

+
+

3.4.4 (2020-07-29)

  • Fix inject return type hint

-
-

3.4.3 (2020-06-24)

+
+

3.4.3 (2020-06-24)

  • Fix Injectable failing to resolve complex/entangled imports

-
-

3.4.2 (2020-05-22)

+
+

3.4.2 (2020-05-22)

  • Fix optional injection bug when the namespace is empty

-
-

3.4.1 (2020-05-11)

+
+

3.4.1 (2020-05-11)

  • Fix the use of named args by the caller breaking autowired functions injection

-
-

3.4.0 (2020-05-09)

+
+

3.4.0 (2020-05-09)

-
-

3.3.0 (2020-04-20)

+
+

3.3.0 (2020-04-20)

  • Include the injectable.testing utilities to ease mocking injectables.

-
-

3.2.1 (2020-04-19)

+
+

3.2.1 (2020-04-19)

  • InjectionContainer::load is more resilient against duplicated injectables registering

-
-

3.2.0 (2020-04-15)

+
+

3.2.0 (2020-04-15)

  • Support for optional injection in declarative fashion: Autowired(Optional[...])

-
-

3.1.4 (2020-04-15)

+
+

3.1.4 (2020-04-15)

  • Fix Autowired(List[...]) not working with qualifiers

-
-

3.1.3 (2020-04-15)

+
+

3.1.3 (2020-04-15)

  • Fix Windows injectables not being loaded.

-
-

3.1.2 (2020-04-14)

+
+

3.1.2 (2020-04-14)

  • Remove unused inspect imports.

-
-

3.1.1 (2020-04-13)

+
+

3.1.1 (2020-04-13)

  • Fix bug of scanning the same module more than once when InjectionContainer.load() is called multiple times with different relative search paths.

-
-

3.1.0 (2020-04-13)

+
+

3.1.0 (2020-04-13)

  • Added @injectable_factory decorator for declaring injectable factory methods

  • Include the console output in the examples

-
-

3.0.1 (2020-04-13)

+
+

3.0.1 (2020-04-13)

  • Fix package content missing

-
-

3.0.0 (2020-04-12)

+
+

3.0.0 (2020-04-12)

@@ -127,7 +127,7 @@

Navigation

diff --git a/docs/index.html b/docs/index.html index 6e61803..0b490ec 100644 --- a/docs/index.html +++ b/docs/index.html @@ -5,7 +5,7 @@ - Contents — injectable 4.0.0 documentation + Contents — injectable 4.0.1 documentation @@ -30,7 +30,7 @@

Navigation

@@ -88,34 +88,35 @@

ContentsContributing
  • Authors
  • Changelog
  • @@ -189,7 +190,7 @@

    Navigation

    diff --git a/docs/installation.html b/docs/installation.html index c588c4f..b6e9232 100644 --- a/docs/installation.html +++ b/docs/installation.html @@ -5,7 +5,7 @@ - Installation — injectable 4.0.0 documentation + Installation — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -117,7 +117,7 @@

    Navigation

    diff --git a/docs/objects.inv b/docs/objects.inv index 9764b03..5f0e9f1 100644 Binary files a/docs/objects.inv and b/docs/objects.inv differ diff --git a/docs/py-modindex.html b/docs/py-modindex.html index 16404ac..d3440b3 100644 --- a/docs/py-modindex.html +++ b/docs/py-modindex.html @@ -4,7 +4,7 @@ - Python Module Index — injectable 4.0.0 documentation + Python Module Index — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -215,7 +215,7 @@

    Navigation

    diff --git a/docs/readme.html b/docs/readme.html index e104fed..848e83f 100644 --- a/docs/readme.html +++ b/docs/readme.html @@ -5,7 +5,7 @@ - Injectable: Dependency Injection for Humans™ — injectable 4.0.0 documentation + Injectable: Dependency Injection for Humans™ — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -78,8 +78,8 @@

    Navigation

    -
    from injectable import Autowired, autowired
    -from typing import List
    +
    from typing import Annotated, List
    +from injectable import Autowired, autowired
     from models import Database
     from messaging import Broker
     
    @@ -87,8 +87,8 @@ 

    Navigation

    @autowired def __init__( self, - database: Autowired(Database), - message_brokers: Autowired(List[Broker]), + database: Annotated[Database, Autowired], + message_brokers: Annotated[List[Broker], Autowired], ): pending = database.get_pending_messages() for broker in message_brokers: @@ -140,7 +140,8 @@

    Features you’ll love ❤️@injectable will be automatically discovered and ready for injection.

  • Qualifier overloading: declare as many injectables as you like for a single qualifier or extending the same base class. You can inject all of them just by -specifying a typing.List to Autowired: deps: Autowired(List["qualifier"]).

  • +specifying a typing.List to Autowired: +deps: Annotated[List["qualifier"], Autowired].

  • Transparent lazy initialization: passing the argument lazy=True for Autowired will make your dependency to be initialized only when actually used, all in a transparent fashion.

  • @@ -148,7 +149,7 @@

    Features you’ll love ❤️@injectable(namespace="foo") and then just use them when annotating your -parameters as in dep: Autowired(..., namespace="foo").

    +parameters as in dep: Annotated[..., Autowired(namespace="foo")].

  • Linters friendly: Autowired is carefully designed to comply with static linter analysis such as PyCharm’s to preserve the parameter original type hint.

  • @@ -221,7 +222,7 @@

    Navigation

    diff --git a/docs/reference/index.html b/docs/reference/index.html index 8a1ff6a..7d4c6cb 100644 --- a/docs/reference/index.html +++ b/docs/reference/index.html @@ -5,7 +5,7 @@ - Reference — injectable 4.0.0 documentation + Reference — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -127,7 +127,7 @@

    Navigation

    diff --git a/docs/reference/injectable.html b/docs/reference/injectable.html index 8c32c79..dbcd5d4 100644 --- a/docs/reference/injectable.html +++ b/docs/reference/injectable.html @@ -5,7 +5,7 @@ - injectable — injectable 4.0.0 documentation + injectable — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -182,7 +182,7 @@

    injectable
    -injectable.autowired(func: injectable.autowiring.autowired_decorator.T) injectable.autowiring.autowired_decorator.T[source]
    +injectable.autowired(func: Callable[[...], injectable.autowiring.autowired_decorator.R]) Callable[[...], injectable.autowiring.autowired_decorator.R][source]

    Function decorator to setup dependency injection autowiring.

    Only parameters annotated with Autowired will be autowired for injection.

    @@ -510,7 +510,7 @@

    Navigation

    diff --git a/docs/reference/injectable_constants.html b/docs/reference/injectable_constants.html index bb8d873..28e83c5 100644 --- a/docs/reference/injectable_constants.html +++ b/docs/reference/injectable_constants.html @@ -5,7 +5,7 @@ - injectable.constants — injectable 4.0.0 documentation + injectable.constants — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -126,7 +126,7 @@

    Navigation

    diff --git a/docs/reference/injectable_errors.html b/docs/reference/injectable_errors.html index 484cf21..a3897bb 100644 --- a/docs/reference/injectable_errors.html +++ b/docs/reference/injectable_errors.html @@ -5,7 +5,7 @@ - injectable.errors — injectable 4.0.0 documentation + injectable.errors — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -133,7 +133,7 @@

    Navigation

    diff --git a/docs/reference/injectable_testing.html b/docs/reference/injectable_testing.html index 8c8df9e..daf443b 100644 --- a/docs/reference/injectable_testing.html +++ b/docs/reference/injectable_testing.html @@ -5,7 +5,7 @@ - injectable.testing — injectable 4.0.0 documentation + injectable.testing — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -215,7 +215,7 @@

    Navigation

    diff --git a/docs/searchindex.js b/docs/searchindex.js index b0486c5..e5c0d67 100644 --- a/docs/searchindex.js +++ b/docs/searchindex.js @@ -1 +1 @@ -Search.setIndex({docnames:["authors","caveats","changelog","contributing","index","installation","readme","reference/index","reference/injectable","reference/injectable_constants","reference/injectable_errors","reference/injectable_testing","usage/TLDR","usage/annotated_usage","usage/basic_usage","usage/cyclic_dependency","usage/dependencies_precedence","usage/factory","usage/index","usage/injectable_mocking_for_tests","usage/injecting_existing_instance","usage/injection_container_resetting_for_tests","usage/lazy_injection","usage/namespaces","usage/optional_injection","usage/qualifier_overloading","usage/service_locator","usage/singletons"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":5,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.intersphinx":1,"sphinx.ext.todo":2,"sphinx.ext.viewcode":1,sphinx:56},filenames:["authors.rst","caveats.rst","changelog.rst","contributing.rst","index.rst","installation.rst","readme.rst","reference/index.rst","reference/injectable.rst","reference/injectable_constants.rst","reference/injectable_errors.rst","reference/injectable_testing.rst","usage/TLDR.rst","usage/annotated_usage.rst","usage/basic_usage.rst","usage/cyclic_dependency.rst","usage/dependencies_precedence.rst","usage/factory.rst","usage/index.rst","usage/injectable_mocking_for_tests.rst","usage/injecting_existing_instance.rst","usage/injection_container_resetting_for_tests.rst","usage/lazy_injection.rst","usage/namespaces.rst","usage/optional_injection.rst","usage/qualifier_overloading.rst","usage/service_locator.rst","usage/singletons.rst"],objects:{"":[[8,0,0,"-","injectable"]],"examples.annotated_usage":[[13,0,0,"-","annotated_usage_example"]],"examples.basic_usage":[[14,0,0,"-","basic_usage_example"]],"examples.cyclic_dependency":[[15,0,0,"-","cyclic_dependency_example"]],"examples.dependencies_precedence":[[16,0,0,"-","dependencies_precedence_example"]],"examples.factory":[[17,0,0,"-","factory_example"]],"examples.injectable_mocking_for_tests":[[19,0,0,"-","injectable_mocking_example"]],"examples.injecting_existing_instance":[[20,0,0,"-","injecting_existing_instance_example"]],"examples.injection_container_resetting_for_tests":[[21,0,0,"-","injection_container_resetting_example"]],"examples.lazy_injection":[[22,0,0,"-","lazy_injection_example"]],"examples.namespaces":[[23,0,0,"-","namespaces_example"]],"examples.optional_injection":[[24,0,0,"-","optional_injection_example"]],"examples.qualifier_overloading":[[25,0,0,"-","qualifier_overloading_example"]],"examples.service_locator":[[26,0,0,"-","service_locator_example"]],"examples.singletons":[[27,0,0,"-","singleton_example"]],"examples.tldr":[[12,0,0,"-","tldr_example"]],"injectable.InjectionContainer":[[8,2,1,"","load"]],"injectable.constants":[[9,4,1,"","DEFAULT_NAMESPACE"]],"injectable.errors":[[10,5,1,"","AutowiringError"],[10,5,1,"","InjectionError"]],"injectable.testing":[[11,3,1,"","clear_injectables"],[11,3,1,"","register_injectables"],[11,3,1,"","reset_injection_container"]],injectable:[[8,1,1,"","Autowired"],[8,1,1,"","Injectable"],[8,1,1,"","InjectionContainer"],[8,3,1,"","autowired"],[9,0,0,"-","constants"],[10,0,0,"-","errors"],[8,3,1,"","inject"],[8,3,1,"","inject_multiple"],[8,3,1,"","injectable"],[8,3,1,"","injectable_factory"],[8,3,1,"","load_injection_container"],[11,0,0,"-","testing"]]},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","function","Python function"],"4":["py","data","Python data"],"5":["py","exception","Python exception"]},objtypes:{"0":"py:module","1":"py:class","2":"py:method","3":"py:function","4":"py:data","5":"py:exception"},terms:{"0":[4,8,11,26],"02":4,"03":4,"04":4,"05":4,"06":[4,23],"07":4,"08":4,"09":4,"1":[4,26],"10":4,"11":4,"12":4,"13":4,"14":4,"15":4,"151":23,"19":4,"2":[4,16,26],"20":4,"2018":4,"2020":4,"2021":4,"2024":4,"22":4,"23":4,"24":4,"29":4,"3":[4,8,11],"38":23,"4":[4,8,11,16],"42":[11,20],"5":4,"593":2,"6":[4,16],"7":4,"8":[2,8,16],"9007":1,"94":23,"abstract":[16,25],"break":2,"case":[1,3,8,13,17],"class":[1,2,6,8,11,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],"default":[2,8,9,11,14,22,23],"do":[1,3,21,22],"final":14,"function":[1,2,6,8,10,11,17,19,20,21],"import":[2,4,6,8,11,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],"long":11,"new":[8,11],"public":8,"return":[2,8,11,13,14,15,17,20,23,26],"static":[2,6],"true":[6,8,11,13,15,16,22,26,27],"try":21,"while":[3,22,24],A:[15,17,27],As:1,At:[5,8,11],By:23,For:[4,11,12,13,15,18,20],If:[1,3,8,16],In:[13,14,15,16,17,19,20,22,23,24,25,26,27],It:8,No:21,One:8,The:[1,8,11,12,13,14,15,16,17,20,22,23,24,25,26],Then:[1,23],These:6,To:23,Will:8,__init__:[6,8,12,13,14,15,16,17,19,20,22,23,24,25,26,27],__main__:[12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],__name__:[12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],__qualname__:1,_global:2,_name:13,_state:[14,26],_statement:13,abc:[6,16,25],about:[3,25],absolut:[1,8],abstract_servic:16,abstract_service_1:16,abstract_service_2:16,abstractmethod:[16,25],abstractservic:[8,16],accept:[2,8],access:15,action:8,actual:[6,17,22],ad:2,add:[2,3,8],address:8,advantag:25,after:8,against:2,airflow:1,alias:1,all:[1,6,8,11,14,16,17,21,24,25],all_basic_service_implement:26,allow:2,alreadi:[8,11,20],also:[8,13,16,17,20,22,23,25],ambigu:[8,16],among:8,an:[1,3,6,8,12,13,15,16,17,19,20,21,22,23,24,26,27],analysi:6,ani:[1,3,8,21,23,24],annot:[2,4,6,8,14,18,26],annotated_usag:13,annotated_usage_exampl:13,annotatedusag:13,anoth:1,another_basic_servic:14,api:[8,26],app:20,appli:8,applic:[1,3,20],ar:[1,2,3,6,8,14,15,16,21,22,23,25],aren:[8,24],arg:2,argument:[2,6,8,23,24],assert_cal:19,assertionrewritinghook:1,assign:[8,20,23],attempt:8,attribut:[1,15,16],attributeerror:1,author:[4,6],auto:3,automat:[4,6,8],autowir:[2,6,8,10,12,13,14,15,16,17,19,20,21,22,23,24,25,27],autowired_decor:8,autowired_typ:8,autowiringerror:[8,10],b:[15,16],bar:[8,14,21,24],base:[6,8,11,16,25,26],basic:[4,12,13,18,26],basic_servic:14,basic_usag:14,basic_usage_exampl:14,basicservic:14,basicusag:14,befor:[8,19,21],behav:27,behavior:14,behind:14,being:[1,2,8,21,22,27],beta:2,better:[3,12],between:27,black:3,bool:[8,11],both:[16,22,23,24,27],branch:3,brief:3,broker:6,bug:2,built:6,builtin:[1,2],bunch_of_servic:24,call:[2,6,8,19,21,22],callabl:8,caller:[2,8],can:[1,2,6,8,12,13,15,17,19,20,21,22,23,27],cannot:[8,17,23],carefulli:6,caus:1,caveat:4,chang:[2,11,27],changelog:4,check:[1,3,6],circular:[15,22],cl:8,clarifi:3,classmethod:8,clear:[3,8,11,21],clear_inject:[11,19],client1:27,client2:27,client:17,client_endpoint:17,client_endpoint_example_env_var:17,client_factori:17,code:[1,2,3,17],collect:[8,11],com:[0,1,8],combin:[1,16],command:5,comment:3,common:17,complet:14,complex:2,compli:[2,6,13],concret:25,conflict:23,conjunct:8,connect:[17,27],consol:2,constant:[4,7,8,11],constructor:[2,8,11],contain:[1,2,4,8,10,11,18],content:2,contribut:4,conveni:13,cool:6,corner:1,correct:8,craig:0,craigminihan:0,crash:2,creat:[2,8,25],cryptic:3,current:1,custom:[8,10],cyclic:[4,18,22],cyclic_dependency_exampl:15,cyclicdepend:15,dag:1,databas:6,david:0,deal:[15,17,22],declar:[1,2,6,8,13,14,16,17,22,23,24,25,26,27],decor:[1,2,6,8,14,17,20,26],def:[6,8,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],default_measuring_servic:23,default_namespac:[2,8,9,11],defin:[8,11,27],demonstr:14,dep:[6,8,12,19],dep_a:8,dep_b:8,dep_c:8,depend:[2,4,8,10,11,13,14,18,19,22,24,25,26,27],dependencies_preced:16,dependencies_precedence_exampl:16,dependenciespreced:16,dependency_nam:10,deprec:[2,8],describ:[1,26],descript:3,design:[6,8],detail:[13,15,22,23,26],dev:1,develop:6,differ:[2,6,8,16,23],direct:8,directli:[1,8,13,26],directori:8,discourag:3,discov:[6,8],discoveri:[4,6],do_someth:21,doc:6,docstr:3,document:[2,3],doe:[2,8,22],doesn:2,dr:[4,18],drop:2,due:8,dummi:17,duplic:[2,8],dure:1,e:[8,21,22],each:[1,14,15,16,23],earth_to_sun_dist:23,eas:[2,11],easier:15,effect:1,either:[1,8],eleg:6,email:25,email_sender_servic:25,emailsenderservic:25,empti:[2,8,21,24],enabl:[2,15],encod:[2,8],encourag:3,end:25,endpoint:17,ensur:3,entangl:2,environ:2,error:[4,7,8,16,21],everi:27,exampl:[2,3,4,6,8,11,12],except:[10,21],exclud:8,exclude_group:[8,25],execut:[1,8],exhaust:1,exist:[2,4,17,18],expect:24,explicit:16,explicitli:[8,16],expos:16,extend:[6,13],extended_servic:13,extendedservic:13,extern:17,external_cli:17,externalcli:17,f:[13,16,17,25],factori:[2,4,8,18,20],factory_exampl:17,fail:[1,2,10,16,24],fall:15,fallback:13,fallback_servic:13,fallbackservic:13,fals:[8,11,27],fashion:[2,6],favor:2,fax:25,fax_sender_servic:25,faxsenderservic:25,featur:4,feedback:3,few:6,file:[1,2,8,11,12],filter:[8,25],finish:22,first:[1,2,8,13,23],fix:2,follow:[1,3],foo:[6,8,11,12,14,21,24],foo_factori:8,fork:3,form:3,format:3,found:[8,24],four:1,framework:[6,12,14,15,23,26],friendli:6,from:[1,2,6,8,11,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],func:8,futur:8,g:8,gener:[2,8],get:[16,19,24],get_cod:1,get_pending_messag:6,get_repository_st:[14,26],get_some_property_from_a:15,get_some_property_from_b:15,getenv:17,github:[0,1],given:[8,11],global:8,good:12,grasp:14,group:[2,8,25],guidelin:3,ha:[1,23],happen:[2,25],hard:3,have:[14,15,16,17,20,23],heart:6,hello:[13,25],high:26,hint:[2,6,13],how:[8,11,13,14,15,16,17,19,20,21,22,23,24,25,26,27],http:[0,1,17],human:4,i:[8,22],idea:14,identifi:8,illustr:[14,23,26],illustrativeexampl:12,implement:[1,16,25],imposs:[1,8],includ:[2,3,21],inclus:11,incompat:1,independ:[14,23],index:4,indic:[8,10,16],infer:2,inform:8,inherit:[13,26],init:22,initi:[2,6,8,20],inject:[1,2,4,5,7,12,13,14,15,16,17,18,23,25,26,27],inject_multipl:[2,8,26],injectable_decor:8,injectable_factori:[1,2,8,17,20],injectable_factory_decor:[8,17],injectable_mocking_exampl:19,injectableloaderror:8,injectablemock:19,injecting_existing_inst:20,injecting_existing_instance_exampl:20,injectingexistinginst:20,injection_container_resetting_exampl:21,injectioncontain:[2,8],injectioncontainerreset:21,injectionerror:[8,10,21,24],insid:[8,26],inspect:2,inspir:1,instal:[2,4],instanc:[4,6,8,14,16,17,18,24,25,27],instanti:[2,8,15,17,22,27],instead:[2,8,14,15,16,24],internationalmeasuringservic:23,intl:23,intl_measuring_servic:23,invoc:8,invok:[8,15,22],isinst:1,isn:8,issu:[1,3],its:[15,23,27],itself:[1,3,8],just:[6,16,20,24],kafkaproduc:6,keep:3,kind:3,klass:11,km:23,know:17,known:1,kulej:0,label:25,lambda:[11,17,19,20],last:[8,23],lazi:[2,4,6,8,15,18],lazili:22,lazy_inject:22,lazy_injection_exampl:22,lazy_object_proxi:2,lazyinject:22,lead:1,learn:[15,25],least:[8,11],level:[1,8,26],leverag:22,librari:1,licens:6,like:[6,13,17],line:5,linter:[3,6,13],list:[1,2,6,8,24,25],ll:[4,13,14,15,16,17,20,22,23,24,25,26,27],load:[1,2,8],load_injection_contain:[2,6,8,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],locat:[2,4,18],log:8,logic:17,look:[1,8,12],lookup:8,loop:15,love:4,low:[8,26],lozano:0,lozanocampillod:0,maco:2,made:[8,21,27],magic:[3,8],mai:[1,3,24],make:[2,3,6,8,14,15,19,21],manag:8,mani:6,manual:11,mark:[2,8],master:3,match:[8,10,21,25],meant:8,measuring_servic:23,messag:[6,25],message_brok:6,metadata:13,method:[2,8,14,15,16,22,24,26],mile:23,million:23,mind:3,minihan:0,minor:2,miss:2,mock:[2,4,11,18],mocked_dep:19,mocked_inject:19,mockeddep:19,model:6,modifi:15,modul:[1,2,4,8],more:[2,8,25],move:1,mt3o:0,multipl:[2,8,25],multipleservic:16,multipli:16,multiply_servic:16,multiplyservic:16,must:[1,8],name:[1,2],namespac:[2,4,6,8,9,11,13,18,21],namespaces_exampl:23,necessari:[8,17],need:[3,8,11,19,22],never:[1,8,19],nevertheless:3,non:[1,8],none:[8,10,11,14,23,24,26],now:[16,17,20,22],number:20,object:1,occurr:1,offici:2,often:3,ok:24,old:25,oliv:0,oliveira:0,omit:13,onc:[2,8,27],one:[1,8,11,13,14,15,16,19,21,23,24,27],ones:[8,23],onli:[6,8,15,22,23,27],open:[2,3],oper:1,option:[2,4,8,11,18,23],optional_injection_exampl:24,optionalinject:24,organ:3,origin:6,os:17,other:[1,8,12,14,15,23,25,27],otherwis:11,our:[6,14,15,16,17,20,22,23,24,25,26,27],out:[6,8,25],outermost:24,output:2,outsid:[1,8],over:26,overload:[4,6,13,16,18,24,26],own:23,packag:[2,6],page:4,paramet:[2,6,8,11,13,22,23,25,27],parenthesi:[2,8,13],particular:23,pass:[6,8,26],path:[1,2,6,8],pend:6,pep:2,perform:8,pip:[2,5],place:[8,27],posit:8,possibl:[1,2,13,15],potenti:1,preced:[4,18,25],prefer:26,present:[8,24],preserv:6,prevent:[8,15],previou:[2,8],previous:8,primari:[8,13,16,24,26],primary_basic_servic:26,print:[12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],project:[3,6,8],propag:[11,25],properti:[13,14,15,26],provid:[2,11],pull:3,purpos:[8,11],py:[12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],pycharm:6,pytest:4,python:[1,2,8,12],qualifi:[2,4,6,8,11,13,15,16,18,23,24,26],qualifier_overload:25,qualifier_overloading_exampl:25,qualifieroverload:25,quirk:2,rais:[2,8,10,11,16],re:25,read:[1,8],readabl:3,readi:6,realdep:19,reason:[1,8,17,20],receiv:[3,8,24],recipi:25,recommend:8,record:11,recurs:[1,11],refactor:2,refer:[4,6,15,22],reflect:27,regard:[8,25],regardless:8,regist:[1,2,8,9,11,15,19,21,23],register_inject:[2,11,19],registri:[8,23],registry_typ:10,regular:[1,20],rel:[2,4,8],releas:2,remov:[2,8],render:1,repositori:[3,14,26],repres:17,request:[3,8],requir:2,reset:[4,11,18],reset_injection_contain:[2,11,21],resili:2,resolut:[8,25],resolv:[2,8,16,23,24,25],respect:[8,23],respons:17,review:3,right:22,rodrigo:0,roo:0,root:[6,21],run:[1,2,3,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],run_exampl:[12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],s:[1,2,3,6,8,14,26],sai:13,same:[1,2,6,8,22,25,27],sample_servic:26,sampleservic:26,satisfi:24,scan:[2,8,11],search:[1,2,4,8,9],search_path:8,section:[8,11,12],see:[13,16,17,20,22,23,24,26,27],self:[6,8,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],send:25,send_messag:25,send_pend:6,sender_servic:25,senderservic:25,separ:13,sequenc:8,servic:[2,4,6,8,13,14,15,18,25],service_a:[15,22],service_b:[15,22],service_loc:26,service_locator_exampl:26,servicea:[15,22],serviceb:[15,22],serviceloc:26,set:[2,10,11,14],set_repository_st:[14,26],setter:[14,26],setup:8,shall:[8,24],share:[6,8,14,27],should:8,shouldn:8,show:[11,13,14,16,17,20,24,25],side:1,side_effect:19,signatur:2,simpl:[6,13],simple_servic:13,simpler:17,simpleservic:13,simpli:24,sinc:[8,16,19],singl:[6,12,23,25],singleton:[4,6,8,14,18],singleton_cli:27,singleton_exampl:27,singletoncli:27,situat:[13,24],sm:25,sms_sender_servic:25,smssenderservic:25,so:[1,3,13,17,20,24],some:[1,15,17,24],some_properti:15,some_servic:24,someth:[21,22],sourc:[8,10,11],speak:[3,13],specialized_servic:26,specializedservic:26,specif:8,specifi:[6,8,11,16,22,23],sqsproduc:6,stabl:2,start:[12,22],state:[11,14,21,26,27],stateful_repositori:[14,26],statefulrepositori:[14,26],statefulservic:14,staticmethod:19,step:1,still:8,store:8,str:[8,10,11,17,25],straightforward:12,string:[1,2,8,15],style:3,submit:3,success:8,successfulli:23,suit:2,suitabl:2,sum:16,sum_servic:16,sumservic:16,suppli:20,support:2,sure:[8,21],system:1,t:[1,2,8,11,16,19,24],take:25,teodor:0,test:[1,2,3,4,6,7,8,18],than:[1,2,3,8],thei:[14,22,27],them:[6,15,23],themselv:8,therefor:23,thi:[1,3,8,11,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],thoroughli:3,those:1,though:[8,16,19,24],three:[23,25],through:[1,2,17],time:[2,8,22],tl:[4,18],tldr_exampl:12,ton:2,trail:8,transpar:6,trial:2,tricki:3,turn:[14,20,26,27],twice:1,two:[14,23,25,27],type:[1,2,6,8,11,13,14,23,24,25],typeerror:2,ubuntu:2,unabl:8,under:8,understand:12,unintend:1,union:[8,11],uniqu:8,unique_id:8,unit:[2,3],unitedstatesmeasuringservic:23,unittest:19,unless:11,unus:2,up:25,us:[1,2,3,6,8,9,11,13,14,15,16,17,19,20,21,23,24,25,26,27],us_measuring_servic:23,usag:[1,2,4,6,8,11,12,26],user:2,utf:[2,8],util:[2,8,11,19,21],uuid:8,valid:8,valu:[8,14,24,26],valueerror:11,variabl:20,varieti:8,version:[2,8,11],wa:[8,16,19,27],wai:[3,22],want:[3,24],warn:[8,21],wasn:[8,16],we:[14,15,16,17,19,20,22,23,24,25,26,27],welcom:3,well:[3,16],were:[23,25],what:[3,23,24],whatev:20,when:[2,6,8,11,13,15,16,22,24,25,27],whenev:27,where:8,which:[2,8,11,14,15,16,17,20,22,24,26,27],window:2,wire:8,without:[2,8,13,17,23],won:[1,11,24],work:[1,2,13,15,22,23,24,25,26],workaround:1,world:25,would:16,wouldn:19,wrap:[8,17,19],write:3,wrote:3,yet:2,you:[3,4,12,13,14,15,16,17,20,22,23,24,25,26,27],your:[3,6,17]},titles:["Authors","Caveats","Changelog","Contributing","Contents","Installation","Injectable: Dependency Injection for Humans\u2122","Reference","injectable","injectable.constants","injectable.errors","injectable.testing","TL;DR","Annotated Usage Example","Basic Usage Example","Cyclic Dependency Example","Dependencies Precedence Example","Factory Example","Usage Examples","Injectable Mocking For Tests Example","Injecting Existing Instance Example","Injection Container Resetting For Tests Example","Lazy Injection Example","Namespaces Example","Optional Injection Example","Qualifier Overloading Example","Service Locator Example","Singletons Example"],titleterms:{"0":2,"02":2,"03":2,"04":2,"05":2,"06":2,"07":2,"08":2,"09":2,"1":2,"10":2,"11":2,"12":2,"13":2,"14":2,"15":2,"19":2,"2":2,"20":2,"2018":2,"2020":2,"2021":2,"2024":2,"22":2,"23":2,"24":2,"29":2,"3":2,"4":2,"5":2,"6":2,"7":2,"import":1,For:[19,21],annot:13,author:0,automat:1,basic:14,caveat:1,changelog:2,constant:9,contain:21,content:4,contribut:3,cyclic:15,depend:[1,6,15,16],discoveri:1,dr:12,error:10,exampl:[13,14,15,16,17,18,19,20,21,22,23,24,25,26,27],exist:20,factori:17,featur:6,human:6,indic:4,inject:[6,8,9,10,11,19,20,21,22,24],instal:5,instanc:20,lazi:22,ll:6,locat:26,love:6,mock:19,namespac:23,option:24,overload:25,preced:16,pytest:1,qualifi:25,refer:7,rel:1,reset:21,servic:26,singleton:27,tabl:4,test:[11,19,21],tl:12,usag:[13,14,18],you:6}}) \ No newline at end of file +Search.setIndex({docnames:["authors","caveats","changelog","contributing","index","installation","readme","reference/index","reference/injectable","reference/injectable_constants","reference/injectable_errors","reference/injectable_testing","usage/TLDR","usage/annotated_usage","usage/basic_usage","usage/cyclic_dependency","usage/dependencies_precedence","usage/factory","usage/index","usage/injectable_mocking_for_tests","usage/injecting_existing_instance","usage/injection_container_resetting_for_tests","usage/lazy_injection","usage/namespaces","usage/optional_injection","usage/qualifier_overloading","usage/service_locator","usage/singletons"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":5,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.intersphinx":1,"sphinx.ext.todo":2,"sphinx.ext.viewcode":1,sphinx:56},filenames:["authors.rst","caveats.rst","changelog.rst","contributing.rst","index.rst","installation.rst","readme.rst","reference/index.rst","reference/injectable.rst","reference/injectable_constants.rst","reference/injectable_errors.rst","reference/injectable_testing.rst","usage/TLDR.rst","usage/annotated_usage.rst","usage/basic_usage.rst","usage/cyclic_dependency.rst","usage/dependencies_precedence.rst","usage/factory.rst","usage/index.rst","usage/injectable_mocking_for_tests.rst","usage/injecting_existing_instance.rst","usage/injection_container_resetting_for_tests.rst","usage/lazy_injection.rst","usage/namespaces.rst","usage/optional_injection.rst","usage/qualifier_overloading.rst","usage/service_locator.rst","usage/singletons.rst"],objects:{"":[[8,0,0,"-","injectable"]],"examples.annotated_usage":[[13,0,0,"-","annotated_usage_example"]],"examples.basic_usage":[[14,0,0,"-","basic_usage_example"]],"examples.cyclic_dependency":[[15,0,0,"-","cyclic_dependency_example"]],"examples.dependencies_precedence":[[16,0,0,"-","dependencies_precedence_example"]],"examples.factory":[[17,0,0,"-","factory_example"]],"examples.injectable_mocking_for_tests":[[19,0,0,"-","injectable_mocking_example"]],"examples.injecting_existing_instance":[[20,0,0,"-","injecting_existing_instance_example"]],"examples.injection_container_resetting_for_tests":[[21,0,0,"-","injection_container_resetting_example"]],"examples.lazy_injection":[[22,0,0,"-","lazy_injection_example"]],"examples.namespaces":[[23,0,0,"-","namespaces_example"]],"examples.optional_injection":[[24,0,0,"-","optional_injection_example"]],"examples.qualifier_overloading":[[25,0,0,"-","qualifier_overloading_example"]],"examples.service_locator":[[26,0,0,"-","service_locator_example"]],"examples.singletons":[[27,0,0,"-","singleton_example"]],"examples.tldr":[[12,0,0,"-","tldr_example"]],"injectable.InjectionContainer":[[8,2,1,"","load"]],"injectable.constants":[[9,4,1,"","DEFAULT_NAMESPACE"]],"injectable.errors":[[10,5,1,"","AutowiringError"],[10,5,1,"","InjectionError"]],"injectable.testing":[[11,3,1,"","clear_injectables"],[11,3,1,"","register_injectables"],[11,3,1,"","reset_injection_container"]],injectable:[[8,1,1,"","Autowired"],[8,1,1,"","Injectable"],[8,1,1,"","InjectionContainer"],[8,3,1,"","autowired"],[9,0,0,"-","constants"],[10,0,0,"-","errors"],[8,3,1,"","inject"],[8,3,1,"","inject_multiple"],[8,3,1,"","injectable"],[8,3,1,"","injectable_factory"],[8,3,1,"","load_injection_container"],[11,0,0,"-","testing"]]},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","function","Python function"],"4":["py","data","Python data"],"5":["py","exception","Python exception"]},objtypes:{"0":"py:module","1":"py:class","2":"py:method","3":"py:function","4":"py:data","5":"py:exception"},terms:{"0":[4,8,11,26],"02":4,"03":4,"04":4,"05":4,"06":[4,23],"07":4,"08":4,"09":4,"1":[4,26],"10":4,"11":4,"12":4,"13":4,"14":4,"15":4,"151":23,"19":4,"2":[4,16,26],"20":4,"2018":4,"2020":4,"2021":4,"2024":4,"22":4,"23":4,"24":4,"29":4,"3":[4,8,11],"31":4,"38":23,"4":[4,8,11,16],"42":[11,20],"5":4,"593":2,"6":[4,16],"7":4,"8":[2,8,16],"9007":1,"94":23,"abstract":[16,23,25],"break":2,"case":[1,3,8,13,17],"class":[1,2,6,8,11,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],"default":[2,8,9,11,14,22,23,24],"do":[1,3,21,22],"final":14,"function":[1,2,6,8,10,11,17,19,20,21],"import":[2,4,6,8,11,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],"long":11,"new":[8,11],"public":8,"return":[2,8,11,13,14,15,17,20,23,26],"static":[2,6],"true":[6,8,11,13,15,16,22,26,27],"try":21,"while":[3,22,24],A:[15,17,27],As:1,At:[5,8,11],But:24,By:23,For:[4,11,12,13,15,18,20],If:[1,3,8,16],In:[13,14,15,16,17,19,20,22,23,24,25,26,27],It:8,No:21,One:8,The:[1,8,11,12,13,14,15,16,17,20,22,23,24,25,26],Then:[1,23],These:6,To:23,Will:8,__init__:[6,8,12,13,14,15,16,17,19,20,22,23,24,25,26,27],__main__:[12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],__name__:[12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],__qualname__:1,_global:2,_name:13,_state:[14,26],_statement:13,abc:[6,16,23,25],about:[3,25],absolut:[1,8],abstract_servic:16,abstract_service_1:16,abstract_service_2:16,abstractmethod:[16,25],abstractservic:[8,16],accept:[2,8],access:15,action:8,actual:[6,17,22],ad:2,add:[2,3,8],address:8,advantag:25,after:8,against:2,airflow:1,alias:1,all:[1,6,8,11,14,16,17,21,24,25],all_basic_service_implement:26,allow:2,alreadi:[8,11,20],also:[8,13,15,16,17,20,22,23,25],ambigu:[8,16],among:8,an:[1,3,6,8,12,13,15,16,17,19,20,21,22,23,24,26,27],analysi:6,ani:[1,3,8,21,23,24],annot:[2,4,6,8,14,16,17,18,19,20,21,22,23,24,25,26,27],annotated_usag:13,annotated_usage_exampl:13,annotatedusag:13,anoth:1,another_basic_servic:14,api:[8,26],app:20,appli:8,applic:[1,3,20],ar:[1,2,3,6,8,14,15,16,21,22,23,24,25],aren:[8,24],arg:2,argument:[2,6,8,23],assert_cal:19,assertionrewritinghook:1,assign:[8,20,23],attempt:8,attribut:[1,15,16],attributeerror:1,author:[4,6],auto:3,automat:[4,6,8],autowir:[2,6,8,10,12,13,14,15,16,17,19,20,21,22,23,24,25,27],autowired_decor:8,autowired_typ:8,autowiringerror:[8,10],avoid:15,b:[15,16],bar:[8,14,21],base:[6,8,11,16,23,25,26],basic:[4,12,13,18,26],basic_servic:14,basic_usag:14,basic_usage_exampl:14,basicservic:14,basicusag:14,befor:[8,19,21],behav:27,behavior:14,behind:14,being:[1,2,8,21,22,27],beta:2,better:[3,12],between:27,black:3,bool:[8,11],both:[16,22,23,24,27],branch:3,brief:3,broker:6,bug:2,built:6,builtin:[1,2],bunch_of_optional_servic:24,bunch_of_servic:[],call:[2,6,8,19,21,22],callabl:8,caller:[2,8],can:[1,2,6,8,12,13,15,17,19,20,21,22,23,27],cannot:[8,17,23],carefulli:6,caus:[1,2],caveat:4,chang:[2,11,27],changelog:4,check:[1,3,6],checker:2,circular:[15,22],cl:8,clarifi:3,classmethod:8,clear:[3,8,11,21],clear_inject:[11,19],client1:27,client2:27,client:17,client_endpoint:17,client_endpoint_example_env_var:17,client_factori:17,code:[1,2,3,17],collect:[8,11],com:[0,1,8],combin:[1,16],command:5,comment:3,common:17,complet:[13,14],complex:2,compli:[2,6,13],concret:25,conflict:23,conjunct:8,connect:[17,27],consol:2,constant:[4,7,8,11],constructor:[2,8,11],contain:[1,2,4,8,10,11,18],content:2,contribut:4,conveni:13,cool:6,corner:1,correct:8,craig:0,craigminihan:0,crash:2,creat:[2,8,15,25],cryptic:3,current:1,custom:[8,10],cyclic:[4,18,22],cyclic_dependency_exampl:15,cyclicdepend:15,dag:1,databas:6,david:0,deal:[15,17,22],declar:[1,2,6,8,13,14,15,16,17,22,23,24,25,26,27],decor:[1,2,6,8,14,17,20,26],def:[6,8,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],default_measuring_servic:23,default_namespac:[2,8,9,11],defin:[8,11,27],demonstr:14,dep:[6,8,12,19],dep_a:8,dep_b:8,dep_c:8,depend:[2,4,8,10,11,13,14,18,19,22,23,24,25,26,27],dependencies_preced:16,dependencies_precedence_exampl:16,dependenciespreced:16,dependency_nam:10,deprec:[2,8],describ:[1,26],descript:3,design:[6,8],detail:[13,15,22,23,26],dev:1,develop:6,differ:[2,6,8,16,23],direct:8,directli:[1,8,13,26],directori:8,discourag:3,discov:[6,8],discoveri:[4,6],do_someth:21,doc:6,docstr:3,document:[2,3],doe:[2,8,22],doesn:2,dr:[4,18],drop:2,due:8,dummi:17,duplic:[2,8],dure:1,e:[8,21,22],each:[1,14,15,16,23],earth_to_sun_dist:23,eas:[2,11],easier:15,effect:1,either:[1,8],eleg:6,email:25,email_sender_servic:25,emailsenderservic:25,empti:[2,8,21,24],enabl:[2,15],encod:[2,8],encourag:3,end:25,endpoint:17,ensur:3,entangl:2,environ:2,error:[4,7,8,16,21],everi:27,exampl:[2,3,4,6,8,11,12],except:[10,21],exclud:8,exclude_group:[8,25],execut:[1,8],exhaust:1,exist:[2,4,17,18],expect:24,explicit:16,explicitli:[8,16],expos:16,extend:[6,13],extended_servic:13,extended_service_2:13,extendedservic:13,extern:17,external_cli:17,externalcli:17,f:[13,16,17,25],factori:[2,4,8,18,20],factory_exampl:17,fail:[1,2,10,16,24],fall:15,fallback:13,fallback_servic:13,fallback_service_2:13,fallbackservic:13,fals:[8,11,27],fashion:[2,6],favor:2,fax:25,fax_sender_servic:25,faxsenderservic:25,featur:4,feedback:3,few:6,file:[1,2,8,11,12],filter:[8,25],finish:22,first:[1,2,8,13,23],fix:2,follow:[1,3],foo:[6,8,11,12,14,21],foo_factori:8,fork:3,form:3,format:3,found:[8,24],four:1,framework:[6,12,14,15,23,26],friendli:6,from:[1,2,6,8,11,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],func:8,futur:8,g:8,gener:[2,8],get:[16,19,24],get_cod:1,get_pending_messag:6,get_repository_st:[14,26],get_some_property_from_a:15,get_some_property_from_b:15,getenv:17,github:[0,1],given:[8,11],global:8,good:12,grasp:14,group:[2,8,25],guidelin:3,ha:[1,23],happen:[2,25],hard:3,have:[14,15,16,17,20,23],heart:6,hello:[13,25],high:26,hint:[2,6,13],how:[8,11,13,14,15,16,17,19,20,21,22,23,24,25,26,27],http:[0,1,17],human:4,i:[8,22],idea:14,identifi:8,illustr:[14,23,26],illustrativeexampl:12,implement:[1,16,23,25],imposs:[1,8],includ:[2,3,21],inclus:11,incompat:1,independ:[14,23],index:4,indic:[8,10,16],infer:2,inform:8,inherit:[13,26],init:22,initi:[2,6,8,20],inject:[1,2,4,5,7,12,13,14,15,16,17,18,23,25,26,27],inject_multipl:[2,8,26],injectable_decor:8,injectable_factori:[1,2,8,17,20],injectable_factory_decor:[8,17],injectable_mocking_exampl:19,injectableloaderror:8,injectablemock:19,injecting_existing_inst:20,injecting_existing_instance_exampl:20,injectingexistinginst:20,injection_container_resetting_exampl:21,injectioncontain:[2,8],injectioncontainerreset:21,injectionerror:[8,10,21,24],insid:[8,26],inspect:2,inspir:1,instal:[2,4],instanc:[4,6,8,14,15,16,17,18,24,25,27],instanti:[2,8,15,17,22,27],instead:[2,8,14,15,16,24],internationalmeasuringservic:23,intl:23,intl_measuring_servic:23,invoc:8,invok:[8,15,22],isinst:1,isn:8,issu:[1,2,3],its:[15,23,27],itself:[1,3,8],just:[6,16,20,24],kafkaproduc:6,keep:3,kind:3,klass:11,km:23,know:17,known:1,kulej:0,label:25,lambda:[11,17,19,20],last:[8,23],lazi:[2,4,6,8,15,18],lazili:22,lazy_inject:22,lazy_injection_exampl:22,lazy_object_proxi:2,lazyinject:22,lead:1,learn:[15,25],least:[8,11],level:[1,8,26],leverag:22,librari:1,licens:6,like:[6,13,17],line:5,linter:[3,6,13],list:[1,2,6,8,24,25],ll:[4,13,14,15,16,17,20,22,23,24,25,26,27],load:[1,2,8],load_injection_contain:[2,6,8,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],locat:[2,4,18],log:8,logic:17,look:[1,8,12],lookup:8,loop:15,love:4,low:[8,26],lozano:0,lozanocampillod:0,maco:2,made:[8,21,27],magic:[3,8],mai:[1,3,24],make:[2,3,6,8,14,15,19,21],manag:8,mani:6,manual:11,mark:[2,8],master:3,match:[8,10,21,25],meant:8,measuring_servic:[],measuring_service_abc:23,measuringservic:23,messag:[6,25],message_brok:6,metadata:13,method:[2,8,14,15,16,22,24,26],mile:23,million:23,mind:3,minihan:0,minor:2,miss:2,mock:[2,4,11,18],mocked_dep:19,mocked_inject:19,mockeddep:19,model:6,modifi:15,modul:[1,2,4,8],more:[2,8,25],move:1,mt3o:0,multipl:[2,8,15,25],multipleservic:16,multipli:16,multiply_servic:16,multiplyservic:16,must:[1,8],mypi:2,name:[1,2],namespac:[2,4,6,8,9,11,13,18,21,24],namespaces_exampl:23,necessari:[8,17],need:[3,8,11,19,22],never:[1,8,19],nevertheless:3,non:[1,8],none:[8,10,11,14,23,24,26],now:[16,17,20,22],number:20,object:1,occurr:1,offici:2,often:3,ok:24,old:25,oliv:0,oliveira:0,omit:13,onc:[2,8,27],one:[1,8,11,13,14,15,16,19,21,23,24,27],ones:[8,23],onli:[6,8,15,22,23,27],open:[2,3],oper:1,option:[2,4,8,11,18,23],optional_inject:24,optional_injection_exampl:24,optional_servic:24,optionalinject:24,organ:3,origin:6,os:17,other:[1,2,8,12,14,15,23,25,27],otherwis:11,our:[6,14,15,16,17,20,22,23,24,25,26,27],out:[6,8,25],outermost:24,output:2,outsid:[1,8],over:26,overload:[4,6,13,16,18,24,26],own:23,packag:[2,6],page:4,paramet:[2,6,8,11,13,22,23,25,27],parenthesi:[2,8,13],particular:23,pass:[6,8,26],path:[1,2,6,8],pend:6,pep:2,perform:8,pip:[2,5],place:[8,27],posit:8,possibl:[1,2,13,15],potenti:1,preced:[4,18,25],prefer:26,present:[8,24],preserv:6,prevent:[8,15],previou:[2,8],previous:8,primari:[8,13,16,24,26],primary_basic_servic:26,print:[12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],project:[3,6,8],propag:[11,25],properti:[13,14,15,26],provid:[2,11],pull:3,purpos:[8,11],py:[12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],pycharm:6,pyright:2,pytest:4,python:[1,2,8,12],qualifi:[2,4,6,8,11,13,15,16,18,23,24,26],qualifier_overload:25,qualifier_overloading_exampl:25,qualifieroverload:25,quirk:2,r:8,rais:[2,8,10,11,16],re:25,read:[1,8],readabl:3,readi:6,realdep:19,reason:[1,8,17,20],receiv:[3,8,24],recipi:25,recommend:8,record:11,recurs:[1,11],refactor:2,refer:[4,6,15,22],reflect:27,regard:[8,25],regardless:8,regist:[1,2,8,9,11,15,19,21,23],register_inject:[2,11,19],registri:[8,23],registry_typ:10,regular:[1,20],rel:[2,4,8],releas:2,remov:[2,8],render:1,repositori:[3,14,26],repres:17,request:[3,8],requir:2,reset:[4,11,18],reset_injection_contain:[2,11,21],resili:2,resolut:[8,25],resolv:[2,8,16,23,24,25],respect:[8,23],respons:17,review:3,right:22,rodrigo:0,roo:0,root:[6,21],run:[1,2,3,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],run_exampl:[12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],s:[1,2,3,6,8,14,26],sai:13,same:[1,2,6,8,15,22,25,27],sample_servic:26,sampleservic:26,satisfi:24,scan:[2,8,11],search:[1,2,4,8,9],search_path:8,section:[8,11,12],see:[13,16,17,20,22,23,24,26,27],self:[6,8,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],send:25,send_messag:25,send_pend:6,sender_servic:25,senderservic:25,separ:13,sequenc:8,servic:[2,4,6,8,13,14,15,18,25],service_a:[15,22],service_b:[15,22],service_loc:26,service_locator_exampl:26,service_xyz:24,servicea:[15,22],serviceb:[15,22],serviceloc:26,servicexyz:24,set:[2,10,11,14],set_repository_st:[14,26],setter:[14,26],setup:8,shall:[8,24],share:[6,8,14,27],should:8,shouldn:8,show:[11,13,14,16,17,20,24,25],shown:13,side:1,side_effect:19,signatur:2,simpl:[6,13],simple_servic:13,simple_service_2:13,simpler:17,simpleservic:13,simpli:24,sinc:[8,16,19,24],singl:[6,12,23,25],singleton:[4,6,8,14,15,18],singleton_cli:27,singleton_exampl:27,singletoncli:27,situat:[13,24],sm:25,sms_sender_servic:25,smssenderservic:25,so:[1,3,13,17,20,24],some:[1,15,17,24],some_properti:15,some_servic:[],someth:[21,22],sourc:[8,10,11],speak:[3,13],specialized_servic:26,specializedservic:26,specif:8,specifi:[6,8,11,16,22,23],sqsproduc:6,stabl:2,start:[12,22],state:[11,14,21,26,27],stateful_repositori:[14,26],statefulrepositori:[14,26],statefulservic:14,staticmethod:19,step:1,still:8,store:8,str:[8,10,11,17,25],straightforward:12,string:[1,2,8,15],style:3,submit:3,success:8,successfulli:23,suit:2,suitabl:2,sum:16,sum_servic:16,sumservic:16,suppli:20,support:2,sure:[8,21],system:1,t:[1,2,8,11,16,19,24],take:25,teodor:0,test:[1,2,3,4,6,7,8,18],than:[1,2,3,8],thei:[14,22,27],them:[6,15],themselv:8,therefor:23,thi:[1,3,8,11,12,13,14,15,16,17,19,20,21,22,23,24,25,26,27],thoroughli:3,those:1,though:[8,16,19],three:[23,25],through:[1,2,17],time:[2,8,22],tl:[4,18],tldr_exampl:12,ton:2,trail:8,transpar:6,trial:2,tricki:3,turn:[14,20,26,27],twice:1,two:[14,23,25,27],type:[1,2,6,8,11,13,14,16,17,19,20,21,22,23,24,25,27],typeerror:2,ubuntu:2,unabl:8,under:8,understand:12,unintend:1,union:[8,11],uniqu:8,unique_id:8,unit:[2,3],unitedstatesmeasuringservic:23,unittest:19,unless:11,unus:2,up:25,us:[1,2,3,6,8,9,11,13,14,15,16,17,19,20,21,23,24,25,26,27],us_measuring_servic:23,usag:[1,2,4,6,8,11,12,26],user:2,utf:[2,8],util:[2,8,11,19,21],uuid:8,valid:8,valu:[8,14,24,26],valueerror:11,variabl:20,varieti:8,version:[2,8,11],wa:[8,16,19,27],wai:[3,22],want:[3,24],warn:[8,21],wasn:[8,16],we:[14,15,16,17,19,20,22,23,24,25,26,27],welcom:3,well:[3,16],were:[23,25],what:[3,23,24],whatev:20,when:[2,6,8,11,13,15,16,22,24,25,27],whenev:27,where:8,which:[2,8,11,14,15,16,17,20,22,24,26,27],window:2,wire:8,without:[2,8,13,17,23],won:[1,11,24],work:[1,2,13,15,22,23,24,25,26],workaround:1,world:25,would:16,wouldn:19,wrap:[8,17,19],write:3,wrong:2,wrote:3,xyz:24,yet:2,you:[3,4,12,13,14,15,16,17,20,22,23,24,25,26,27],your:[3,6,17]},titles:["Authors","Caveats","Changelog","Contributing","Contents","Installation","Injectable: Dependency Injection for Humans\u2122","Reference","injectable","injectable.constants","injectable.errors","injectable.testing","TL;DR","Annotated Usage Example","Basic Usage Example","Cyclic Dependency Example","Dependencies Precedence Example","Factory Example","Usage Examples","Injectable Mocking For Tests Example","Injecting Existing Instance Example","Injection Container Resetting For Tests Example","Lazy Injection Example","Namespaces Example","Optional Injection Example","Qualifier Overloading Example","Service Locator Example","Singletons Example"],titleterms:{"0":2,"02":2,"03":2,"04":2,"05":2,"06":2,"07":2,"08":2,"09":2,"1":2,"10":2,"11":2,"12":2,"13":2,"14":2,"15":2,"19":2,"2":2,"20":2,"2018":2,"2020":2,"2021":2,"2024":2,"22":2,"23":2,"24":2,"29":2,"3":2,"31":2,"4":2,"5":2,"6":2,"7":2,"import":1,For:[19,21],annot:13,author:0,automat:1,basic:14,caveat:1,changelog:2,constant:9,contain:21,content:4,contribut:3,cyclic:15,depend:[1,6,15,16],discoveri:1,dr:12,error:10,exampl:[13,14,15,16,17,18,19,20,21,22,23,24,25,26,27],exist:20,factori:17,featur:6,human:6,indic:4,inject:[6,8,9,10,11,19,20,21,22,24],instal:5,instanc:20,lazi:22,ll:6,locat:26,love:6,mock:19,namespac:23,option:24,overload:25,preced:16,pytest:1,qualifi:25,refer:7,rel:1,reset:21,servic:26,singleton:27,tabl:4,test:[11,19,21],tl:12,usag:[13,14,18],you:6}}) \ No newline at end of file diff --git a/docs/usage/TLDR.html b/docs/usage/TLDR.html index f9147dd..3b33402 100644 --- a/docs/usage/TLDR.html +++ b/docs/usage/TLDR.html @@ -5,7 +5,7 @@ - TL;DR — injectable 4.0.0 documentation + TL;DR — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -170,7 +170,7 @@

    Navigation

    diff --git a/docs/usage/annotated_usage.html b/docs/usage/annotated_usage.html index 3fd7f9b..1387590 100644 --- a/docs/usage/annotated_usage.html +++ b/docs/usage/annotated_usage.html @@ -5,7 +5,7 @@ - Annotated Usage Example — injectable 4.0.0 documentation + Annotated Usage Example — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -52,7 +52,8 @@

    Navigation

    Annotated Usage Example

    In this example you’ll see how the Autowired type annotation can be used with the typing.Annotated type annotation to separate metadata -from type hints and comply with linters.

    +from type hints and comply with linters. For completeness, the use of +Autowired without typing.Annotated is also shown.

    Note

    When using typing.Annotated it is possible to omit the dependency type parameter @@ -78,6 +79,7 @@

    Navigation

    annotated_usage_example.py
    from typing import Annotated
    +
     from examples import Example
     from examples.annotated_usage.extended_service import ExtendedService
     from examples.annotated_usage.simple_service import SimpleService
    @@ -91,10 +93,16 @@ 

    Navigation

    simple_service: Annotated[SimpleService, Autowired], extended_service: Annotated[SimpleService, Autowired(ExtendedService)], fallback_service: Annotated[SimpleService, Autowired(namespace="fallback")], + simple_service_2: Autowired(SimpleService), + extended_service_2: Autowired(ExtendedService), + fallback_service_2: Autowired(SimpleService, namespace="fallback"), ): self.simple_service = simple_service self.extended_service = extended_service self.fallback_service = fallback_service + self.simple_service_2 = simple_service_2 + self.extended_service_2 = extended_service_2 + self.fallback_service_2 = fallback_service_2 def run(self): self.simple_service.speak() @@ -106,6 +114,15 @@

    Navigation

    self.fallback_service.speak() # Fallback Service says: Hello! + self.simple_service_2.speak() + # Simple Service says: Hello! + + self.extended_service_2.speak() + # Extended Service says: Hello! + + self.fallback_service_2.speak() + # Fallback Service says: Hello! + def run_example(): load_injection_container() @@ -246,7 +263,7 @@

    Navigation

    diff --git a/docs/usage/basic_usage.html b/docs/usage/basic_usage.html index 621b32a..c8dfba7 100644 --- a/docs/usage/basic_usage.html +++ b/docs/usage/basic_usage.html @@ -5,7 +5,7 @@ - Basic Usage Example — injectable 4.0.0 documentation + Basic Usage Example — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -69,7 +69,9 @@

    Navigation

    basic_usage_example.py
    -
    from examples import Example
    +
    from typing import Annotated
    +
    +from examples import Example
     from examples.basic_usage.basic_service import BasicService
     from injectable import autowired, Autowired, load_injection_container
     
    @@ -78,8 +80,8 @@ 

    Navigation

    @autowired def __init__( self, - basic_service: Autowired(BasicService), - another_basic_service: Autowired(BasicService), + basic_service: Annotated[BasicService, Autowired], + another_basic_service: Annotated[BasicService, Autowired], ): self.basic_service = basic_service self.another_basic_service = another_basic_service @@ -114,14 +116,16 @@

    Navigation

    basic_service.py
    -
    from examples.basic_usage.stateful_repository import StatefulRepository
    +
    from typing import Annotated
    +
    +from examples.basic_usage.stateful_repository import StatefulRepository
     from injectable import injectable, autowired, Autowired
     
     
     @injectable
     class BasicService:
         @autowired
    -    def __init__(self, repository: Autowired(StatefulRepository)):
    +    def __init__(self, repository: Annotated[StatefulRepository, Autowired]):
             self.repository = repository
     
         def set_repository_state(self, state):
    @@ -233,7 +237,7 @@ 

    Navigation

    diff --git a/docs/usage/cyclic_dependency.html b/docs/usage/cyclic_dependency.html index 590a465..feea8df 100644 --- a/docs/usage/cyclic_dependency.html +++ b/docs/usage/cyclic_dependency.html @@ -5,7 +5,7 @@ - Cyclic Dependency Example — injectable 4.0.0 documentation + Cyclic Dependency Example — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -58,11 +58,16 @@

    Navigation

    falling into a cyclic import loop.

    For each of the services we inject the other one with a lazy modifier which will prevent us from falling into an instantiation loop as lazy dependencies are only instantiated -when its attributes are accessed or its methods are invoked.

    +when its attributes are accessed or its methods are invoked. Also, each service can be +declared as singleton to avoid creating multiple instances of the same service.

    See also

    The Lazy Injection Example details how lazy injection works.

    +
    +

    See also

    +

    The Singletons Example details how singletons work.

    +
    cyclic_dependency_example.py
    from examples import Example
    @@ -99,7 +104,7 @@ 

    Navigation

    from injectable import injectable, Autowired, autowired
     
     
    -@injectable(qualifier="A")
    +@injectable(qualifier="A", singleton=True)
     class ServiceA:
         @autowired
         def __init__(self, service_b: Autowired("B", lazy=True)):
    @@ -117,7 +122,7 @@ 

    Navigation

    from injectable import injectable, autowired, Autowired
     
     
    -@injectable(qualifier="B")
    +@injectable(qualifier="B", singleton=True)
     class ServiceB:
         @autowired
         def __init__(self, service_a: Autowired("A", lazy=True)):
    @@ -211,7 +216,7 @@ 

    Navigation

    diff --git a/docs/usage/dependencies_precedence.html b/docs/usage/dependencies_precedence.html index 021adfe..2a4082d 100644 --- a/docs/usage/dependencies_precedence.html +++ b/docs/usage/dependencies_precedence.html @@ -5,7 +5,7 @@ - Dependencies Precedence Example — injectable 4.0.0 documentation + Dependencies Precedence Example — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -73,7 +73,9 @@

    Navigation

    dependencies_precedence_example.py
    -
    from examples import Example
    +
    from typing import Annotated
    +
    +from examples import Example
     from examples.dependencies_precedence.abstract_service import AbstractService
     from injectable import (
         autowired,
    @@ -86,8 +88,8 @@ 

    Navigation

    @autowired def __init__( self, - abstract_service_1: Autowired(AbstractService), - abstract_service_2: Autowired("multiply"), + abstract_service_1: Annotated[AbstractService, Autowired], + abstract_service_2: Annotated[AbstractService, Autowired("multiply")], ): self.abstract_service_1 = abstract_service_1 self.abstract_service_2 = abstract_service_2 @@ -229,7 +231,7 @@

    Navigation

    diff --git a/docs/usage/factory.html b/docs/usage/factory.html index ee194cf..fa6780b 100644 --- a/docs/usage/factory.html +++ b/docs/usage/factory.html @@ -5,7 +5,7 @@ - Factory Example — injectable 4.0.0 documentation + Factory Example — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -68,7 +68,9 @@

    Navigation

    factory_example.py
    -
    from examples import Example
    +
    from typing import Annotated
    +
    +from examples import Example
     from examples.factory.external_client import ExternalClient
     from injectable import autowired, Autowired, load_injection_container
     
    @@ -77,7 +79,7 @@ 

    Navigation

    @autowired def __init__( self, - client: Autowired(ExternalClient), + client: Annotated[ExternalClient, Autowired], ): self.client = client @@ -206,7 +208,7 @@

    Navigation

    diff --git a/docs/usage/index.html b/docs/usage/index.html index c801877..46f11ad 100644 --- a/docs/usage/index.html +++ b/docs/usage/index.html @@ -5,7 +5,7 @@ - Usage Examples — injectable 4.0.0 documentation + Usage Examples — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -149,7 +149,7 @@

    Navigation

    diff --git a/docs/usage/injectable_mocking_for_tests.html b/docs/usage/injectable_mocking_for_tests.html index 0cb2d2d..c83315f 100644 --- a/docs/usage/injectable_mocking_for_tests.html +++ b/docs/usage/injectable_mocking_for_tests.html @@ -5,7 +5,7 @@ - Injectable Mocking For Tests Example — injectable 4.0.0 documentation + Injectable Mocking For Tests Example — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -63,7 +63,8 @@

    Navigation

    we wouldn’t need to use clear_injectables.

    injectable_mocking_example.py
    -
    from unittest.mock import Mock
    +
    from typing import Annotated
    +from unittest.mock import Mock
     
     from examples import Example
     from injectable import (
    @@ -92,7 +93,7 @@ 

    Navigation

    register_injectables({mocked_injectable}, RealDep) @autowired - def run(self, dep: Autowired(RealDep)): + def run(self, dep: Annotated[RealDep, Autowired]): dep.print() # MockedDep dep.print.assert_called() @@ -190,7 +191,7 @@

    Navigation

    diff --git a/docs/usage/injecting_existing_instance.html b/docs/usage/injecting_existing_instance.html index a9cf9a8..01b8a28 100644 --- a/docs/usage/injecting_existing_instance.html +++ b/docs/usage/injecting_existing_instance.html @@ -5,7 +5,7 @@ - Injecting Existing Instance Example — injectable 4.0.0 documentation + Injecting Existing Instance Example — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -65,7 +65,9 @@

    Navigation

    injecting_existing_instance_example.py
    -
    from examples import Example
    +
    from typing import Annotated
    +
    +from examples import Example
     from examples.injecting_existing_instance.app import Application
     from injectable import autowired, Autowired, load_injection_container
     
    @@ -74,7 +76,7 @@ 

    Navigation

    @autowired def __init__( self, - app: Autowired(Application), + app: Annotated[Application, Autowired], ): self.app = app @@ -192,7 +194,7 @@

    Navigation

    diff --git a/docs/usage/injection_container_resetting_for_tests.html b/docs/usage/injection_container_resetting_for_tests.html index d0035d3..e6a6e25 100644 --- a/docs/usage/injection_container_resetting_for_tests.html +++ b/docs/usage/injection_container_resetting_for_tests.html @@ -5,7 +5,7 @@ - Injection Container Resetting For Tests Example — injectable 4.0.0 documentation + Injection Container Resetting For Tests Example — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -56,7 +56,9 @@

    Navigation

    namespaces.

    injection_container_resetting_example.py
    -
    from examples import Example
    +
    from typing import Annotated
    +
    +from examples import Example
     from injectable import (
         injectable,
         autowired,
    @@ -89,7 +91,7 @@ 

    Navigation

    # No injectable matches class 'Foo' @autowired - def bar(self, foo: Autowired(Foo)): + def bar(self, foo: Annotated[Foo, Autowired]): foo.do_something() @@ -185,7 +187,7 @@

    Navigation

    diff --git a/docs/usage/lazy_injection.html b/docs/usage/lazy_injection.html index edb9d97..a970f2e 100644 --- a/docs/usage/lazy_injection.html +++ b/docs/usage/lazy_injection.html @@ -5,7 +5,7 @@ - Lazy Injection Example — injectable 4.0.0 documentation + Lazy Injection Example — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -67,7 +67,9 @@

    Navigation

    lazy_injection_example.py
    -
    from examples import Example
    +
    from typing import Annotated
    +
    +from examples import Example
     from examples.lazy_injection.service_a import ServiceA
     from examples.lazy_injection.service_b import ServiceB
     from injectable import autowired, Autowired, load_injection_container
    @@ -76,7 +78,9 @@ 

    Navigation

    class LazyInjection(Example): @autowired def __init__( - self, service_a: Autowired(ServiceA, lazy=True), service_b: Autowired(ServiceB) + self, + service_a: Annotated[ServiceA, Autowired(lazy=True)], + service_b: Annotated[ServiceB, Autowired], ): # ServiceB::__init__ called print("example init started") @@ -220,7 +224,7 @@

    Navigation

    diff --git a/docs/usage/namespaces.html b/docs/usage/namespaces.html index 82c1ad3..aab36e8 100644 --- a/docs/usage/namespaces.html +++ b/docs/usage/namespaces.html @@ -5,7 +5,7 @@ - Namespaces Example — injectable 4.0.0 documentation + Namespaces Example — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -54,11 +54,11 @@

    Navigation

    Each namespace has its own independent injectables registry and one namespace cannot see the others injectables.

    To illustrate how this works we declare two classes, InternationalMeasuringService -and UnitedStatesMeasuringService, and register them both as injectables for the -"MEASURING_SERVICE" qualifier but each is assigned to a different namespace, -"INTL" and "US" respectively.

    +and UnitedStatesMeasuringService, both implementing the MeasuringService +abstract base class but each is assigned to a different namespace, "INTL" and +"US" respectively.

    In our Namespace example class we inject three parameters with -"MEASURING_SERVICE" injectables: first without specifying any particular namespace +MeasuringService injectables: first without specifying any particular namespace and also declaring the injection as optional; then specifying the "INTL" namespace; and at last specifying the "US" namespace.

    By running the example we can see that the default_measuring_service is not injected @@ -66,9 +66,9 @@

    Navigation

    qualifier.

    What we see for the default_measuring_service argument is that without specifying a namespace the default namespace is used and no injectable that resolves the -"MEASURING_SERVICE" qualifier were registered in the default namespace. Then, for +MeasuringService dependency were registered in the default namespace. Then, for the intl_measuring_service and us_measuring_service arguments we only have a -single injectable resolving the "MEASURING_SERVICE" qualifier declared in each +single injectable resolving the MeasuringService dependency declared in each namespace, therefore no conflicts.

    See also

    @@ -77,9 +77,10 @@

    Navigation

    namespaces_example.py
    -
    from typing import Optional
    +
    from typing import Annotated, Optional
     
     from examples import Example
    +from examples.namespaces.measuring_service_abc import MeasuringService
     from injectable import Autowired, autowired, load_injection_container
     
     
    @@ -87,9 +88,11 @@ 

    Navigation

    @autowired def __init__( self, - default_measuring_service: Autowired(Optional["MEASURING_SERVICE"]), - intl_measuring_service: Autowired("MEASURING_SERVICE", namespace="INTL"), - us_measuring_service: Autowired("MEASURING_SERVICE", namespace="US"), + default_measuring_service: Annotated[Optional[MeasuringService], Autowired], + intl_measuring_service: Annotated[ + MeasuringService, Autowired(namespace="INTL") + ], + us_measuring_service: Annotated[MeasuringService, Autowired(namespace="US")], ): self.default_measuring_service = default_measuring_service self.intl_measuring_service = intl_measuring_service @@ -118,24 +121,36 @@

    Navigation

    -
    intl_measuring_service.py
    -
    from injectable import injectable
    +
    measuring_service_abc.py
    +
    from abc import ABC
     
     
    -@injectable(qualifier="MEASURING_SERVICE", namespace="INTL")
    -class InternationalMeasuringService:
    +class MeasuringService(ABC):
    +    def earth_to_sun_distance(self): ...
    +
    +
    +
    +
    +
    intl_measuring_service.py
    +
    from examples.namespaces.measuring_service_abc import MeasuringService
    +from injectable import injectable
    +
    +
    +@injectable(namespace="INTL")
    +class InternationalMeasuringService(MeasuringService):
         def earth_to_sun_distance(self):
             return "151.38 million km"
     
    -
    -
    us_measuring_service.py
    -
    from injectable import injectable
    +
    +
    us_measuring_service.py
    +
    from examples.namespaces.measuring_service_abc import MeasuringService
    +from injectable import injectable
     
     
    -@injectable(qualifier="MEASURING_SERVICE", namespace="US")
    -class UnitedStatesMeasuringService:
    +@injectable(namespace="US")
    +class UnitedStatesMeasuringService(MeasuringService):
         def earth_to_sun_distance(self):
             return "94.06 million miles"
     
    @@ -222,7 +237,7 @@

    Navigation

    diff --git a/docs/usage/namespaces.rst b/docs/usage/namespaces.rst index 9b31091..220edd4 100644 --- a/docs/usage/namespaces.rst +++ b/docs/usage/namespaces.rst @@ -10,6 +10,9 @@ Namespaces Example :caption: namespaces_example.py :start-after: sphinx-start +.. literalinclude:: ../../examples/namespaces/measuring_service_abc.py + :caption: measuring_service_abc.py + .. literalinclude:: ../../examples/namespaces/intl_measuring_service.py :caption: intl_measuring_service.py diff --git a/docs/usage/optional_injection.html b/docs/usage/optional_injection.html index 3bea5d6..8ef9388 100644 --- a/docs/usage/optional_injection.html +++ b/docs/usage/optional_injection.html @@ -5,7 +5,7 @@ - Optional Injection Example — injectable 4.0.0 documentation + Optional Injection Example — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -55,14 +55,15 @@

    Navigation

    When a dependency is not found for injection you’ll receive an injectable.InjectionError. This may not be what you want if it is expected and OK that in some situations the dependency simply won’t be present.

    -

    In our OptionalInjection example class we optionally autowire the some_service -argument with the "foo" qualifier and we optionally autowire the -bunch_of_services argument with a list of all injectables that satisfy the "bar" -qualifier.

    -

    In this example, both qualifiers, "foo" and "bar", aren’t declared by any -injectable though as we declared both injections as optional, the __init__ method -won’t fail and instead will inject the value None to some_service and an empty -list [] to bunch_of_services.

    +

    In our OptionalInjection example class we optionally autowire ServiceXYZ and we +optionally autowire a list of all ServiceXYZ injectables. We declare the +ServiceXYZ as injectable but in the "XYZ" namespace.

    +

    In this example, both autowirings, optional_service and +bunch_of_optional_services, aren’t satisfied by any injectable since there are no +ServiceXYZ declared in the default namespace. But since we declared both injections +as optional, the __init__ method won’t fail and instead will inject the value +None to optional_service and an empty list [] to +bunch_of_optional_services.

    Note

    The typing.Optional type shall be the outermost declared type, so @@ -76,9 +77,10 @@

    Navigation

    optional_injection_example.py
    -
    from typing import Optional, List
    +
    from typing import Annotated, Optional, List
     
     from examples import Example
    +from examples.optional_injection.service_xyz import ServiceXYZ
     from injectable import autowired, Autowired, load_injection_container
     
     
    @@ -86,17 +88,17 @@ 

    Navigation

    @autowired def __init__( self, - some_service: Autowired(Optional["foo"]), - bunch_of_services: Autowired(Optional[List["bar"]]), + optional_service: Annotated[Optional[ServiceXYZ], Autowired], + bunch_of_optional_services: Annotated[Optional[List[ServiceXYZ]], Autowired], ): - self.some_service = some_service - self.bunch_of_services = bunch_of_services + self.optional_service = optional_service + self.bunch_of_optional_services = bunch_of_optional_services def run(self): - print(self.some_service) + print(self.optional_service) # None - print(self.bunch_of_services) + print(self.bunch_of_optional_services) # [] @@ -111,6 +113,16 @@

    Navigation

    +
    +
    service_xyz.py
    +
    from injectable import injectable
    +
    +
    +@injectable(namespace="XYZ")
    +class ServiceXYZ: ...
    +
    +
    +
    @@ -192,7 +204,7 @@

    Navigation

    diff --git a/docs/usage/optional_injection.rst b/docs/usage/optional_injection.rst index 67a5a95..506572d 100644 --- a/docs/usage/optional_injection.rst +++ b/docs/usage/optional_injection.rst @@ -9,3 +9,6 @@ Optional Injection Example .. literalinclude:: ../../examples/optional_injection/optional_injection_example.py :caption: optional_injection_example.py :start-after: sphinx-start + +.. literalinclude:: ../../examples/optional_injection/service_xyz.py + :caption: service_xyz.py diff --git a/docs/usage/qualifier_overloading.html b/docs/usage/qualifier_overloading.html index 0569e5f..399b71f 100644 --- a/docs/usage/qualifier_overloading.html +++ b/docs/usage/qualifier_overloading.html @@ -5,7 +5,7 @@ - Qualifier Overloading Example — injectable 4.0.0 documentation + Qualifier Overloading Example — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -66,12 +66,13 @@

    Navigation

    See also

    The Dependencies Precedence Example shows how dependency resolution works in -regards to precedence when a qualifier or class are resolved by multiple -injectables and you’re injecting a single instance and not all matching injectables.

    +regard to precedence when a qualifier or class are resolved by multiple +injectables, and you’re injecting a single instance and not all matching +injectables.

    qualifier_overloading_example.py
    -
    from typing import List
    +
    from typing import Annotated, List
     
     from examples import Example
     from examples.qualifier_overloading.sender_service import SenderService
    @@ -82,7 +83,9 @@ 

    Navigation

    @autowired def __init__( self, - sender_services: Autowired(List[SenderService], exclude_groups=["old"]), + sender_services: Annotated[ + List[SenderService], Autowired(exclude_groups=["old"]) + ], ): self.sender_services = sender_services @@ -238,7 +241,7 @@

    Navigation

    diff --git a/docs/usage/service_locator.html b/docs/usage/service_locator.html index d52a32e..9f030cf 100644 --- a/docs/usage/service_locator.html +++ b/docs/usage/service_locator.html @@ -5,7 +5,7 @@ - Service Locator Example — injectable 4.0.0 documentation + Service Locator Example — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -85,9 +85,7 @@

    Navigation

    class ServiceLocator(Example): - def __init__( - self, - ): + def __init__(self): self.primary_basic_service = inject(SampleService) self.all_basic_service_implementations = inject_multiple(SampleService) @@ -263,7 +261,7 @@

    Navigation

    diff --git a/docs/usage/singletons.html b/docs/usage/singletons.html index 6a5ecb4..6c458ce 100644 --- a/docs/usage/singletons.html +++ b/docs/usage/singletons.html @@ -5,7 +5,7 @@ - Singletons Example — injectable 4.0.0 documentation + Singletons Example — injectable 4.0.1 documentation @@ -31,7 +31,7 @@

    Navigation

    @@ -60,7 +60,9 @@

    Navigation

    with it.

    singleton_example.py
    -
    from examples import Example
    +
    from typing import Annotated
    +
    +from examples import Example
     from examples.singletons.singleton_client import SingletonClient
     from injectable import Autowired, autowired, load_injection_container
     
    @@ -69,8 +71,8 @@ 

    Navigation

    @autowired def __init__( self, - client1: Autowired(SingletonClient), - client2: Autowired(SingletonClient), + client1: Annotated[SingletonClient, Autowired], + client2: Annotated[SingletonClient, Autowired], ): self.client1 = client1 self.client2 = client2 @@ -197,7 +199,7 @@

    Navigation

    diff --git a/examples/annotated_usage/annotated_usage_example.py b/examples/annotated_usage/annotated_usage_example.py index 38f6003..114c6f2 100644 --- a/examples/annotated_usage/annotated_usage_example.py +++ b/examples/annotated_usage/annotated_usage_example.py @@ -1,7 +1,8 @@ """ In this example you'll see how the :class:`Autowired ` type annotation can be used with the ``typing.Annotated`` type annotation to separate metadata -from type hints and comply with linters. +from type hints and comply with linters. For completeness, the use of +:class:`Autowired ` without ``typing.Annotated`` is also shown. .. note:: @@ -28,6 +29,7 @@ # sphinx-start from typing import Annotated + from examples import Example from examples.annotated_usage.extended_service import ExtendedService from examples.annotated_usage.simple_service import SimpleService @@ -41,10 +43,16 @@ def __init__( simple_service: Annotated[SimpleService, Autowired], extended_service: Annotated[SimpleService, Autowired(ExtendedService)], fallback_service: Annotated[SimpleService, Autowired(namespace="fallback")], + simple_service_2: Autowired(SimpleService), + extended_service_2: Autowired(ExtendedService), + fallback_service_2: Autowired(SimpleService, namespace="fallback"), ): self.simple_service = simple_service self.extended_service = extended_service self.fallback_service = fallback_service + self.simple_service_2 = simple_service_2 + self.extended_service_2 = extended_service_2 + self.fallback_service_2 = fallback_service_2 def run(self): self.simple_service.speak() @@ -56,6 +64,15 @@ def run(self): self.fallback_service.speak() # Fallback Service says: Hello! + self.simple_service_2.speak() + # Simple Service says: Hello! + + self.extended_service_2.speak() + # Extended Service says: Hello! + + self.fallback_service_2.speak() + # Fallback Service says: Hello! + def run_example(): load_injection_container() diff --git a/examples/basic_usage/basic_service.py b/examples/basic_usage/basic_service.py index 24436bf..09ff011 100644 --- a/examples/basic_usage/basic_service.py +++ b/examples/basic_usage/basic_service.py @@ -1,3 +1,5 @@ +from typing import Annotated + from examples.basic_usage.stateful_repository import StatefulRepository from injectable import injectable, autowired, Autowired @@ -5,7 +7,7 @@ @injectable class BasicService: @autowired - def __init__(self, repository: Autowired(StatefulRepository)): + def __init__(self, repository: Annotated[StatefulRepository, Autowired]): self.repository = repository def set_repository_state(self, state): diff --git a/examples/basic_usage/basic_usage_example.py b/examples/basic_usage/basic_usage_example.py index 8895e3d..cd1fae6 100644 --- a/examples/basic_usage/basic_usage_example.py +++ b/examples/basic_usage/basic_usage_example.py @@ -22,6 +22,8 @@ """ # sphinx-start +from typing import Annotated + from examples import Example from examples.basic_usage.basic_service import BasicService from injectable import autowired, Autowired, load_injection_container @@ -31,8 +33,8 @@ class BasicUsage(Example): @autowired def __init__( self, - basic_service: Autowired(BasicService), - another_basic_service: Autowired(BasicService), + basic_service: Annotated[BasicService, Autowired], + another_basic_service: Annotated[BasicService, Autowired], ): self.basic_service = basic_service self.another_basic_service = another_basic_service diff --git a/examples/cyclic_dependency/cyclic_dependency_example.py b/examples/cyclic_dependency/cyclic_dependency_example.py index 7e3cacf..ba914e4 100644 --- a/examples/cyclic_dependency/cyclic_dependency_example.py +++ b/examples/cyclic_dependency/cyclic_dependency_example.py @@ -9,11 +9,16 @@ For each of the services we inject the other one with a lazy modifier which will prevent us from falling into an instantiation loop as lazy dependencies are only instantiated -when its attributes are accessed or its methods are invoked. +when its attributes are accessed or its methods are invoked. Also, each service can be +declared as singleton to avoid creating multiple instances of the same service. .. seealso:: The :ref:`lazy_injection_example` details how lazy injection works. + +.. seealso:: + + The :ref:`singleton_example` details how singletons work. """ # sphinx-start diff --git a/examples/cyclic_dependency/service_a.py b/examples/cyclic_dependency/service_a.py index 5f4d056..289280c 100644 --- a/examples/cyclic_dependency/service_a.py +++ b/examples/cyclic_dependency/service_a.py @@ -1,7 +1,7 @@ from injectable import injectable, Autowired, autowired -@injectable(qualifier="A") +@injectable(qualifier="A", singleton=True) class ServiceA: @autowired def __init__(self, service_b: Autowired("B", lazy=True)): diff --git a/examples/cyclic_dependency/service_b.py b/examples/cyclic_dependency/service_b.py index f5cd939..46ecf7b 100644 --- a/examples/cyclic_dependency/service_b.py +++ b/examples/cyclic_dependency/service_b.py @@ -1,7 +1,7 @@ from injectable import injectable, autowired, Autowired -@injectable(qualifier="B") +@injectable(qualifier="B", singleton=True) class ServiceB: @autowired def __init__(self, service_a: Autowired("A", lazy=True)): diff --git a/examples/dependencies_precedence/dependencies_precedence_example.py b/examples/dependencies_precedence/dependencies_precedence_example.py index 0eee80b..f58bfa8 100644 --- a/examples/dependencies_precedence/dependencies_precedence_example.py +++ b/examples/dependencies_precedence/dependencies_precedence_example.py @@ -25,6 +25,8 @@ class we will get an instance of the ``SumService`` class since we declared it a """ # sphinx-start +from typing import Annotated + from examples import Example from examples.dependencies_precedence.abstract_service import AbstractService from injectable import ( @@ -38,8 +40,8 @@ class DependenciesPrecedence(Example): @autowired def __init__( self, - abstract_service_1: Autowired(AbstractService), - abstract_service_2: Autowired("multiply"), + abstract_service_1: Annotated[AbstractService, Autowired], + abstract_service_2: Annotated[AbstractService, Autowired("multiply")], ): self.abstract_service_1 = abstract_service_1 self.abstract_service_2 = abstract_service_2 diff --git a/examples/factory/factory_example.py b/examples/factory/factory_example.py index f46fe3d..df50393 100644 --- a/examples/factory/factory_example.py +++ b/examples/factory/factory_example.py @@ -21,6 +21,8 @@ class through the :meth:`@injectable_factory ` de """ # sphinx-start +from typing import Annotated + from examples import Example from examples.factory.external_client import ExternalClient from injectable import autowired, Autowired, load_injection_container @@ -30,7 +32,7 @@ class Factory(Example): @autowired def __init__( self, - client: Autowired(ExternalClient), + client: Annotated[ExternalClient, Autowired], ): self.client = client diff --git a/examples/injectable_mocking_for_tests/injectable_mocking_example.py b/examples/injectable_mocking_for_tests/injectable_mocking_example.py index 5392fa6..67cf3b5 100644 --- a/examples/injectable_mocking_for_tests/injectable_mocking_example.py +++ b/examples/injectable_mocking_for_tests/injectable_mocking_example.py @@ -14,6 +14,7 @@ """ # sphinx-start +from typing import Annotated from unittest.mock import Mock from examples import Example @@ -43,7 +44,7 @@ def __init__(self): register_injectables({mocked_injectable}, RealDep) @autowired - def run(self, dep: Autowired(RealDep)): + def run(self, dep: Annotated[RealDep, Autowired]): dep.print() # MockedDep dep.print.assert_called() diff --git a/examples/injecting_existing_instance/injecting_existing_instance_example.py b/examples/injecting_existing_instance/injecting_existing_instance_example.py index fb3c8ac..a32f2dd 100644 --- a/examples/injecting_existing_instance/injecting_existing_instance_example.py +++ b/examples/injecting_existing_instance/injecting_existing_instance_example.py @@ -17,6 +17,8 @@ """ # sphinx-start +from typing import Annotated + from examples import Example from examples.injecting_existing_instance.app import Application from injectable import autowired, Autowired, load_injection_container @@ -26,7 +28,7 @@ class InjectingExistingInstance(Example): @autowired def __init__( self, - app: Autowired(Application), + app: Annotated[Application, Autowired], ): self.app = app diff --git a/examples/injection_container_resetting_for_tests/injection_container_resetting_example.py b/examples/injection_container_resetting_for_tests/injection_container_resetting_example.py index 6d443ca..5063a1d 100644 --- a/examples/injection_container_resetting_for_tests/injection_container_resetting_example.py +++ b/examples/injection_container_resetting_for_tests/injection_container_resetting_example.py @@ -6,6 +6,8 @@ """ # sphinx-start +from typing import Annotated + from examples import Example from injectable import ( injectable, @@ -39,7 +41,7 @@ def run(self): # No injectable matches class 'Foo' @autowired - def bar(self, foo: Autowired(Foo)): + def bar(self, foo: Annotated[Foo, Autowired]): foo.do_something() diff --git a/examples/lazy_injection/lazy_injection_example.py b/examples/lazy_injection/lazy_injection_example.py index e7889f0..a791de3 100644 --- a/examples/lazy_injection/lazy_injection_example.py +++ b/examples/lazy_injection/lazy_injection_example.py @@ -21,6 +21,8 @@ """ # sphinx-start +from typing import Annotated + from examples import Example from examples.lazy_injection.service_a import ServiceA from examples.lazy_injection.service_b import ServiceB @@ -30,7 +32,9 @@ class LazyInjection(Example): @autowired def __init__( - self, service_a: Autowired(ServiceA, lazy=True), service_b: Autowired(ServiceB) + self, + service_a: Annotated[ServiceA, Autowired(lazy=True)], + service_b: Annotated[ServiceB, Autowired], ): # ServiceB::__init__ called print("example init started") diff --git a/examples/namespaces/intl_measuring_service.py b/examples/namespaces/intl_measuring_service.py index 7d7c58e..cd17301 100644 --- a/examples/namespaces/intl_measuring_service.py +++ b/examples/namespaces/intl_measuring_service.py @@ -1,7 +1,8 @@ +from examples.namespaces.measuring_service_abc import MeasuringService from injectable import injectable -@injectable(qualifier="MEASURING_SERVICE", namespace="INTL") -class InternationalMeasuringService: +@injectable(namespace="INTL") +class InternationalMeasuringService(MeasuringService): def earth_to_sun_distance(self): return "151.38 million km" diff --git a/examples/namespaces/measuring_service_abc.py b/examples/namespaces/measuring_service_abc.py new file mode 100644 index 0000000..9cf2cb9 --- /dev/null +++ b/examples/namespaces/measuring_service_abc.py @@ -0,0 +1,5 @@ +from abc import ABC + + +class MeasuringService(ABC): + def earth_to_sun_distance(self): ... diff --git a/examples/namespaces/namespaces_example.py b/examples/namespaces/namespaces_example.py index 47f23fd..6408d21 100644 --- a/examples/namespaces/namespaces_example.py +++ b/examples/namespaces/namespaces_example.py @@ -5,12 +5,12 @@ see the others injectables. To illustrate how this works we declare two classes, ``InternationalMeasuringService`` -and ``UnitedStatesMeasuringService``, and register them both as injectables for the -``"MEASURING_SERVICE"`` qualifier but each is assigned to a different namespace, -``"INTL"`` and ``"US"`` respectively. +and ``UnitedStatesMeasuringService``, both implementing the ``MeasuringService`` +abstract base class but each is assigned to a different namespace, ``"INTL"`` and +``"US"`` respectively. In our ``Namespace`` example class we inject three parameters with -``"MEASURING_SERVICE"`` injectables: first without specifying any particular namespace +``MeasuringService`` injectables: first without specifying any particular namespace and also declaring the injection as optional; then specifying the ``"INTL"`` namespace; and at last specifying the ``"US"`` namespace. @@ -20,9 +20,9 @@ What we see for the ``default_measuring_service`` argument is that without specifying a namespace the default namespace is used and no injectable that resolves the -``"MEASURING_SERVICE"`` qualifier were registered in the default namespace. Then, for +``MeasuringService`` dependency were registered in the default namespace. Then, for the ``intl_measuring_service`` and ``us_measuring_service`` arguments we only have a -single injectable resolving the ``"MEASURING_SERVICE"`` qualifier declared in each +single injectable resolving the ``MeasuringService`` dependency declared in each namespace, therefore no conflicts. .. seealso:: @@ -32,9 +32,10 @@ """ # sphinx-start -from typing import Optional +from typing import Annotated, Optional from examples import Example +from examples.namespaces.measuring_service_abc import MeasuringService from injectable import Autowired, autowired, load_injection_container @@ -42,9 +43,11 @@ class Namespaces(Example): @autowired def __init__( self, - default_measuring_service: Autowired(Optional["MEASURING_SERVICE"]), - intl_measuring_service: Autowired("MEASURING_SERVICE", namespace="INTL"), - us_measuring_service: Autowired("MEASURING_SERVICE", namespace="US"), + default_measuring_service: Annotated[Optional[MeasuringService], Autowired], + intl_measuring_service: Annotated[ + MeasuringService, Autowired(namespace="INTL") + ], + us_measuring_service: Annotated[MeasuringService, Autowired(namespace="US")], ): self.default_measuring_service = default_measuring_service self.intl_measuring_service = intl_measuring_service diff --git a/examples/namespaces/us_measuring_service.py b/examples/namespaces/us_measuring_service.py index 26b872a..1b2cd2c 100644 --- a/examples/namespaces/us_measuring_service.py +++ b/examples/namespaces/us_measuring_service.py @@ -1,7 +1,8 @@ +from examples.namespaces.measuring_service_abc import MeasuringService from injectable import injectable -@injectable(qualifier="MEASURING_SERVICE", namespace="US") -class UnitedStatesMeasuringService: +@injectable(namespace="US") +class UnitedStatesMeasuringService(MeasuringService): def earth_to_sun_distance(self): return "94.06 million miles" diff --git a/examples/optional_injection/optional_injection_example.py b/examples/optional_injection/optional_injection_example.py index 126c5a7..72886dc 100644 --- a/examples/optional_injection/optional_injection_example.py +++ b/examples/optional_injection/optional_injection_example.py @@ -6,15 +6,16 @@ :exc:`injectable.InjectionError`. This may not be what you want if it is expected and OK that in some situations the dependency simply won't be present. -In our ``OptionalInjection`` example class we optionally autowire the ``some_service`` -argument with the ``"foo"`` qualifier and we optionally autowire the -``bunch_of_services`` argument with a list of all injectables that satisfy the ``"bar"`` -qualifier. +In our ``OptionalInjection`` example class we optionally autowire ``ServiceXYZ`` and we +optionally autowire a list of all ``ServiceXYZ`` injectables. We declare the +``ServiceXYZ`` as injectable but in the ``"XYZ"`` namespace. -In this example, both qualifiers, ``"foo"`` and ``"bar"``, aren't declared by any -injectable though as we declared both injections as optional, the ``__init__`` method -won't fail and instead will inject the value ``None`` to ``some_service`` and an empty -list ``[]`` to ``bunch_of_services``. +In this example, both autowirings, ``optional_service`` and +``bunch_of_optional_services``, aren't satisfied by any injectable since there are no +``ServiceXYZ`` declared in the default namespace. But since we declared both injections +as optional, the ``__init__`` method won't fail and instead will inject the value +``None`` to ``optional_service`` and an empty list ``[]`` to +``bunch_of_optional_services``. .. note:: @@ -29,9 +30,10 @@ """ # sphinx-start -from typing import Optional, List +from typing import Annotated, Optional, List from examples import Example +from examples.optional_injection.service_xyz import ServiceXYZ from injectable import autowired, Autowired, load_injection_container @@ -39,17 +41,17 @@ class OptionalInjection(Example): @autowired def __init__( self, - some_service: Autowired(Optional["foo"]), - bunch_of_services: Autowired(Optional[List["bar"]]), + optional_service: Annotated[Optional[ServiceXYZ], Autowired], + bunch_of_optional_services: Annotated[Optional[List[ServiceXYZ]], Autowired], ): - self.some_service = some_service - self.bunch_of_services = bunch_of_services + self.optional_service = optional_service + self.bunch_of_optional_services = bunch_of_optional_services def run(self): - print(self.some_service) + print(self.optional_service) # None - print(self.bunch_of_services) + print(self.bunch_of_optional_services) # [] diff --git a/examples/optional_injection/service_xyz.py b/examples/optional_injection/service_xyz.py new file mode 100644 index 0000000..1f97802 --- /dev/null +++ b/examples/optional_injection/service_xyz.py @@ -0,0 +1,5 @@ +from injectable import injectable + + +@injectable(namespace="XYZ") +class ServiceXYZ: ... diff --git a/examples/qualifier_overloading/qualifier_overloading_example.py b/examples/qualifier_overloading/qualifier_overloading_example.py index bf59d78..86c25c0 100644 --- a/examples/qualifier_overloading/qualifier_overloading_example.py +++ b/examples/qualifier_overloading/qualifier_overloading_example.py @@ -19,12 +19,13 @@ .. seealso:: The :ref:`dependencies_precedence_example` shows how dependency resolution works in - regards to precedence when a qualifier or class are resolved by multiple - injectables and you're injecting a single instance and not all matching injectables. + regard to precedence when a qualifier or class are resolved by multiple + injectables, and you're injecting a single instance and not all matching + injectables. """ # sphinx-start -from typing import List +from typing import Annotated, List from examples import Example from examples.qualifier_overloading.sender_service import SenderService @@ -35,7 +36,9 @@ class QualifierOverloading(Example): @autowired def __init__( self, - sender_services: Autowired(List[SenderService], exclude_groups=["old"]), + sender_services: Annotated[ + List[SenderService], Autowired(exclude_groups=["old"]) + ], ): self.sender_services = sender_services diff --git a/examples/service_locator/service_locator_example.py b/examples/service_locator/service_locator_example.py index d4ae928..176c9fa 100644 --- a/examples/service_locator/service_locator_example.py +++ b/examples/service_locator/service_locator_example.py @@ -38,9 +38,7 @@ class ServiceLocator(Example): - def __init__( - self, - ): + def __init__(self): self.primary_basic_service = inject(SampleService) self.all_basic_service_implementations = inject_multiple(SampleService) diff --git a/examples/singletons/singleton_example.py b/examples/singletons/singleton_example.py index adc0a26..0e14ba5 100644 --- a/examples/singletons/singleton_example.py +++ b/examples/singletons/singleton_example.py @@ -13,6 +13,8 @@ """ # sphinx-start +from typing import Annotated + from examples import Example from examples.singletons.singleton_client import SingletonClient from injectable import Autowired, autowired, load_injection_container @@ -22,8 +24,8 @@ class Singletons(Example): @autowired def __init__( self, - client1: Autowired(SingletonClient), - client2: Autowired(SingletonClient), + client1: Annotated[SingletonClient, Autowired], + client2: Annotated[SingletonClient, Autowired], ): self.client1 = client1 self.client2 = client2