Human-friendly static checks for Python: correctness, security, robustness — grouped by impact.
Project description
pycodereview
Static checks for common Python code risks and hygiene issues.
Runs on a single file or an entire tree and outputs a concise CSV report you can diff, gate in CI, or hand to a teammate.
Why pycodereview?
Most static analysis tools (like pylint, flake8, or ruff) focus on style compliance, lint rules, and PEP8/typing.
pycodereview is different — it’s designed for human code review augmentation, not just linting.
It aims to:
-
Group findings by impact rather than rule ID.
You get concise categories (Correctness, Security, Robustness, etc.) with human-readable explanations instead of cryptic codes. -
Bridge readability and auditability.
The CSV format and per-issue “potential impact” line make it easy to share results with non-developers (QA, auditors, project managers). -
Highlight “risky patterns,” not just style issues.
e.g., mutable default arguments, missing joins on threads, unsafe deserialization, misuse ofassert— issues ordinary linters often miss. -
Run with zero setup.
No configs, plugins, or rule IDs needed — just point it to a file and go. -
Stay lightweight.
Uses Python’s built-inastandtokenize— no heavy deps. -
Complement other tools.
Meant to run alongside type checkers and formatters — catching logic and lifecycle issues they miss.
What it checks
- Error Handling: catch-alls, empty
except, exception re-raise quality. - Correctness: mutable default args, misuse of
assert, identity vs equality, undefined names, magic token numbers, ignored returns, return/annotation mismatches, premature exits. - Security:
eval/exec, unsafesubprocess,os.system, unsafe YAML/Pickle loads. - Concurrency: thread/process lifecycle, import-time multiprocessing, shared mutable globals.
- Resource Management:
open()without context manager, read/write mode mismatches, missing encodings. - Robustness: brittle CSV parsing, unguarded dict/key access, potential type/len pitfalls.
- Maintainability & Style: wildcard imports, unused imports/variables, naming conventions, docstrings (optional), print statements, non-Pythonic loops, len comparisons, import order, magic literals.
- Portability: hardcoded platform paths.
- Process: TODO/FIXME markers.
Each finding has category, priority, impacted lines, potential impact, and description.
Installation
From source (recommended while iterating)
git clone git@github.com:<you>/pycodereview.git
cd pycodereview
# optional virtualenv
python -m venv .venv
# Windows:
# .venv\\Scripts\\activate
# POSIX:
. .venv/bin/activate
pip install -U pip setuptools wheel
pip install -e .
One-off usage (no install)
python -m pycodereview.code_review path/to/target.py
Quick start
Analyze a single file:
pycodereview ./src/test_cases.py
Analyze a whole project:
pycodereview ./src
Write CSV report:
pycodereview ./src > review_report.csv
Show only MEDIUM and higher:
pycodereview ./src --min-priority MEDIUM
Merge identical issues across multiple lines:
pycodereview ./src --merge-issues
Limit checks for large functions (max 600 lines):
pycodereview ./src --max-lines 600
CLI options
pycodereview [PATH ...] [options]
Options:
--min-priority {LOW,MEDIUM,HIGH} Minimum priority to include (default: LOW)
--max-lines N Skip checks in functions longer than N lines (default: 1200)
--merge-issues Merge same issues across multiple lines into a single report row
--format {csv,table} Output format (default: csv)
--version Show version and exit
-h, --help Show this help message and exit
Multiple files or directories are supported in one run.
Output format (CSV)
Columns:
- category of issue
- priority of issue
- impacted lines (single line, range
a-b, or comma-separated list) - potential impact
- description (
<file>: <message>)
Example:
Correctness;MEDIUM;257,332,380,396,401,426;"Asserts can be stripped with -O; critical checks may disappear.";"testfile.py: Avoid assert for runtime validation; raise exceptions instead."
Example integrations
Pre-commit
# .pre-commit-config.yaml
- repo: https://github.com/<you>/pycodereview
rev: v0.1.1
hooks:
- id: pycodereview
args: [--min-priority, MEDIUM, --merge-issues]
GitHub Actions
# .github/workflows/review.yml
name: Static review
on: [push, pull_request]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: '3.11' }
- run: pip install .
- run: pycodereview ./src --min-priority MEDIUM --merge-issues > review_report.csv
- run: grep -q "HIGH" review_report.csv && echo "High issues found" && exit 1 || echo "OK"
Limitations
- Static checks can’t replace full linters/type checkers (
ruff,flake8,mypy, etc.). - Some security rules err on the side of caution (false positives possible).
- This tool only reports; no auto-fixes are applied.
Contributing
PRs welcome! Please:
- add unit tests for new rules,
- keep messages concise and actionable,
- document new options in the README,
- run
blackandruffbefore committing.
License
MIT — see LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pycodereview-0.1.1.tar.gz.
File metadata
- Download URL: pycodereview-0.1.1.tar.gz
- Upload date:
- Size: 25.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
35c31c288a1f7cc5ee276036f19512d7eec77c87947885419290634961e41429
|
|
| MD5 |
c72b98b24e22c3710155450f1ef5d997
|
|
| BLAKE2b-256 |
e177c75dbf90f9cfd7a92198ed1fa0c9ab56fccac5a8665619992e6bca87dd09
|
File details
Details for the file pycodereview-0.1.1-py3-none-any.whl.
File metadata
- Download URL: pycodereview-0.1.1-py3-none-any.whl
- Upload date:
- Size: 22.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd96d6e9468c8f7aa3ce0be396fb4ea4a6362bfa41a09b06d00a9adc08c5ef68
|
|
| MD5 |
749d2e0be8021875d5e564730e23b4e4
|
|
| BLAKE2b-256 |
6fa4240153334ef260236bd25f544fe09d84f6854d9133494716eb2c8f5d5256
|