pycodegate 0.1.1__tar.gz → 0.1.2__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.
Files changed (71) hide show
  1. {pycodegate-0.1.1 → pycodegate-0.1.2}/AGENTS.md +5 -5
  2. {pycodegate-0.1.1 → pycodegate-0.1.2}/PKG-INFO +41 -41
  3. {pycodegate-0.1.1 → pycodegate-0.1.2}/README.md +40 -40
  4. {pycodegate-0.1.1 → pycodegate-0.1.2}/pyproject.toml +4 -4
  5. {pycodegate-0.1.1/skills/py-gate → pycodegate-0.1.2/skills/pycodegate}/SKILL.md +3 -3
  6. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/__init__.py +1 -1
  7. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/cli.py +3 -3
  8. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/config.py +5 -5
  9. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/output.py +3 -1
  10. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/rules/dependencies.py +1 -1
  11. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/utils/badge.py +7 -7
  12. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/utils/precommit.py +9 -9
  13. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/test_cli.py +4 -3
  14. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/test_config.py +9 -9
  15. {pycodegate-0.1.1 → pycodegate-0.1.2}/uv.lock +1 -1
  16. {pycodegate-0.1.1 → pycodegate-0.1.2}/.github/workflows/ci.yml +0 -0
  17. {pycodegate-0.1.1 → pycodegate-0.1.2}/.github/workflows/publish.yml +0 -0
  18. {pycodegate-0.1.1 → pycodegate-0.1.2}/.gitignore +0 -0
  19. {pycodegate-0.1.1 → pycodegate-0.1.2}/LICENSE +0 -0
  20. {pycodegate-0.1.1 → pycodegate-0.1.2}/docs/superpowers/plans/2026-03-22-python-doctor.md +0 -0
  21. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/_compat.py +0 -0
  22. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/api.py +0 -0
  23. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/constants.py +0 -0
  24. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/discover.py +0 -0
  25. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/profile.py +0 -0
  26. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/rules/__init__.py +0 -0
  27. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/rules/architecture.py +0 -0
  28. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/rules/base.py +0 -0
  29. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/rules/complexity.py +0 -0
  30. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/rules/correctness.py +0 -0
  31. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/rules/dead_code.py +0 -0
  32. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/rules/django.py +0 -0
  33. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/rules/fastapi.py +0 -0
  34. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/rules/flask.py +0 -0
  35. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/rules/imports.py +0 -0
  36. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/rules/performance.py +0 -0
  37. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/rules/security.py +0 -0
  38. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/rules/structure.py +0 -0
  39. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/scan.py +0 -0
  40. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/score.py +0 -0
  41. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/types.py +0 -0
  42. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/utils/__init__.py +0 -0
  43. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/utils/ast_helpers.py +0 -0
  44. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/utils/diff.py +0 -0
  45. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/utils/file_discovery.py +0 -0
  46. {pycodegate-0.1.1 → pycodegate-0.1.2}/src/pycodegate/utils/fixer.py +0 -0
  47. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/conftest.py +0 -0
  48. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/fixtures/basic_python/app.py +0 -0
  49. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/fixtures/clean_project/app.py +0 -0
  50. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/rules/__init__.py +0 -0
  51. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/rules/test_architecture.py +0 -0
  52. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/rules/test_complexity.py +0 -0
  53. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/rules/test_correctness.py +0 -0
  54. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/rules/test_dead_code.py +0 -0
  55. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/rules/test_dependencies.py +0 -0
  56. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/rules/test_django.py +0 -0
  57. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/rules/test_fastapi.py +0 -0
  58. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/rules/test_flask.py +0 -0
  59. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/rules/test_imports.py +0 -0
  60. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/rules/test_performance.py +0 -0
  61. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/rules/test_security.py +0 -0
  62. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/rules/test_structure.py +0 -0
  63. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/test_discover.py +0 -0
  64. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/test_fixer.py +0 -0
  65. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/test_integration.py +0 -0
  66. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/test_output.py +0 -0
  67. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/test_profile.py +0 -0
  68. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/test_scan.py +0 -0
  69. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/test_score.py +0 -0
  70. {pycodegate-0.1.1 → pycodegate-0.1.2}/tests/test_types.py +0 -0
  71. {pycodegate-0.1.1 → pycodegate-0.1.2}/whitelist.py +0 -0
@@ -2,17 +2,17 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- py-gate is a Python code quality gate that produces a 0–100 health score. It detects your framework, runs parallel lint and dead-code analysis across 40+ rules, and reports findings by severity so you always know what to fix first.
5
+ pycodegate is a Python code quality gate that produces a 0–100 health score. It detects your framework, runs parallel lint and dead-code analysis across 40+ rules, and reports findings by severity so you always know what to fix first.
6
6
 
7
7
  ## Quick Start
8
8
 
