Use when writing, reviewing, or modifying Python code (*.py, pyproject.toml, setup.cfg files) or reviewing diffs/PRs containing Python changes — ensures code quality and adherence to established Python conventions for naming, error handling, concurrency, typing, logging, and code organization
typing / collections.abc for complex types.UserID = NewType('UserID', int), not bare int. Use Literal, TypeAlias, TypeVar where they add clarity.@dataclass or NamedTuple for structured data — not plain dicts or tuples for domain objects.__init__.py to define the public API of a package. Re-export only what external consumers need.snake_case for functions, methods, variables, modules. PascalCase for classes. UPPER_SNAKE for module-level constants._prefix for internal. No double __ mangling unless avoiding name collision in inheritance.def remove_push_to(
self,
target: Abstract,
*,
force: bool = False,
) -> None:
Exception.raise NewError("...") from original_err.with) for all resource cleanup — files, connections, locks.except: or except Exception: without re-raise.resource = acquire()
try:
use(resource)
except SomeError:
resource.rollback()
raise
asyncio for I/O-bound concurrency. concurrent.futures for CPU-bound parallelism.asyncio.to_thread() or run_in_executor().async with) for async resource lifecycle.match/case (3.10+) over if/elif chains when semantically there could be more than 2 options.Enum for finite sets of related constants, not string or int literals.typing.Protocol) for structural subtyping.logging stdlib module. Get logger per module: logger = logging.getLogger(__name__).extra= or structured formatters, not string interpolation in the message.print() for operational output outside of CLI entry points.DEBUG — detailed diagnostic, state changes, request handling.INFO — rare, notable events only (startup, shutdown, config reload). Most messages should be DEBUG, not INFO.WARNING — recoverable problems, degraded operation, unexpected-but-handled conditions.ERROR — operation failed, needs attention but process continues.CRITICAL — unrecoverable, process must exit.pytest as test runner. assert statements directly — no self.assertEqual.how-it-works explanations and TODOs. No "generated by AI" or similar attributions.x > y silently accepts cases you didn't consider — use explicit checks for each supported case and error on the rest.A name is a contract — implementation fulfills exactly what the name promises.
resolve_table resolves a table — not decide whether to, retry, or log analytics. Extra behavior belongs in the caller or the name.validate_and_save must validate and save. If either can happen without the other, split or rename.disable must not return an "enabled" state. remove must not archive.get_user → User. is_valid → bool. list_items → collection.do_x() assumes X should happen. "If not needed, return early" inside it is a violation — the caller decides.is_, has_, can_) don't change anything. If they must, the name must reveal it.Review check: read the name, predict the body, read the body. Any surprise is a violation.
Same concept → same name everywhere. Same name → same meaning everywhere. Related concepts → parallel structure.
handle can't mean "process a request" here and "resource reference" there.start_capture/stop_capture — not begin_encoding/end_encoding. Pick one verb set per domain.initialize_cluster, configure_network, go — the last one breaks the level.StreamProcessor over DictWithLock. Name must survive an implementation change.Everything as local as possible, as short-lived as possible.
with blocks scoped tightly — don't hold files/connections open longer than needed.pyproject.toml or requirements.txt. Never install packages without recording them.if/for/try blocks. Use early returns, continue, and guard clauses to reduce nesting. If a block is nested 3+ levels deep, refactor it.