Let Kody automatically check quality, security and performance in every pull request—cloud or self-hosted, in under 2 minutes.
A complete checklist to guide Python code review for reliability, security and performance, ensuring every pull request is production ready.
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.
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.
Let Kody automatically check quality, security and performance in every pull request—cloud or self-hosted, in under 2 minutes.