9
9
  ```bash
10
- uvx py-gate . --json
10
+ uvx pycodegate . --json
11
11
  ```
12
12
 
13
13
  ## For AI Agents
14
14
 
15
- Run `py-gate . --json` after modifying Python files. Fix findings with severity `"error"` first (security, correctness). Re-run to verify the score improved. Target: **80+**.
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 py-gate . --verbose # dogfood on ourselves
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 (py-gate.toml / pyproject.toml)
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycodegate
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: One command. One score. Your Python quality gate.
5
5
  Project-URL: Homepage, https://github.com/themohitkhare/pycodegate
6
6
  Project-URL: Repository, https://github.com/themohitkhare/pycodegate
@@ -32,14 +32,14 @@ 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">Py Gate</h1>
35
+ <h1 align="center">PyCodeGate</h1>
36
36
  <p align="center">
37
37
  <strong>One command. One score. Your Python quality gate.</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/py-gate/"><img src="https://img.shields.io/pypi/v/py-gate" alt="PyPI"></a>
42
- <a href="https://pypi.org/project/py-gate/"><img src="https://img.shields.io/pypi/pyversions/py-gate" alt="Python"></a>
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
 
@@ -47,7 +47,7 @@ Description-Content-Type: text/markdown
47
47
 
48
48
  ## How it works
49
49
 
50
- Py Gate starts by detecting 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.
50
+ PyCodeGate starts by detecting 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
51
 
52
52
  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
53
 
@@ -58,39 +58,39 @@ Findings are filtered through your configuration and scored using a **weighted c
58
58
  Run instantly with `uvx` — no install needed:
59
59
 
60
60
  ```bash
61
- uvx py-gate .
61
+ uvx pycodegate .
62
62
  ```
63
63
 
64
64
  Install globally with pipx or uv:
65
65
 
66
66
  ```bash
67
- pipx install py-gate
67
+ pipx install pycodegate
68
68
  # or
69
- uv tool install py-gate
69
+ uv tool install pycodegate
70
70
  # or
71
- pip install py-gate
71
+ pip install pycodegate
72
72
  ```
73
73
 
74
74
  ## Quick Start
75
75
 
76
76
  ```bash
77
77
  # Basic scan — score + summary
78
- py-gate .
78
+ pycodegate .
79
79
 
80
80
  # Show file paths and line numbers for every finding
81
- py-gate . --verbose
81
+ pycodegate . --verbose
82
82
 
83
83
  # Machine-readable output for AI agents and CI
84
- py-gate . --json
84
+ pycodegate . --json
85
85
 
86
86
  # Auto-fix ruff-fixable issues, then scan
87
- py-gate . --fix
87
+ pycodegate . --fix
88
88
 
89
89
  # Output only the numeric score (useful in scripts)
90
- py-gate . --score
90
+ pycodegate . --score
91
91
 
92
92
  # Scan only files changed vs a base branch
93
- py-gate . --diff main
93
+ pycodegate . --diff main
94
94
  ```
95
95
 
96
96
  ## JSON Output
@@ -98,7 +98,7 @@ py-gate . --diff main
98
98
  Pass `--json` to get structured output that AI agents and CI pipelines can parse:
99
99
 
100
100
  ```bash
101
- py-gate . --json
101
+ pycodegate . --json
102
102
  ```
103
103
 
104
104
  ```json
@@ -139,7 +139,7 @@ py-gate . --json
139
139
 
140
140
  ## Agent Integration
141
141
 
142
- Py Gate is designed to be used by AI coding agents. Add it to your agent's context so it runs after every Python change.
142
+ 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
143
 
144
144
  ### Claude Code
145
145
 
@@ -147,18 +147,18 @@ Add the skill to your project:
147
147
 
148
148
  ```bash
149
149
  mkdir -p .claude/skills
150
- curl -fsSL https://raw.githubusercontent.com/themohitkhare/pycodegate/main/skills/py-gate/SKILL.md \
151
- -o .claude/skills/py-gate.md
150
+ curl -fsSL https://raw.githubusercontent.com/themohitkhare/pycodegate/main/skills/pycodegate/SKILL.md \
151
+ -o .claude/skills/pycodegate.md
152
152
  ```
153
153
 
154
154
  Or copy `AGENTS.md` to your project root — Claude Code picks it up automatically.
155
155
 
156
156
  ### Cursor
157
157
 
158
- Add to `.cursor/rules/py-gate.mdc`:
158
+ Add to `.cursor/rules/pycodegate.mdc`:
159
159
 
160
160
  ```markdown
161
- After modifying Python files, run `uvx py-gate . --json` and fix all findings
161
+ After modifying Python files, run `uvx pycodegate . --json` and fix all findings
162
162
  with severity "error" before marking the task complete. Target score: 80+.
