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. 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 in the Autowired. In this case, the first type declared in typing.Annotated will be used. For convenience, one can use Autowired without parenthesis in these situations.

See also

The Autowired type annotation can also be used directly without using the typing.Annotated type annotation. The Basic Usage Example shows how to use it like so.

See also

The Qualifier Overloading Example details how overloading an injectable works by using class inheritance.

See also

The Namespaces Example details how namespaces work.

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
from injectable import autowired, Autowired, load_injection_container


class AnnotatedUsage(Example):
    @autowired
    def __init__(
        self,
        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()
        # Simple Service says: Hello!

        self.extended_service.speak()
        # Extended Service says: Hello!

        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()
    example = AnnotatedUsage()
    example.run()


if __name__ == "__main__":
    run_example()
simple_service.py
from injectable import injectable


@injectable(primary=True)
class SimpleService:
    def __init__(self):
        self._statement = "says: Hello!"

    @property
    def _name(self):
        return "Simple Service"

    def speak(self):
        print(f"{self._name} {self._statement}")
extended_service.py
from examples.annotated_usage.simple_service import SimpleService
from injectable import injectable


@injectable
class ExtendedService(SimpleService):
    @property
    def _name(self):
        return "Extended Service"
fallback_service.py
from examples.annotated_usage.simple_service import SimpleService
from injectable import injectable


@injectable(namespace="fallback")
class FallbackService(SimpleService):
    @property
    def _name(self):
        return "Fallback Service"