pycodegate 0.1.0__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.0/.github/workflows/ci.yml +45 -0
  2. pycodegate-0.1.0/.github/workflows/publish.yml +16 -0
  3. pycodegate-0.1.0/.gitignore +17 -0
  4. pycodegate-0.1.0/AGENTS.md +78 -0
  5. pycodegate-0.1.0/LICENSE +21 -0
  6. pycodegate-0.1.0/PKG-INFO +357 -0
  7. pycodegate-0.1.0/README.md +323 -0
  8. pycodegate-0.1.0/docs/superpowers/plans/2026-03-22-python-doctor.md +3305 -0
  9. pycodegate-0.1.0/pyproject.toml +74 -0
  10. pycodegate-0.1.0/skills/py-gate/SKILL.md +26 -0
  11. pycodegate-0.1.0/src/pycodegate/__init__.py +3 -0
  12. pycodegate-0.1.0/src/pycodegate/_compat.py +15 -0
  13. pycodegate-0.1.0/src/pycodegate/api.py +26 -0
  14. pycodegate-0.1.0/src/pycodegate/cli.py +131 -0
  15. pycodegate-0.1.0/src/pycodegate/config.py +81 -0
  16. pycodegate-0.1.0/src/pycodegate/constants.py +32 -0
  17. pycodegate-0.1.0/src/pycodegate/discover.py +114 -0
  18. pycodegate-0.1.0/src/pycodegate/output.py +270 -0
  19. pycodegate-0.1.0/src/pycodegate/profile.py +107 -0
  20. pycodegate-0.1.0/src/pycodegate/rules/__init__.py +38 -0
  21. pycodegate-0.1.0/src/pycodegate/rules/architecture.py +121 -0
  22. pycodegate-0.1.0/src/pycodegate/rules/base.py +23 -0
  23. pycodegate-0.1.0/src/pycodegate/rules/complexity.py +87 -0
  24. pycodegate-0.1.0/src/pycodegate/rules/correctness.py +131 -0
  25. pycodegate-0.1.0/src/pycodegate/rules/dead_code.py +58 -0
  26. pycodegate-0.1.0/src/pycodegate/rules/dependencies.py +107 -0
  27. pycodegate-0.1.0/src/pycodegate/rules/django.py +144 -0
  28. pycodegate-0.1.0/src/pycodegate/rules/fastapi.py +70 -0
  29. pycodegate-0.1.0/src/pycodegate/rules/flask.py +115 -0
  30. pycodegate-0.1.0/src/pycodegate/rules/imports.py +96 -0
  31. pycodegate-0.1.0/src/pycodegate/rules/performance.py +104 -0
  32. pycodegate-0.1.0/src/pycodegate/rules/security.py +167 -0
  33. pycodegate-0.1.0/src/pycodegate/rules/structure.py +242 -0
  34. pycodegate-0.1.0/src/pycodegate/scan.py +201 -0
  35. pycodegate-0.1.0/src/pycodegate/score.py +69 -0
  36. pycodegate-0.1.0/src/pycodegate/types.py +65 -0
  37. pycodegate-0.1.0/src/pycodegate/utils/__init__.py +1 -0
  38. pycodegate-0.1.0/src/pycodegate/utils/ast_helpers.py +19 -0
  39. pycodegate-0.1.0/src/pycodegate/utils/badge.py +51 -0
  40. pycodegate-0.1.0/src/pycodegate/utils/diff.py +24 -0
  41. pycodegate-0.1.0/src/pycodegate/utils/file_discovery.py +62 -0
  42. pycodegate-0.1.0/src/pycodegate/utils/fixer.py +32 -0
  43. pycodegate-0.1.0/src/pycodegate/utils/precommit.py +48 -0
  44. pycodegate-0.1.0/tests/conftest.py +1 -0
  45. pycodegate-0.1.0/tests/fixtures/basic_python/app.py +24 -0
  46. pycodegate-0.1.0/tests/fixtures/clean_project/app.py +19 -0
  47. pycodegate-0.1.0/tests/rules/__init__.py +0 -0
  48. pycodegate-0.1.0/tests/rules/test_architecture.py +52 -0
  49. pycodegate-0.1.0/tests/rules/test_complexity.py +92 -0
  50. pycodegate-0.1.0/tests/rules/test_correctness.py +61 -0
  51. pycodegate-0.1.0/tests/rules/test_dead_code.py +30 -0
  52. pycodegate-0.1.0/tests/rules/test_dependencies.py +60 -0
  53. pycodegate-0.1.0/tests/rules/test_django.py +39 -0
  54. pycodegate-0.1.0/tests/rules/test_fastapi.py +57 -0
  55. pycodegate-0.1.0/tests/rules/test_flask.py +36 -0
  56. pycodegate-0.1.0/tests/rules/test_imports.py +49 -0
  57. pycodegate-0.1.0/tests/rules/test_performance.py +47 -0
  58. pycodegate-0.1.0/tests/rules/test_security.py +59 -0
  59. pycodegate-0.1.0/tests/rules/test_structure.py +114 -0
  60. pycodegate-0.1.0/tests/test_cli.py +125 -0
  61. pycodegate-0.1.0/tests/test_config.py +100 -0
  62. pycodegate-0.1.0/tests/test_discover.py +104 -0
  63. pycodegate-0.1.0/tests/test_fixer.py +33 -0
  64. pycodegate-0.1.0/tests/test_integration.py +30 -0
  65. pycodegate-0.1.0/tests/test_output.py +286 -0
  66. pycodegate-0.1.0/tests/test_profile.py +170 -0
  67. pycodegate-0.1.0/tests/test_scan.py +51 -0
  68. pycodegate-0.1.0/tests/test_score.py +145 -0
  69. pycodegate-0.1.0/tests/test_types.py +56 -0
  70. pycodegate-0.1.0/uv.lock +386 -0
  71. pycodegate-0.1.0/whitelist.py +14 -0
