pyiv.override

Config overlay for replacing production bindings in tests.

What Problem Does This Solve?

Test suites need the real module graph with a few bindings swapped for doubles. Rebuilding the whole Config is brittle. override(base).with_(test) keeps the base registrations and replaces only keys present in the override.

Real-World Use Cases:

  • Swap Clock / Filesystem for synthetic doubles in integration tests

  • Replace a remote client with an in-memory stub while keeping the rest of the graph

Usage Examples:

>>> from pyiv import Config, get_injector
>>> from pyiv.override import override
>>> class Database:
...     def name(self) -> str:
...         return "prod"
>>> class ProdDatabase(Database):
...     def name(self) -> str:
...         return "prod"
>>> class FakeDatabase(Database):
...     def name(self) -> str:
...         return "fake"
>>> class ProdConfig(Config):
...     def configure(self):
...         self.register(Database, ProdDatabase)
>>> class TestConfig(Config):
...     def configure(self):
...         self.register(Database, FakeDatabase)
>>> inj = get_injector(override(ProdConfig).with_(TestConfig))
>>> inj.inject(Database).name()
'fake'
class pyiv.override.OverriddenConfig(bases: Tuple[Type[Config] | Config, ...], overrides: Tuple[Type[Config] | Config, ...])[source]

Bases: Config

Merged config: base bindings with override bindings on top.

Why this exists: Tests need the production graph with a few keys swapped. Prefer override() rather than constructing this directly.

See the OverrideBuilder example for usage via override(...).with_(...).

__init__(bases: Tuple[Type[Config] | Config, ...], overrides: Tuple[Type[Config] | Config, ...])[source]

Initialize the configuration.

configure() → None[source]

No-op; bindings come from merged modules.

class pyiv.override.OverrideBuilder(bases: Tuple[Type[Config] | Config, ...])[source]

Bases: object

Fluent step after override() — call with_() to finish.

Why this exists: Splitting override(base) from .with_(test) keeps the API readable when overlaying several override modules.

Example

>>> from pyiv import Config, get_injector
>>> class Database:
...     def name(self) -> str:
...         return "prod"
>>> class Fake(Database):
...     def name(self) -> str:
...         return "fake"
>>> class Prod(Config):
...     def configure(self):
...         self.register(Database, Database)
>>> class Test(Config):
...     def configure(self):
...         self.register(Database, Fake)
>>> get_injector(override(Prod).with_(Test)).inject(Database).name()
'fake'
__init__(bases: Tuple[Type[Config] | Config, ...])[source]
with_(*overrides: Type[Config] | Config) → Config[source]

Return a config that overlays overrides on the bases.

Bindings in later overrides win over earlier ones and over the bases.

pyiv.override.override(*bases: Type[Config] | Config) → OverrideBuilder[source]

Start an override overlay over one or more base configs.

Example:

get_injector(override(ProdConfig).with_(TestConfig))