Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ change/decision index. The applied convention version is in

This package is a thin pytest adapter over [`modern-di`](https://github.com/modern-python/modern-di). All implementation lives in `modern_di_pytest/factory.py` and exposes exactly two public symbols:

- `modern_di_fixture(dependency, *, container_fixture="di_container", name=None, pytest_scope="function")` — wraps a single type or `AbstractProvider` in a `@pytest.fixture`. At fixture time it calls `request.getfixturevalue(container_fixture)`, then dispatches: `AbstractProvider` → `container.resolve_provider(...)`, otherwise `container.resolve(...)`.
- `modern_di_fixture(dependency, *, container_fixture="di_container", name=None, pytest_scope="function")` — wraps a single type or `AbstractProvider` in a `@pytest.fixture`. At fixture time it calls `request.getfixturevalue(container_fixture)`, then delegates to `container.resolve_dependency(dependency)` — the type-or-provider dispatch lives in modern-di itself.
- `expose(*groups, container_fixture="di_container", pytest_scope="function", module=None)` — variadic: accepts one or more `Group` subclasses. For each, iterates `vars(group)` and for every attribute that is an `AbstractProvider` instance, builds a `modern_di_fixture` and `setattr`s it onto the target module under the attribute's name. Non-Provider attributes (strings, ints, underscored, etc.) are silently skipped. A duplicate attribute name across the given groups raises `ValueError`; calling with no groups raises `TypeError`. When `module` is omitted, the caller's module is located via `inspect.stack()[1]` — `expose` therefore only works when called from module scope of a `conftest.py` / test module, not from inside a function.

Key contract: this package does **not** own the container. The user defines a `di_container` pytest fixture (any scope) that yields a `modern_di.Container`. Child-scoped containers (e.g. `REQUEST`) are accessed by passing a different `container_fixture=` name — see `tests/conftest.py` for the `di_container` / `di_request_container` pattern. Overrides are not re-implemented here; users call `Container.override()` / `reset_override()` directly.
Expand Down
8 changes: 3 additions & 5 deletions modern_di_pytest/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ def modern_di_fixture(
"""Turn a modern-di dependency into a pytest fixture.

Args:
dependency: A type (resolved via ``container.resolve``) or a Provider
(resolved via ``container.resolve_provider``).
dependency: A type or a Provider, resolved via
``container.resolve_dependency``.
container_fixture: Name of the pytest fixture that yields the container
to resolve from. Defaults to ``"di_container"``. Use a child
container fixture (e.g. ``"di_request_container"``) to resolve at a
Expand All @@ -49,9 +49,7 @@ def test_listing(user_service):
@pytest.fixture(name=name, scope=pytest_scope)
def _fixture(request: pytest.FixtureRequest) -> typing.Any: # noqa: ANN401
container = request.getfixturevalue(container_fixture)
if isinstance(dependency, AbstractProvider):
return container.resolve_provider(dependency)
return container.resolve(dependency)
return container.resolve_dependency(dependency)

return _fixture

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ classifiers = [
"Topic :: Software Development :: Libraries",
"Topic :: Software Development :: Testing",
]
dependencies = ["modern-di>=2.16.1,<3", "pytest>=7"]
dependencies = ["modern-di>=2.25,<3", "pytest>=7"]
version = "0"

[project.urls]
Expand Down
Loading