|
| 1 | +# modern-python org conventions |
| 2 | + |
| 3 | +This repo (`modern-python/.github`) builds the org site at **modern-python.org** |
| 4 | +(MkDocs Material, in `docs/`) and hosts the org profile shown on the GitHub org page |
| 5 | +(`profile/README.md`). The conventions below apply across **all** repos in the |
| 6 | +`modern-python` org, not just this one. |
| 7 | + |
| 8 | +## Naming & branding |
| 9 | + |
| 10 | +- Brand/framework casing — use exactly: `modern-di`, `that-depends`, `Litestar` |
| 11 | + (not "LiteStar"), `FastStream`, `FastAPI`, `Typer`, `SQLAlchemy`, `PostgreSQL`. |
| 12 | +- Per-project docs sites live at `<name>.modern-python.org` (only some repos have one). |
| 13 | + |
| 14 | +## Repository metadata (three surfaces kept consistent) |
| 15 | + |
| 16 | +Every repo's summary appears in up to three places — keep them saying the same thing: |
| 17 | +the **GitHub description**, the pyproject **`description`**, and the repo's blurb in |
| 18 | +`profile/README.md`. Write one canonical one-liner per repo: purpose-first, |
| 19 | +≤ ~120 chars, **no trailing period** (GitHub convention). |
| 20 | + |
| 21 | +### GitHub topics |
| 22 | +- Lowercase letters/numbers/hyphens only, ≤50 chars each, ≤12 per repo. |
| 23 | +- Draw from the shared org vocabulary so `/topics/*` pages cluster: `python`, |
| 24 | + `dependency-injection`, `di`, `ioc-container`, `modern-di`, `fastapi`, `litestar`, |
| 25 | + `faststream`, `sqlalchemy`, `postgresql`, `asyncio`, `docker`, `cli`, `messaging`. |
| 26 | +- `modern-di-*` integrations share a base set |
| 27 | + (`python, dependency-injection, di, ioc-container, modern-di`) plus their framework. |
| 28 | +- Also set the repo **website field** to its docs site, or `modern-python.org` if none. |
| 29 | + |
| 30 | +### pyproject `[project]` |
| 31 | +- **`keywords`** mirror the GitHub topics (lowercase/hyphenated). Never use |
| 32 | + `"dependency injector"` — that is another package's name (`dependency-injector`). |
| 33 | +- **`classifiers`**: include `Development Status :: <level>`, |
| 34 | + `Intended Audience :: Developers`, the relevant `Programming Language :: Python ::` |
| 35 | + versions, `Typing :: Typed`, and a `Topic ::` where apt. Validate every string |
| 36 | + against <https://pypi.org/classifiers/> before committing. |
| 37 | +- **Do NOT add a `License :: OSI Approved :: ...` classifier.** All repos are MIT and |
| 38 | + declare the SPDX `license = "MIT"` key; PEP 639 deprecates pairing that with a |
| 39 | + License classifier, and `uv_build` warns on it. |
| 40 | +- **`[project.urls]`** uses PyPI well-known labels (capitalized): |
| 41 | + `Homepage`, `Documentation` (only if a docs site exists), `Repository`, |
| 42 | + `Issues` (`…/issues`), `Changelog` (`…/releases`). |
| 43 | + |
| 44 | +## Tooling |
| 45 | + |
| 46 | +Projects use **uv** (packaging), **ruff** (lint/format), **ty** (type check), and |
| 47 | +the build backend is **uv_build**. `that-depends` additionally runs `mypy` and |
| 48 | +`pyrefly` in its `lint-ci` recipe. Lint/test live behind a `justfile` in most repos. |
| 49 | + |
| 50 | +## CI gotcha |
| 51 | + |
| 52 | +GitHub occasionally type-checks a **stale `refs/pull/<n>/merge`** after a push, so a |
| 53 | +PR can show an old lint/test failure that no longer matches the branch. Confirm by |
| 54 | +running the failing check locally at the branch HEAD (with the pinned tool version); |
| 55 | +if it's clean, push a fresh commit to force GitHub to recompute the merge ref. |
0 commit comments