163
163
  ```
164
164
 
@@ -167,7 +167,7 @@ with severity "error" before marking the task complete. Target score: 80+.
167
167
  Add to `.windsurfrules`:
168
168
 
169
169
  ```
170
- After modifying Python files, run: uvx py-gate . --json
170
+ After modifying Python files, run: uvx pycodegate . --json
171
171
  Fix all "error" severity findings. Re-run to verify the score improved.
172
172
  ```
173
173
 
@@ -176,7 +176,7 @@ Fix all "error" severity findings. Re-run to verify the score improved.
176
176
  Add to your system prompt:
177
177
 
178
178
  ```
179
- After modifying Python files, run `uvx py-gate . --json` to check code quality.
179
+ After modifying Python files, run `uvx pycodegate . --json` to check code quality.
180
180
  Fix errors first. Target score: 80+.
181
181
  ```
182
182
 
@@ -194,7 +194,7 @@ name: Quality Gate
194
194
  on: [push, pull_request]
195
195
 
196
196
  jobs:
197
- py-gate:
197
+ pycodegate:
198
198
  runs-on: ubuntu-latest
199
199
  steps:
200
200
  - uses: actions/checkout@v4
@@ -205,10 +205,10 @@ jobs:
205
205
  with:
206
206
  python-version: "3.12"
207
207
 
208
- - name: Run Py Gate
208
+ - name: Run PyCodeGate
209
209
  run: |
210
- pip install py-gate
211
- py-gate . --verbose --diff main --fail-on error
210
+ pip install pycodegate
211
+ pycodegate . --verbose --diff main --fail-on error
212
212
  ```
213
213
 
214
214
  ## CLI Reference
@@ -244,7 +244,7 @@ Framework-specific rules (Django, FastAPI, Flask) are mapped into the Security o
244
244
 
245
245
  ## Scoring
246
246
 
247
- Py Gate uses a **weighted category-budget system**:
247
+ PyCodeGate uses a **weighted category-budget system**:
248
248
 
249
249
  1. Each category has a weight (see table above). Weights are normalized to sum to 100 points of total deduction budget.
250
250
  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 +260,7 @@ Py Gate uses a **weighted category-budget system**:
260
260
 
261
261
  ## Configuration
262
262
 
263
- Create `py-gate.toml` in your project root:
263
+ Create `pycodegate.toml` in your project root:
264
264
 
265
265
  ```toml
266
266
  [options]
@@ -284,27 +284,27 @@ max-deduction.Dead Code = 0 # disable dead-code penalty entirely
284
284
  Or use `pyproject.toml`:
285
285
 
286
286
  ```toml
287
- [tool.py-gate]
287
+ [tool.pycodegate]
288
288
  lint = true
289
289
  dead_code = true
290
290
  fail_on = "error"
291
291
 
292
- [tool.py-gate.ignore]
292
+ [tool.pycodegate.ignore]
293
293
  rules = ["no-import-in-function"]
294
294
  files = ["tests/fixtures/**"]
295
295
 
296
- [tool.py-gate.per-file-ignores]
296
+ [tool.pycodegate.per-file-ignores]
297
297
  "src/legacy/*.py" = ["high-complexity"]
298
298
 
299
- [tool.py-gate.scoring]
299
+ [tool.pycodegate.scoring]
300
300
  "max-deduction" = { Security = 20, "Dead Code" = 0 }
301
301
  ```
302
302
 
303
- If both files exist, `py-gate.toml` takes precedence. CLI flags always override config values.
303
+ If both files exist, `pycodegate.toml` takes precedence. CLI flags always override config values.
304
304
 
305
305
  ## Profiles
306
306
 
307
- Py Gate auto-detects a project profile and adjusts rule weights accordingly. You can also set a profile explicitly in config (`profile = "library"`).
307
+ PyCodeGate auto-detects a project profile and adjusts rule weights accordingly. You can also set a profile explicitly in config (`profile = "library"`).
308
308
 
309
309
  | Profile | Auto-detected when | Adjustments |
310
310
  |---------|--------------------|-------------|
@@ -315,10 +315,10 @@ Py Gate auto-detects a project profile and adjusts rule weights accordingly. You
315
315
 
316
316
  ## Pre-commit Hook
317
317
 
318
- Use `--pre-commit` to run Py Gate as a pre-commit hook. It automatically scans only the staged files:
318
+ Use `--pre-commit` to run PyCodeGate as a pre-commit hook. It automatically scans only the staged files:
319
319
 
320
320
  ```bash