@@ -0,0 +1,45 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v5
18
+ - uses: astral-sh/setup-uv@v4
19
+
20
+ - name: Set up Python ${{ matrix.python-version }}
21
+ run: uv python install ${{ matrix.python-version }}
22
+
23
+ - name: Install dependencies
24
+ run: uv sync --all-extras
25
+
26
+ - name: Run tests
27
+ run: uv run pytest --tb=short -q
28
+
29
+ - name: Run py-gate on itself
30
+ run: uv run py-gate . --fail-on error
31
+
32
+ lint:
33
+ runs-on: ubuntu-latest
34
+ steps:
35
+ - uses: actions/checkout@v5
36
+ - uses: astral-sh/setup-uv@v4
37
+
38
+ - name: Install dependencies
39
+ run: uv sync --all-extras
40
+
41
+ - name: Ruff check
42
+ run: uv run ruff check .
43
+
44
+ - name: Ruff format check
45
+ run: uv run ruff format --check .
@@ -0,0 +1,16 @@
1
+ name: Publish to PyPI
2
+ on:
3
+ release:
4
+ types: [published]
5
+
6
+ jobs:
7
+ publish:
8
+ runs-on: ubuntu-latest
9
+ permissions:
10
+ id-token: write
11
+ environment: pypi
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: astral-sh/setup-uv@v5
15
+ - run: uv build
16
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,17 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .eggs/
7
+ *.egg
8
+ .venv/
9
+ venv/
10
+ .mypy_cache/
11
+ .pytest_cache/
12
+ .ruff_cache/
13
+ htmlcov/
14
+ .coverage
15
+ *.so
16
+ .env
17
+ .DS_Store
@@ -0,0 +1,78 @@
1
+ # AGENTS.md
2
+
3
+ ## Overview
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.
6
+
7
+ ## Quick Start
8
+
9
+ ```bash
10
+ uvx py-gate . --json
11
+ ```
12
+
13
+ ## For AI Agents
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+**.
16
+
17
+ The JSON output includes the score, label, per-diagnostic severity and file location, and detected project context (framework, Python version, package manager).
18
+
19
+ ## General Rules
20
+
21
+ - MUST: Use `uv` for all Python operations. `uv run` to execute, `uv sync` to install.
22
+ - MUST: Follow existing code patterns — AST-based rule checks extending `BaseRules`.
23
+ - MUST: Keep all types in `src/pycodegate/types.py`.
24
+ - MUST: Use dataclasses (frozen) for data containers.
25
+ - MUST: Never comment unless absolutely necessary.
26
+ - If the code is a hack, prefix with `# HACK: reason`
27
+ - MUST: Use snake_case for files and variables.
28
+ - MUST: Use descriptive names (avoid shorthands or 1-2 character names).
29
+ - MUST: Do not use `type: ignore` unless absolutely necessary.
30
+ - MUST: Remove unused code and don't repeat yourself.
31
+ - MUST: Put all magic numbers in `constants.py` using `SCREAMING_SNAKE_CASE`.
32
+ - MUST: Put small, focused utility functions in `utils/` with one utility per file.
33
+ - MUST: Use early returns and guard clauses to reduce nesting depth below 5.
34
+ - MUST: Keep functions under 50 lines.
35
+
36
+ ## Development
37
+
38
+ ```bash
39
+ uv run pytest -q # run all tests
40
+ uv run ruff check . && uv run ruff format --check . # lint + format check
41
+ uv run py-gate . --verbose # dogfood on ourselves
42
+ ```
43
+
44
+ ## Adding Rules
45
+
46
+ 1. Create a new file in `src/pycodegate/rules/` extending `BaseRules`
47
+ 2. Implement `check(self, source: str, filename: str) -> list[Diagnostic]`
48
+ 3. Register in `src/pycodegate/rules/__init__.py`
49
+ 4. Add tests in `tests/rules/`
50
+
51
+ ## Architecture
52
+
53
+ ```
54
+ src/pycodegate/
55
+ cli.py — Click CLI entry point
56
+ api.py — Programmatic API (diagnose function)
57
+ scan.py — Orchestrator: parallel lint + dead code
58
+ score.py — Score calculation from diagnostics
59
+ config.py — Config loading (py-gate.toml / pyproject.toml)
60
+ discover.py — Project detection (framework, package manager, etc.)
61
+ output.py — Rich terminal output
62
+ types.py — All data types (Diagnostic, Score, etc.)
63
+ constants.py — Magic numbers and thresholds
64
+ rules/
65
+ base.py — Abstract BaseRules with AST parsing
66
+ security.py — eval, exec, pickle, yaml, secrets, hashes
67
+ performance.py — string concat, imports in functions, star imports
68
+ architecture.py — giant modules, nesting, god functions, too many args
69
+ correctness.py — mutable defaults, bare except, assert, return in init
70
+ django.py — raw SQL, DEBUG, SECRET_KEY, N+1
71
+ fastapi.py — sync endpoints, missing response_model
72
+ flask.py — secret key, debug mode, SQL f-strings
73
+ dead_code.py — Vulture integration
74
+ utils/
75
+ file_discovery.py — Python file discovery (git + fallback)
76
+ ast_helpers.py — Common AST utilities
77
+ diff.py — Git diff file resolution
78
+ ```
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mohit Khare
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,357 @@
1
+ Metadata-Version: 2.4
2
+ Name: pycodegate
3
+ Version: 0.1.0
4
+ Summary: One command. One score. Your Python quality gate.
5
+ Project-URL: Homepage, https://github.com/themohitkhare/pycodegate
6
+ Project-URL: Repository, https://github.com/themohitkhare/pycodegate
7
+ Project-URL: Issues, https://github.com/themohitkhare/pycodegate/issues
8
+ Author: Mohit Khare
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: ai-agents,code-quality,developer-tools,linting,python,quality-gate,static-analysis
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development :: Quality Assurance
22
+ Classifier: Topic :: Software Development :: Testing
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.10
25
+ Requires-Dist: click>=8.1
26
+ Requires-Dist: rich>=13.0
27
+ Requires-Dist: tomli>=2.0; python_version < '3.11'
28
+ Requires-Dist: vulture>=2.11
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
31
+ Requires-Dist: pytest>=8.0; extra == 'dev'
32
+ Requires-Dist: ruff>=0.4; extra == 'dev'
33
+ Description-Content-Type: text/markdown
34
+
35
+ <h1 align="center">Py Gate</h1>
36
+ <p align="center">
37
+ <strong>One command. One score. Your Python quality gate.</strong>
38
+ </p>
39
+ <p align="center">
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>
43
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a>
44
+ </p>
45
+
46
+ ---
47
+
48
+ ## How it works
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.
51
+
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
+
54
+ Findings are filtered through your configuration and scored using a **weighted category-budget system**. Each category has a maximum deduction budget proportional to its weight. Within a category the top 3 findings apply at full cost; additional findings apply diminishing returns (10% each), so fixing the worst issues always moves the needle. The final result is a **0–100 health score** with a label: Excellent (90+), Great (75–89), Needs work (50–74), or Critical (<50).
55
+
56
+ ## Install
57
+
58
+ Run instantly with `uvx` — no install needed:
59
+
60
+ ```bash
61
+ uvx py-gate .
62
+ ```
63
+
64
+ Install globally with pipx or uv:
65
+
66
+ ```bash
67
+ pipx install py-gate
68
+ # or
69
+ uv tool install py-gate
70
+ # or
71
+ pip install py-gate
72
+ ```
73
+
74
+ ## Quick Start
75
+
76
+ ```bash
77
+ # Basic scan — score + summary
78
+ py-gate .
79
+
80
+ # Show file paths and line numbers for every finding
81
+ py-gate . --verbose
82
+
83
+ # Machine-readable output for AI agents and CI
84
+ py-gate . --json
85
+
86
+ # Auto-fix ruff-fixable issues, then scan
87
+ py-gate . --fix
88
+
89
+ # Output only the numeric score (useful in scripts)
90
+ py-gate . --score
91
+
92
+ # Scan only files changed vs a base branch
93
+ py-gate . --diff main
94
+ ```
95
+
96
+ ## JSON Output
97
+
98
+ Pass `--json` to get structured output that AI agents and CI pipelines can parse:
99
+
100
+ ```bash
101
+ py-gate . --json
102
+ ```
103
+
104
+ ```json
105
+ {
106
+ "version": "0.1.0",
107
+ "path": ".",
108
+ "score": 87,
109
+ "label": "Great",
110
+ "errors": 1,
111
+ "warnings": 4,
112
+ "elapsed_ms": 212,
113
+ "project": {
114
+ "framework": "fastapi",
115
+ "python_version": "3.12",
116
+ "package_manager": "uv",
117
+ "test_framework": "pytest"
118
+ },
119
+ "diagnostics": [
120
+ {
121
+ "rule": "no-mutable-default",
122
+ "severity": "error",
123
+ "category": "Correctness",
124
+ "message": "Mutable default argument `[]` is shared across all calls",
125
+ "file_path": "src/api/routes.py",
126
+ "line": 34
127
+ },
128
+ {
129
+ "rule": "high-complexity",
130
+ "severity": "warning",
131
+ "category": "Complexity",
132
+ "message": "Function 'process_order' has cyclomatic complexity 17 (max 15)",
133
+ "file_path": "src/api/orders.py",
134
+ "line": 88
135
+ }
136
+ ]
137
+ }
138
+ ```
139
+
140
+ ## Agent Integration
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.
143
+
144
+ ### Claude Code
145
+
146
+ Add the skill to your project:
147
+
148
+ ```bash
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
152
+ ```
153
+
154
+ Or copy `AGENTS.md` to your project root — Claude Code picks it up automatically.
155
+
156
+ ### Cursor
157
+
158
+ Add to `.cursor/rules/py-gate.mdc`:
159
+
160
+ ```markdown
161
+ After modifying Python files, run `uvx py-gate . --json` and fix all findings
162
+ with severity "error" before marking the task complete. Target score: 80+.
163
+ ```
164
+
165
+ ### Windsurf
166
+
167
+ Add to `.windsurfrules`:
168
+
169
+ ```
170
+ After modifying Python files, run: uvx py-gate . --json
171
+ Fix all "error" severity findings. Re-run to verify the score improved.
172
+ ```
173
+
174
+ ### Codex
175
+
176
+ Add to your system prompt:
177
+
178
+ ```
179
+ After modifying Python files, run `uvx py-gate . --json` to check code quality.
180
+ Fix errors first. Target score: 80+.
181
+ ```
182
+
183
+ ### Aider
184
+
185
+ ```bash
186
+ aider --read AGENTS.md
187
+ ```
188
+
189
+ ## GitHub Actions
190
+
191
+ ```yaml
192
+ name: Quality Gate
193
+
194
+ on: [push, pull_request]
195
+
196
+ jobs:
197
+ py-gate:
198
+ runs-on: ubuntu-latest
199
+ steps:
200
+ - uses: actions/checkout@v4
201
+ with:
202
+ fetch-depth: 0 # required for --diff
203
+
204
+ - uses: actions/setup-python@v5
205
+ with:
206
+ python-version: "3.12"
207
+
208
+ - name: Run Py Gate
209
+ run: |
210
+ pip install py-gate
211
+ py-gate . --verbose --diff main --fail-on error
212
+ ```
213
+
214
+ ## CLI Reference
215
+
216
+ | Flag | Default | Description |
217
+ |------|---------|-------------|
218
+ | `[DIRECTORY]` | `.` | Path to the Python project to scan |
219
+ | `--lint / --no-lint` | on | Enable or disable lint checks |
220
+ | `--dead-code / --no-dead-code` | on | Enable or disable dead code detection |
221
+ | `--verbose` | off | Show file path and line number per finding |
222
+ | `--score` | off | Print only the numeric score and exit |
223
+ | `--json` | off | Emit structured JSON (for agents and CI) |
224
+ | `--fix` | off | Run `ruff --fix` before scanning |
225
+ | `--diff TEXT` | — | Scan only files changed vs this base branch |
226
+ | `--fail-on [error\|warning\|none]` | `none` | Exit code 1 when findings at this level exist |
227
+ | `-v, --version` | — | Show version and exit |
228
+ | `-h, --help` | — | Show help and exit |
229
+
230
+ ## What It Checks
231
+
232
+ | Category | Weight | Max Deduction | What it catches |
233
+ |----------|--------|---------------|-----------------|
234
+ | Security | 5 | ~24 pts | `eval`, `exec`, `pickle.load`, unsafe YAML, hardcoded secrets, weak hashes |
235
+ | Correctness | 4 | ~19 pts | Mutable defaults, bare/broad except, assert in production, bad `__init__` return |
236
+ | Complexity | 3 | ~14 pts | Cyclomatic complexity > 15 (warning) or > 25 (error) |
237
+ | Architecture | 3 | ~14 pts | Giant modules (>500 lines), deep nesting (>5), god functions (>50 lines), too many args (>7) |
238
+ | Performance | 2 | ~10 pts | String concat in loops, imports inside functions, star imports |
239
+ | Structure | 2 | ~10 pts | Missing `__init__.py`, missing tests directory, no type hints |
240
+ | Imports | 1 | ~5 pts | Circular imports, wildcard imports, import order issues |
241
+ | Dead Code | 1 | ~5 pts | Unused functions, classes, variables, and imports via Vulture |
242
+
243
+ Framework-specific rules (Django, FastAPI, Flask) are mapped into the Security or Correctness budget.
244
+
245
+ ## Scoring
246
+
247
+ Py Gate uses a **weighted category-budget system**:
248
+
249
+ 1. Each category has a weight (see table above). Weights are normalized to sum to 100 points of total deduction budget.
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).
251
+ 3. A category's deduction is capped at its budget, so a single broken category can never zero out an otherwise healthy project.
252
+ 4. Final score = `100 - sum(capped category deductions)`, floored at 0.
253
+
254
+ | Score | Label | Meaning |
255
+ |-------|-------|---------|
256
+ | 90–100 | Excellent | Production-ready |
257
+ | 75–89 | Great | Minor issues to address |
258
+ | 50–74 | Needs work | Significant issues present |
259
+ | 0–49 | Critical | Blocking issues, do not ship |
260
+
261
+ ## Configuration
262
+
263
+ Create `py-gate.toml` in your project root:
264
+
265
+ ```toml
266
+ [options]
267
+ lint = true
268
+ dead_code = true
269
+ verbose = false
270
+ fail_on = "none"
271
+
272
+ [ignore]
273
+ rules = ["dead-code", "no-import-in-function"]
274
+ files = ["tests/fixtures/**", "migrations/**", "scripts/**"]
275
+
276
+ [per-file-ignores]
277
+ "src/legacy/*.py" = ["high-complexity", "no-god-function"]
278
+
279
+ [scoring]
280
+ max-deduction.Security = 20
281
+ max-deduction.Dead Code = 0 # disable dead-code penalty entirely
282
+ ```
283
+
284
+ Or use `pyproject.toml`:
285
+
286
+ ```toml
287
+ [tool.py-gate]
288
+ lint = true
289
+ dead_code = true
290
+ fail_on = "error"
291
+
292
+ [tool.py-gate.ignore]
293
+ rules = ["no-import-in-function"]
294
+ files = ["tests/fixtures/**"]
295
+
296
+ [tool.py-gate.per-file-ignores]
297
+ "src/legacy/*.py" = ["high-complexity"]
298
+
299
+ [tool.py-gate.scoring]
300
+ "max-deduction" = { Security = 20, "Dead Code" = 0 }
301
+ ```
302
+
303
+ If both files exist, `py-gate.toml` takes precedence. CLI flags always override config values.
304
+
305
+ ## Profiles
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"`).
308
+
309
+ | Profile | Auto-detected when | Adjustments |
310
+ |---------|--------------------|-------------|
311
+ | `cli` | `[project.scripts]` in pyproject.toml | Architecture rules weighted up; dead-code weighted down |
312
+ | `web` | Django / FastAPI / Flask detected | Security and correctness weighted up; framework rules active |
313
+ | `library` | No scripts, no framework, has `py.typed` | Public API checks active; dead-code weighted up |
314
+ | `script` | Single-file project or `scripts/` directory | Architecture rules relaxed; complexity thresholds raised |
315
+
316
+ ## Pre-commit Hook
317
+
318
+ Use `--pre-commit` to run Py Gate as a pre-commit hook. It automatically scans only the staged files:
319
+
320
+ ```bash
321
+ py-gate . --pre-commit --fail-on error
322
+ ```
323
+
324
+ Add to `.pre-commit-config.yaml`:
325
+
326
+ ```yaml
327
+ repos:
328
+ - repo: local
329
+ hooks:
330
+ - id: py-gate
331
+ name: Py Gate quality check
332
+ entry: py-gate . --pre-commit --fail-on error
333
+ language: system
334
+ types: [python]
335
+ pass_filenames: false
336
+ ```
337
+
338
+ ## Contributing
339
+
340
+ ```bash
341
+ git clone https://github.com/themohitkhare/pycodegate
342
+ cd pycodegate
343
+ uv sync --all-extras
344
+ uv run pytest -q
345
+ uv run py-gate . --verbose # dogfood it
346
+ ```
347
+
348
+ To add a new rule:
349
+
350
+ 1. Create a file in `src/pycodegate/rules/` extending `BaseRules`
351
+ 2. Implement `check(self, source: str, filename: str) -> list[Diagnostic]`
352
+ 3. Register it in `src/pycodegate/rules/__init__.py`
353
+ 4. Add tests in `tests/rules/`
354
+
355
+ ## License
356
+
357
+ MIT