From f603260b8c7fb1fc26fecc2ecb1df41de416c0ce Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Thu, 2 Jul 2026 11:47:58 +0300 Subject: [PATCH 1/5] docs: design for onboarding modern-di-starlette into brand + surfaces Full-lane bundle: mint the sparkle-cluster mark, regenerate brand assets, list the integration on the profile README and docs site, and align its GitHub repo settings with org conventions. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../2026-07-02.01-starlette-brand/design.md | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 planning/changes/2026-07-02.01-starlette-brand/design.md diff --git a/planning/changes/2026-07-02.01-starlette-brand/design.md b/planning/changes/2026-07-02.01-starlette-brand/design.md new file mode 100644 index 0000000..e479e18 --- /dev/null +++ b/planning/changes/2026-07-02.01-starlette-brand/design.md @@ -0,0 +1,126 @@ +--- +summary: Add modern-di-starlette to the org brand kit (sparkle-cluster mark) and list it on the profile README, docs site, and its GitHub repo settings. +--- + +# Design: Onboard modern-di-starlette into the org brand and surfaces + +## Summary + +`modern-di-starlette` is a new DI integration. Its repo already ships a README +that references central brand assets under +`brand/projects/modern-di-starlette/` — assets that do not exist yet, so those +image links are currently broken. This change mints the project's mark (a +four-point **sparkle cluster**), regenerates its brand assets, adds it to the +`profile/README.md` DI table and the `docs/index.md` DI list, and brings its +GitHub repo metadata (description, topics, website) in line with org +conventions. All code changes live in this repo (`.github`); the integration +repo itself is already complete. + +## Motivation + +The `modern-di-starlette` README (in its own repo) points at +`https://raw.githubusercontent.com/modern-python/.github/main/brand/projects/modern-di-starlette/lockup-{light,dark}.svg` +and `lockup.png`. None of those files exist, so the README renders with a broken +image. Every sibling integration (`modern-di-fastapi`, `modern-di-litestar`, +`modern-di-faststream`, `modern-di-typer`, `modern-di-pytest`) has a mark, a +profile-README row, and a docs-site entry; Starlette must match to keep the +three metadata surfaces (GitHub description, pyproject `description`, profile +blurb) consistent. + +## Non-goals + +- No changes to the `modern-di-starlette` repo contents (README, CI, planning, + architecture already present and correct). +- No social card: integrations are not in `DOCS_REPOS`, matching the other + `modern-di-*` integrations, which have no per-project docs site. +- No new symbol vocabulary beyond the one Starlette mark. + +## Design + +### 1. Sparkle-cluster symbol — `brand/build/symbols.py` + +Add a `sparkle_cluster(cx, cy, r)` function: a large four-point sparkle with a +small secondary sparkle at upper-right, both filled in `GOLD` (no disc). The +four-point sparkle is a concave 8-vertex polygon (outer points at N/E/S/W, +inner points at the 45-degree diagonals). Uses only `GOLD`, so it satisfies the +`test_only_allowed_colours` palette check. It follows the same contract as the +existing `star_disc` / `bolt_disc` (takes `cx, cy, r`, returns bare SVG markup). + +The exact geometry is the approved candidate B, verified in the visual +companion: large sparkle centred slightly down-left, `r*0.82`, `inner=0.34`; +small sparkle up-right, `r*0.36`. The `project_lockup` dark-mode path already +swaps `GOLD_LIGHT` -> `GOLD_DARK` globally, so the dark lockup needs no special +handling. + +### 2. Manifest entry — `brand/build/projects.py` + +Add `"modern-di-starlette": lambda: sym.sparkle_cluster(_CX, _CY, R)` to +`MANIFEST`, in the dependency-injection block, immediately after +`modern-di-litestar` (keeps the web-framework integrations fastapi -> litestar -> +starlette adjacent). + +### 3. Test — `tests/test_projects.py` + +Add `"modern-di-starlette"` to `EXPECTED_REPOS`. That set is asserted equal to +`MANIFEST`, and the valid-SVG / allowed-colours / render tests are parametrized +off it, so no other test edits are required. `DOCS_EXPECTED` is unchanged +(Starlette gets no social card). + +### 4. Regenerate assets — `just sync-assets` + +Runs `python -m brand.build.render`, producing +`brand/projects/modern-di-starlette/{mark.svg, mark-512.png, mark-1024.png, +lockup-light.svg, lockup-dark.svg, lockup.png}`. Commit the generated files. +This resolves the integration repo's broken README image links. + +### 5. Profile README — `profile/README.md` + +Add one row to the **Dependency injection** table, immediately after the +`modern-di-litestar` row, blurb `modern-di integration for Starlette`, carrying +the same badge set as its siblings (Stars, PyPI, Downloads, Context7). + +### 6. Docs site — `docs/index.md` + +Add one bullet to the `Dependency injection { #di }` list after the Litestar +line: `` `modern-di-starlette` — `modern-di` integration for Starlette.`` Also +extend the "The stack" sentence to read "...shared across FastAPI, Starlette, +Litestar, FastStream, and Typer" so the narrative names the new integration. + +## Operations + +GitHub repo settings for `modern-python/modern-di-starlette`, set via `gh` to +match org conventions: + +- **Description:** `modern-di integration for Starlette` (the canonical + one-liner, matching pyproject and the profile blurb). +- **Website:** `https://modern-di.modern-python.org` (integrations have no own + docs site; they point at the modern-di docs). +- **Topics:** the `modern-di-*` integration base set plus the framework — + `python, dependency-injection, di, ioc-container, modern-di, starlette`. + +These are verified against the live repo before/after: read current values, +compare to the intended set, apply only the diff. + +## Testing + +- `just test` green, in particular `tests/test_projects.py`: + `test_manifest_covers_every_repo` (MANIFEST == EXPECTED_REPOS), + `test_only_allowed_colours`, `test_project_mark_is_valid_svg`, and the + render tests. +- Visually inspect the regenerated `mark.svg` and `lockup-light/dark.svg` / + `lockup.png` for the Starlette entry. +- Confirm the integration repo's README image links now resolve to real files + at the referenced paths. +- `just check-planning` passes before pushing. +- `gh repo view modern-python/modern-di-starlette` reflects the intended + description, homepage, and topics. + +## Risk + +- **Low: mark reads too close to Litestar.** Mitigated — the sparkle cluster is + four-point and disc-less, visibly distinct from Litestar's 5-point star-in- + disc; confirmed against the sibling marks in the visual companion. +- **Low: stray colour fails the palette test.** Mitigated — the symbol uses only + `GOLD`; `test_only_allowed_colours` is the guardrail. +- **Low: GitHub settings drift from pyproject/profile.** Mitigated — all three + use the single canonical one-liner `modern-di integration for Starlette`. From 558e01d15acc456f1024d1e53c17acc95544f0c7 Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Thu, 2 Jul 2026 11:51:29 +0300 Subject: [PATCH 2/5] docs: implementation plan for modern-di-starlette onboarding Five tasks: mint the sparkle-cluster mark, regenerate assets, list on the profile README + docs site, align GitHub repo settings, open the PR. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../2026-07-02.01-starlette-brand/design.md | 5 +- .../2026-07-02.01-starlette-brand/plan.md | 272 ++++++++++++++++++ 2 files changed, 275 insertions(+), 2 deletions(-) create mode 100644 planning/changes/2026-07-02.01-starlette-brand/plan.md diff --git a/planning/changes/2026-07-02.01-starlette-brand/design.md b/planning/changes/2026-07-02.01-starlette-brand/design.md index e479e18..444c3a7 100644 --- a/planning/changes/2026-07-02.01-starlette-brand/design.md +++ b/planning/changes/2026-07-02.01-starlette-brand/design.md @@ -83,8 +83,9 @@ the same badge set as its siblings (Stars, PyPI, Downloads, Context7). Add one bullet to the `Dependency injection { #di }` list after the Litestar line: `` `modern-di-starlette` — `modern-di` integration for Starlette.`` Also -extend the "The stack" sentence to read "...shared across FastAPI, Starlette, -Litestar, FastStream, and Typer" so the narrative names the new integration. +extend the "The stack" sentence to read "...shared across FastAPI, Litestar, +Starlette, FastStream, and Typer" so the narrative names the new integration +(matching the table/manifest order fastapi -> litestar -> starlette). ## Operations diff --git a/planning/changes/2026-07-02.01-starlette-brand/plan.md b/planning/changes/2026-07-02.01-starlette-brand/plan.md new file mode 100644 index 0000000..0a3bbe2 --- /dev/null +++ b/planning/changes/2026-07-02.01-starlette-brand/plan.md @@ -0,0 +1,272 @@ +# starlette-brand — implementation plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use +> superpowers:subagent-driven-development (recommended) or +> superpowers:executing-plans to implement this plan task-by-task. Steps +> use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Onboard `modern-di-starlette` into the org brand kit and every surface +its siblings appear on (mark, profile README, docs site, GitHub repo settings). + +**Spec:** [`design.md`](./design.md) + +**Branch:** `starlette-brand` (already created) + +**Commit strategy:** Per-task commits. + +## Global Constraints + +- Canonical one-liner, used verbatim on every surface: `modern-di integration for Starlette`. +- Brand marks may use only the allowed palette; the Starlette mark uses only `GOLD` (`GOLD_LIGHT = #c98a00`). `test_only_allowed_colours` is the guardrail. +- Ordering everywhere: web-framework integrations run fastapi -> litestar -> starlette (starlette inserted immediately after litestar) in the manifest, the profile table, the docs list, and the stack sentence. +- All Python edits: imports at module level, annotate every argument (repo house style + ruff `ALL`). +- Run from repo root `/Users/kevinsmith/src/pypi/modern-python`. Commands use `uv run` / `just` as the repo does. + +--- + +### Task 1: Mint the Starlette mark (symbol + manifest + test) + +**Files:** +- Modify: `tests/test_projects.py` (add repo to `EXPECTED_REPOS`) +- Modify: `brand/build/symbols.py` (add `_sparkle4` + `sparkle_cluster`) +- Modify: `brand/build/projects.py` (add `MANIFEST` entry) + +**Interfaces:** +- Produces: `sparkle_cluster(cx: float, cy: float, r: float) -> str` in `brand.build.symbols`, returning bare SVG markup (no `` wrapper), consumed by `MANIFEST["modern-di-starlette"]` in `brand.build.projects`. + +- [ ] **Step 1: Write the failing test** + + In `tests/test_projects.py`, add `"modern-di-starlette"` to the `EXPECTED_REPOS` set, immediately after the `"modern-di-litestar"` line: + + ```python + "modern-di-litestar", + "modern-di-starlette", + "modern-di-faststream", + ``` + +- [ ] **Step 2: Run the test to verify it fails** + + Run: `uv run pytest tests/test_projects.py -q` + Expected: FAIL — `test_manifest_covers_every_repo` asserts `set(p.MANIFEST) == EXPECTED_REPOS` and the manifest is missing `modern-di-starlette`; the `project_mark`/`only_allowed_colours` params for that repo also error with `KeyError: 'modern-di-starlette'`. + +- [ ] **Step 3: Add the sparkle symbols** + + In `brand/build/symbols.py`, add these two functions next to `_star5` (which ends just before `_circ_arc`). `_sparkle4` is a private helper; `sparkle_cluster` is the public mark. Colours: `GOLD` only. + + ```python + def _sparkle4(cx: float, cy: float, radius: float, color: str, inner: float = 0.34) -> str: + """Four-point sparkle (concave star) centred on (cx,cy).""" + pts: list[tuple[float, float]] = [] + for i in range(4): + ao = -90 + i * 90 + pts.append( + ( + cx + radius * math.cos(math.radians(ao)), + cy + radius * math.sin(math.radians(ao)), + ) + ) + ai = ao + 45 + pts.append( + ( + cx + radius * inner * math.cos(math.radians(ai)), + cy + radius * inner * math.sin(math.radians(ai)), + ) + ) + body = " ".join(f"{x:.1f},{y:.1f}" for x, y in pts) + return f'' + + + def sparkle_cluster(cx: float, cy: float, r: float) -> str: + """Starlette cue: a large four-point sparkle with a small companion + (a "little star" — starlette).""" + big = _sparkle4(cx - 0.174 * r, cy + 0.130 * r, r * 0.82, GOLD) + small = _sparkle4(cx + 0.565 * r, cy - 0.522 * r, r * 0.36, GOLD) + return big + small + ``` + +- [ ] **Step 4: Add the manifest entry** + + In `brand/build/projects.py`, inside `MANIFEST`, add the Starlette line immediately after `modern-di-litestar`: + + ```python + "modern-di-litestar": lambda: sym.star_disc(_CX, _CY, R), + "modern-di-starlette": lambda: sym.sparkle_cluster(_CX, _CY, R), + "modern-di-faststream": lambda: sym.faststream(_CX, _CY, R), + ``` + +- [ ] **Step 5: Run the tests to verify they pass** + + Run: `uv run pytest tests/test_projects.py -q` + Expected: PASS — manifest now equals `EXPECTED_REPOS`; the new repo's mark parses as valid SVG and uses only allowed colours. + +- [ ] **Step 6: Commit** + + ```bash + git add tests/test_projects.py brand/build/symbols.py brand/build/projects.py + git commit -m "feat(brand): add sparkle-cluster mark for modern-di-starlette" + ``` + +--- + +### Task 2: Regenerate and commit the brand assets + +**Files:** +- Create: `brand/projects/modern-di-starlette/{mark.svg,mark-512.png,mark-1024.png,lockup-light.svg,lockup-dark.svg,lockup.png}` + +Regenerate the kit so the integration repo's README image links resolve. + +- [ ] **Step 1: Regenerate** + + Run: `just sync-assets` + (Runs `uv run python -m brand.build.render`, then copies the org subset into `docs/assets/`.) + +- [ ] **Step 2: Verify only the new files changed** + + Run: `git status --short` + Expected: six new untracked files under `brand/projects/modern-di-starlette/` and nothing else. The render is deterministic, so existing project/org/docs assets must show no diff. If any other file changed, STOP and investigate (likely a tool/font version drift) before committing — do not blanket-commit unexpected diffs. + +- [ ] **Step 3: Visually inspect the mark and lockups** + + Confirm the four-point sparkle cluster renders inside the green/gold frame, and that light/dark lockups carry the `modern-di-starlette` name: + + ```bash + ls -1 brand/projects/modern-di-starlette/ + open brand/projects/modern-di-starlette/mark.svg brand/projects/modern-di-starlette/lockup-light.svg brand/projects/modern-di-starlette/lockup-dark.svg + ``` + Expected: `lockup-dark.svg lockup-light.svg lockup.png mark-1024.png mark-512.png mark.svg`; the dark lockup uses the darker gold (`#f0b528`). + +- [ ] **Step 4: Commit** + + ```bash + git add brand/projects/modern-di-starlette + git commit -m "chore(brand): generate modern-di-starlette assets" + ``` + +--- + +### Task 3: List Starlette on the profile README and docs site + +**Files:** +- Modify: `profile/README.md` (Dependency injection table) +- Modify: `docs/index.md` (DI list + stack sentence) + +Add the integration to both public catalogs, using the canonical one-liner. + +- [ ] **Step 1: Add the profile README table row** + + In `profile/README.md`, in the `### Dependency injection` table, insert this row immediately after the `modern-di-litestar` row (mirrors the sibling row exactly, name swapped): + + ```markdown + | [`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) [![PyPI](https://img.shields.io/pypi/v/modern-di-starlette)](https://pypi.org/project/modern-di-starlette/) [![Downloads](https://static.pepy.tech/badge/modern-di-starlette/month)](https://pepy.tech/projects/modern-di-starlette) [![Context7](https://img.shields.io/badge/Context7-docs-blue)](https://context7.com/modern-python/modern-di-starlette) | + ``` + +- [ ] **Step 2: Add the docs DI list bullet** + + In `docs/index.md`, in the `## Dependency injection { #di }` list, insert this bullet immediately after the `modern-di-litestar` line: + + ```markdown + - [`modern-di-starlette`](https://github.com/modern-python/modern-di-starlette) — `modern-di` integration for Starlette. + ``` + +- [ ] **Step 3: Extend the stack sentence** + + In `docs/index.md`, in the `## The stack` section, update the `modern-di` bullet. Replace: + + ``` + dependency injection with one wiring shared across FastAPI, Litestar, + FastStream, and Typer. + ``` + + with: + + ``` + dependency injection with one wiring shared across FastAPI, Litestar, + Starlette, FastStream, and Typer. + ``` + +- [ ] **Step 4: Verify surfaces and run the full suite** + + ```bash + grep -n "modern-di-starlette" profile/README.md docs/index.md + uv run just check-planning + uv run just test + ``` + Expected: the slug `modern-di-starlette` appears once in `profile/README.md` and once in `docs/index.md` (the DI bullet). The stack sentence names "Starlette" (not the slug), so it does not add a grep hit. `check-planning` prints `planning: OK`; the pytest suite is green. + +- [ ] **Step 5: Commit** + + ```bash + git add profile/README.md docs/index.md + git commit -m "docs: list modern-di-starlette on profile README and docs site" + ``` + +--- + +### Task 4: Align the GitHub repo settings + +**Files:** none (out-of-repo; GitHub settings via `gh`). No commit. + +Bring `modern-python/modern-di-starlette` description, website, and topics in line with org conventions. Apply only the diff from current state. + +- [ ] **Step 1: Read current settings** + + ```bash + gh repo view modern-python/modern-di-starlette --json description,homepageUrl,repositoryTopics + ``` + Note which of the three fields already match the intended values below; skip any that already match. + +- [ ] **Step 2: Set description and website** + + ```bash + gh repo edit modern-python/modern-di-starlette \ + --description "modern-di integration for Starlette" \ + --homepage "https://modern-di.modern-python.org" + ``` + +- [ ] **Step 3: Set topics** + + Intended set (integration base set + framework): + `python, dependency-injection, di, ioc-container, modern-di, starlette`. + + ```bash + gh repo edit modern-python/modern-di-starlette \ + --add-topic python \ + --add-topic dependency-injection \ + --add-topic di \ + --add-topic ioc-container \ + --add-topic modern-di \ + --add-topic starlette + ``` + If Step 1 showed stray topics not in the intended set, remove each with `--remove-topic `. + +- [ ] **Step 4: Verify** + + ```bash + gh repo view modern-python/modern-di-starlette --json description,homepageUrl,repositoryTopics + ``` + Expected: description `modern-di integration for Starlette`, homepage `https://modern-di.modern-python.org`, topics exactly the six above. + +--- + +### Task 5: Open the PR + +**Files:** none. + +- [ ] **Step 1: Push the branch** + + ```bash + git push -u origin starlette-brand + ``` + +- [ ] **Step 2: Open the PR** + + ```bash + gh pr create --fill --title "Onboard modern-di-starlette: brand mark + surfaces" + ``` + +- [ ] **Step 3: Watch CI** + + ```bash + gh pr checks --watch + ``` + Expected: all checks green. (If a stale `refs/pull//merge` lint failure appears that doesn't reproduce locally at branch HEAD, push a fresh commit to force GitHub to recompute the merge ref — see CLAUDE.md "CI gotcha".) From e86ca678ac4eb12ac69740a1f8108a8839d8b9fc Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Thu, 2 Jul 2026 12:01:51 +0300 Subject: [PATCH 3/5] feat(brand): add sparkle-cluster mark for modern-di-starlette --- brand/build/projects.py | 1 + brand/build/symbols.py | 30 ++++++++++++++++++++++++++++++ tests/test_projects.py | 1 + 3 files changed, 32 insertions(+) diff --git a/brand/build/projects.py b/brand/build/projects.py index f01310c..ccce029 100644 --- a/brand/build/projects.py +++ b/brand/build/projects.py @@ -20,6 +20,7 @@ "that-depends": lambda: sym.graph(_CX, _CY, R, dashed=False), "modern-di-fastapi": lambda: sym.bolt_disc(_CX, _CY, R), "modern-di-litestar": lambda: sym.star_disc(_CX, _CY, R), + "modern-di-starlette": lambda: sym.sparkle_cluster(_CX, _CY, R), "modern-di-faststream": lambda: sym.faststream(_CX, _CY, R), "modern-di-typer": lambda: sym.terminal(_CX, _CY, R), "modern-di-pytest": lambda: sym.bars(_CX, _CY, R), diff --git a/brand/build/symbols.py b/brand/build/symbols.py index c5c2aaf..e538d8e 100644 --- a/brand/build/symbols.py +++ b/brand/build/symbols.py @@ -54,6 +54,36 @@ def _star5(cx: float, cy: float, radius: float, color: str, inner: float = 0.42) return f'' +def _sparkle4(cx: float, cy: float, radius: float, color: str, inner: float = 0.34) -> str: + """Four-point sparkle (concave star) centred on (cx,cy).""" + pts: list[tuple[float, float]] = [] + for i in range(4): + ao = -90 + i * 90 + pts.append( + ( + cx + radius * math.cos(math.radians(ao)), + cy + radius * math.sin(math.radians(ao)), + ) + ) + ai = ao + 45 + pts.append( + ( + cx + radius * inner * math.cos(math.radians(ai)), + cy + radius * inner * math.sin(math.radians(ai)), + ) + ) + body = " ".join(f"{x:.1f},{y:.1f}" for x, y in pts) + return f'' + + +def sparkle_cluster(cx: float, cy: float, r: float) -> str: + """Starlette cue: a large four-point sparkle with a small companion + (a "little star" — starlette).""" + big = _sparkle4(cx - 0.174 * r, cy + 0.130 * r, r * 0.82, GOLD) + small = _sparkle4(cx + 0.565 * r, cy - 0.522 * r, r * 0.36, GOLD) + return big + small + + def _circ_arc(cx: float, cy: float, rad: float, a0: float, a1: float, w: float) -> str: """Clockwise arc a0->a1 (deg, increasing) with a leading arrowhead at a1.""" a1s = a1 - 7 # stop the stroke short so the head caps it cleanly diff --git a/tests/test_projects.py b/tests/test_projects.py index 5651627..3a9f0d2 100644 --- a/tests/test_projects.py +++ b/tests/test_projects.py @@ -20,6 +20,7 @@ def test_project_frame_parses_and_uses_tokens() -> None: "that-depends", "modern-di-fastapi", "modern-di-litestar", + "modern-di-starlette", "modern-di-faststream", "modern-di-typer", "modern-di-pytest", From 78fcdcee0d2381edee006ef8bc8877fae7c5c882 Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Thu, 2 Jul 2026 12:04:46 +0300 Subject: [PATCH 4/5] chore(brand): generate modern-di-starlette assets --- .../projects/modern-di-starlette/lockup-dark.svg | 1 + .../modern-di-starlette/lockup-light.svg | 1 + brand/projects/modern-di-starlette/lockup.png | Bin 0 -> 1957 bytes brand/projects/modern-di-starlette/mark-1024.png | Bin 0 -> 7288 bytes brand/projects/modern-di-starlette/mark-512.png | Bin 0 -> 3270 bytes brand/projects/modern-di-starlette/mark.svg | 1 + 6 files changed, 3 insertions(+) create mode 100644 brand/projects/modern-di-starlette/lockup-dark.svg create mode 100644 brand/projects/modern-di-starlette/lockup-light.svg create mode 100644 brand/projects/modern-di-starlette/lockup.png create mode 100644 brand/projects/modern-di-starlette/mark-1024.png create mode 100644 brand/projects/modern-di-starlette/mark-512.png create mode 100644 brand/projects/modern-di-starlette/mark.svg diff --git a/brand/projects/modern-di-starlette/lockup-dark.svg b/brand/projects/modern-di-starlette/lockup-dark.svg new file mode 100644 index 0000000..a9f8867 --- /dev/null +++ b/brand/projects/modern-di-starlette/lockup-dark.svg @@ -0,0 +1 @@ + diff --git a/brand/projects/modern-di-starlette/lockup-light.svg b/brand/projects/modern-di-starlette/lockup-light.svg new file mode 100644 index 0000000..e45b907 --- /dev/null +++ b/brand/projects/modern-di-starlette/lockup-light.svg @@ -0,0 +1 @@ + diff --git a/brand/projects/modern-di-starlette/lockup.png b/brand/projects/modern-di-starlette/lockup.png new file mode 100644 index 0000000000000000000000000000000000000000..1b92debe70bcde0da760bbcd8680006013c96b0b GIT binary patch literal 1957 zcmZvddpy%^AIIm^H1VsMl4_WUhz=zD!k99NnPWLVR>+~-x;<<~wy5Qhl|Am~Z&p&m0yVdmo{Ar|uvYNb{qJpB5lKdtZ3^!@f41;ZWi^pNT zD1+bg&t2jhZldi{?;Rv(8+?xo`yrL~D7BxB4mBXNl8Vh@VoXwl)O7jxO0ih%DgUo;`$I`0`t})ei(#8v_XF;7vGWkM2}ZqUr!B*_PlVz#a&Oh@kSg`si&q zLe@0=pYHl?EV`3#{q5qytjfI5mMt8GL(6MHFZ(gfZTy4wzv|L-2mN1%r zyv^*Xwnb8l-!Wg^?`B%!6>v#in!A)T`-(qaFSG(L(^FcEA^lFi9C$G{Hu#o14h?*+ z&L_v}js|h~w?%e6Wyte0VJr$C2MU!SWP@6sqIRcqI1*2 zOEOQDR*duNSy}ax)4^WLZQ`=#P^lZ$?{+VtV2W`1!kSsFu7Y+p(s*tTJ3RnN$`NSm zZm;fvu5z){hT8q#cpH6>XyUyEWYpVW6|ESf5x*pENA+Wb_I{3MHXKczxC*zFXB)7e zsoe>P*|D+tZEb4oD-2MUsMotco0GcmJd-D!qE0t45?<@EvKUo)%VB>N-g4w=47hD& zDfgwk=0&dN#2D`~0k$Mr4f%B=K!@+pPU_BcamZh{dPwso$e9J^Nm19h?ZPM2>7`F? zk`WiMrcd+G9nTx78--Cbxn3)XMVs&$gz>o-FGs8$-aY<;SpYL~KdzmK*``>sx5}qg z)w++gzkCA)+MTJ2GZa01Z@DQilyqMs@fjt zgf>5b=VdX6g}$fzCa412+aCvO=S6oOM4nNZ;#z&rsi@IT?J3P@{~BN}n4)%&j`hW@ z-i#8Qm_g0%)mE%*fntp~3P6iHB)_Rl2%!e7x+o*#fZxp&UF;l>r7 zLvIQWP${HP^AquO#>Y7Os8&-SF%6Ck9R5YSt}nXU1)VZ*^!iCUWAsvkj!nlO74sWV z6wR@v{@aDq7to$Xzx3^S-?X_U4X*gWtGit%3UjC9{$;Z77a}ju1ftAcTlD)%ARPUGdJh;&&~c^Jduo?ot*Pb_x!5=4_0}hfF>7! zF)09*V=^b;$P#RATGXjZ%7qX1_dX1~Lsp2G^(rQJ^9!g)29K8{pFmdVJVHd7>rVz~ z1P5Mphkzr?1J)p6FXh=;GhgvGYGo_wi_`o<69CoiVV3+@Y7y~eldAyCWrA6K85m|G zRDOg$=JrypXhC%VbFgY#gBo=>Skd2K z52Eao4gUXn;y)%(ctHo(THcg#<1Y#3qql2Ej{0=NA&N57SW#w_|Kpc}95cM4)UIk= gEXJWwsGP+yJA92x=f$(-!gVL&o!oFNhmb3O15+=w;{X5v literal 0 HcmV?d00001 diff --git a/brand/projects/modern-di-starlette/mark-1024.png b/brand/projects/modern-di-starlette/mark-1024.png new file mode 100644 index 0000000000000000000000000000000000000000..25040de4af41f1e61a2b381358c65e6e84f06cb0 GIT binary patch literal 7288 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 TJ7xi{IgB4WWz11O#p?e61CF8< literal 0 HcmV?d00001 diff --git a/brand/projects/modern-di-starlette/mark-512.png b/brand/projects/modern-di-starlette/mark-512.png new file mode 100644 index 0000000000000000000000000000000000000000..eafd98067d605195c4910758499c2aba34bc5edb GIT binary patch literal 3270 zcmcgueK?fq8o%H7#b_{7LLv;QSS3z~Bok@V=Y$m%##XWtLn$9k^VVX*%4}Om+oG*} zMUy^!Y?zc?eF&=%O{Ro=L}7f4X5RC*=jWV0>({K&2TYGT=i*Cfk0?6K7o z6bdZ|t<_s^q&9}RRZvusgBY6rNJ&-g-(kiVyXOO_N!{12^@{FzFP@dvX{V{eDs)e| zuvGdcx>vEpAg$Ye>&ujNCrzl)1TtEe-&S}@71^@TmTq;pdiCnrk`dllThpyW*En6S=Plb?rNIcEJ7wDS!(|1X=Ouf%gx50{ zqWV;sVh7}}AM^iZ=$5IdwyJyJ@}s0?Gp$dUZJ3h?sh!57z^;ar;${^&oK+fBGX$}r(t!#umqa-@B4 z>Wr0?!v6LkRqDEoj#SX0Gp&T^wULS7qW<~z6)(fM#zk>Pfj8O z0S@?)`!pesUVc?^4%1y3Gv};3y}VEng$2*$`Av>28X3FJ6GQKVw2%q5eNwIXiqw?#_fPh4A66-Bv2xR}miHEq zJA3?zEMz>XbNthz(bE-eH9@fFcg@>l;~lc6ey^n0bw%B2+8aLV|1>NeAS$f)4jGOW z^Xj0|>tLmRUYd8zP~-X5ny+C`vYkBAP0BlF(H;ndwrQhfZ)WZkAgUjFzi(byTT{(<#1 z#YVGwuMl(nE`lt9$8Qv87RtDtp_TIx{D7k<^#bazxfx9=qKmS+IF>K8guTA(j<ZptfJK67z4#=Oa~5G6XXgW*&Qa^@I&vcPC51mEG!Ir|}3 zUfMZ7kPIwCuXSmC_!YOd1)J@|jhm(WBw>@vAgshp`;opX+9{M>N9N3a5htFn#7vGF zIHGv&01egp`+LhLRZw9ycKJQxi7}5uhm!u=(YubixaqDXeZn$6CLC~UQXzjU)YC-{ z4J06P!C42CL`M90OADm(emEt zZ0iR7J{|lMtoFanXf)5!&>+?C&d7I8-1lz51jhIvEn44mw@DZJhaa`^qh?+>nUID7hqNj%jFC+ZC{f2KgOD*B$ zlEzsjlX^2cxB#AVE7cU1po9s=w6o!@!?>Ff715gP*&+GglZ5)9Tz9TEaf8{@}aE9J8gm%%5BX!dwFjAkt7)sz-gS z#5qsDu_6F`X6X8PLL-p-s+q}OIA0h^pz_qelj;h8qo+I~Ow5u`1ZH19Svd8@ROgNp zg#j~gv|CWQ_eoF6UI_W(M^0Ywz;cz#RkX&j#A+A_{izU==&q zU|v8w7bz>=CQ9js;NN%aPdlZ77DbY7Xk|xY&Y=T7V(<_1`9TeoUoBWw>2NCyxXlKD zFBUhPSO$yGa@lZ`fSez8Vt+m-ePdki~@}3CQ)!!O_FRl`!)tmmt%}=P}V>2l6D#}FByJ7na%L4ha-Od6>DmVl7LDgQK zNd}CCP|-#-7+RqMRAfEm5e25eQ5Sl9TKCnyr7&FNUD3u`zhHY&iEeapEO=w5wiCTK zgvIaz?AQBVyK$E$z;G)mPny7@i#9^U05R~5^)eWQ1q+K?St z!)n9UeZj~nb+-Mr2965D5}y{XSqOp1ExuMioT9QfqikS&ft%05UAwf;Rp`MttMGW` zrUG9v#M)y2O@H^lwzGN}>yf5%I~u;Yw(k4lV~u+}yT#4QuMGXRb!>E=Htjhi3Z0Mb zZv|DK9mKo?x{hMurB9yw5j9=qz6hVQzSC~&{ From 3ad22c724c79521c77c2c4f3f717ee9a380f4c05 Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Thu, 2 Jul 2026 12:09:35 +0300 Subject: [PATCH 5/5] docs: list modern-di-starlette on profile README and docs site --- docs/index.md | 3 ++- profile/README.md | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 1c5d487..3b572c4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -67,7 +67,7 @@ production Python services. Use one piece or all of them — each is independent - **Wire your dependencies** with [`modern-di`](https://github.com/modern-python/modern-di) — typed, scoped dependency injection with one wiring shared across FastAPI, Litestar, - FastStream, and Typer. + Starlette, FastStream, and Typer. ([`that-depends`](https://github.com/modern-python/that-depends), its production-proven predecessor, is still maintained.) - **Call other services reliably** with @@ -98,6 +98,7 @@ catalog below. - [`modern-di`](https://github.com/modern-python/modern-di) — powerful DI framework with scopes. - [`modern-di-fastapi`](https://github.com/modern-python/modern-di-fastapi) — `modern-di` integration for FastAPI. - [`modern-di-litestar`](https://github.com/modern-python/modern-di-litestar) — `modern-di` integration for Litestar. +- [`modern-di-starlette`](https://github.com/modern-python/modern-di-starlette) — `modern-di` integration for Starlette. - [`modern-di-faststream`](https://github.com/modern-python/modern-di-faststream) — `modern-di` integration for FastStream. - [`modern-di-typer`](https://github.com/modern-python/modern-di-typer) — `modern-di` integration for Typer. - [`modern-di-pytest`](https://github.com/modern-python/modern-di-pytest) — `modern-di` integration for pytest. diff --git a/profile/README.md b/profile/README.md index d09f0f5..ff9d5e4 100644 --- a/profile/README.md +++ b/profile/README.md @@ -26,6 +26,7 @@ Open-source templates and libraries for building production-ready Python applica | [`modern-di`](https://github.com/modern-python/modern-di) | Powerful DI framework with scopes | [![Stars](https://img.shields.io/github/stars/modern-python/modern-di)](https://github.com/modern-python/modern-di/stargazers) [![PyPI](https://img.shields.io/pypi/v/modern-di)](https://pypi.org/project/modern-di/) [![Downloads](https://static.pepy.tech/badge/modern-di/month)](https://pepy.tech/projects/modern-di) [![Context7](https://img.shields.io/badge/Context7-docs-blue)](https://context7.com/modern-python/modern-di) | | [`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) [![PyPI](https://img.shields.io/pypi/v/modern-di-fastapi)](https://pypi.org/project/modern-di-fastapi/) [![Downloads](https://static.pepy.tech/badge/modern-di-fastapi/month)](https://pepy.tech/projects/modern-di-fastapi) [![Context7](https://img.shields.io/badge/Context7-docs-blue)](https://context7.com/modern-python/modern-di-fastapi) | | [`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) [![PyPI](https://img.shields.io/pypi/v/modern-di-litestar)](https://pypi.org/project/modern-di-litestar/) [![Downloads](https://static.pepy.tech/badge/modern-di-litestar/month)](https://pepy.tech/projects/modern-di-litestar) [![Context7](https://img.shields.io/badge/Context7-docs-blue)](https://context7.com/modern-python/modern-di-litestar) | +| [`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) [![PyPI](https://img.shields.io/pypi/v/modern-di-starlette)](https://pypi.org/project/modern-di-starlette/) [![Downloads](https://static.pepy.tech/badge/modern-di-starlette/month)](https://pepy.tech/projects/modern-di-starlette) [![Context7](https://img.shields.io/badge/Context7-docs-blue)](https://context7.com/modern-python/modern-di-starlette) | | [`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) [![PyPI](https://img.shields.io/pypi/v/modern-di-faststream)](https://pypi.org/project/modern-di-faststream/) [![Downloads](https://static.pepy.tech/badge/modern-di-faststream/month)](https://pepy.tech/projects/modern-di-faststream) [![Context7](https://img.shields.io/badge/Context7-docs-blue)](https://context7.com/modern-python/modern-di-faststream) | | [`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) [![PyPI](https://img.shields.io/pypi/v/modern-di-typer)](https://pypi.org/project/modern-di-typer/) [![Downloads](https://static.pepy.tech/badge/modern-di-typer/month)](https://pepy.tech/projects/modern-di-typer) [![Context7](https://img.shields.io/badge/Context7-docs-blue)](https://context7.com/modern-python/modern-di-typer) | | [`modern-di-pytest`](https://github.com/modern-python/modern-di-pytest) | modern-di integration for pytest | [![Stars](https://img.shields.io/github/stars/modern-python/modern-di-pytest)](https://github.com/modern-python/modern-di-pytest/stargazers) [![PyPI](https://img.shields.io/pypi/v/modern-di-pytest)](https://pypi.org/project/modern-di-pytest/) [![Downloads](https://static.pepy.tech/badge/modern-di-pytest/month)](https://pepy.tech/projects/modern-di-pytest) [![Context7](https://img.shields.io/badge/Context7-docs-blue)](https://context7.com/modern-python/modern-di-pytest) |