321
- py-gate . --pre-commit --fail-on error
321
+ pycodegate . --pre-commit --fail-on error
322
322
  ```
323
323
 
324
324
  Add to `.pre-commit-config.yaml`:
@@ -327,9 +327,9 @@ Add to `.pre-commit-config.yaml`:
327
327
  repos:
328
328
  - repo: local
329
329
  hooks:
330
- - id: py-gate
331
- name: Py Gate quality check
332
- entry: py-gate . --pre-commit --fail-on error
330
+ - id: pycodegate
331
+ name: PyCodeGate quality check
332
+ entry: pycodegate . --pre-commit --fail-on error
333
333
  language: system
334
334
  types: [python]
335
335
  pass_filenames: false
@@ -342,7 +342,7 @@ git clone https://github.com/themohitkhare/pycodegate
342
342
  cd pycodegate
343
343
  uv sync --all-extras
344
344
  uv run pytest -q
345
- uv run py-gate . --verbose # dogfood it
345
+ uv run pycodegate . --verbose # dogfood it
346
346
  ```
347
347
 
348
348
  To add a new rule:
@@ -1,11 +1,11 @@
1
- <h1 align="center">Py Gate</h1>
1
+ <h1 align="center">PyCodeGate</h1>
2
2
  <p align="center">
3
3
  <strong>One command. One score. Your Python quality gate.</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/py-gate/"><img src="https://img.shields.io/pypi/v/py-gate" alt="PyPI"></a>
8
- <a href="https://pypi.org/project/py-gate/"><img src="https://img.shields.io/pypi/pyversions/py-gate" alt="Python"></a>
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
 
@@ -13,7 +13,7 @@
13
13
 
14
14
  ## How it works
15
15
 
16
- Py Gate starts by detecting 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.
16
+ PyCodeGate starts by detecting 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
17
 
18
18
  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
19
 
@@ -24,39 +24,39 @@ Findings are filtered through your configuration and scored using a **weighted c
24
24
  Run instantly with `uvx` — no install needed:
25
25
 
26
26
  ```bash
27
- uvx py-gate .
27
+ uvx pycodegate .
28
28
  ```
29
29
 
30
30
  Install globally with pipx or uv:
31
31
 
32
32
  ```bash
33
- pipx install py-gate
33
+ pipx install pycodegate
34
34
  # or
35
- uv tool install py-gate
35
+ uv tool install pycodegate
36
36
  # or
37
- pip install py-gate
37
+ pip install pycodegate
38
38
  ```
39
39
 
40
40
  ## Quick Start
41
41
 
42
42
  ```bash
43
43
  # Basic scan — score + summary
44
- py-gate .
44
+ pycodegate .
45
45
 
46
46
  # Show file paths and line numbers for every finding
47
- py-gate . --verbose
47
+ pycodegate . --verbose
48
48
 
49
49
  # Machine-readable output for AI agents and CI
50
- py-gate . --json
50
+ pycodegate . --json
51
51
 
52
52
  # Auto-fix ruff-fixable issues, then scan
53
- py-gate . --fix
53
+ pycodegate . --fix
54
54
 
55
55
  # Output only the numeric score (useful in scripts)
56
- py-gate . --score
56
+ pycodegate . --score
57
57
 
58
58
  # Scan only files changed vs a base branch
59
- py-gate . --diff main
59
+ pycodegate . --diff main
60
60
  ```
61
61
 
62
62
  ## JSON Output
@@ -64,7 +64,7 @@ py-gate . --diff main
64
64
  Pass `--json` to get structured output that AI agents and CI pipelines can parse:
65
65
 
66
66
  ```bash
67
- py-gate . --json
67
+ pycodegate . --json
68
68
  ```
69
69
 
70
70
  ```json
@@ -105,7 +105,7 @@ py-gate . --json
105
105
 
106
106
  ## Agent Integration
107
107
 
108
- Py Gate is designed to be used by AI coding agents. Add it to your agent's context so it runs after every Python change.
108
+ 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
109
 
110
110
  ### Claude Code
111
111
 
@@ -113,18 +113,18 @@ Add the skill to your project:
113
113
 
114
114
  ```bash
115
115
  mkdir -p .claude/skills
116
- curl -fsSL https://raw.githubusercontent.com/themohitkhare/pycodegate/main/skills/py-gate/SKILL.md \
117
- -o .claude/skills/py-gate.md
116
+ curl -fsSL https://raw.githubusercontent.com/themohitkhare/pycodegate/main/skills/pycodegate/SKILL.md \
117
+ -o .claude/skills/pycodegate.md
118
118
  ```
119
119
 
120
120
  Or copy `AGENTS.md` to your project root — Claude Code picks it up automatically.
121
121
 
122
122
  ### Cursor
123
123
 
124
- Add to `.cursor/rules/py-gate.mdc`:
124
+ Add to `.cursor/rules/pycodegate.mdc`:
125
125
 
126
126
  ```markdown
127
- After modifying Python files, run `uvx py-gate . --json` and fix all findings
127
+ After modifying Python files, run `uvx pycodegate . --json` and fix all findings
128
128
  with severity "error" before marking the task complete. Target score: 80+.
