Read the latest Real Python tutorials
Project description
Documentation for IOCFramework
This project is a dependency injection frameework for python Object Oriented projects.
Installation
pip install iocframework
Basic uses
- Registering a project's class dependency maps.
- Resolving a project's dependencies from registered dependency maps.
- Resolving a project's class' nested dependency, leveraging typing to instantiate dependencies that have no args constructors.
Example use case
from IOCFramework import get_app
class BarService:
def __init__(self):
pass
class FooService:
bar_service: BarService
def __init__(self, bar_service: BarService):
self.bar_service = bar_service
class FooController:
foo_service: FooService
def __init__(self, foo_service: FooService):
self.foo_service = foo_service
app = get_app()
foo_controller = app.make(FooController) # makes an instance of fooController
In the example above the dependency tree goes from FooController
down to BarService
, in real life it could be deeper, this package smartly resolves and instantiates FooController by going down the dependency graph. It recognizes BarService
as a dependency of FooService
which on its own is a dependency of the required FooController
.
Another use case is when you want to resolve a class but with some default values.
Example use case
from IOCFramework import get_app
class BarService:
def __init__(self):
pass
class FooService:
bar_service: BarService
def __init__(self, bar_service: BarService):
self.bar_service = bar_service
app = get_app()
custom_bar_service = BarService() # custom instance of barService
foo_service = app.make_with(FooService, {"bar_service": custom_bar_service})
In the example above, we created an instance of FooService
to which we we manually injected an already created instance of its dependency BarService
by manually creating an instance of BarService
and passing it by parameter name to the container. This is very helpful for passing constants to class instances or when passing an object created by another class to the new class.
Another use case is binding classes or interfaces to their implementation in the container.
Example use case
from IOCFramework import get_app
class BarService:
def __init__(self):
pass
class AbstractFooService:
def say_foo(self):
raise MethodNotImplemented
class FooService(AbstractFooService):
bar_service: BarService
def __init__(self, bar_service: BarService):
self.bar_service = bar_service
def say_foo(self):
return "foo"
app = get_app()
bindings = {
AbstractFooService: FooService
}
app.add_bindings(bindings)
foo_service = app.make(AbstractFooService)
foo_val = foo_service.say_foo() # returns foo
In the example above, we registered AbstractFooService
to return an instance of FOOService
, this pattern can be useful when a single base class has multiple different implementations for differenct use cases.
The use case above can be extended for singletons, suppose we want our entire application to use a single instance of a very expensive class, we can use the singleton method of app; here is an example
Example use case
from IOCFramework import get_app
class BarService:
def __init__(self):
pass
class FooService:
bar_service: BarService
def __init__(self, bar_service: BarService):
self.bar_service = bar_service
class FizzService:'
bar_service: BarService
def __init__(self, bar_service: BarService):
self.bar_service = bar_service
app = get_app()
singletons = {
BarService: BarService
}
app.add_singletons(singletons)
foo_service = app.make(FooService)
fizz_service = app.make(FizzService)
fizz_service.bar_service == foo_service.bar_service # True because barService is a singleton
There is yet another use case which adds power to the use cases above, imagine for you have a base class with multiple subclasses, with each of the subclasses serving a single service class. To resolve this, you could type the dependency on the services with their specific class implementation, locking yourself to an implementation or you could type them all with their base class and resolve them by need.
Example use case
from IOCFramework import get_app
class BaseBarService:
def __init__(self):
pass
class FooBarService(BaseBarService):
def __init__(self):
pass
class FizzBarService(BaseBarService):
def __init__(self):
pass
class FooService:
bar_service: BaseBarService
def __init__(self, bar_service: BaseBarService):
self.bar_service = bar_service
class FizzService:'
bar_service: BaseBarService
def __init__(self, bar_service: BaseBarService):
self.bar_service = bar_service
app = get_app()
app.when(FizzService, needs=BaseBarService, give=FizzBarService) # give can also be a callable which returns an instance of the service in question
app.when(FooService, needs=BaseBarService, give=FooBarService)
fizz_service = app.make(FizzService)
foo_service = app.make(FooService)
isinstance(fizz_service.bar_service, FizzBarService) # True
isinstance(foo_service.bar_service, FooBarService) # True
This project is based on Laravel's IOC container.
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
Hashes for iocframework-1.0.0-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 68b37fd609b54a6cdba790ae2fe258fe8d15624b5f9254749655a972d6d7b045 |
|
MD5 | aed2d0e1528176057803bdbbf2ddd219 |
|
BLAKE2b-256 | 2793fbd95ec3c46d7cf0e8181e67825d0920a5c7fe59d44372563f34c896b926 |