Python Code Quality

A complete checklist to guide Python code review for reliability, security and performance, ensuring every pull request is production ready.

What We Cover in the Python Analysis​

Here’s what this checklist helps you review before approving a pull request.

Code & Design Quality – correctness, readability and Pythonic structure, with clear module boundaries and maintainable design.
Security & Performance – protection against common vulnerabilities, efficient algorithms, caching and scalable I/O/concurrency.
Operational Readiness – testing strategy, error handling, observability and safe CI/CD rollouts.
Integration & Boundaries – APIs and data contracts, database migrations and transactions, configuration and secrets management.

Python Code Review Checklist

Export this Checklist as Markdown

Use these points as a starting guide to automate code reviews with your agent.

Follows PEP 8 (line length, naming) and project formatter (e.g., black) with imports ordered (e.g., isort).

Descriptive names (snake_case for functions/vars, PascalCase for classes, UPPER_SNAKE_CASE for constants).

Functions/methods are small, single-responsibility; modules are cohesive; avoid “God” files.

Remove dead/commented code; TODOs tracked in issues, not left in source.

Clear module/package structure; no circular imports; __init__.py used intentionally.

Docstrings on public modules/classes/functions; comments explain why, not what.

Avoid “clever” tricks; prefer explicit over implicit; early returns instead of deep nesting.

f-strings used for formatting; avoid string concatenation in loops.

Comprehensions readable; avoid multi-clause comprehensions that harm clarity; prefer named helpers.

No wildcard imports; explicit imports kept local when they reduce import cycles.

Prefer EAFP (Easier to Ask Forgiveness…) where appropriate; avoid broad try/except.

Use context managers for resources (with open(...), DB sessions, locks); implement __enter__/__exit__ when needed.

Prefer dataclasses/attrs/pydantic models for structured data over dicts/tuples.

Use Enum for closed sets; avoid magic numbers/strings.

Prefer iterators/generators for streaming; avoid loading entire datasets into memory.

Avoid mutable default args; use None sentinel and initialize inside.

Use pathlib.Path over os.path and subprocess.run([...], check=True) over shell strings.

Avoid monkey-patching and runtime metaprogramming unless clearly justified and tested.

Type hints on public APIs and complex internals; consistent with pyproject.toml typing settings.

mypy/pyright passes at target strictness; ignore rules are local, documented, and minimal.

Use typing features: Protocol, TypedDict, Literal, Annotated, NewType where helpful.

Avoid Any; narrow unions; prefer collections.abc for generic interfaces.

Runtime validation where needed (e.g., pydantic) complements, not replaces, static typing.

Contracts: pre/postconditions enforced via checks or validators on boundaries.

Injection: use parameterized queries (SQLAlchemy ORM/Core), no string-concat SQL; sanitize shell args.

XSS: template auto-escape on (Jinja2/Django templates); never render untrusted HTML without sanitization.

CSRF: enabled on state-changing endpoints (Django/Starlette middleware); exceptions justified.

Authentication/Authorization: consistent enforcement at handlers/services; least privilege for service accounts.

Deserialization: never pickle/yaml.load on untrusted input; use json/yaml.safe_load.

Secrets: never committed; loaded via secret manager or environment; rotation plan documented.

Transport: TLS required for all external comms; cert verification on HTTP clients.

SSRF: restrict outbound requests; block link-local/metadata IPs; validate/allow-list URLs.

File Uploads: validate content type/size; store outside webroot; randomize names; scan if needed.

Dependencies: pip-audit/safety/osv-scanner clean; transitive CVEs evaluated; pinned hashes optional.

Rate limiting & abuse: throttling on auth and expensive endpoints; lockouts for brute force.

Audit: sensitive actions logged with user/request IDs; logs avoid secrets/PII.

Algorithmic complexity acceptable; hotspots identified; avoid quadratic behavior for user-controlled sizes.

Avoid excessive allocations; prefer generator pipelines; batch operations when possible.

Use vectorized libs (NumPy/Pandas/Polars) when appropriate; avoid Python loops in hot paths.

Caching strategy defined (LRU, Redis); keys/TTLs/invalidation rules clear; no unbounded dict caches.

I/O: timeouts set; streaming for large responses; keep-alive/reuse sessions (httpx, requests.Session).

CPU-bound work offloaded (C extensions, multiprocessing, joblib, Numba) or queued.

Memory usage measured; no large objects retained; chunked processing used.

For web apps: worker counts, thread/async model sized for workload (Gunicorn/Uvicorn), keep startup fast.

Exceptions are specific; never except Exception: without re-raise/log/context; never swallow errors.

Rich error context (operation, inputs, correlation ID); user-facing errors sanitized.

Retries are bounded with backoff/jitter and only for idempotent operations.

Timeouts on all external calls; circuit breaker/bulkhead where needed.

Health/readiness endpoints implemented; graceful shutdown closes connections/queues.

Metrics (RED/USE) exposed; SLOs monitored; traces propagate context (W3C Trace Context/OpenTelemetry).

Tests use pytest (or unittest) with clear Arrange/Act/Assert; names describe behavior.

Unit tests deterministic/fast; integration tests cover DB/cache/HTTP/brokers (Testcontainers where useful).

