Examples¶
Reusing functions by dependencies¶
import siringa
@siringa.register
def mul(x, y):
return x * y
@siringa.register
def mul2(x, mul: '!mul'):
return mul(x, 2)
@siringa.register
def pow2(x):
return x ** 2
@siringa.inject
def compute(x, pow: '!pow2', mul: '!mul2'):
return pow(mul(x))
print('Result:', compute(2)) # => 16
Invoke function with automatic dependency injection¶
import siringa
@siringa.register
def mul2(x):
return x * 2
# Note that the function was not instrumented yet!
def compute(x, mul: '!mul2'):
return mul(x)
# Invoke function
print('Result:', siringa.invoke(compute, 2))
Create a custom dependency container¶
import siringa
# Create a custom dependency layer
layer = siringa.Layer('app')
# Then you can use the standard API
layer.register('print', print)
# Then you can use the standard API
@layer.inject
def mul2(x, print: '!'):
print('Argument:', x)
return x * 2
print('Result:', mul2(2))
Custom layer with parent inheritance¶
import siringa
# Create parent dependency layer
parent = siringa.Layer('parent')
# Create child dependency layer that inherits from parent
child = siringa.Layer('child', parent)
# Register a sample dependency within parent container
@parent.register
def mul2(x):
return x * 2
# Verify that the dependency is injectable from child layer
print('Is injectable from parent:', parent.is_injectable('mul2'))
print('Is injectable from child:', child.is_injectable('mul2'))
@child.inject
def compute(x, mul: '!mul2'):
return mul(x)
print('Result:', compute(2))
Featured example using classes¶
import sys
import siringa
import logging
@siringa.register
def logger():
logger = logging.getLogger('siringa')
handler = logging.StreamHandler(sys.stdout)
logger.addHandler(handler)
logger.setLevel(logging.CRITICAL)
return logger
@siringa.register
def log(logger: '!logger', *args):
logger().info(*args)
@siringa.register
class Owner(object):
def __init__(self, name):
self.name = name
@siringa.register
class Pet(object):
@siringa.inject
def __init__(self, name, owner, log: '!log'):
self.name = name
self.owner = owner
log('new pet with name {}'.format(name))
@siringa.inject
def factory(owner, pet_name, Pet: '!Pet', Owner: '!Owner'):
return Pet(pet_name, Owner(owner))
pet = factory('Tomás', 'Arya')
print('Pet is name:', pet.name)
print('Owner is name:', pet.owner.name)
Injection flag based annotations¶
import siringa
@siringa.register
def foo():
return 'foo'
# Use '!' flag for DRYer dependency injection
# Argument name expression will be used for dependency pattern matching
@siringa.inject
def bar(foo: '!'):
return foo()
assert bar() == foo()
print('Succeeded!')
Mocking dependencies¶
import siringa
@siringa.register
class DB(object):
def query(self, sql):
return ['john', 'mike']
@siringa.mock('DB')
class DBMock(object):
def query(self, sql):
return ['foo', 'bar']
@siringa.inject
def run(sql, db: '!DB'):
return db().query(sql)
# Test mock call
assert run('SELECT name FROM foo') == ['foo', 'bar']
# Once done, clear the mock
siringa.unregister_mock('DB')
# Or alternatively clear all the registed mocks within the container
siringa.clear_mocks()
# Test read call
assert run('SELECT name FROM foo') == ['john', 'mike']