pycodegate 0.1.1__tar.gz → 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pycodegate-0.1.1 → pycodegate-0.1.3}/AGENTS.md +5 -5
- {pycodegate-0.1.1 → pycodegate-0.1.3}/PKG-INFO +47 -43
- {pycodegate-0.1.1 → pycodegate-0.1.3}/README.md +45 -41
- {pycodegate-0.1.1 → pycodegate-0.1.3}/pyproject.toml +10 -6
- {pycodegate-0.1.1/skills/py-gate → pycodegate-0.1.3/skills/pycodegate}/SKILL.md +3 -3
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/__init__.py +1 -1
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/cli.py +112 -45
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/config.py +5 -5
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/output.py +43 -25
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/profile.py +56 -48
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/rules/dependencies.py +28 -18
- pycodegate-0.1.3/src/pycodegate/rules/imports.py +109 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/rules/structure.py +34 -37
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/score.py +32 -24
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/utils/badge.py +7 -7
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/utils/fixer.py +1 -1
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/utils/precommit.py +9 -9
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/test_cli.py +4 -3
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/test_config.py +9 -9
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/test_output.py +2 -4
- {pycodegate-0.1.1 → pycodegate-0.1.3}/uv.lock +1 -1
- pycodegate-0.1.3/whitelist.py +14 -0
- pycodegate-0.1.1/src/pycodegate/rules/imports.py +0 -96
- pycodegate-0.1.1/whitelist.py +0 -14
- {pycodegate-0.1.1 → pycodegate-0.1.3}/.github/workflows/ci.yml +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/.github/workflows/publish.yml +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/.gitignore +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/LICENSE +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/docs/superpowers/plans/2026-03-22-python-doctor.md +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/_compat.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/api.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/constants.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/discover.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/rules/__init__.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/rules/architecture.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/rules/base.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/rules/complexity.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/rules/correctness.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/rules/dead_code.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/rules/django.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/rules/fastapi.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/rules/flask.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/rules/performance.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/rules/security.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/scan.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/types.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/utils/__init__.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/utils/ast_helpers.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/utils/diff.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/src/pycodegate/utils/file_discovery.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/conftest.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/fixtures/basic_python/app.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/fixtures/clean_project/app.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/rules/__init__.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/rules/test_architecture.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/rules/test_complexity.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/rules/test_correctness.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/rules/test_dead_code.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/rules/test_dependencies.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/rules/test_django.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/rules/test_fastapi.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/rules/test_flask.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/rules/test_imports.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/rules/test_performance.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/rules/test_security.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/rules/test_structure.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/test_discover.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/test_fixer.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/test_integration.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/test_profile.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/test_scan.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/test_score.py +0 -0
- {pycodegate-0.1.1 → pycodegate-0.1.3}/tests/test_types.py +0 -0
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
PyCodeGate is the quality gate for AI-generated Python code. It produces a 0–100 health score by detecting your framework, running parallel lint and dead-code analysis across 40+ rules, and reporting findings by severity — so you can trust what your AI agent just wrote.
|
|
6
6
|
|
|
7
7
|
## Quick Start
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
uvx
|
|
10
|
+
uvx pycodegate . --json
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
## For AI Agents
|
|
14
14
|
|
|
15
|
-
Run `
|
|
15
|
+
Run `pycodegate . --json` after modifying Python files. Fix findings with severity `"error"` first (security, correctness). Re-run to verify the score improved. Target: **80+**.
|
|
16
16
|
|
|
17
17
|
The JSON output includes the score, label, per-diagnostic severity and file location, and detected project context (framework, Python version, package manager).
|
|
18
18
|
|
|
@@ -38,7 +38,7 @@ The JSON output includes the score, label, per-diagnostic severity and file loca
|
|
|
38
38
|
```bash
|
|
39
39
|
uv run pytest -q # run all tests
|
|
40
40
|
uv run ruff check . && uv run ruff format --check . # lint + format check
|
|
41
|
-
uv run
|
|
41
|
+
uv run pycodegate . --verbose # dogfood on ourselves
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
## Adding Rules
|
|
@@ -56,7 +56,7 @@ src/pycodegate/
|
|
|
56
56
|
api.py — Programmatic API (diagnose function)
|
|
57
57
|
scan.py — Orchestrator: parallel lint + dead code
|
|
58
58
|
score.py — Score calculation from diagnostics
|
|
59
|
-
config.py — Config loading (
|
|
59
|
+
config.py — Config loading (pycodegate.toml / pyproject.toml)
|
|
60
60
|
discover.py — Project detection (framework, package manager, etc.)
|
|
61
61
|
output.py — Rich terminal output
|
|
62
62
|
types.py — All data types (Diagnostic, Score, etc.)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pycodegate
|
|
3
|
-
Version: 0.1.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: Trust, but verify. The quality gate for AI-generated Python code.
|
|
5
5
|
Project-URL: Homepage, https://github.com/themohitkhare/pycodegate
|
|
6
6
|
Project-URL: Repository, https://github.com/themohitkhare/pycodegate
|
|
7
7
|
Project-URL: Issues, https://github.com/themohitkhare/pycodegate/issues
|
|
@@ -32,22 +32,26 @@ Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
|
32
32
|
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
33
33
|
Description-Content-Type: text/markdown
|
|
34
34
|
|
|
35
|
-
<h1 align="center">
|
|
35
|
+
<h1 align="center">PyCodeGate</h1>
|
|
36
36
|
<p align="center">
|
|
37
|
-
<strong>
|
|
37
|
+
<strong>Trust, but verify. The quality gate for AI-generated Python code.</strong>
|
|
38
38
|
</p>
|
|
39
39
|
<p align="center">
|
|
40
40
|
<a href="https://github.com/themohitkhare/pycodegate/actions/workflows/ci.yml"><img src="https://github.com/themohitkhare/pycodegate/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
41
|
-
<a href="https://pypi.org/project/
|
|
42
|
-
<a href="https://pypi.org/project/
|
|
41
|
+
<a href="https://pypi.org/project/pycodegate/"><img src="https://img.shields.io/pypi/v/pycodegate" alt="PyPI"></a>
|
|
42
|
+
<a href="https://pypi.org/project/pycodegate/"><img src="https://img.shields.io/pypi/pyversions/pycodegate" alt="Python"></a>
|
|
43
43
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a>
|
|
44
44
|
</p>
|
|
45
45
|
|
|
46
46
|
---
|
|
47
47
|
|
|
48
|
+
## Why PyCodeGate?
|
|
49
|
+
|
|
50
|
+
AI coding agents ship code fast — but fast doesn't mean safe. Every `eval()` an LLM drops in, every mutable default it forgets, every circular import it creates is a landmine waiting to go off. PyCodeGate is the trust layer between AI-generated code and your production codebase: one command, one score, zero ambiguity.
|
|
51
|
+
|
|
48
52
|
## How it works
|
|
49
53
|
|
|
50
|
-
|
|
54
|
+
PyCodeGate detects your project's context: framework (Django, FastAPI, Flask), Python version, package manager (uv, poetry, pip), and test framework. That context drives which rules are active — Django projects get SQL injection checks, FastAPI projects get async-correctness checks, and so on.
|
|
51
55
|
|
|
52
56
|
It then runs two analysis passes **in parallel**: a lint pass that evaluates 40+ rules across 8 categories (Security, Correctness, Complexity, Architecture, Performance, Structure, Imports, Dead Code), and a dead-code pass powered by [Vulture](https://github.com/jendrikseipp/vulture) that finds unused functions, classes, imports, and variables.
|
|
53
57
|
|
|
@@ -58,39 +62,39 @@ Findings are filtered through your configuration and scored using a **weighted c
|
|
|
58
62
|
Run instantly with `uvx` — no install needed:
|
|
59
63
|
|
|
60
64
|
```bash
|
|
61
|
-
uvx
|
|
65
|
+
uvx pycodegate .
|
|
62
66
|
```
|
|
63
67
|
|
|
64
68
|
Install globally with pipx or uv:
|
|
65
69
|
|
|
66
70
|
```bash
|
|
67
|
-
pipx install
|
|
71
|
+
pipx install pycodegate
|
|
68
72
|
# or
|
|
69
|
-
uv tool install
|
|
73
|
+
uv tool install pycodegate
|
|
70
74
|
# or
|
|
71
|
-
pip install
|
|
75
|
+
pip install pycodegate
|
|
72
76
|
```
|
|
73
77
|
|
|
74
78
|
## Quick Start
|
|
75
79
|
|
|
76
80
|
```bash
|
|
77
81
|
# Basic scan — score + summary
|
|
78
|
-
|
|
82
|
+
pycodegate .
|
|
79
83
|
|
|
80
84
|
# Show file paths and line numbers for every finding
|
|
81
|
-
|
|
85
|
+
pycodegate . --verbose
|
|
82
86
|
|
|
83
87
|
# Machine-readable output for AI agents and CI
|
|
84
|
-
|
|
88
|
+
pycodegate . --json
|
|
85
89
|
|
|
86
90
|
# Auto-fix ruff-fixable issues, then scan
|
|
87
|
-
|
|
91
|
+
pycodegate . --fix
|
|
88
92
|
|
|
89
93
|
# Output only the numeric score (useful in scripts)
|
|
90
|
-
|
|
94
|
+
pycodegate . --score
|
|
91
95
|
|
|
92
96
|
# Scan only files changed vs a base branch
|
|
93
|
-
|
|
97
|
+
pycodegate . --diff main
|
|
94
98
|
```
|
|
95
99
|
|
|
96
100
|
## JSON Output
|
|
@@ -98,7 +102,7 @@ py-gate . --diff main
|
|
|
98
102
|
Pass `--json` to get structured output that AI agents and CI pipelines can parse:
|
|
99
103
|
|
|
100
104
|
```bash
|
|
101
|
-
|
|
105
|
+
pycodegate . --json
|
|
102
106
|
```
|
|
103
107
|
|
|
104
108
|
```json
|
|
@@ -139,7 +143,7 @@ py-gate . --json
|
|
|
139
143
|
|
|
140
144
|
## Agent Integration
|
|
141
145
|
|
|
142
|
-
|
|
146
|
+
PyCodeGate is designed to be used by AI coding agents. Add it to your agent's context so it runs after every Python change.
|
|
143
147
|
|
|
144
148
|
### Claude Code
|
|
145
149
|
|
|
@@ -147,18 +151,18 @@ Add the skill to your project:
|
|
|
147
151
|
|
|
148
152
|
```bash
|
|
149
153
|
mkdir -p .claude/skills
|
|
150
|
-
curl -fsSL https://raw.githubusercontent.com/themohitkhare/pycodegate/main/skills/
|
|
151
|
-
-o .claude/skills/
|
|
154
|
+
curl -fsSL https://raw.githubusercontent.com/themohitkhare/pycodegate/main/skills/pycodegate/SKILL.md \
|
|
155
|
+
-o .claude/skills/pycodegate.md
|
|
152
156
|
```
|
|
153
157
|
|
|
154
158
|
Or copy `AGENTS.md` to your project root — Claude Code picks it up automatically.
|
|
155
159
|
|
|
156
160
|
### Cursor
|
|
157
161
|
|
|
158
|
-
Add to `.cursor/rules/
|
|
162
|
+
Add to `.cursor/rules/pycodegate.mdc`:
|
|
159
163
|
|
|
160
164
|
```markdown
|
|
161
|
-
After modifying Python files, run `uvx
|
|
165
|
+
After modifying Python files, run `uvx pycodegate . --json` and fix all findings
|
|
162
166
|
with severity "error" before marking the task complete. Target score: 80+.
|
|
163
167
|
```
|
|
164
168
|
|
|
@@ -167,7 +171,7 @@ with severity "error" before marking the task complete. Target score: 80+.
|
|
|
167
171
|
Add to `.windsurfrules`:
|
|
168
172
|
|
|
169
173
|
```
|
|
170
|
-
After modifying Python files, run: uvx
|
|
174
|
+
After modifying Python files, run: uvx pycodegate . --json
|
|
171
175
|
Fix all "error" severity findings. Re-run to verify the score improved.
|
|
172
176
|
```
|
|
173
177
|
|
|
@@ -176,7 +180,7 @@ Fix all "error" severity findings. Re-run to verify the score improved.
|
|
|
176
180
|
Add to your system prompt:
|
|
177
181
|
|
|
178
182
|
```
|
|
179
|
-
After modifying Python files, run `uvx
|
|
183
|
+
After modifying Python files, run `uvx pycodegate . --json` to check code quality.
|
|
180
184
|
Fix errors first. Target score: 80+.
|
|
181
185
|
```
|
|
182
186
|
|
|
@@ -194,7 +198,7 @@ name: Quality Gate
|
|
|
194
198
|
on: [push, pull_request]
|
|
195
199
|
|
|
196
200
|
jobs:
|
|
197
|
-
|
|
201
|
+
pycodegate:
|
|
198
202
|
runs-on: ubuntu-latest
|
|
199
203
|
steps:
|
|
200
204
|
- uses: actions/checkout@v4
|
|
@@ -205,10 +209,10 @@ jobs:
|
|
|
205
209
|
with:
|
|
206
210
|
python-version: "3.12"
|
|
207
211
|
|
|
208
|
-
- name: Run
|
|
212
|
+
- name: Run PyCodeGate
|
|
209
213
|
run: |
|
|
210
|
-
pip install
|
|
211
|
-
|
|
214
|
+
pip install pycodegate
|
|
215
|
+
pycodegate . --verbose --diff main --fail-on error
|
|
212
216
|
```
|
|
213
217
|
|
|
214
218
|
## CLI Reference
|
|
@@ -244,7 +248,7 @@ Framework-specific rules (Django, FastAPI, Flask) are mapped into the Security o
|
|
|
244
248
|
|
|
245
249
|
## Scoring
|
|
246
250
|
|
|
247
|
-
|
|
251
|
+
PyCodeGate uses a **weighted category-budget system**:
|
|
248
252
|
|
|
249
253
|
1. Each category has a weight (see table above). Weights are normalized to sum to 100 points of total deduction budget.
|
|
250
254
|
2. Within a category, findings are sorted by cost (errors cost more than warnings). The top 3 findings apply at full cost; every additional finding applies **diminishing returns** (10% of its cost).
|
|
@@ -260,7 +264,7 @@ Py Gate uses a **weighted category-budget system**:
|
|
|
260
264
|
|
|
261
265
|
## Configuration
|
|
262
266
|
|
|
263
|
-
Create `
|
|
267
|
+
Create `pycodegate.toml` in your project root:
|
|
264
268
|
|
|
265
269
|
```toml
|
|
266
270
|
[options]
|
|
@@ -284,27 +288,27 @@ max-deduction.Dead Code = 0 # disable dead-code penalty entirely
|
|
|
284
288
|
Or use `pyproject.toml`:
|
|
285
289
|
|
|
286
290
|
```toml
|
|
287
|
-
[tool.
|
|
291
|
+
[tool.pycodegate]
|
|
288
292
|
lint = true
|
|
289
293
|
dead_code = true
|
|
290
294
|
fail_on = "error"
|
|
291
295
|
|
|
292
|
-
[tool.
|
|
296
|
+
[tool.pycodegate.ignore]
|
|
293
297
|
rules = ["no-import-in-function"]
|
|
294
298
|
files = ["tests/fixtures/**"]
|
|
295
299
|
|
|
296
|
-
[tool.
|
|
300
|
+
[tool.pycodegate.per-file-ignores]
|
|
297
301
|
"src/legacy/*.py" = ["high-complexity"]
|
|
298
302
|
|
|
299
|
-
[tool.
|
|
303
|
+
[tool.pycodegate.scoring]
|
|
300
304
|
"max-deduction" = { Security = 20, "Dead Code" = 0 }
|
|
301
305
|
```
|
|
302
306
|
|
|
303
|
-
If both files exist, `
|
|
307
|
+
If both files exist, `pycodegate.toml` takes precedence. CLI flags always override config values.
|
|
304
308
|
|
|
305
309
|
## Profiles
|
|
306
310
|
|
|
307
|
-
|
|
311
|
+
PyCodeGate auto-detects a project profile and adjusts rule weights accordingly. You can also set a profile explicitly in config (`profile = "library"`).
|
|
308
312
|
|
|
309
313
|
| Profile | Auto-detected when | Adjustments |
|
|
310
314
|
|---------|--------------------|-------------|
|
|
@@ -315,10 +319,10 @@ Py Gate auto-detects a project profile and adjusts rule weights accordingly. You
|
|
|
315
319
|
|
|
316
320
|
## Pre-commit Hook
|
|
317
321
|
|
|
318
|
-
Use `--pre-commit` to run
|
|
322
|
+
Use `--pre-commit` to run PyCodeGate as a pre-commit hook. It automatically scans only the staged files:
|
|
319
323
|
|
|
320
324
|
```bash
|
|
321
|
-
|
|
325
|
+
pycodegate . --pre-commit --fail-on error
|
|
322
326
|
```
|
|
323
327
|
|
|
324
328
|
Add to `.pre-commit-config.yaml`:
|
|
@@ -327,9 +331,9 @@ Add to `.pre-commit-config.yaml`:
|
|
|
327
331
|
repos:
|
|
328
332
|
- repo: local
|
|
329
333
|
hooks:
|
|
330
|
-
- id:
|
|
331
|
-
name:
|
|
332
|
-
entry:
|
|
334
|
+
- id: pycodegate
|
|
335
|
+
name: PyCodeGate quality check
|
|
336
|
+
entry: pycodegate . --pre-commit --fail-on error
|
|
333
337
|
language: system
|
|
334
338
|
types: [python]
|
|
335
339
|
pass_filenames: false
|
|
@@ -342,7 +346,7 @@ git clone https://github.com/themohitkhare/pycodegate
|
|
|
342
346
|
cd pycodegate
|
|
343
347
|
uv sync --all-extras
|
|
344
348
|
uv run pytest -q
|
|
345
|
-
uv run
|
|
349
|
+
uv run pycodegate . --verbose # dogfood it
|
|
346
350
|
```
|
|
347
351
|
|
|
348
352
|
To add a new rule:
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
<h1 align="center">
|
|
1
|
+
<h1 align="center">PyCodeGate</h1>
|
|
2
2
|
<p align="center">
|
|
3
|
-
<strong>
|
|
3
|
+
<strong>Trust, but verify. The quality gate for AI-generated Python code.</strong>
|
|
4
4
|
</p>
|
|
5
5
|
<p align="center">
|
|
6
6
|
<a href="https://github.com/themohitkhare/pycodegate/actions/workflows/ci.yml"><img src="https://github.com/themohitkhare/pycodegate/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
7
|
-
<a href="https://pypi.org/project/
|
|
8
|
-
<a href="https://pypi.org/project/
|
|
7
|
+
<a href="https://pypi.org/project/pycodegate/"><img src="https://img.shields.io/pypi/v/pycodegate" alt="PyPI"></a>
|
|
8
|
+
<a href="https://pypi.org/project/pycodegate/"><img src="https://img.shields.io/pypi/pyversions/pycodegate" alt="Python"></a>
|
|
9
9
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a>
|
|
10
10
|
</p>
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
+
## Why PyCodeGate?
|
|
15
|
+
|
|
16
|
+
AI coding agents ship code fast — but fast doesn't mean safe. Every `eval()` an LLM drops in, every mutable default it forgets, every circular import it creates is a landmine waiting to go off. PyCodeGate is the trust layer between AI-generated code and your production codebase: one command, one score, zero ambiguity.
|
|
17
|
+
|
|
14
18
|
## How it works
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
PyCodeGate detects your project's context: framework (Django, FastAPI, Flask), Python version, package manager (uv, poetry, pip), and test framework. That context drives which rules are active — Django projects get SQL injection checks, FastAPI projects get async-correctness checks, and so on.
|
|
17
21
|
|
|
18
22
|
It then runs two analysis passes **in parallel**: a lint pass that evaluates 40+ rules across 8 categories (Security, Correctness, Complexity, Architecture, Performance, Structure, Imports, Dead Code), and a dead-code pass powered by [Vulture](https://github.com/jendrikseipp/vulture) that finds unused functions, classes, imports, and variables.
|
|
19
23
|
|
|
@@ -24,39 +28,39 @@ Findings are filtered through your configuration and scored using a **weighted c
|
|
|
24
28
|
Run instantly with `uvx` — no install needed:
|
|
25
29
|
|
|
26
30
|
```bash
|
|
27
|
-
uvx
|
|
31
|
+
uvx pycodegate .
|
|
28
32
|
```
|
|
29
33
|
|
|
30
34
|
Install globally with pipx or uv:
|
|
31
35
|
|
|
32
36
|
```bash
|
|
33
|
-
pipx install
|
|
37
|
+
pipx install pycodegate
|
|
34
38
|
# or
|
|
35
|
-
uv tool install
|
|
39
|
+
uv tool install pycodegate
|
|
36
40
|
# or
|
|
37
|
-
pip install
|
|
41
|
+
pip install pycodegate
|
|
38
42
|
```
|
|
39
43
|
|
|
40
44
|
## Quick Start
|
|
41
45
|
|
|
42
46
|
```bash
|
|
43
47
|
# Basic scan — score + summary
|
|
44
|
-
|
|
48
|
+
pycodegate .
|
|
45
49
|
|
|
46
50
|
# Show file paths and line numbers for every finding
|
|
47
|
-
|
|
51
|
+
pycodegate . --verbose
|
|
48
52
|
|
|
49
53
|
# Machine-readable output for AI agents and CI
|
|
50
|
-
|
|
54
|
+
pycodegate . --json
|
|
51
55
|
|
|
52
56
|
# Auto-fix ruff-fixable issues, then scan
|
|
53
|
-
|
|
57
|
+
pycodegate . --fix
|
|
54
58
|
|
|
55
59
|
# Output only the numeric score (useful in scripts)
|
|
56
|
-
|
|
60
|
+
pycodegate . --score
|
|
57
61
|
|
|
58
62
|
# Scan only files changed vs a base branch
|
|
59
|
-
|
|
63
|
+
pycodegate . --diff main
|
|
60
64
|
```
|
|
61
65
|
|
|
62
66
|
## JSON Output
|
|
@@ -64,7 +68,7 @@ py-gate . --diff main
|
|
|
64
68
|
Pass `--json` to get structured output that AI agents and CI pipelines can parse:
|
|
65
69
|
|
|
66
70
|
```bash
|
|
67
|
-
|
|
71
|
+
pycodegate . --json
|
|
68
72
|
```
|
|
69
73
|
|
|
70
74
|
```json
|
|
@@ -105,7 +109,7 @@ py-gate . --json
|
|
|
105
109
|
|
|
106
110
|
## Agent Integration
|
|
107
111
|
|
|
108
|
-
|
|
112
|
+
PyCodeGate is designed to be used by AI coding agents. Add it to your agent's context so it runs after every Python change.
|
|
109
113
|
|
|
110
114
|
### Claude Code
|
|
111
115
|
|
|
@@ -113,18 +117,18 @@ Add the skill to your project:
|
|
|
113
117
|
|
|
114
118
|
```bash
|
|
115
119
|
mkdir -p .claude/skills
|
|
116
|
-
curl -fsSL https://raw.githubusercontent.com/themohitkhare/pycodegate/main/skills/
|
|
117
|
-
-o .claude/skills/
|
|
120
|
+
curl -fsSL https://raw.githubusercontent.com/themohitkhare/pycodegate/main/skills/pycodegate/SKILL.md \
|
|
121
|
+
-o .claude/skills/pycodegate.md
|
|
118
122
|
```
|
|
119
123
|
|
|
120
124
|
Or copy `AGENTS.md` to your project root — Claude Code picks it up automatically.
|
|
121
125
|
|
|
122
126
|
### Cursor
|
|
123
127
|
|
|
124
|
-
Add to `.cursor/rules/
|
|
128
|
+
Add to `.cursor/rules/pycodegate.mdc`:
|
|
125
129
|
|
|
126
130
|
```markdown
|
|
127
|
-
After modifying Python files, run `uvx
|
|
131
|
+
After modifying Python files, run `uvx pycodegate . --json` and fix all findings
|
|
128
132
|
with severity "error" before marking the task complete. Target score: 80+.
|
|
129
133
|
```
|
|
130
134
|
|
|
@@ -133,7 +137,7 @@ with severity "error" before marking the task complete. Target score: 80+.
|
|
|
133
137
|
Add to `.windsurfrules`:
|
|
134
138
|
|
|
135
139
|
```
|
|
136
|
-
After modifying Python files, run: uvx
|
|
140
|
+
After modifying Python files, run: uvx pycodegate . --json
|
|
137
141
|
Fix all "error" severity findings. Re-run to verify the score improved.
|
|
138
142
|
```
|
|
139
143
|
|
|
@@ -142,7 +146,7 @@ Fix all "error" severity findings. Re-run to verify the score improved.
|
|
|
142
146
|
Add to your system prompt:
|
|
143
147
|
|
|
144
148
|
```
|
|
145
|
-
After modifying Python files, run `uvx
|
|
149
|
+
After modifying Python files, run `uvx pycodegate . --json` to check code quality.
|
|
146
150
|
Fix errors first. Target score: 80+.
|
|
147
151
|
```
|
|
148
152
|
|
|
@@ -160,7 +164,7 @@ name: Quality Gate
|
|
|
160
164
|
on: [push, pull_request]
|
|
161
165
|
|
|
162
166
|
jobs:
|
|
163
|
-
|
|
167
|
+
pycodegate:
|
|
164
168
|
runs-on: ubuntu-latest
|
|
165
169
|
steps:
|
|
166
170
|
- uses: actions/checkout@v4
|
|
@@ -171,10 +175,10 @@ jobs:
|
|
|
171
175
|
with:
|
|
172
176
|
python-version: "3.12"
|
|
173
177
|
|
|
174
|
-
- name: Run
|
|
178
|
+
- name: Run PyCodeGate
|
|
175
179
|
run: |
|
|
176
|
-
pip install
|
|
177
|
-
|
|
180
|
+
pip install pycodegate
|
|
181
|
+
pycodegate . --verbose --diff main --fail-on error
|
|
178
182
|
```
|
|
179
183
|
|
|
180
184
|
## CLI Reference
|
|
@@ -210,7 +214,7 @@ Framework-specific rules (Django, FastAPI, Flask) are mapped into the Security o
|
|
|
210
214
|
|
|
211
215
|
## Scoring
|
|
212
216
|
|
|
213
|
-
|
|
217
|
+
PyCodeGate uses a **weighted category-budget system**:
|
|
214
218
|
|
|
215
219
|
1. Each category has a weight (see table above). Weights are normalized to sum to 100 points of total deduction budget.
|
|
216
220
|
2. Within a category, findings are sorted by cost (errors cost more than warnings). The top 3 findings apply at full cost; every additional finding applies **diminishing returns** (10% of its cost).
|
|
@@ -226,7 +230,7 @@ Py Gate uses a **weighted category-budget system**:
|
|
|
226
230
|
|
|
227
231
|
## Configuration
|
|
228
232
|
|
|
229
|
-
Create `
|
|
233
|
+
Create `pycodegate.toml` in your project root:
|
|
230
234
|
|
|
231
235
|
```toml
|
|
232
236
|
[options]
|
|
@@ -250,27 +254,27 @@ max-deduction.Dead Code = 0 # disable dead-code penalty entirely
|
|
|
250
254
|
Or use `pyproject.toml`:
|
|
251
255
|
|
|
252
256
|
```toml
|
|
253
|
-
[tool.
|
|
257
|
+
[tool.pycodegate]
|
|
254
258
|
lint = true
|
|
255
259
|
dead_code = true
|
|
256
260
|
fail_on = "error"
|
|
257
261
|
|
|
258
|
-
[tool.
|
|
262
|
+
[tool.pycodegate.ignore]
|
|
259
263
|
rules = ["no-import-in-function"]
|
|
260
264
|
files = ["tests/fixtures/**"]
|
|
261
265
|
|
|
262
|
-
[tool.
|
|
266
|
+
[tool.pycodegate.per-file-ignores]
|
|
263
267
|
"src/legacy/*.py" = ["high-complexity"]
|
|
264
268
|
|
|
265
|
-
[tool.
|
|
269
|
+
[tool.pycodegate.scoring]
|
|
266
270
|
"max-deduction" = { Security = 20, "Dead Code" = 0 }
|
|
267
271
|
```
|
|
268
272
|
|
|
269
|
-
If both files exist, `
|
|
273
|
+
If both files exist, `pycodegate.toml` takes precedence. CLI flags always override config values.
|
|
270
274
|
|
|
271
275
|
## Profiles
|
|
272
276
|
|
|
273
|
-
|
|
277
|
+
PyCodeGate auto-detects a project profile and adjusts rule weights accordingly. You can also set a profile explicitly in config (`profile = "library"`).
|
|
274
278
|
|
|
275
279
|
| Profile | Auto-detected when | Adjustments |
|
|
276
280
|
|---------|--------------------|-------------|
|
|
@@ -281,10 +285,10 @@ Py Gate auto-detects a project profile and adjusts rule weights accordingly. You
|
|
|
281
285
|
|
|
282
286
|
## Pre-commit Hook
|
|
283
287
|
|
|
284
|
-
Use `--pre-commit` to run
|
|
288
|
+
Use `--pre-commit` to run PyCodeGate as a pre-commit hook. It automatically scans only the staged files:
|
|
285
289
|
|
|
286
290
|
```bash
|
|
287
|
-
|
|
291
|
+
pycodegate . --pre-commit --fail-on error
|
|
288
292
|
```
|
|
289
293
|
|
|
290
294
|
Add to `.pre-commit-config.yaml`:
|
|
@@ -293,9 +297,9 @@ Add to `.pre-commit-config.yaml`:
|
|
|
293
297
|
repos:
|
|
294
298
|
- repo: local
|
|
295
299
|
hooks:
|
|
296
|
-
- id:
|
|
297
|
-
name:
|
|
298
|
-
entry:
|
|
300
|
+
- id: pycodegate
|
|
301
|
+
name: PyCodeGate quality check
|
|
302
|
+
entry: pycodegate . --pre-commit --fail-on error
|
|
299
303
|
language: system
|
|
300
304
|
types: [python]
|
|
301
305
|
pass_filenames: false
|
|
@@ -308,7 +312,7 @@ git clone https://github.com/themohitkhare/pycodegate
|
|
|
308
312
|
cd pycodegate
|
|
309
313
|
uv sync --all-extras
|
|
310
314
|
uv run pytest -q
|
|
311
|
-
uv run
|
|
315
|
+
uv run pycodegate . --verbose # dogfood it
|
|
312
316
|
```
|
|
313
317
|
|
|
314
318
|
To add a new rule:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pycodegate"
|
|
3
|
-
version = "0.1.
|
|
4
|
-
description = "
|
|
3
|
+
version = "0.1.3"
|
|
4
|
+
description = "Trust, but verify. The quality gate for AI-generated Python code."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
7
7
|
license = "MIT"
|
|
@@ -42,7 +42,7 @@ dev = [
|
|
|
42
42
|
|
|
43
43
|
[project.scripts]
|
|
44
44
|
pycodegate = "pycodegate.cli:main"
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
|
|
47
47
|
[build-system]
|
|
48
48
|
requires = ["hatchling"]
|
|
@@ -70,6 +70,10 @@ ignore = ["SIM102"] # nested ifs in AST walking are clearer than combined condi
|
|
|
70
70
|
"src/pycodegate/rules/base.py" = ["TC001"] # runtime import in abstract method
|
|
71
71
|
"src/pycodegate/utils/*.py" = ["E501"]
|
|
72
72
|
|
|
73
|
-
[tool.
|
|
74
|
-
[tool.
|
|
75
|
-
files = ["tests/fixtures/**"]
|
|
73
|
+
[tool.pycodegate]
|
|
74
|
+
[tool.pycodegate.ignore]
|
|
75
|
+
files = ["tests/fixtures/**", "tests/**"]
|
|
76
|
+
|
|
77
|
+
[tool.pycodegate.per-file-suppress]
|
|
78
|
+
# Click CLI entry-points must declare all options as individual parameters
|
|
79
|
+
"src/pycodegate/cli.py" = ["too-many-arguments"]
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: pycodegate
|
|
3
3
|
description: Run after making Python changes to catch issues early. Use when reviewing code, finishing a feature, or fixing bugs.
|
|
4
4
|
version: 1.0.0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
#
|
|
7
|
+
# PyCodeGate
|
|
8
8
|
|
|
9
9
|
Scans your Python codebase for security, performance, correctness, architecture, and structure issues. Outputs a 0-100 score with actionable diagnostics. Auto-detects Django, FastAPI, and Flask to activate framework-specific rules.
|
|
10
10
|
|
|
11
11
|
## Usage
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
uvx
|
|
14
|
+
uvx pycodegate . --verbose --diff
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
## Workflow
|