Property-based tests (hypothesis) for parsers/pure logic/boundaries.

Concurrency tests for async/multiprocessing where applicable; flake-resistant.

Regression tests added for prod bugs and fail without the fix.

Coverage monitored on critical paths/error handling; don’t chase % at expense of value.

Static checks in CI: ruff (lint), black (format), mypy/pyright (types), bandit (security), pip-audit/safety.

Mutation testing (mutmut, cosmic-ray) on critical modules when risk justifies.

Clear module boundaries; domain logic decoupled from frameworks (ports/adapters).

Dependency direction maintained (no inward imports from outer layers).

Public API stable; breaking changes versioned and documented.

Feature flags for risky paths; dark launches/canaries available.

ADRs/design notes for non-trivial changes; rationale captured.

Single source of truth in pyproject.toml (build backend: Hatchling/Setuptools/Poetry).

Reproducible installs (pip-tools/Poetry lock); hashes pinned if required; extras defined.

Wheels built; no implicit local paths; console scripts declared.

Python version spec aligned with runtime; from __future__ imports only when needed.

Optional native deps documented; manylinux/macOS wheels considered.

API contract versioned; OpenAPI/JSON Schema current; breaking changes gated.

Consistent error model (RFC7807/problem+json or similar); validation errors structured.

Idempotency keys for unsafe POST; replay protection for webhooks (HMAC + timestamp window).

Pagination/filter/sort standardized; limits enforced; N+1 prevented.

HTTP clients: retries/backoff for idempotent calls, timeouts, connection pooling; PII redaction in logs.

gRPC/GraphQL: deadlines, auth, complexity limits, N+1 prevention (dataloaders).

Async code uses asyncio correctly: no blocking I/O; libraries are async-native; event loop not nested.

Threading used only for I/O bound; locks used sparingly; race conditions tested.

CPU-bound moved to processes or native/C; GIL impact understood.

Executors sized; task cancellation handled; timeouts and backpressure enforced.

Queues/brokers (Celery/Arq/RQ) tasks are idempotent; visibility timeouts and retries configured.

ORM (SQLAlchemy/Django ORM) queries profiled; no N+1; eager loading/projections used.

Transactions scoped; isolation level chosen; long transactions avoided.

Migrations managed (Alembic/Django migrations); forward-only or safe rollback plan; data backfills planned.

Indexes match query patterns; no full scans on hot paths.

Time handled with datetime timezone-aware (UTC in storage); pendulum/zoneinfo as needed.

Serialization stable; versioned schemas; bigints/decimals handled correctly (money uses Decimal).

Django

Settings split by env; DEBUG=False in prod; ALLOWED_HOSTS, CSRF, and secure cookies configured.

Forms/DRF serializers validate/normalize; permissions on every view/action.

Querysets lazy usage understood; annotate/prefetch/eager load; no logic in models that breaks testability.

Static/media served correctly; file uploads validated; storage backend safe.

FastAPI (Starlette/Pydantic)

Request/response models typed; validation errors consistent; pydantic settings for strict types.

Dependencies (auth/db/cache) via dependency injection; lifespans manage startup/shutdown.

Uvicorn/Gunicorn workers sized; keep-alive/timeouts set; CORS minimal.

OpenAPI docs accurate; response models return only intended fields.

12-factor: config via env (or typed settings layer like pydantic-settings); sane defaults; no env branching in code paths.

Secrets from manager (AWS Secrets Manager, GCP SM, Vault); never .env in prod; rotation tested.

Config validated on startup; misconfigurations fail fast with actionable errors.

CI runs lint/type/security/tests; failing gates block merges; artifacts are reproducible.

Images minimal (distroless/alpine when compatible), non-root, read-only fs; health checks exposed.

Gunicorn/Uvicorn/ASGI/WSGI tuned (workers, threads, timeouts); graceful shutdown handles in-flight work.

Blue/green or canary deploys available; quick rollback path; DB compatibility checks in pipeline.

SBOM generated; vulnerabilities triaged with SLAs; provenance/attestations optional.

Start/stop hooks drain queues and close DB pools.

Structured logging (JSON) with logging or structlog; correlation/request IDs included.

Log levels appropriate; no sensitive data; sampling for noisy paths.

Metrics exported (Prometheus/OpenMetrics); key RED/USE metrics instrumented.

Tracing (OpenTelemetry) spans for inbound/outbound calls; baggage/trace context propagated.

PII classified; data maps maintained; access controls audited.

Data retention/erasure implemented (GDPR/LGPD/CCPA); subject requests supported.

Encryption in transit/at rest; key management documented; audit trails immutable.

Third-party processors reviewed; DPAs in place; regional data residency respected.

CLI uses argparse/click/typer; helpful --help; exit codes meaningful.

No hard-coded paths; works cross-platform; idempotent and safe to re-run.

Logging consistent with app; errors actionable; integrates with config/secrets mechanisms.

README/quickstart updated; runbooks and on-call docs for ops behavior.

API docs generated (Sphinx/MkDocs, OpenAPI UI); examples tested.

ADRs capture key decisions; changelog maintained; deprecations documented with timelines.

Turn this checklist into automated reviews

Let Kody automatically check quality, security and performance in every pull request—cloud or self-hosted, in under 2 minutes.