Usage examples

Injecting services and parameters

from glorpen.di import Container

class MyParamService(object):
    pass

class MyService(object):
    def __init__(self, obj, text, value):
        super(MyService, self).__init__()
        print("service instance: %s" % obj)
        print("container parameter: %s" % text)
        print("provided value: %s" % value)

c = Container()

c.add_service(MyParamService)
c.add_parameter('my-param', "value from container")
c.add_service(MyService).kwargs(obj__svc=MyParamService, text__param="my-param", value="defined value")

c.get(MyService)

Running snippet will print:

service instance: <__main__.MyParamService object at 0x7f2fef6e9828>
container parameter: value from container
provided value: defined value

Arguments

In cases when you want to use inject parameter already used by internal methods, eg. glorpen.di.container.Service.call(), you can pass args with glorpen.di.container.Kwargs helper class.

svc.configurator(callable=configurator, kwargs=Kwargs(router__svc=Router), other_param="param")
svc.call("some_method", kwargs=Kwargs(router__svc=Router), other_param="param")

Arguments defined by glorpen.di.container.Kwargs are overriding ones provided by **kwargs notation.

Configurators

Configurators are services or callables used to configure main service. Provided callables are given main service instance as first argument.

def configurator(obj, some_service):
   obj.some_thing = some_service()
svc.configurator(callable=configurator, some_service__svc=MyClass)
svc.configurator(service=ConfiguratorClass, method="some_method", some_service__svc=MyClass)

Factories

Services that create other objects. It is possible to provide parameters/other services from Container to given callables.

def factory(some_service):
   return some_service("arg1")
svc1.factory(callable=factory, some_service__svc=MyClass)

class FactoryClass(object):
   def create_new(self, some_service):
   return some_service("arg1")
svc2.factory(service=FactoryClass, method="create_new", some_service__svc=MyClass)

Calling methods and settings properties

To call method on service creation:

svc.call("some_method", some_service__svc=MyClass)

To set properties on service creation:

svc.set(my_prop__svc=MyClass)

Using type hints for auto injection

Sometimes it is easier to just auto-fill function arguments, when using Python3 it can be done by arguments type hinting (see typing for more information).

You can enable function hints lookup by using glorpen.di.container.Service.kwargs_from_signature() for constructor arguments and glorpen.di.container.Service.call_with_signature() for methods.

from glorpen.di import Container

class MyParamService(object):
    pass

class MyService(object):
    def __init__(self, param:MyParamService):
        super(MyService, self).__init__()
        print("MyService.__init__: %s" % param.__class__.__name__)

    def some_method(self, param:MyParamService):
        print("MyService.some_method: %s" % param.__class__.__name__)

c = Container()

c.add_service(MyParamService)
c.add_service(MyService).kwargs_from_signature().call_with_signature("some_method")

print("Continer.get: %s" % c.get(MyService).__class__.__name__)

Snippet will create following output:

MyService.__init__: MyParamService
MyService.some_method: MyParamService
Continer.get: MyService

Adding custom scope

You can define new scope by extending glorpen.di.scopes.ScopeBase and using glorpen.di.container.Container.set_scope_hierarchy().

from glorpen.di.scopes import ScopePrototype, ScopeSingleton, ScopeBase
from random import randint

class RandomScope(ScopeBase):
    """Returns new or cached instances based on random factor."""
    def __init__(self, randomity=3):
        super(RandomScope, self).__init__()
        self.rnd = randomity
        self.instances = {}

    def get(self, creator, name):
        if not name in self.instances or randint(0, self.rnd) == 0:
            self.instances[name] = creator()
        return self.instances[name]

c = Container()

# add scope with parameter
c.set_scope_hierarchy(ScopeSingleton, RandomScope(5), ScopePrototype)

# configure "str" service so we can see instances count
counter = 0
def configurator(kwargs):
    global counter
    kwargs.setdefault("object", "instance number: %d" % counter)
    counter+=1

c.add_service('arg.test').implementation(str)\
    .configurator(args_callable=configurator)\
    .scope(RandomScope)

for i in range(0,10):
    print(c.get("arg.test"))

Running script will print:

instance number: 0
instance number: 0
instance number: 0
instance number: 0
instance number: 1
instance number: 2
instance number: 2
instance number: 3
instance number: 4
instance number: 4