python · diff

git:20260722.f0eb407 to git:20261105.39988c5

8 added, 26 removed. Audit A to A.

---
name: python
- description: Engineer Python language, interpreter, typing, async, packaging, imports, subprocess, and serialization behavior. Use for Python-owned semantics; not non-Python work merely because pyproject.toml or a Python tool exists.
+ description: Implements and tests Python changes with interpreter, typing, packaging, and asyncio checks. Use for Python code, pytest failures, or Python environment mismatches.
---
- # Python
-
- ## Establish the Python contract
-
- - Inspect the touched modules, `pyproject.toml`, lock and requirements files, `setup.cfg`, tox/nox configuration, runtime images, CI matrix, and project scripts. Resolve the interpreter actually used by the project command or environment and its exact version; distinguish it from the declared minimum in `requires-python` and classifiers.
- - Identify the packaging workflow—such as uv, Poetry, PDM, Hatch, setuptools, pip-tools, pip, or conda—from repository evidence. Use its existing environments, dependency groups, lock behavior, entry points, and commands; do not substitute another tool.
- - Determine package roots, import style, namespace packages, editable-install assumptions, generated metadata, type-checker mode, and sync/async entry points before editing.
-
- Read [version, packaging, and security boundaries](references/version-packaging-security.md) before changing the minimum version, annotations, free-threaded behavior, packaging metadata or locks, archives, subprocesses, or serialization. Use [authoritative Python sources](references/sources.md) for exact interpreter and packaging behavior.
+ 1. Before editing, run `python --version` through the project's environment runner and `python -c "import sys; print(sys.executable); print(sys.prefix)"`. Read `pyproject.toml`, existing requirements or lockfiles, `.python-version`, test settings, and CI. Establish the minimum supported Python, build backend, dependency groups, and installed framework versions. `requires-python` constrains installation, classifiers do not. Read version-matched documentation for changed Django, FastAPI, SQLAlchemy, or stdlib APIs.
- ## Preserve language, typing, and package semantics
+ 2. For implementation or dependency work, read [the shared procedure](references/common.md). For a version-only question, inspect the environment without installing or updating packages. Use `python -m pip show PACKAGE` in pip environments, or the existing manager's installed-package inspection. A lockfile records resolution, not proof of what the active interpreter imports.
- - Match syntax to the supported minimum: built-in generics, union syntax, `Self`, type-parameter syntax, exception groups, `TaskGroup`, and newer annotation behavior are version-sensitive.
- - Type public APIs and non-obvious boundaries. Prefer precise read-only protocols such as `Sequence` and `Mapping`, structural `Protocol` where substitution is real, and `TypedDict` or dataclasses for stable records. Keep `Any`, casts, and ignores local.
- - Treat annotations as tooling input, not runtime validation. Reflection and deferred annotations vary by Python version; verify before relying on evaluated annotation objects.
- - Avoid import-time network calls, file mutation, secret reads, migrations, and worker startup. Keep library code from taking ownership of the event loop with `asyncio.run()`.
- - Preserve packaging contracts: import names, entry points, extras or dependency groups, wheel contents, data files, editable installs, and minimum-Python metadata. Update locks only through the project's package manager when dependency input actually changes.
- - Raise specific exceptions in libraries and translate them at CLI, worker, or service boundaries. Chain useful causes and clean up context-managed resources without hiding the original failure.
+ 3. Preserve exception types, result shapes, missing-value semantics, and external serialization. Distinguish `None` from false or empty values. Avoid mutable defaults, shared class-level mutable data, and generators consumed twice. Follow existing annotations and narrow types from actual checks. Do not silence mismatches with `Any`, casts, or ignores. Syntax and typing APIs must work at the supported minimum, not just locally.
- ## Bound concurrency and unsafe boundaries
+ 4. For async changes, identify who owns, cancels, and awaits every task. Use context managers or `try/finally` for files, sessions, and connections. Propagate `asyncio.CancelledError` after cleanup. Keep blocking clients off the event loop using the established mechanism. A thread offload does not make the operation cancellable. Check ORM-session scope and sharing across tasks. Exercise cancellation, failure cleanup, and task termination on the changed path.
- - Use async for I/O concurrency, not CPU acceleration. Keep blocking filesystem, database, network, sleep, and CPU-heavy calls off the event loop; use existing thread or process executors when required.
- - Bound task creation, queues, pools, and worker counts. Use structured concurrency and timeout APIs only when supported by the minimum version. Preserve cancellation and re-raise `asyncio.CancelledError` after cleanup.
- - Treat free-threaded builds and subinterpreters as separate compatibility targets. Verify extension and dependency support before assuming shared state is safe without the GIL or portable across interpreters.
- - Prefer `subprocess.run` with a verified executable, argument list, `shell=False`, `check=True`, and a timeout. On Windows, batch wrappers still introduce shell parsing; never pass untrusted values through them.
- - Do not load untrusted pickle, marshal, unsafe YAML, dynamic imports, or executable strings. Resolve user-controlled paths beneath an allowed root. For archives, validate members and bound count, total bytes, depth, links, and extraction location even when a safe filter is available.
- - Use explicit encodings, timezone-aware datetimes, `Decimal` for exact decimal quantities, and stable serialization rules at persistent or public boundaries.
+ 5. Preserve the existing manager. With uv, restore using `uv sync --locked` and run checks with `uv run --locked` so a check cannot silently rewrite `uv.lock`. Exact sync removes unselected packages, so use the project environment and required groups. With pip, use the selected interpreter's `python -m pip install -r requirements.txt` only when that is the project's declared dependency source. Requirements with ranges are not a reproducible lock. For authorized updates, use the existing resolver and review manifest, lock, markers, extras, and transitive changes together. Keep system packages separate.
- ## Use project feedback
+ 6. Before reporting a code change, run the repository's affected test command. For a pytest project, use `python -m pytest PATH` with the real affected test path. Run configured typing, lint, and formatting checks too. Where already configured, use `python -m mypy PATH`, `ruff check PATH`, and `ruff format --check PATH` through the same environment. Retain Black, Pyright, or other existing tools instead of adding replacements. Do not impose a stricter configuration. For packages, test supported Python versions when API availability or packaging changes.
- Run the smallest configured formatter or lint check, type checker, and focused test or import check that covers the touched package. Run tox/nox environments, build wheels/sdists, or test installed artifacts when changing supported Python versions, imports, entry points, package metadata, generated declarations, or dependency resolution. Exercise cancellation, subprocess failure, archive rejection, or serialization errors when those semantics changed.
+ Consult [asyncio cancellation](https://docs.python.org/3/library/asyncio-task.html), [pyproject metadata](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/), and [uv locking](https://docs.astral.sh/uv/concepts/projects/sync/) when those boundaries change.