Lifetime / scoping

Different class instances are meant to live for different time. For example we’ll want our database Session instance to live as long as our web request does.

On the other hand we may want our Redis class instance - which is thread-safe and uses connection pool to live for as long as the application, regardless of the web request lifetime.

injectpy has three lifetime types:

  • transient: default lifetime. It means that a new class instance is created every time (they are never re-used).
  • singleton: only a single instance will be created and every time an instance is requested we will re-use it.
  • scoped: only one instance is created per scope. You’ll learn to manage scopes later in this chapter.

Specyfing lifetime

Specyfing lifetime is pretty easy: just use lifetime argument:

from injectpy import Kernel, Singleton, Scoped

kernel = Kernel()

kernel.bind(Flask, factory=app_factory, lifetime=Singleton)

lifetime argument applies to a binding. This means that if you set lifetime on a concrete class - only a single instance will be created of that class, like above.

Let’s consider a different example. When writing tests you may want to bind some e-mail interface to an implementation which doesn’t send out real e-mails and allows you to inspect them:

kernel.bind(IEmailPort, to=InMemoryEmailAdapter, lifetime=Singleton)

# create service
service = kernel.get(RegistrationService)
adapter = kernel.get(InMemoryEmailAdapter)
# simulate registration
service.register('john@example.com')
# make sure that the e-mail was sent
assert len(adapter.inbox) == 1

The above test WILL FAIL. The reason is that lifetime applies to IEmailPort. So:

kernel.bind(IEmailPort, to=InMemoryEmailAdapter, lifetime=Singleton)

inst1 = kernel.get(IEmailPort)
inst2 = kernel.get(InMemoryEmailAdapter)

assert inst1 is not inst2

To make sure that we get only one instance of InMemoryEmailAdapter, not IEmailPort we need to apply lifetime like this:

kernel.bind(IEmailPort, to=InMemoryEmailAdapter)
kernel.bind(InMemoryEmailAdapter, lifetime=Singleton)

inst1 = kernel.get(IEmailPort)
inst2 = kernel.get(InMemoryEmailAdapter)

assert inst1 is inst2

Controlling scope

TBD