chore: agentic upgrade
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
---
|
||||
name: python-practices
|
||||
description: Use when writing, reviewing, refactoring, or debugging Python code in this repository, including style, typing, error handling, async work, tests, packaging, security, and verification.
|
||||
---
|
||||
|
||||
# Python Practices
|
||||
|
||||
## Core Rule
|
||||
|
||||
Write Python that is boring to maintain: explicit, typed, small, tested, and easy
|
||||
to inspect in production. Prefer this repository's existing conventions over
|
||||
generic advice. When a library, framework, SDK, CLI, or cloud-service detail
|
||||
matters, fetch current docs with Context7; use Tavily for broader ecosystem
|
||||
practice research.
|
||||
|
||||
## Source Priority
|
||||
|
||||
1. Project files: `AGENTS.md`, `pyproject.toml`, existing `cpv3/` code, tests.
|
||||
2. Current official docs and PEPs.
|
||||
3. High-quality community research for trade-offs, checked against project needs.
|
||||
4. Memory or intuition, only after the above.
|
||||
|
||||
## Readability
|
||||
|
||||
- Keep functions small enough to read in one pass. Extract helpers when branching,
|
||||
parsing, or side effects start competing for attention.
|
||||
- Use intention-revealing names: `snake_case` for functions and variables,
|
||||
`CapWords` for classes, `UPPER_SNAKE_CASE` for constants.
|
||||
- Prefer direct control flow, early returns, and clear condition names over nested
|
||||
cleverness.
|
||||
- Avoid ad hoc string parsing when Python, Pydantic, SQLAlchemy, JSON, pathlib,
|
||||
or another structured API can express the operation.
|
||||
- Comments should explain non-obvious reasons, not repeat the code.
|
||||
|
||||
## Types And Data
|
||||
|
||||
- Annotate public functions, service/repository boundaries, async helpers, and
|
||||
values that cross module boundaries.
|
||||
- Prefer precise built-in generics such as `list[str]`, `dict[str, Any]`, and
|
||||
`tuple[int, int]`; avoid bare `dict`, `list`, or `Any` unless the shape is
|
||||
genuinely unknown.
|
||||
- Use Pydantic schemas for API and validation boundaries. Use dataclasses or small
|
||||
typed objects for internal value bundles when Pydantic validation is not needed.
|
||||
- Do not mutate default containers. Use `None` plus initialization or a factory.
|
||||
- Convert external data at the boundary, then keep internal code working with typed
|
||||
values instead of raw payload dictionaries.
|
||||
|
||||
## Errors And Logging
|
||||
|
||||
- Catch specific exceptions. Avoid bare `except`, silent fallbacks, and swallowing
|
||||
errors without observability.
|
||||
- Preserve context with exception chaining: `raise DomainError(...) from exc`.
|
||||
- Define reusable user-facing or domain error strings as `ERROR_...` constants.
|
||||
- Use `logging.getLogger(__name__)` for diagnostics. Do not use `print` in
|
||||
application code.
|
||||
- Error messages should help the next maintainer find the failing input, dependency,
|
||||
or state without leaking secrets.
|
||||
|
||||
## Async And Resources
|
||||
|
||||
- Do not block the event loop. Use async APIs, subprocess APIs, or
|
||||
`anyio.to_thread.run_sync` for sync I/O and CPU-bound library calls.
|
||||
- Use context managers for files, sessions, locks, temporary resources, and network
|
||||
clients. Cleanup must be visible in normal and exceptional paths.
|
||||
- Add timeouts around network, subprocess, and external-service operations when the
|
||||
called API supports them.
|
||||
- Do not share mutable state across concurrent tasks unless access is synchronized.
|
||||
- For this backend, do not share one SQLAlchemy `AsyncSession` across concurrent
|
||||
tasks; use a session per task/request.
|
||||
|
||||
## Tests
|
||||
|
||||
- Test behavior, not implementation details. Name tests after the observable rule.
|
||||
- Prefer deterministic fixtures, explicit inputs, and parametrized edge cases.
|
||||
- Cover failure paths for parsing, permissions, missing data, external services,
|
||||
and persistence boundaries.
|
||||
- Use unit tests for pure helpers and service/repository rules. Use integration tests
|
||||
for endpoint contracts and dependency overrides.
|
||||
- For bug fixes, write or update the failing test first when practical, then make
|
||||
the smallest code change that proves the fix.
|
||||
|
||||
## Security And Configuration
|
||||
|
||||
- Keep secrets in environment-backed settings, never source files, tests, fixtures,
|
||||
generated docs, or logs.
|
||||
- Validate paths, object keys, URLs, filenames, and user-controlled identifiers at
|
||||
the boundary.
|
||||
- Prefer allowlists for modes, providers, file types, and status transitions.
|
||||
- Treat serialization as a boundary: expose only fields that should leave the module
|
||||
or API.
|
||||
|
||||
## Project Tooling
|
||||
|
||||
Use the repository's Python 3.11+ and `uv` workflow. Keep Ruff formatting with the
|
||||
configured 100-character line length.
|
||||
|
||||
```bash
|
||||
uv run ruff format cpv3 tests
|
||||
uv run ruff check cpv3 tests
|
||||
uv run pytest
|
||||
```
|
||||
|
||||
Run narrower checks while iterating, then broaden when the change touches shared
|
||||
behavior. If verification cannot run, record the exact blocker.
|
||||
|
||||
## Project Overlay
|
||||
|
||||
- FastAPI HTTP concerns belong in `router.py`.
|
||||
- Pydantic DTOs belong in `schemas.py` and usually inherit
|
||||
`cpv3.common.schemas.Schema`.
|
||||
- Business orchestration belongs in `service.py`.
|
||||
- SQLAlchemy statements belong in `repository.py`.
|
||||
- Database shape changes need Alembic migrations and tests.
|
||||
- Do not rely on `.claude/` directory contents.
|
||||
Reference in New Issue
Block a user