Knot is a small do-it-yourself (DIY) dependency container for Python.
Unlike other existing implementations, knot does not make use of introspection. Therefore, dependencies are manually defined in a straight forward manner. The container acts as a central registry for providers and configuration settings.
The container is just an ordinary dictionary with some additional methods. As a result, it is very easy to assign or retrieve data from it. Probably the most common way to assign configuration settings is passing a dict to the constructor.
from knot import Container
c = Container({'host': 'localhost', 'port': 6379})
Obviously it is also possible to add configuration settings to an existing container.
c = Container()
c['host'] = 'localhost'
c['port'] = 6379
A provider creates and returns a particular value or object. It has the ability to utilize an injected container to retrieve the necessary configuration settings and dependencies.
The container expects a provider to adhere to the following rules:
- It must be callable.
- It must accept the container as the only argument.
- It must return anything except
None
.
Assigning a provider to a container is easy.
def connection(c):
from redis import Redis
return Redis(host=c['host'], port=c['port'])
c.add_provider(connection, True)
It is also possible to use a decorator.
from knot import provider
@provider(c, True)
def connection(c):
from redis import Redis
return Redis(host=c['host'], port=c['port'])
The second argument in c.add_provider(connection, True)
and in
@provider(c, True)
indicates whether or not the return value of a provider
must be cached.
Retrieve what you have defined.
conn = c.provide('connection')
For convenience, you can also use the shortcut.
conn = c('connection')
A service is just a provider with the cache argument set to True
.
Basically this means the return value is created only once.
def connection(c):
from redis import Redis
return Redis(host=c['host'], port=c['port'])
c.add_service(connection)
Or with a decorator.
from knot import service
@service(c)
def connection(c):
from redis import Redis
return Redis(host=c['host'], port=c['port'])
conn1 = c('connection')
conn2 = c('connection')
print conn1 is conn2 # True
A factory is just a provider with the cache argument set to False
.
Basically this means the return value is created on every call.
def urgent_job(c):
from somewhere import Job
connection = c('connection')
return Job(connection=connection, queue='urgent')
c.add_factory(urgent_job)
job1 = c('urgent_job')
job1.enqueue('send_activation_mail', username='johndoe')
job2 = c('urgent_job')
job2.enqueue('send_activation_mail', username='janedoe')
print job1 is job2 # False
Or with a decorator.
from knot import @factory
@factory(c)
def urgent_job(c):
from somewhere import Job
connection = c('connection')
return Job(connection=connection, queue='urgent')
Install Knot with the following command:
$ pip install knot
To run the tests, install tox first:
$ pip install tox
Then, run the tests with the following command:
$ tox
Pimple (http://pimple.sensiolabs.org/)
MIT, see LICENSE for more details.