Small, annotation-driven dependency injection for Python.
Project description
Small DI
The smallest dependency injection mechanism possible in python. SmallDI provides you with an intuitive and simple interface for doing dependency injections in your project.
Example usage
Injection
import random
from smalldi import Injector
from smalldi.annotation import Provide
# Lets create some service
@Injector.singleton
class MeowService:
_MEOWS = ["Meow", "Meow-meow", "Meowwwwww", "Mrromeowww", "Meeeeoooow"]
def __init__(self):
print("Meow-meow! Meowing service is initialized")
def meow(self):
print(random.choice(self._MEOWS))
# Now lets make purring service.
# But cats do not purr without telling meow!(at least in this test)
# So its time to inject dependency
@Injector.singleton
class PurrService:
_PURRS = ["Purrrrr", "Purr-purr"]
@Injector.inject
def __init__(self, meow_service: Provide[MeowService]):
self.meow_service = meow_service
print("Purr-purr! Purring service is initialized")
def purr(self):
self.meow_service.meow()
print(random.choice(self._PURRS))
# Now lets put it all together.
# Ask our services to meow and then purr
@Injector.inject
def main(meow_service: Provide[MeowService], purr_service: Provide[PurrService]):
meow_service.meow()
purr_service.purr()
if __name__ == '__main__':
main()
Container
import sys
from abc import ABC, abstractmethod
from smalldi.container import Container
from smalldi import Injector, Provide
# Define interface for catnip
class Catnip(ABC):
@property
@abstractmethod
def flavour(self):
pass
# Create a container to store different flavours of catnip
@Injector.singleton
class CatnipContainer(Container):
def get_all_flavours(self) -> list[str]:
flavours = list()
for catnip in self._get_components():
flavours.append(catnip().flavour)
return flavours
@CatnipContainer.component
class PlainCatnip(Catnip):
@property
def flavour(self):
return "plain"
@CatnipContainer.component
class ChocolateCatnip(Catnip):
@property
def flavour(self):
return "chocolate"
@CatnipContainer.component
class StrawberryCatnip(Catnip):
@property
def flavour(self):
return "strawberry"
@Injector.inject
def main(catnip_container: Provide[CatnipContainer]) -> int:
print(catnip_container.get_all_flavours())
return 0
if __name__ == '__main__':
sys.exit(main())
Library structure
Injector
Injector is a static class(i.e., one that should never be instantiated) which is the main (and currently the only) DI container inside the library. Injector provides two decorators:
@Injector.singletoncreates an instance of a class which may further be injected in functions@Injector.injectreplaces parameters annotated with typeProvide[Singleton]with actual instances of Singleton
Singletons
Singletons are classes having a single instance. In smalldi singletons may not take constructor(__init__) other
than annotated with Provide[] type. Only singletons may be decorated with @Injector.singleton. As a consequence,
only singleton classes may be injected at the current state of library development.
Provide
Provide[T] is an annotation for injector telling it that instead of this argument
instance of T should be passed. Caller of function with Provide[T] may explicitly
override argument annotated with Provide[T] by directly passing annotated_di_arg=my_value.
Container
Container helps to collect classes and potential functions into a single unit.
All containers must be singletons inherited from Container class.
To create a container, write and inheritor of Container class and annotate it with @Injector.singleton.
Then you may register components in the container by annotating them with @MyContainer.component.
Additionally, @MyContainer.component may be called with () in order to provide metadata about the component.
Container._get_components
The container expose protected method _get_components which returns all components registered in the container
in form of iterable of registrations.
Container._on_component_registered
The container have protected method _on_component_registered which is called every time a new component is registered
in the container.
ComponentRegistration
ComponentRegistration is a dataclass which holds information about registered component which
consists of:
component: an actual component typeargs: arguments passed to@MyContainer.componentduring registrationkwargs: keyword arguments passed to@MyContainer.componentduring registration
Collector
Collector is a class which imports all modules in order execute decorators.
[!WARNING] Collector should be used in top-level modules of the project as calling it from a submodule which is imported by other submodules may lead to circular imports.
Collector.collect_from_package
This method imports all modules in a given package.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file smalldi-0.2.0.tar.gz.
File metadata
- Download URL: smalldi-0.2.0.tar.gz
- Upload date:
- Size: 8.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
47134e79b0c1c36607284b979bcb30a85fa05100d454ac51649e014e71dab46e
|
|
| MD5 |
397da5cd115b8ac0867f24dde7929462
|
|
| BLAKE2b-256 |
d84381a8e269ff8d9c3a01a7db0409c416cefee940641b11f7a60e47747e6979
|
Provenance
The following attestation bundles were made for smalldi-0.2.0.tar.gz:
Publisher:
publish.yaml on 0xf104a/smalldi
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
smalldi-0.2.0.tar.gz -
Subject digest:
47134e79b0c1c36607284b979bcb30a85fa05100d454ac51649e014e71dab46e - Sigstore transparency entry: 941910770
- Sigstore integration time:
-
Permalink:
0xf104a/smalldi@9ea179d965bb3c946126bed3114afdfb79ee0369 -
Branch / Tag:
refs/tags/0.2.0 - Owner: https://github.com/0xf104a
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@9ea179d965bb3c946126bed3114afdfb79ee0369 -
Trigger Event:
release
-
Statement type:
File details
Details for the file smalldi-0.2.0-py3-none-any.whl.
File metadata
- Download URL: smalldi-0.2.0-py3-none-any.whl
- Upload date:
- Size: 8.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
16dabc0272b90f135870612b5946a4216ecdc16518e1950b827d98361c32f5df
|
|
| MD5 |
939cb3e159bb73b99a353b9e757c5f79
|
|
| BLAKE2b-256 |
5f9662f20288f163472b3680b444e157d129bbd5fe4c0670c8d579bdaf47999e
|
Provenance
The following attestation bundles were made for smalldi-0.2.0-py3-none-any.whl:
Publisher:
publish.yaml on 0xf104a/smalldi
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
smalldi-0.2.0-py3-none-any.whl -
Subject digest:
16dabc0272b90f135870612b5946a4216ecdc16518e1950b827d98361c32f5df - Sigstore transparency entry: 941910776
- Sigstore integration time:
-
Permalink:
0xf104a/smalldi@9ea179d965bb3c946126bed3114afdfb79ee0369 -
Branch / Tag:
refs/tags/0.2.0 - Owner: https://github.com/0xf104a
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@9ea179d965bb3c946126bed3114afdfb79ee0369 -
Trigger Event:
release
-
Statement type: