diff --git a/docs/index.md b/docs/index.md index 65baf38..0500809 100644 --- a/docs/index.md +++ b/docs/index.md @@ -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) @@ -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 @@ -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 } diff --git a/profile/README.md b/profile/README.md index 4334d0a..5bcb3aa 100644 --- a/profile/README.md +++ b/profile/README.md @@ -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 diff --git a/scripts/check_site_content.sh b/scripts/check_site_content.sh index ac92caf..cd429bb 100755 --- a/scripts/check_site_content.sh +++ b/scripts/check_site_content.sh @@ -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 diff --git a/tests/test_profile.py b/tests/test_profile.py index 2e2fb01..f575673 100644 --- a/tests/test_profile.py +++ b/tests/test_profile.py @@ -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]: @@ -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: