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
18 changes: 3 additions & 15 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ wires them together.

---

The `modern-di` family of DI frameworks and integrations.
The `modern-di` and `that-depends` DI frameworks.

[:octicons-arrow-right-24: Browse DI](#di)

Expand Down Expand Up @@ -100,7 +100,8 @@ Every project is built with the same tooling
!!! tip "Which one should I use?"

Start new projects on [`modern-di`](https://github.com/modern-python/modern-di)
— a minimal core plus the integrations listed below.
— a minimal core plus framework integrations, listed in
[its docs](https://modern-di.modern-python.org/).

[`that-depends`](https://github.com/modern-python/that-depends) is the earlier,
async-first sibling and stays maintained. `modern-di` has migration guides
Expand All @@ -109,19 +110,6 @@ Every project is built with the same tooling
[from `dependency-injector`](https://modern-di.modern-python.org/migration/from-dependency-injector/).

- [`modern-di`](https://github.com/modern-python/modern-di): Powerful dependency-injection framework with IoC container and scopes
- [`modern-di-aiogram`](https://github.com/modern-python/modern-di-aiogram): modern-di integration for aiogram
- [`modern-di-aiohttp`](https://github.com/modern-python/modern-di-aiohttp): modern-di integration for aiohttp
- [`modern-di-arq`](https://github.com/modern-python/modern-di-arq): modern-di integration for arq
- [`modern-di-celery`](https://github.com/modern-python/modern-di-celery): modern-di integration for Celery
- [`modern-di-fastapi`](https://github.com/modern-python/modern-di-fastapi): modern-di integration for FastAPI
- [`modern-di-faststream`](https://github.com/modern-python/modern-di-faststream): modern-di integration for FastStream
- [`modern-di-flask`](https://github.com/modern-python/modern-di-flask): modern-di integration for Flask
- [`modern-di-grpc`](https://github.com/modern-python/modern-di-grpc): modern-di integration for gRPC
- [`modern-di-litestar`](https://github.com/modern-python/modern-di-litestar): modern-di integration for Litestar
- [`modern-di-pytest`](https://github.com/modern-python/modern-di-pytest): Pytest integration for modern-di that turns DI dependencies into fixtures
- [`modern-di-starlette`](https://github.com/modern-python/modern-di-starlette): modern-di integration for Starlette
- [`modern-di-taskiq`](https://github.com/modern-python/modern-di-taskiq): modern-di integration for taskiq
- [`modern-di-typer`](https://github.com/modern-python/modern-di-typer): modern-di integration for Typer
- [`that-depends`](https://github.com/modern-python/that-depends): Simple, typed dependency-injection framework for Python

## Microservices, HTTP & messaging { #services }
Expand Down
15 changes: 1 addition & 14 deletions profile/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,13 @@ Open-source templates and libraries for building production-ready Python applica

### Dependency injection

**Which one?** Start new projects on [`modern-di`](https://github.com/modern-python/modern-di) — a minimal core plus the integrations below.
**Which one?** Start new projects on [`modern-di`](https://github.com/modern-python/modern-di) — a minimal core plus framework integrations, listed in [its docs](https://modern-di.modern-python.org/).

[`that-depends`](https://github.com/modern-python/that-depends) is the earlier, async-first sibling and stays maintained. `modern-di` has migration guides [from `that-depends`](https://modern-di.modern-python.org/migration/from-that-depends/) and [from `dependency-injector`](https://modern-di.modern-python.org/migration/from-dependency-injector/).

| Project | What it is | Stars | Downloads |
|---|---|---|---|
| [`modern-di`](https://github.com/modern-python/modern-di) | Powerful dependency-injection framework with IoC container and scopes | [![Stars](https://img.shields.io/github/stars/modern-python/modern-di)](https://github.com/modern-python/modern-di/stargazers) | [![Downloads](https://static.pepy.tech/badge/modern-di/month)](https://pepy.tech/projects/modern-di) |
| [`modern-di-aiogram`](https://github.com/modern-python/modern-di-aiogram) | modern-di integration for aiogram | [![Stars](https://img.shields.io/github/stars/modern-python/modern-di-aiogram)](https://github.com/modern-python/modern-di-aiogram/stargazers) | [![Downloads](https://static.pepy.tech/badge/modern-di-aiogram/month)](https://pepy.tech/projects/modern-di-aiogram) |
| [`modern-di-aiohttp`](https://github.com/modern-python/modern-di-aiohttp) | modern-di integration for aiohttp | [![Stars](https://img.shields.io/github/stars/modern-python/modern-di-aiohttp)](https://github.com/modern-python/modern-di-aiohttp/stargazers) | [![Downloads](https://static.pepy.tech/badge/modern-di-aiohttp/month)](https://pepy.tech/projects/modern-di-aiohttp) |
| [`modern-di-arq`](https://github.com/modern-python/modern-di-arq) | modern-di integration for arq | [![Stars](https://img.shields.io/github/stars/modern-python/modern-di-arq)](https://github.com/modern-python/modern-di-arq/stargazers) | [![Downloads](https://static.pepy.tech/badge/modern-di-arq/month)](https://pepy.tech/projects/modern-di-arq) |
| [`modern-di-celery`](https://github.com/modern-python/modern-di-celery) | modern-di integration for Celery | [![Stars](https://img.shields.io/github/stars/modern-python/modern-di-celery)](https://github.com/modern-python/modern-di-celery/stargazers) | [![Downloads](https://static.pepy.tech/badge/modern-di-celery/month)](https://pepy.tech/projects/modern-di-celery) |
| [`modern-di-fastapi`](https://github.com/modern-python/modern-di-fastapi) | modern-di integration for FastAPI | [![Stars](https://img.shields.io/github/stars/modern-python/modern-di-fastapi)](https://github.com/modern-python/modern-di-fastapi/stargazers) | [![Downloads](https://static.pepy.tech/badge/modern-di-fastapi/month)](https://pepy.tech/projects/modern-di-fastapi) |
| [`modern-di-faststream`](https://github.com/modern-python/modern-di-faststream) | modern-di integration for FastStream | [![Stars](https://img.shields.io/github/stars/modern-python/modern-di-faststream)](https://github.com/modern-python/modern-di-faststream/stargazers) | [![Downloads](https://static.pepy.tech/badge/modern-di-faststream/month)](https://pepy.tech/projects/modern-di-faststream) |
| [`modern-di-flask`](https://github.com/modern-python/modern-di-flask) | modern-di integration for Flask | [![Stars](https://img.shields.io/github/stars/modern-python/modern-di-flask)](https://github.com/modern-python/modern-di-flask/stargazers) | [![Downloads](https://static.pepy.tech/badge/modern-di-flask/month)](https://pepy.tech/projects/modern-di-flask) |
| [`modern-di-grpc`](https://github.com/modern-python/modern-di-grpc) | modern-di integration for gRPC | [![Stars](https://img.shields.io/github/stars/modern-python/modern-di-grpc)](https://github.com/modern-python/modern-di-grpc/stargazers) | [![Downloads](https://static.pepy.tech/badge/modern-di-grpc/month)](https://pepy.tech/projects/modern-di-grpc) |
| [`modern-di-litestar`](https://github.com/modern-python/modern-di-litestar) | modern-di integration for Litestar | [![Stars](https://img.shields.io/github/stars/modern-python/modern-di-litestar)](https://github.com/modern-python/modern-di-litestar/stargazers) | [![Downloads](https://static.pepy.tech/badge/modern-di-litestar/month)](https://pepy.tech/projects/modern-di-litestar) |
| [`modern-di-pytest`](https://github.com/modern-python/modern-di-pytest) | Pytest integration for modern-di that turns DI dependencies into fixtures | [![Stars](https://img.shields.io/github/stars/modern-python/modern-di-pytest)](https://github.com/modern-python/modern-di-pytest/stargazers) | [![Downloads](https://static.pepy.tech/badge/modern-di-pytest/month)](https://pepy.tech/projects/modern-di-pytest) |
| [`modern-di-starlette`](https://github.com/modern-python/modern-di-starlette) | modern-di integration for Starlette | [![Stars](https://img.shields.io/github/stars/modern-python/modern-di-starlette)](https://github.com/modern-python/modern-di-starlette/stargazers) | [![Downloads](https://static.pepy.tech/badge/modern-di-starlette/month)](https://pepy.tech/projects/modern-di-starlette) |
| [`modern-di-taskiq`](https://github.com/modern-python/modern-di-taskiq) | modern-di integration for taskiq | [![Stars](https://img.shields.io/github/stars/modern-python/modern-di-taskiq)](https://github.com/modern-python/modern-di-taskiq/stargazers) | [![Downloads](https://static.pepy.tech/badge/modern-di-taskiq/month)](https://pepy.tech/projects/modern-di-taskiq) |
| [`modern-di-typer`](https://github.com/modern-python/modern-di-typer) | modern-di integration for Typer | [![Stars](https://img.shields.io/github/stars/modern-python/modern-di-typer)](https://github.com/modern-python/modern-di-typer/stargazers) | [![Downloads](https://static.pepy.tech/badge/modern-di-typer/month)](https://pepy.tech/projects/modern-di-typer) |
| [`that-depends`](https://github.com/modern-python/that-depends) | Simple, typed dependency-injection framework for Python | [![Stars](https://img.shields.io/github/stars/modern-python/that-depends)](https://github.com/modern-python/that-depends/stargazers) | [![Downloads](https://static.pepy.tech/badge/that-depends/month)](https://pepy.tech/projects/that-depends) |

### Microservices, HTTP & messaging
Expand Down
3 changes: 1 addition & 2 deletions scripts/check_site_content.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ test -f "$HTML" || { echo "MISSING $HTML — run 'uv run mkdocs build' first"; e

REPOS=(
fastapi-sqlalchemy-template litestar-sqlalchemy-template chat-app
modern-di modern-di-fastapi modern-di-litestar modern-di-faststream
modern-di-typer modern-di-pytest that-depends
modern-di that-depends
lite-bootstrap httpware jwks-client faststream-redis-timers
faststream-concurrent-aiokafka faststream-outbox
db-retry eof-fixer release-scope semvertag
Expand Down
40 changes: 24 additions & 16 deletions tests/test_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from brand.build import projects as p

_PROFILE = Path(__file__).parent.parent / "profile" / "README.md"
_INDEX = Path(__file__).parent.parent / "docs" / "index.md"


def _sections() -> dict[str, str]:
Expand All @@ -15,32 +16,39 @@ def _repos(section: str) -> list[str]:
return re.findall(r"^\| \[`([^`]+)`\]", section, flags=re.M)


def test_every_project_mark_has_a_profile_row() -> None:
"""INVARIANT: the repos in `projects.py::MANIFEST` and the repos listed in
`profile/README.md` are the same set.
def test_every_listed_project_mark_has_a_profile_row() -> None:
"""INVARIANT: the repos listed in `profile/README.md` are exactly the repos in
`projects.py::MANIFEST` minus the `modern-di-*` integrations.

They are the two halves of one act — a repo joins the org by getting a mark and a
profile row — but nothing links them, so adding, renaming, or unpublishing a repo
updates one and silently leaves the other behind. The failure is invisible: a mark
nobody links to, or a row whose banner 404s.
nobody links to, or a row whose banner 404s. Integrations keep their marks, because
their READMEs load the lockups from this repo, but are listed only on the modern-di
docs site.
"""
listed = {repo for section in _sections().values() for repo in _repos(section)}
assert listed == set(p.MANIFEST)
assert listed == {repo for repo in p.MANIFEST if not repo.startswith("modern-di-")}


def test_di_table_lists_core_first_then_alphabetical_then_that_depends() -> None:
"""INVARIANT: the Dependency injection table opens with `modern-di`, ends with
`that-depends`, and sorts every integration between them alphabetically.
def test_di_table_lists_only_the_two_frameworks() -> None:
"""INVARIANT: the Dependency injection table lists `modern-di` then `that-depends`.

The two anchors carry meaning — the core users should start from, and the earlier
framework that stays maintained — and alphabetical order in between is what makes a
new integration slot in with no insertion-point decision to make. Appending the
newest integration to the bottom is the natural move, and it lands past the anchor.
The order carries meaning: the core users should start from, then the earlier
framework that stays maintained.
"""
rows = _repos(_sections()["Dependency injection"])
assert rows[0] == "modern-di"
assert rows[-1] == "that-depends"
assert rows[1:-1] == sorted(rows[1:-1])
assert _repos(_sections()["Dependency injection"]) == ["modern-di", "that-depends"]


def test_no_modern_di_integration_on_the_org_profile_or_site() -> None:
"""INVARIANT: neither the org profile nor the org site homepage links a
`modern-di-*` integration repo.

Integrations are listed on the modern-di docs site. Re-adding one here is the
natural move when a new integration ships, and it brings the clutter back.
"""
for page in (_PROFILE, _INDEX):
assert re.findall(r"github\.com/modern-python/(modern-di-[\w-]+)", page.read_text(encoding="utf-8")) == []


def test_templates_carry_stars_only() -> None:
Expand Down
Loading