python-code-quality 0.2.2__tar.gz → 0.3.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.
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/PKG-INFO +116 -103
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/README.md +114 -101
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/pyproject.toml +18 -15
- python_code_quality-0.3.0/pyproject.toml.orig +71 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/api.py +26 -5
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/cli.py +21 -11
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/config/config.toml +30 -22
- python_code_quality-0.3.0/src/py_cq/context_hash.py +137 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/execution_engine.py +175 -38
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/localtypes.py +10 -7
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/parsers/common.py +17 -18
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/parsers/complexityparser.py +2 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/parsers/coverageparser.py +11 -18
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/parsers/halsteadparser.py +4 -3
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/parsers/interrogateparser.py +20 -21
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/parsers/pytestparser.py +1 -1
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/parsers/ruffparser.py +1 -1
- python_code_quality-0.3.0/src/py_cq/source_file.py +199 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/table_formatter.py +1 -1
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/tool_registry.py +3 -0
- python_code_quality-0.2.2/src/py_cq/context_hash.py +0 -91
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/__init__.py +0 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/config/__init__.py +0 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/language_detector.py +0 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/llm_formatter.py +0 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/main.py +0 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/metric_aggregator.py +0 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/parsers/__init__.py +0 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/parsers/banditparser.py +0 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/parsers/compileparser.py +0 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/parsers/exitcodeparser.py +0 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/parsers/linecountparser.py +0 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/parsers/maintainabilityparser.py +0 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/parsers/regexcountparser.py +0 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/parsers/typarser.py +0 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/parsers/vultureparser.py +0 -0
- {python_code_quality-0.2.2 → python_code_quality-0.3.0}/src/py_cq/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-code-quality
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Python Code Quality Analysis Tool - feed the results from 11 CQ tools straight into an LLM. Minimal tokens.
|
|
5
5
|
Author: Chris Kilner
|
|
6
6
|
Author-email: Chris Kilner <chris@rhiza.fr>
|
|
@@ -17,7 +17,7 @@ Requires-Dist: pytest-cov>=6.1.1
|
|
|
17
17
|
Requires-Dist: pytest-json-report>=1.5.0
|
|
18
18
|
Requires-Dist: radon>=6.0.1
|
|
19
19
|
Requires-Dist: rich>=14.0.0
|
|
20
|
-
Requires-Dist: ruff>=0.14.1
|
|
20
|
+
Requires-Dist: ruff>=0.14.1,<0.17
|
|
21
21
|
Requires-Dist: tomlkit>=0.13.0
|
|
22
22
|
Requires-Dist: ty>=0.0.17
|
|
23
23
|
Requires-Dist: typer>=0.16.0
|
|
@@ -65,6 +65,8 @@ uv tool install .
|
|
|
65
65
|
|
|
66
66
|
These tools are run in **parallel** except:
|
|
67
67
|
When running '-o llm', we run sequentially and exit early at the first error.
|
|
68
|
+
`coverage` is a special case: it starts alongside `pytest` and is cancelled if
|
|
69
|
+
`pytest` fails, scoring `0%` without a second test run.
|
|
68
70
|
|
|
69
71
|
| Order | Tool | Measures |
|
|
70
72
|
|----------|------|----------|
|
|
@@ -74,11 +76,11 @@ When running '-o llm', we run sequentially and exit early at the first error.
|
|
|
74
76
|
| 4 | bandit | Security vulnerabilities |
|
|
75
77
|
| 5 | pytest | Test pass rate |
|
|
76
78
|
| 6 | coverage | Test coverage |
|
|
77
|
-
| 7 |
|
|
78
|
-
| 8 |
|
|
79
|
-
| 9 | radon
|
|
80
|
-
| 10 |
|
|
81
|
-
| 11 |
|
|
79
|
+
| 7 | vulture | Dead code |
|
|
80
|
+
| 8 | interrogate | Docstring coverage |
|
|
81
|
+
| 9 | radon cc | Cyclomatic complexity |
|
|
82
|
+
| 10 | radon mi | Maintainability index |
|
|
83
|
+
| 11 | radon hal | Halstead volume / bug estimate |
|
|
82
84
|
|
|
83
85
|
Diskcache is used to cache tool output for lightning fast re-runs. Sane defaults: <100 Mb, <5 days, No pickle risk.
|
|
84
86
|
|
|
@@ -337,106 +339,117 @@ warning = 0.9
|
|
|
337
339
|
error = 0.7
|
|
338
340
|
```
|
|
339
341
|
|
|
340
|
-
Tool IDs match the keys in `config/config.
|
|
342
|
+
Tool IDs match the keys in `src/py_cq/config/config.toml`: `compile`, `ruff`, `ty`, `bandit`, `pytest`, `coverage`, `radon-cc`, `radon-mi`, `radon-hal`, `vulture`, `interrogate`.
|
|
341
343
|
|
|
342
344
|
|
|
343
345
|
### Default config
|
|
344
346
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
347
|
+
Defined in `src/py_cq/config/config.toml` (sections are namespaced by language):
|
|
348
|
+
|
|
349
|
+
```toml
|
|
350
|
+
[python.compile]
|
|
351
|
+
command = "{python} -m compileall -r 10 -j 8 \"{context_path}\" -x .*venv|\\.claude"
|
|
352
|
+
parser = "CompileParser"
|
|
353
|
+
order = 1
|
|
354
|
+
warning_threshold = 0.9999
|
|
355
|
+
error_threshold = 0.9999
|
|
356
|
+
cache_invariant = "ast"
|
|
357
|
+
|
|
358
|
+
[python.ruff]
|
|
359
|
+
command = "{python} -m ruff check --output-format concise --no-cache \"{context_path}\" --exclude .claude{exclude}"
|
|
360
|
+
exclude_format = " --exclude {path}"
|
|
361
|
+
parser = "RuffParser"
|
|
362
|
+
order = 2
|
|
363
|
+
warning_threshold = 0.9999
|
|
364
|
+
error_threshold = 0.9
|
|
365
|
+
|
|
366
|
+
[python.ty]
|
|
367
|
+
command = "{python} -m ty check --output-format concise --color never \"{context_path}\" --exclude .claude{exclude}"
|
|
368
|
+
exclude_format = " --exclude {path}"
|
|
369
|
+
parser = "TyParser"
|
|
370
|
+
order = 3
|
|
371
|
+
warning_threshold = 0.9999
|
|
372
|
+
error_threshold = 0.8
|
|
373
|
+
run_in_target_env = true
|
|
374
|
+
extra_deps = ["ty"]
|
|
375
|
+
|
|
376
|
+
[python.bandit]
|
|
377
|
+
command = "{python} -m bandit -r {scan_targets} -f json -q -s B101 --severity-level medium{exclude}"
|
|
378
|
+
scan_exclude_names = [".venv", ".claude", "tests"]
|
|
379
|
+
exclude_format = " --exclude {abs_native_path}"
|
|
380
|
+
parser = "BanditParser"
|
|
381
|
+
order = 4
|
|
382
|
+
warning_threshold = 0.9999
|
|
383
|
+
error_threshold = 0.8
|
|
384
|
+
|
|
385
|
+
[python.pytest]
|
|
386
|
+
command = "{python} -m pytest -vv \"{context_path}\" --ignore .claude{exclude}"
|
|
387
|
+
exclude_format = " --ignore {path}"
|
|
388
|
+
parser = "PytestParser"
|
|
389
|
+
order = 5
|
|
390
|
+
warning_threshold = 1.0
|
|
391
|
+
error_threshold = 1.0
|
|
392
|
+
run_in_target_env = true
|
|
393
|
+
extra_deps = ["pytest"]
|
|
394
|
+
skip_for_file = true
|
|
395
|
+
cache_invariant = "ast"
|
|
396
|
+
|
|
397
|
+
[python.coverage]
|
|
398
|
+
command = "{python} -m coverage run --omit=*/tests/*,*/test_*.py -m pytest \"{context_path}\" --ignore .claude{exclude} && {python} -m coverage report --show-missing --omit=*/tests/*,*/test_*.py"
|
|
399
|
+
exclude_format = " --ignore {path}"
|
|
400
|
+
parser = "CoverageParser"
|
|
401
|
+
order = 6
|
|
402
|
+
warning_threshold = 0.9
|
|
403
|
+
error_threshold = 0.5
|
|
404
|
+
run_in_target_env = true
|
|
405
|
+
extra_deps = ["coverage", "pytest"]
|
|
406
|
+
skip_for_file = true
|
|
407
|
+
skip_if = "pytest"
|
|
408
|
+
cache_invariant = "ast"
|
|
409
|
+
|
|
410
|
+
[python.vulture]
|
|
411
|
+
command = "{python} -m vulture \"{context_path}\" --min-confidence 80 --exclude .venv,dist,.*_cache,docs,.git,.claude{exclude}"
|
|
412
|
+
exclude_format = ",{path}"
|
|
413
|
+
parser = "VultureParser"
|
|
414
|
+
order = 7
|
|
415
|
+
warning_threshold = 0.9999
|
|
416
|
+
error_threshold = 0.8
|
|
417
|
+
cache_invariant = "ast"
|
|
418
|
+
|
|
419
|
+
[python.interrogate]
|
|
420
|
+
command = "{python} -m interrogate \"{context_path}\" -e .claude{exclude} -v --fail-under 0"
|
|
421
|
+
exclude_format = " -e {path}"
|
|
422
|
+
parser = "InterrogateParser"
|
|
423
|
+
order = 8
|
|
424
|
+
warning_threshold = 0.8
|
|
425
|
+
error_threshold = 0.5
|
|
426
|
+
|
|
427
|
+
[python.interrogate.parser_config]
|
|
428
|
+
skip_empty_init = true
|
|
429
|
+
|
|
430
|
+
[python.radon-cc]
|
|
431
|
+
command = "{python} -m radon cc --json --exclude '.claude/**' \"{context_path}\""
|
|
432
|
+
parser = "ComplexityParser"
|
|
433
|
+
order = 9
|
|
434
|
+
gate_strict = false
|
|
435
|
+
warning_threshold = 0.6
|
|
436
|
+
error_threshold = 0.4
|
|
437
|
+
|
|
438
|
+
[python.radon-mi]
|
|
439
|
+
command = "{python} -m radon mi -s --json --exclude '.claude/**' \"{context_path}\""
|
|
440
|
+
parser = "MaintainabilityParser"
|
|
441
|
+
order = 10
|
|
442
|
+
gate_strict = false
|
|
443
|
+
warning_threshold = 0.6
|
|
444
|
+
error_threshold = 0.4
|
|
445
|
+
|
|
446
|
+
[python.radon-hal]
|
|
447
|
+
command = "{python} -m radon hal -f --json --exclude '.claude/**' \"{context_path}\""
|
|
448
|
+
parser = "HalsteadParser"
|
|
449
|
+
order = 11
|
|
450
|
+
gate_strict = false
|
|
451
|
+
warning_threshold = 0.35
|
|
452
|
+
error_threshold = 0.3
|
|
440
453
|
```
|
|
441
454
|
|
|
442
455
|
## Respect
|
|
@@ -36,6 +36,8 @@ uv tool install .
|
|
|
36
36
|
|
|
37
37
|
These tools are run in **parallel** except:
|
|
38
38
|
When running '-o llm', we run sequentially and exit early at the first error.
|
|
39
|
+
`coverage` is a special case: it starts alongside `pytest` and is cancelled if
|
|
40
|
+
`pytest` fails, scoring `0%` without a second test run.
|
|
39
41
|
|
|
40
42
|
| Order | Tool | Measures |
|
|
41
43
|
|----------|------|----------|
|
|
@@ -45,11 +47,11 @@ When running '-o llm', we run sequentially and exit early at the first error.
|
|
|
45
47
|
| 4 | bandit | Security vulnerabilities |
|
|
46
48
|
| 5 | pytest | Test pass rate |
|
|
47
49
|
| 6 | coverage | Test coverage |
|
|
48
|
-
| 7 |
|
|
49
|
-
| 8 |
|
|
50
|
-
| 9 | radon
|
|
51
|
-
| 10 |
|
|
52
|
-
| 11 |
|
|
50
|
+
| 7 | vulture | Dead code |
|
|
51
|
+
| 8 | interrogate | Docstring coverage |
|
|
52
|
+
| 9 | radon cc | Cyclomatic complexity |
|
|
53
|
+
| 10 | radon mi | Maintainability index |
|
|
54
|
+
| 11 | radon hal | Halstead volume / bug estimate |
|
|
53
55
|
|
|
54
56
|
Diskcache is used to cache tool output for lightning fast re-runs. Sane defaults: <100 Mb, <5 days, No pickle risk.
|
|
55
57
|
|
|
@@ -308,106 +310,117 @@ warning = 0.9
|
|
|
308
310
|
error = 0.7
|
|
309
311
|
```
|
|
310
312
|
|
|
311
|
-
Tool IDs match the keys in `config/config.
|
|
313
|
+
Tool IDs match the keys in `src/py_cq/config/config.toml`: `compile`, `ruff`, `ty`, `bandit`, `pytest`, `coverage`, `radon-cc`, `radon-mi`, `radon-hal`, `vulture`, `interrogate`.
|
|
312
314
|
|
|
313
315
|
|
|
314
316
|
### Default config
|
|
315
317
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
318
|
+
Defined in `src/py_cq/config/config.toml` (sections are namespaced by language):
|
|
319
|
+
|
|
320
|
+
```toml
|
|
321
|
+
[python.compile]
|
|
322
|
+
command = "{python} -m compileall -r 10 -j 8 \"{context_path}\" -x .*venv|\\.claude"
|
|
323
|
+
parser = "CompileParser"
|
|
324
|
+
order = 1
|
|
325
|
+
warning_threshold = 0.9999
|
|
326
|
+
error_threshold = 0.9999
|
|
327
|
+
cache_invariant = "ast"
|
|
328
|
+
|
|
329
|
+
[python.ruff]
|
|
330
|
+
command = "{python} -m ruff check --output-format concise --no-cache \"{context_path}\" --exclude .claude{exclude}"
|
|
331
|
+
exclude_format = " --exclude {path}"
|
|
332
|
+
parser = "RuffParser"
|
|
333
|
+
order = 2
|
|
334
|
+
warning_threshold = 0.9999
|
|
335
|
+
error_threshold = 0.9
|
|
336
|
+
|
|
337
|
+
[python.ty]
|
|
338
|
+
command = "{python} -m ty check --output-format concise --color never \"{context_path}\" --exclude .claude{exclude}"
|
|
339
|
+
exclude_format = " --exclude {path}"
|
|
340
|
+
parser = "TyParser"
|
|
341
|
+
order = 3
|
|
342
|
+
warning_threshold = 0.9999
|
|
343
|
+
error_threshold = 0.8
|
|
344
|
+
run_in_target_env = true
|
|
345
|
+
extra_deps = ["ty"]
|
|
346
|
+
|
|
347
|
+
[python.bandit]
|
|
348
|
+
command = "{python} -m bandit -r {scan_targets} -f json -q -s B101 --severity-level medium{exclude}"
|
|
349
|
+
scan_exclude_names = [".venv", ".claude", "tests"]
|
|
350
|
+
exclude_format = " --exclude {abs_native_path}"
|
|
351
|
+
parser = "BanditParser"
|
|
352
|
+
order = 4
|
|
353
|
+
warning_threshold = 0.9999
|
|
354
|
+
error_threshold = 0.8
|
|
355
|
+
|
|
356
|
+
[python.pytest]
|
|
357
|
+
command = "{python} -m pytest -vv \"{context_path}\" --ignore .claude{exclude}"
|
|
358
|
+
exclude_format = " --ignore {path}"
|
|
359
|
+
parser = "PytestParser"
|
|
360
|
+
order = 5
|
|
361
|
+
warning_threshold = 1.0
|
|
362
|
+
error_threshold = 1.0
|
|
363
|
+
run_in_target_env = true
|
|
364
|
+
extra_deps = ["pytest"]
|
|
365
|
+
skip_for_file = true
|
|
366
|
+
cache_invariant = "ast"
|
|
367
|
+
|
|
368
|
+
[python.coverage]
|
|
369
|
+
command = "{python} -m coverage run --omit=*/tests/*,*/test_*.py -m pytest \"{context_path}\" --ignore .claude{exclude} && {python} -m coverage report --show-missing --omit=*/tests/*,*/test_*.py"
|
|
370
|
+
exclude_format = " --ignore {path}"
|
|
371
|
+
parser = "CoverageParser"
|
|
372
|
+
order = 6
|
|
373
|
+
warning_threshold = 0.9
|
|
374
|
+
error_threshold = 0.5
|
|
375
|
+
run_in_target_env = true
|
|
376
|
+
extra_deps = ["coverage", "pytest"]
|
|
377
|
+
skip_for_file = true
|
|
378
|
+
skip_if = "pytest"
|
|
379
|
+
cache_invariant = "ast"
|
|
380
|
+
|
|
381
|
+
[python.vulture]
|
|
382
|
+
command = "{python} -m vulture \"{context_path}\" --min-confidence 80 --exclude .venv,dist,.*_cache,docs,.git,.claude{exclude}"
|
|
383
|
+
exclude_format = ",{path}"
|
|
384
|
+
parser = "VultureParser"
|
|
385
|
+
order = 7
|
|
386
|
+
warning_threshold = 0.9999
|
|
387
|
+
error_threshold = 0.8
|
|
388
|
+
cache_invariant = "ast"
|
|
389
|
+
|
|
390
|
+
[python.interrogate]
|
|
391
|
+
command = "{python} -m interrogate \"{context_path}\" -e .claude{exclude} -v --fail-under 0"
|
|
392
|
+
exclude_format = " -e {path}"
|
|
393
|
+
parser = "InterrogateParser"
|
|
394
|
+
order = 8
|
|
395
|
+
warning_threshold = 0.8
|
|
396
|
+
error_threshold = 0.5
|
|
397
|
+
|
|
398
|
+
[python.interrogate.parser_config]
|
|
399
|
+
skip_empty_init = true
|
|
400
|
+
|
|
401
|
+
[python.radon-cc]
|
|
402
|
+
command = "{python} -m radon cc --json --exclude '.claude/**' \"{context_path}\""
|
|
403
|
+
parser = "ComplexityParser"
|
|
404
|
+
order = 9
|
|
405
|
+
gate_strict = false
|
|
406
|
+
warning_threshold = 0.6
|
|
407
|
+
error_threshold = 0.4
|
|
408
|
+
|
|
409
|
+
[python.radon-mi]
|
|
410
|
+
command = "{python} -m radon mi -s --json --exclude '.claude/**' \"{context_path}\""
|
|
411
|
+
parser = "MaintainabilityParser"
|
|
412
|
+
order = 10
|
|
413
|
+
gate_strict = false
|
|
414
|
+
warning_threshold = 0.6
|
|
415
|
+
error_threshold = 0.4
|
|
416
|
+
|
|
417
|
+
[python.radon-hal]
|
|
418
|
+
command = "{python} -m radon hal -f --json --exclude '.claude/**' \"{context_path}\""
|
|
419
|
+
parser = "HalsteadParser"
|
|
420
|
+
order = 11
|
|
421
|
+
gate_strict = false
|
|
422
|
+
warning_threshold = 0.35
|
|
423
|
+
error_threshold = 0.3
|
|
411
424
|
```
|
|
412
425
|
|
|
413
426
|
## Respect
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-code-quality"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.0"
|
|
4
4
|
description = "Python Code Quality Analysis Tool - feed the results from 11 CQ tools straight into an LLM. Minimal tokens."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
7
7
|
license = "MIT"
|
|
8
|
-
authors = [{name = "Chris Kilner", email = "chris@rhiza.fr"}]
|
|
9
8
|
classifiers = [
|
|
10
9
|
"Programming Language :: Python :: 3.12",
|
|
11
10
|
"Programming Language :: Python :: 3.13",
|
|
12
11
|
"Programming Language :: Python :: 3.14",
|
|
13
12
|
]
|
|
14
|
-
|
|
15
13
|
dependencies = [
|
|
16
14
|
"bandit>=1.8.0",
|
|
17
15
|
"coverage>=7.8.2",
|
|
@@ -22,43 +20,48 @@ dependencies = [
|
|
|
22
20
|
"pytest-json-report>=1.5.0",
|
|
23
21
|
"radon>=6.0.1",
|
|
24
22
|
"rich>=14.0.0",
|
|
25
|
-
"ruff>=0.14.1",
|
|
23
|
+
"ruff>=0.14.1,<0.17",
|
|
26
24
|
"tomlkit>=0.13.0",
|
|
27
25
|
"ty>=0.0.17",
|
|
28
26
|
"typer>=0.16.0",
|
|
29
27
|
"vulture>=2.14",
|
|
30
28
|
]
|
|
31
29
|
|
|
30
|
+
[[project.authors]]
|
|
31
|
+
name = "Chris Kilner"
|
|
32
|
+
email = "chris@rhiza.fr"
|
|
33
|
+
|
|
32
34
|
[project.urls]
|
|
33
35
|
Homepage = "https://github.com/rhiza-fr/py-cq"
|
|
34
36
|
Repository = "https://github.com/rhiza-fr/py-cq"
|
|
35
37
|
|
|
38
|
+
[project.scripts]
|
|
39
|
+
cq = "py_cq.main:main"
|
|
40
|
+
|
|
36
41
|
[build-system]
|
|
37
|
-
requires = ["uv_build"]
|
|
42
|
+
requires = ["uv_build>=0.12.0,<0.13.0"]
|
|
38
43
|
build-backend = "uv_build"
|
|
39
44
|
|
|
40
45
|
[tool.uv.build-backend]
|
|
41
46
|
module-name = "py_cq"
|
|
42
47
|
|
|
43
|
-
[project.scripts]
|
|
44
|
-
cq = "py_cq.main:main"
|
|
45
|
-
|
|
46
48
|
[tool.pytest.ini_options]
|
|
47
49
|
testpaths = ["tests"]
|
|
48
|
-
norecursedirs = [
|
|
49
|
-
|
|
50
|
-
"
|
|
50
|
+
norecursedirs = [
|
|
51
|
+
".venv",
|
|
52
|
+
"dist",
|
|
51
53
|
]
|
|
54
|
+
markers = ["slow: tests that have real side effects (e.g. clearing disk cache)"]
|
|
52
55
|
addopts = "-m 'not slow'"
|
|
53
56
|
|
|
54
57
|
[[tool.ty.overrides]]
|
|
55
58
|
include = ["demo/**"]
|
|
56
|
-
|
|
59
|
+
|
|
60
|
+
[tool.ty.overrides.rules]
|
|
61
|
+
unresolved-import = "ignore"
|
|
57
62
|
|
|
58
63
|
[tool.cq]
|
|
59
64
|
exclude = ["demo"]
|
|
60
65
|
|
|
61
66
|
[dependency-groups]
|
|
62
|
-
dev = [
|
|
63
|
-
"hypothesis>=6.151.10",
|
|
64
|
-
]
|
|
67
|
+
dev = ["hypothesis>=6.151.10"]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "python-code-quality"
|
|
3
|
+
version = "0.3.0"
|
|
4
|
+
description = "Python Code Quality Analysis Tool - feed the results from 11 CQ tools straight into an LLM. Minimal tokens."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.12"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
authors = [{name = "Chris Kilner", email = "chris@rhiza.fr"}]
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Programming Language :: Python :: 3.12",
|
|
11
|
+
"Programming Language :: Python :: 3.13",
|
|
12
|
+
"Programming Language :: Python :: 3.14",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
dependencies = [
|
|
16
|
+
"bandit>=1.8.0",
|
|
17
|
+
"coverage>=7.8.2",
|
|
18
|
+
"diskcache>=5.6.3",
|
|
19
|
+
"interrogate>=1.7.0",
|
|
20
|
+
"pytest>=8.4.0",
|
|
21
|
+
"pytest-cov>=6.1.1",
|
|
22
|
+
"pytest-json-report>=1.5.0",
|
|
23
|
+
"radon>=6.0.1",
|
|
24
|
+
"rich>=14.0.0",
|
|
25
|
+
# Upper-capped: ruff's default rule set is not stable across minor versions
|
|
26
|
+
# (0.15 enabled ~60 rules, 0.16 enables 413). cq runs ruff from its own
|
|
27
|
+
# environment, so an unbounded bump silently changes every user's lint score.
|
|
28
|
+
# Raise this deliberately, with a changelog note.
|
|
29
|
+
"ruff>=0.14.1,<0.17",
|
|
30
|
+
"tomlkit>=0.13.0",
|
|
31
|
+
"ty>=0.0.17",
|
|
32
|
+
"typer>=0.16.0",
|
|
33
|
+
"vulture>=2.14",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://github.com/rhiza-fr/py-cq"
|
|
38
|
+
Repository = "https://github.com/rhiza-fr/py-cq"
|
|
39
|
+
|
|
40
|
+
[build-system]
|
|
41
|
+
# Upper-capped for the same reason as ruff: an unbounded backend requirement
|
|
42
|
+
# lets a future breaking uv_build release break the sdist build with no change
|
|
43
|
+
# here. Raise deliberately alongside the uv version this is built with.
|
|
44
|
+
requires = ["uv_build>=0.12.0,<0.13.0"]
|
|
45
|
+
build-backend = "uv_build"
|
|
46
|
+
|
|
47
|
+
[tool.uv.build-backend]
|
|
48
|
+
module-name = "py_cq"
|
|
49
|
+
|
|
50
|
+
[project.scripts]
|
|
51
|
+
cq = "py_cq.main:main"
|
|
52
|
+
|
|
53
|
+
[tool.pytest.ini_options]
|
|
54
|
+
testpaths = ["tests"]
|
|
55
|
+
norecursedirs = [".venv", "dist"]
|
|
56
|
+
markers = [
|
|
57
|
+
"slow: tests that have real side effects (e.g. clearing disk cache)",
|
|
58
|
+
]
|
|
59
|
+
addopts = "-m 'not slow'"
|
|
60
|
+
|
|
61
|
+
[[tool.ty.overrides]]
|
|
62
|
+
include = ["demo/**"]
|
|
63
|
+
rules = {unresolved-import = "ignore"}
|
|
64
|
+
|
|
65
|
+
[tool.cq]
|
|
66
|
+
exclude = ["demo"]
|
|
67
|
+
|
|
68
|
+
[dependency-groups]
|
|
69
|
+
dev = [
|
|
70
|
+
"hypothesis>=6.151.10",
|
|
71
|
+
]
|