129
129
  ```
130
130
 
@@ -133,7 +133,7 @@ with severity "error" before marking the task complete. Target score: 80+.
133
133
  Add to `.windsurfrules`:
134
134
 
135
135
  ```
136
- After modifying Python files, run: uvx py-gate . --json
136
+ After modifying Python files, run: uvx pycodegate . --json
137
137
  Fix all "error" severity findings. Re-run to verify the score improved.
138
138
  ```
139
139
 
@@ -142,7 +142,7 @@ Fix all "error" severity findings. Re-run to verify the score improved.
142
142
  Add to your system prompt:
143
143
 
144
144
  ```
145
- After modifying Python files, run `uvx py-gate . --json` to check code quality.
145
+ After modifying Python files, run `uvx pycodegate . --json` to check code quality.
146
146
  Fix errors first. Target score: 80+.
147
147
  ```
148
148
 
@@ -160,7 +160,7 @@ name: Quality Gate
160
160
  on: [push, pull_request]
161
161
 
162
162
  jobs:
163
- py-gate:
163
+ pycodegate:
164
164
  runs-on: ubuntu-latest
165
165
  steps:
166
166
  - uses: actions/checkout@v4
@@ -171,10 +171,10 @@ jobs:
171
171
  with:
172
172
  python-version: "3.12"
173
173
 
174
- - name: Run Py Gate
174
+ - name: Run PyCodeGate
175
175
  run: |
176
- pip install py-gate
177
- py-gate . --verbose --diff main --fail-on error
176
+ pip install pycodegate
177
+ pycodegate . --verbose --diff main --fail-on error
178
178
  ```
179
179
 
180
180
  ## CLI Reference
@@ -210,7 +210,7 @@ Framework-specific rules (Django, FastAPI, Flask) are mapped into the Security o
210
210
 
211
211
  ## Scoring
212
212
 
213
- Py Gate uses a **weighted category-budget system**:
213
+ PyCodeGate uses a **weighted category-budget system**:
214
214
 
215
215
  1. Each category has a weight (see table above). Weights are normalized to sum to 100 points of total deduction budget.
216
216
  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 +226,7 @@ Py Gate uses a **weighted category-budget system**:
226
226
 
227
227
  ## Configuration
228
228
 
229
- Create `py-gate.toml` in your project root:
229
+ Create `pycodegate.toml` in your project root:
230
230
 
231
231
  ```toml
232
232
  [options]
@@ -250,27 +250,27 @@ max-deduction.Dead Code = 0 # disable dead-code penalty entirely
250
250
  Or use `pyproject.toml`:
251
251
 
252
252
  ```toml
253
- [tool.py-gate]
253
+ [tool.pycodegate]
254
254
  lint = true
255
255
  dead_code = true
256
256
  fail_on = "error"
257
257
 
258
- [tool.py-gate.ignore]
258
+ [tool.pycodegate.ignore]
259
259
  rules = ["no-import-in-function"]
260
260
  files = ["tests/fixtures/**"]
261
261
 
262
- [tool.py-gate.per-file-ignores]
262
+ [tool.pycodegate.per-file-ignores]
263
263
  "src/legacy/*.py" = ["high-complexity"]
264
264
 
265
- [tool.py-gate.scoring]
265
+ [tool.pycodegate.scoring]
266
266
  "max-deduction" = { Security = 20, "Dead Code" = 0 }
267
267
  ```
268
268
 
269
- If both files exist, `py-gate.toml` takes precedence. CLI flags always override config values.
269
+ If both files exist, `pycodegate.toml` takes precedence. CLI flags always override config values.
270
270
 
271
271
  ## Profiles
272
272
 
273
- Py Gate auto-detects a project profile and adjusts rule weights accordingly. You can also set a profile explicitly in config (`profile = "library"`).
273
+ PyCodeGate auto-detects a project profile and adjusts rule weights accordingly. You can also set a profile explicitly in config (`profile = "library"`).
274
274
 
275
275
  | Profile | Auto-detected when | Adjustments |
276
276
  |---------|--------------------|-------------|
@@ -281,10 +281,10 @@ Py Gate auto-detects a project profile and adjusts rule weights accordingly. You
281
281
 
282
282
  ## Pre-commit Hook
283
283
 
284
- Use `--pre-commit` to run Py Gate as a pre-commit hook. It automatically scans only the staged files:
284
+ Use `--pre-commit` to run PyCodeGate as a pre-commit hook. It automatically scans only the staged files:
285
285
 
286
286
  ```bash
