Binding

Register an abstract type once. The injector builds constructor arguments from annotations.

Config.register

The direct API. concrete can be a class or a zero-argument factory:

from pyiv import Config, get_injector

class Database:
    pass

class PostgreSQL(Database):
    pass

class Logger:
    pass

class FileLogger(Logger):
    pass

class MyConfig(Config):
    def configure(self):
        self.register(Database, PostgreSQL)
        self.register(Logger, FileLogger, singleton=True)

injector = get_injector(MyConfig)
injector.inject(Database)  # PostgreSQL

singleton=True is a per-injector singleton. See Scopes for Scope and process-wide singletons.

Binder

get_binder() is the same registrations with a fluent chain. Use it when you want .to(...), .to_instance(...), or .in_scope(...) in one expression:

from pyiv import Config
from pyiv.scope import SingletonScope

class Cache:
    pass

class MyConfig(Config):
    def configure(self):
        binder = self.get_binder()
        binder.bind(Database).to(PostgreSQL)
        binder.bind(Logger).to(FileLogger).in_scope(SingletonScope())
        binder.bind_instance(Cache, Cache())

register and Binder write the same config. Pick one style per project; mixing them in one configure() is fine.

Installing modules

install merges another Config into this one. Later installs overwrite the same type or key (last wins). Use pyiv.override.override() when you want an explicit base/override overlay for tests.

from pyiv import Config, get_injector

class Database:
    pass

class PostgreSQL(Database):
    pass

class DbConfig(Config):
    def configure(self):
        self.register(Database, PostgreSQL)

class AppConfig(Config):
    def configure(self):
        self.install(DbConfig)

get_injector(AppConfig).inject(Database)  # PostgreSQL

Untargeted bindings

binder.bind(Concrete) without .to(...) registers a self-binding (needed for explicit-binding mode and private modules):

class Service:
    pass

class MyConfig(Config):
    def configure(self):
        self.get_binder().bind(Service)

Stages

get_injector(config, stage=Stage.PRODUCTION) eagerly creates singleton-scoped bindings at build time so misconfiguration fails fast. The default is Stage.DEVELOPMENT (lazy).

See also Hierarchy and private modules for child injectors and private modules.

Unregistered concrete types

If you inject() a concrete class that was never registered, the injector still constructs it and fills its annotated parameters (unless require_explicit_bindings() is set). Interfaces and ABCs must be bound (or marked optional — see Keys and collections). Concrete constructor dependencies are also just-in-time constructed when explicit mode is off.

See also pyiv.config and pyiv.binder.