Refine Python pattern boundaries and Pydantic guidance

This commit is contained in:
Rodin
2026-06-02 00:53:38 +00:00
parent 60ffec18e4
commit 7007b73099
6 changed files with 273 additions and 83 deletions
+31 -25
View File
@@ -6,10 +6,7 @@ This repo captures reusable Python patterns extracted from mature upstream codeb
A good pattern doc here includes:
- **Why** — the reasoning, not just the rule
- **When to use** — the trigger conditions
- **When NOT to use** — where the pattern causes harm
- **Preferred shapes** — examples of the intended form
- **Counterexamples** — what to avoid and why
- **When to use / not use** — where the pattern helps or causes harm
- **Source citations** — verified `file:line` anchors from real codebases
These docs should be derived from what strong Python codebases actually do, not from generic style-blog advice.
@@ -17,6 +14,7 @@ These docs should be derived from what strong Python codebases actually do, not
## Structure
- `patterns/` — what to do
- `comparison/` — where framework or library choices bend the generic Python guidance
- `smells/` — what to avoid
- `sources/` — extracted source-study notes and upstream references
- `PROCESS.md` — the repeatable extraction/refinement workflow used to build this repo
@@ -32,15 +30,6 @@ Primary upstreams mined so far:
- `pallets/click`
- `sqlalchemy/sqlalchemy`
Why this mix works:
- CPython: API boundaries, exceptions, context managers, typing surface design
- HTTPX: package facade design, sync/async split, transport seams, error taxonomy
- pytest: fixture lifetime, parametrization, test ergonomics
- Pydantic: validation and serialization boundaries
- attrs: lightweight value-object/data-model patterns
- Click: CLI-facing exception and public-surface patterns
- SQLAlchemy: explicit persistence/session lifetime and sync-vs-async caveats
## Current pattern set
- `patterns/module-design.md`
@@ -49,22 +38,39 @@ Why this mix works:
- `patterns/async-boundaries.md`
- `patterns/testing.md`
- `patterns/data-models.md`
- `comparison/pydantic-vs-python.md`
- `smells/common-mistakes.md`
## Reviewing this repo
## Boundary rubric: does this belong in `python-patterns`?
Recommended review order:
1. `README.md`
2. `PROCESS.md`
3. `sources/*.md` for evidence quality
4. `patterns/*.md` for synthesis quality
5. `smells/*.md` for anti-pattern coverage
Use this rubric both when writing docs here and when deciding where a real code example belongs.
Questions to ask during review:
- Is each claim grounded in repeated upstream evidence?
- Are caveats preserved instead of flattened away?
- Does the pattern stay at the Python level rather than drifting into framework guidance?
- Are citations specific enough to be re-checked quickly?
Put the guidance here when most of the rule is about:
- module and package structure
- API shape that would still make sense in a library, CLI, worker, or batch job
- internal data modeling and state boundaries
- exception design independent of HTTP or framework behavior
- typing, protocols, sync/async design, and test structure that do not depend on a web framework
Push the guidance out to a framework repo when most of the rule is about:
- request or response handling owned by FastAPI
- dependency injection through framework signatures
- HTTP exception translation, status codes, or response envelopes
- OpenAPI-facing schema behavior as part of a service contract
- app lifespan and other framework-owned resource wiring
Tie-break:
- if the guidance could reasonably live in multiple places and a clean split would make it harder for someone writing code to find, prefer the **higher-level abstraction** and cross-link to the narrower guidance instead of over-optimizing repo purity
### How to handle sloppy mixed examples
Real code often mixes Python and framework concerns in the same file, function, or even line. Do **not** classify by file path alone.
Instead:
- extract the **Python-level rule** from the mixed example and keep only that part here
- move or link the **framework-owned rule** to the framework repo
- if one line expresses both concerns, write down which part is reusable without FastAPI and which part depends on FastAPI being present
- when in doubt, prefer a narrower Python rule plus a comparison note instead of smuggling framework behavior into the base pattern
## Extraction rule