287
- py-gate . --pre-commit --fail-on error
287
+ pycodegate . --pre-commit --fail-on error
288
288
  ```
289
289
 
290
290
  Add to `.pre-commit-config.yaml`:
@@ -293,9 +293,9 @@ Add to `.pre-commit-config.yaml`:
293
293
  repos:
294
294
  - repo: local
295
295
  hooks:
296
- - id: py-gate
297
- name: Py Gate quality check
298
- entry: py-gate . --pre-commit --fail-on error
296
+ - id: pycodegate
297
+ name: PyCodeGate quality check
298
+ entry: pycodegate . --pre-commit --fail-on error
299
299
  language: system
300
300
  types: [python]
301
301
  pass_filenames: false
@@ -308,7 +308,7 @@ git clone https://github.com/themohitkhare/pycodegate
308
308
  cd pycodegate
309
309
  uv sync --all-extras
310
310
  uv run pytest -q
311
- uv run py-gate . --verbose # dogfood it
311
+ uv run pycodegate . --verbose # dogfood it
312
312
  ```
313
313
 
314
314
  To add a new rule:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pycodegate"
3
- version = "0.1.1"
3
+ version = "0.1.2"
4
4
  description = "One command. One score. Your Python quality gate."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -42,7 +42,7 @@ dev = [
42
42
 
43
43
  [project.scripts]
44
44
  pycodegate = "pycodegate.cli:main"
45
- py-gate = "pycodegate.cli:main"
45
+
46
46
 
47
47
  [build-system]
48
48
  requires = ["hatchling"]
@@ -70,6 +70,6 @@ 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.py-gate]
74
- [tool.py-gate.ignore]
73
+ [tool.pycodegate]
74
+ [tool.pycodegate.ignore]
75
75
  files = ["tests/fixtures/**"]
@@ -1,17 +1,17 @@
1
1
  ---
2
- name: py-gate
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
- # Py Gate
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 py-gate . --verbose --diff
14
+ uvx pycodegate . --verbose --diff
15
15
  ```
16
16
 
17
17
  ## Workflow
@@ -1,3 +1,3 @@
1
1
  """Python Doctor - Diagnose your Python project's health."""
2
2
 
3
- __version__ = "0.1.1"
3
+ __version__ = "0.1.2"
@@ -17,7 +17,7 @@ from pycodegate.utils.precommit import install_precommit_hook
17
17
 
18
18
 
19
19
  @click.command(context_settings={"help_option_names": ["-h", "--help"]})
20
- @click.version_option(__version__, "-v", "--version", prog_name="Py Gate")
20
+ @click.version_option(__version__, "-v", "--version", prog_name="PyCodeGate")
21
21
  @click.argument("directory", default=".", type=click.Path(exists=True))
22
22
  @click.option("--lint/--no-lint", default=True, help="Enable/disable lint checks.")
23
23
  @click.option(
@@ -79,7 +79,7 @@ def main(
79
79
  precommit: bool,
80
80
  min_score: int | None,
81
81
  ) -> None:
82
- """Py Gate — Diagnose your Python project's health."""
82
+ """PyCodeGate — Diagnose your Python project's health."""
83
83
  if ci_workflow:
84
84
  click.echo(generate_ci_workflow(), nl=False)
85
85
  return
@@ -125,7 +125,7 @@ def main(
125
125
 
126
126
  if min_score is not None and result.score.value < min_score:
127
127
  click.echo(
128
- f"py-gate: score {result.score.value} is below minimum {min_score}",
128
+ f"pycodegate: score {result.score.value} is below minimum {min_score}",
129
129
  err=True,
130
130
  )
131
131
  sys.exit(1)
@@ -1,4 +1,4 @@
1
- """Configuration loading for py-gate."""
1
+ """Configuration loading for pycodegate."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
@@ -22,11 +22,11 @@ class Config:
22
22
 
23
23
 
24
24
  def load_config(project_path: str) -> Config:
25
- """Load config from py-gate.toml or pyproject.toml [tool.py-gate]."""
25
+ """Load config from pycodegate.toml or pyproject.toml [tool.pycodegate]."""
26
26
  root = Path(project_path)
27
27
 
28
- # py-gate.toml takes precedence
29
- doctor_toml = root / "py-gate.toml"
28
+ # pycodegate.toml takes precedence
29
+ doctor_toml = root / "pycodegate.toml"
30
30
  if doctor_toml.exists():
31
31
  return _parse_doctor_toml(doctor_toml)
32
32
 
@@ -62,7 +62,7 @@ def _parse_pyproject_toml(path: Path) -> Config:
62
62
  with open(path, "rb") as f:
63
63
  data = tomllib.load(f)
64
64
 
65
- section = data.get("tool", {}).get("py-gate", {})
65
+ section = data.get("tool", {}).get("pycodegate", {})
66
66
  if not section:
67
67
  return Config()
68
68
 
@@ -138,7 +138,9 @@ def print_scan_result(result: ScanResult, verbose: bool = False) -> None:
138
138
  # Project info header
139
139
  p = result.project
140
140
  console.print()
141
- console.print(" [bold]Py Gate[/bold] — v0.1.0")
141
+ from pycodegate import __version__
142
+
143
+ console.print(f" [bold]PyCodeGate[/bold] — v{__version__}")
142
144
  console.print()
143
145
  console.print(f" [dim]Path:[/dim] {p.path}")
144
146
  if p.python_version:
@@ -81,7 +81,7 @@ class DependencyRules:
81
81
  # Try uv export
82
82
  if shutil.which("uv") and (path / "pyproject.toml").exists():
83
83
  try:
84
- tmp = Path(tempfile.gettempdir()) / "py-gate-reqs.txt"
84
+ tmp = Path(tempfile.gettempdir()) / "pycodegate-reqs.txt"
85
85
  result = subprocess.run(
86
86
  [
87
87
  "uv",
@@ -17,7 +17,7 @@ def generate_badge(score: int, label: str) -> str:
17
17
  color = "red"
18
18
 
19
19
  score_text = urllib.parse.quote(f"{score}/100")
20
- return f"![py-gate score](https://img.shields.io/badge/py--gate-{score_text}-{color})"
20
+ return f"![pycodegate score](https://img.shields.io/badge/py--gate-{score_text}-{color})"
21
21
 
22
22
 
23
23
  def generate_ci_workflow() -> str:
@@ -36,16 +36,16 @@ jobs:
36
36
  steps:
37
37
  - uses: actions/checkout@v4
38
38
  - uses: astral-sh/setup-uv@v5
39
- - run: uv tool install py-gate
40
- - name: Run py-gate
39
+ - run: uv tool install pycodegate
40
+ - name: Run pycodegate
41
41
  run: |
42
- SCORE=$(py-gate . --score)
43
- BADGE=$(py-gate . --badge)
42
+ SCORE=$(pycodegate . --score)
43
+ BADGE=$(pycodegate . --badge)
44
44
  # Update badge in README
45
- sed -i "s|!\\[py-gate score\\](.*)|${BADGE}|" README.md
45
+ sed -i "s|!\\[pycodegate score\\](.*)|${BADGE}|" README.md
46
46
  - name: Commit badge update
47
47
  run: |
48
48
  git config user.name "github-actions[bot]"
49
49
  git config user.email "github-actions[bot]@users.noreply.github.com"
50
- git diff --quiet README.md || (git add README.md && git commit -m "chore: update py-gate score badge" && git push)
50
+ git diff --quiet README.md || (git add README.md && git commit -m "chore: update pycodegate score badge" && git push)
51
51
  """
@@ -6,31 +6,31 @@ from pathlib import Path
6
6
 
7
7
 
8
8
  def install_precommit_hook(project_path: str, min_score: int = 50) -> str:
9
- """Install a git pre-commit hook that runs py-gate."""
9
+ """Install a git pre-commit hook that runs pycodegate."""
10
10
  hooks_dir = Path(project_path) / ".git" / "hooks"
11
11
  if not hooks_dir.exists():
12
12
  return "Error: not a git repository"
13
13
 
14
14
  hook_path = hooks_dir / "pre-commit"
15
15
  hook_content = f"""#!/bin/sh
16
- # py-gate pre-commit hook
17
- SCORE=$(py-gate . --score 2>/dev/null)
16
+ # pycodegate pre-commit hook
17
+ SCORE=$(pycodegate . --score 2>/dev/null)
18
18
  if [ $? -ne 0 ]; then
19
- echo "py-gate not found. Install with: uvx py-gate"
19
+ echo "pycodegate not found. Install with: uvx pycodegate"
20
20
  exit 0
21
21
  fi
22
22
  if [ "$SCORE" -lt {min_score} ]; then
23
- echo "py-gate: score $SCORE is below minimum {min_score}. Fix issues before committing."
24
- py-gate . 2>/dev/null
23
+ echo "pycodegate: score $SCORE is below minimum {min_score}. Fix issues before committing."
24
+ pycodegate . 2>/dev/null
25
25
  exit 1
26
26
  fi
27
- echo "py-gate: score $SCORE/{min_score} — passed"
27
+ echo "pycodegate: score $SCORE/{min_score} — passed"
28
28
  """
29
29
 
30
30
  # Don't overwrite existing hook — append or warn
31
31
  if hook_path.exists():
32
32
  existing = hook_path.read_text()
33
- if "py-gate" in existing:
33
+ if "pycodegate" in existing:
34
34
  hook_path.write_text(hook_content)
35
35
  hook_path.chmod(0o755)
36
36
  return f"Updated pre-commit hook at {hook_path} (min-score: {min_score})"
@@ -41,7 +41,7 @@ echo "py-gate: score $SCORE/{min_score} — passed"
41
41
  body = "".join(lines[1:]) if lines[0].startswith("#!/") else hook_content
42
42
  with open(hook_path, "a") as f:
43
43
  f.write("\n" + body)
44
- return f"Appended py-gate to existing pre-commit hook at {hook_path}"
44
+ return f"Appended pycodegate to existing pre-commit hook at {hook_path}"
45
45
 
46
46
  hook_path.write_text(hook_content)
47
47
  hook_path.chmod(0o755)
@@ -2,6 +2,7 @@ import json
2
2
 
3
3
  from click.testing import CliRunner
4
4
 
5
+ from pycodegate import __version__
5
6
  from pycodegate.cli import main
6
7
 
7
8
 
@@ -9,14 +10,14 @@ def test_cli_help():
9
10
  runner = CliRunner()
10
11
  result = runner.invoke(main, ["--help"])
11
12
  assert result.exit_code == 0
12
- assert "Py Gate" in result.output or "py-gate" in result.output
13
+ assert "PyCodeGate" in result.output or "pycodegate" in result.output
13
14
 
14
15
 
15
16
  def test_cli_version():
16
17
  runner = CliRunner()
17
18
  result = runner.invoke(main, ["--version"])
18
19
  assert result.exit_code == 0
19
- assert "0.1.0" in result.output
20
+ assert __version__ in result.output
20
21
 
21
22
 
22
23
  def test_cli_scan_clean_project(tmp_path):
@@ -122,4 +123,4 @@ def test_ci_workflow(tmp_path):
122
123
  result = runner.invoke(main, [str(tmp_path), "--ci"])
123
124
  assert result.exit_code == 0
124
125
  assert "name: Py Gate Score" in result.output
125
- assert "py-gate" in result.output
126
+ assert "pycodegate" in result.output
@@ -22,7 +22,7 @@ dead_code = false
22
22
  verbose = true
23
23
  fail_on = "error"
24
24
  """
25
- (tmp_path / "py-gate.toml").write_text(toml_content)
25
+ (tmp_path / "pycodegate.toml").write_text(toml_content)
26
26
  cfg = load_config(str(tmp_path))
27
27
  assert cfg.dead_code is False
28
28
  assert cfg.verbose is True
@@ -33,13 +33,13 @@ fail_on = "error"
33
33
 
34
34
  def test_load_from_pyproject_toml(tmp_path):
35
35
  toml_content = """
36
- [tool.py-gate]
36
+ [tool.pycodegate]
37
37
  lint = true
38
38
  dead_code = true
39
39
  verbose = false
40
40
  fail_on = "none"
41
41
 
42
- [tool.py-gate.ignore]
42
+ [tool.pycodegate.ignore]
43
43
  rules = ["no-pickle"]
44
44
  files = []
45
45
  """
@@ -50,12 +50,12 @@ files = []
50
50
 
51
51
 
52
52
  def test_pycodegate_toml_takes_precedence(tmp_path):
53
- (tmp_path / "py-gate.toml").write_text("""
53
+ (tmp_path / "pycodegate.toml").write_text("""
54
54
  [options]
55
55
  verbose = true
56
56
  """)
57
57
  (tmp_path / "pyproject.toml").write_text("""
58
- [tool.py-gate]
58
+ [tool.pycodegate]
59
59
  verbose = false
60
60
  """)
61
61
  cfg = load_config(str(tmp_path))
@@ -69,7 +69,7 @@ lint = true
69
69
  [per-file-suppress]
70
70
  "tests/*" = ["no-bare-except"]
71
71
  """
72
- (tmp_path / "py-gate.toml").write_text(toml_content)
72
+ (tmp_path / "pycodegate.toml").write_text(toml_content)
73
73
  config = load_config(str(tmp_path))
74
74
  assert config.per_file_suppress == {"tests/*": ["no-bare-except"]}
75
75
 
@@ -82,16 +82,16 @@ lint = true
82
82
  security = 15
83
83
  structure = 5
84
84
  """
85
- (tmp_path / "py-gate.toml").write_text(toml_content)
85
+ (tmp_path / "pycodegate.toml").write_text(toml_content)
86
86
  config = load_config(str(tmp_path))
87
87
  assert config.max_deduction == {"security": 15, "structure": 5}
88
88
 
89
89
 
90
90
  def test_per_file_suppress_from_pyproject(tmp_path):
91
- pyproject = """[tool.py-gate.per-file-suppress]
91
+ pyproject = """[tool.pycodegate.per-file-suppress]
92
92
  "tests/*" = ["no-bare-except"]
93
93
 
94
- [tool.py-gate.max-deduction]
94
+ [tool.pycodegate.max-deduction]
95
95
  security = 10
96
96
  """
97
97
  (tmp_path / "pyproject.toml").write_text(pyproject)
@@ -203,7 +203,7 @@ wheels = [
203
203
 
204
204
  [[package]]
205
205
  name = "pycodegate"
206
- version = "0.1.0"
206
+ version = "0.1.1"
207
207
  source = { editable = "." }
208
208
  dependencies = [
209
209
  { name = "click" },
File without changes
File without changes
File without changes
File without changes