python-code-quality 0.1.7__py3-none-any.whl → 0.1.8__py3-none-any.whl
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.
- py_cq/cli.py +13 -9
- py_cq/config/tools.yaml +12 -12
- py_cq/execution_engine.py +14 -2
- py_cq/llm_formatter.py +1 -1
- py_cq/localtypes.py +4 -4
- py_cq/parsers/halsteadparser.py +1 -1
- py_cq/parsers/pytestparser.py +8 -0
- py_cq/tool_registry.py +1 -1
- {python_code_quality-0.1.7.dist-info → python_code_quality-0.1.8.dist-info}/METADATA +63 -65
- {python_code_quality-0.1.7.dist-info → python_code_quality-0.1.8.dist-info}/RECORD +13 -13
- {python_code_quality-0.1.7.dist-info → python_code_quality-0.1.8.dist-info}/WHEEL +0 -0
- {python_code_quality-0.1.7.dist-info → python_code_quality-0.1.8.dist-info}/entry_points.txt +0 -0
- {python_code_quality-0.1.7.dist-info → python_code_quality-0.1.8.dist-info}/licenses/LICENSE +0 -0
py_cq/cli.py
CHANGED
|
@@ -43,7 +43,8 @@ app = typer.Typer(
|
|
|
43
43
|
" cq check . # full table with all metrics (default)\n\n"
|
|
44
44
|
" cq check . -o llm # top defect as markdown (primary LLM workflow)\n\n"
|
|
45
45
|
" cq check . -o score # numeric score only\n\n"
|
|
46
|
-
" cq check . -o json #
|
|
46
|
+
" cq check . -o json # parsed metrics as json\n\n"
|
|
47
|
+
" cq check . -o raw # unprocessed tool output as json\n\n"
|
|
47
48
|
" cq config . # show effective tool configuration"
|
|
48
49
|
),
|
|
49
50
|
)
|
|
@@ -74,6 +75,7 @@ class OutputMode(str, Enum):
|
|
|
74
75
|
SCORE = "score"
|
|
75
76
|
JSON = "json"
|
|
76
77
|
LLM = "llm"
|
|
78
|
+
RAW = "raw"
|
|
77
79
|
|
|
78
80
|
|
|
79
81
|
@app.callback()
|
|
@@ -114,16 +116,18 @@ def check(
|
|
|
114
116
|
effective_registry = _apply_user_config(tool_registry, load_user_config(path_obj))
|
|
115
117
|
if clear_cache:
|
|
116
118
|
tool_cache.clear()
|
|
117
|
-
tool_results = run_tools(effective_registry.values(), path, workers)
|
|
118
|
-
for tr in tool_results:
|
|
119
|
-
|
|
119
|
+
tool_results = run_tools(effective_registry.values(), path, workers, early_exit=(output == OutputMode.LLM))
|
|
120
|
+
# for tr in tool_results:
|
|
121
|
+
# log.debug(json.dumps(tr.to_dict(), indent=2))
|
|
120
122
|
combined_metrics = aggregate_metrics(path=path, metrics=tool_results)
|
|
121
123
|
if output == OutputMode.SCORE:
|
|
122
124
|
console.print(combined_metrics.score)
|
|
123
125
|
elif output == OutputMode.JSON:
|
|
124
|
-
console.print(json.dumps(
|
|
126
|
+
console.print(json.dumps([tr.to_dict() for tr in tool_results], indent=2))
|
|
127
|
+
elif output == OutputMode.RAW:
|
|
128
|
+
console.print(json.dumps([tr.raw.to_dict() for tr in tool_results], indent=2))
|
|
125
129
|
elif output == OutputMode.LLM:
|
|
126
|
-
log.setLevel("CRITICAL")
|
|
130
|
+
# log.setLevel("CRITICAL")
|
|
127
131
|
from py_cq.llm_formatter import format_for_llm
|
|
128
132
|
console.print(format_for_llm(effective_registry, combined_metrics))
|
|
129
133
|
else:
|
|
@@ -163,18 +167,18 @@ def config(
|
|
|
163
167
|
|
|
164
168
|
table = Table()
|
|
165
169
|
table.add_column("Tool", style="cyan")
|
|
166
|
-
table.add_column("
|
|
170
|
+
table.add_column("Order", justify="right")
|
|
167
171
|
table.add_column("Warning", justify="right")
|
|
168
172
|
table.add_column("Error", justify="right")
|
|
169
173
|
table.add_column("Status", justify="center")
|
|
170
174
|
|
|
171
|
-
for tool_id in sorted(tool_registry, key=lambda t: tool_registry[t].
|
|
175
|
+
for tool_id in sorted(tool_registry, key=lambda t: tool_registry[t].order):
|
|
172
176
|
tc = effective_registry.get(tool_id, tool_registry[tool_id])
|
|
173
177
|
is_disabled = tool_id in disabled_ids
|
|
174
178
|
status = "[red]disabled[/red]" if is_disabled else "[green]enabled[/green]"
|
|
175
179
|
table.add_row(
|
|
176
180
|
tc.name,
|
|
177
|
-
str(tc.
|
|
181
|
+
str(tc.order),
|
|
178
182
|
f"{tc.warning_threshold:.2f}",
|
|
179
183
|
f"{tc.error_threshold:.2f}",
|
|
180
184
|
status,
|
py_cq/config/tools.yaml
CHANGED
|
@@ -4,7 +4,7 @@ tools:
|
|
|
4
4
|
name: "compile"
|
|
5
5
|
command: "{python} -m compileall -r 10 -j 8 {context_path} -x .*venv"
|
|
6
6
|
parser: "CompileParser"
|
|
7
|
-
|
|
7
|
+
order: 1
|
|
8
8
|
warning_threshold: 0.9999
|
|
9
9
|
error_threshold: 0.9999
|
|
10
10
|
|
|
@@ -12,7 +12,7 @@ tools:
|
|
|
12
12
|
name: "bandit"
|
|
13
13
|
command: "{python} -m bandit -r {context_path} -f json -q -s B101 --severity-level medium --exclude {input_path_posix}/.venv,{input_path_posix}/tests"
|
|
14
14
|
parser: "BanditParser"
|
|
15
|
-
|
|
15
|
+
order: 2
|
|
16
16
|
warning_threshold: 0.9999
|
|
17
17
|
error_threshold: 0.8
|
|
18
18
|
|
|
@@ -20,7 +20,7 @@ tools:
|
|
|
20
20
|
name: "ruff"
|
|
21
21
|
command: "{python} -m ruff check --output-format concise --no-cache {context_path}"
|
|
22
22
|
parser: "RuffParser"
|
|
23
|
-
|
|
23
|
+
order: 3
|
|
24
24
|
warning_threshold: 0.9999
|
|
25
25
|
error_threshold: 0.9
|
|
26
26
|
|
|
@@ -28,7 +28,7 @@ tools:
|
|
|
28
28
|
name: "ty"
|
|
29
29
|
command: "{python} -m ty check --output-format concise --color never {context_path}"
|
|
30
30
|
parser: "TyParser"
|
|
31
|
-
|
|
31
|
+
order: 4
|
|
32
32
|
warning_threshold: 0.9999
|
|
33
33
|
error_threshold: 0.8
|
|
34
34
|
run_in_target_env: true
|
|
@@ -39,16 +39,16 @@ tools:
|
|
|
39
39
|
name: "pytest"
|
|
40
40
|
command: "{python} -m pytest -v {context_path}"
|
|
41
41
|
parser: "PytestParser"
|
|
42
|
-
|
|
42
|
+
order: 5
|
|
43
43
|
warning_threshold: 0.7
|
|
44
44
|
error_threshold: 0.5
|
|
45
45
|
run_in_target_env: true
|
|
46
46
|
|
|
47
47
|
coverage:
|
|
48
48
|
name: "coverage"
|
|
49
|
-
command: "{python} -m coverage run -m pytest {context_path} && {python} -m coverage report"
|
|
49
|
+
command: "{python} -m coverage run --omit=*/tests/*,*/test_*.py -m pytest {context_path} && {python} -m coverage report --omit=*/tests/*,*/test_*.py"
|
|
50
50
|
parser: "CoverageParser"
|
|
51
|
-
|
|
51
|
+
order: 6
|
|
52
52
|
warning_threshold: 0.9
|
|
53
53
|
error_threshold: 0.5
|
|
54
54
|
run_in_target_env: true
|
|
@@ -60,7 +60,7 @@ tools:
|
|
|
60
60
|
name: "radon cc"
|
|
61
61
|
command: "{python} -m radon cc --json {context_path}"
|
|
62
62
|
parser: "ComplexityParser"
|
|
63
|
-
|
|
63
|
+
order: 7
|
|
64
64
|
warning_threshold: 0.6
|
|
65
65
|
error_threshold: 0.4
|
|
66
66
|
|
|
@@ -68,7 +68,7 @@ tools:
|
|
|
68
68
|
name: "radon mi"
|
|
69
69
|
command: "{python} -m radon mi -s --json {context_path}"
|
|
70
70
|
parser: "MaintainabilityParser"
|
|
71
|
-
|
|
71
|
+
order: 8
|
|
72
72
|
warning_threshold: 0.6
|
|
73
73
|
error_threshold: 0.4
|
|
74
74
|
|
|
@@ -76,7 +76,7 @@ tools:
|
|
|
76
76
|
name: "radon hal"
|
|
77
77
|
command: "{python} -m radon hal -f --json {context_path}"
|
|
78
78
|
parser: "HalsteadParser"
|
|
79
|
-
|
|
79
|
+
order: 9
|
|
80
80
|
warning_threshold: 0.5
|
|
81
81
|
error_threshold: 0.3
|
|
82
82
|
|
|
@@ -84,7 +84,7 @@ tools:
|
|
|
84
84
|
name: "vulture"
|
|
85
85
|
command: "{python} -m vulture {context_path} --min-confidence 80 --exclude .venv,dist,.*_cache,docs,.git"
|
|
86
86
|
parser: "VultureParser"
|
|
87
|
-
|
|
87
|
+
order: 10
|
|
88
88
|
warning_threshold: 0.9999
|
|
89
89
|
error_threshold: 0.8
|
|
90
90
|
|
|
@@ -92,6 +92,6 @@ tools:
|
|
|
92
92
|
name: "interrogate"
|
|
93
93
|
command: "{python} -m interrogate {context_path} -v --fail-under 0"
|
|
94
94
|
parser: "InterrogateParser"
|
|
95
|
-
|
|
95
|
+
order: 11
|
|
96
96
|
warning_threshold: 0.8
|
|
97
97
|
error_threshold: 0.3
|
py_cq/execution_engine.py
CHANGED
|
@@ -96,7 +96,7 @@ def run_tool(tool_config: ToolConfig, context_path: str) -> RawResult:
|
|
|
96
96
|
return raw_result
|
|
97
97
|
|
|
98
98
|
|
|
99
|
-
def run_tools(tool_configs: Collection[ToolConfig], path: str, max_workers: int = 0) -> list[ToolResult]:
|
|
99
|
+
def run_tools(tool_configs: Collection[ToolConfig], path: str, max_workers: int = 0, early_exit: bool = False) -> list[ToolResult]:
|
|
100
100
|
"""Run multiple tools and return their parsed results.
|
|
101
101
|
|
|
102
102
|
Runs each tool specified in *tool_configs* on the file or directory at
|
|
@@ -141,12 +141,24 @@ def run_tools(tool_configs: Collection[ToolConfig], path: str, max_workers: int
|
|
|
141
141
|
raw_result = run_tool(tool_config, path)
|
|
142
142
|
tr = tool_config.parser_class().parse(raw_result)
|
|
143
143
|
tr.duration_s = time.perf_counter() - t0
|
|
144
|
-
return tool_config.
|
|
144
|
+
return tool_config.order, tr
|
|
145
145
|
|
|
146
146
|
if not tool_configs:
|
|
147
147
|
return []
|
|
148
148
|
t_start = time.perf_counter()
|
|
149
149
|
prioritized: list[tuple[int, ToolResult]] = []
|
|
150
|
+
if early_exit:
|
|
151
|
+
for tool_config in sorted(tool_configs, key=lambda tc: tc.order):
|
|
152
|
+
try:
|
|
153
|
+
prioritized.append(_run_and_parse(tool_config))
|
|
154
|
+
except Exception as exc:
|
|
155
|
+
log.error(f"{tool_config.name} generated an exception: {exc}")
|
|
156
|
+
break
|
|
157
|
+
_, tr = prioritized[-1]
|
|
158
|
+
if tr.metrics and min(tr.metrics.values()) < tool_config.error_threshold:
|
|
159
|
+
break
|
|
160
|
+
log.info(f"run_tools elapsed: {time.perf_counter() - t_start:.2f}s")
|
|
161
|
+
return [tr for _, tr in sorted(prioritized)]
|
|
150
162
|
with ThreadPoolExecutor(max_workers=max_workers or len(tool_configs)) as executor:
|
|
151
163
|
future_to_tool = {
|
|
152
164
|
executor.submit(_run_and_parse, tool_config): tool_config
|
py_cq/llm_formatter.py
CHANGED
py_cq/localtypes.py
CHANGED
|
@@ -10,13 +10,13 @@ from typing import Any
|
|
|
10
10
|
|
|
11
11
|
@dataclass
|
|
12
12
|
class ToolConfig:
|
|
13
|
-
"""Represents the configuration for an analysis tool, including its name, command, parser class, context path,
|
|
13
|
+
"""Represents the configuration for an analysis tool, including its name, command, parser class, context path, order, and thresholds for warnings and errors."""
|
|
14
14
|
|
|
15
15
|
name: str # e.g., "pytest", "coverage", "pydocstyle"
|
|
16
16
|
command: str # The command to execute (can include placeholders)
|
|
17
17
|
parser_class: Callable # Name of the parser class to use
|
|
18
18
|
context_path: str = "" # Path to project or file
|
|
19
|
-
|
|
19
|
+
order: int = 5 # 1=first (compilation), 11=last (style)
|
|
20
20
|
warning_threshold: float = 0.7 # Yellow warning if below this
|
|
21
21
|
error_threshold: float = 0.5 # Red error if below this
|
|
22
22
|
run_in_target_env: bool = False # If True, run in target project's env via uv
|
|
@@ -73,11 +73,11 @@ class ToolResult:
|
|
|
73
73
|
self.metrics = {}
|
|
74
74
|
|
|
75
75
|
def to_dict(self) -> dict:
|
|
76
|
-
"""Returns a dictionary containing the metrics, details, and
|
|
76
|
+
"""Returns a dictionary containing the tool name, metrics, details, and duration."""
|
|
77
77
|
return {
|
|
78
|
+
"tool_name": self.raw.tool_name,
|
|
78
79
|
"metrics": self.metrics,
|
|
79
80
|
"details": self.details,
|
|
80
|
-
"raw": self.raw.to_dict(),
|
|
81
81
|
"duration_s": self.duration_s,
|
|
82
82
|
}
|
|
83
83
|
|
py_cq/parsers/halsteadparser.py
CHANGED
py_cq/parsers/pytestparser.py
CHANGED
|
@@ -67,6 +67,14 @@ class PytestParser(AbstractParser):
|
|
|
67
67
|
num_tests += 1
|
|
68
68
|
if test_status == "PASSED":
|
|
69
69
|
passed_tests += 1
|
|
70
|
+
if num_tests == 0:
|
|
71
|
+
# No individual test lines found (e.g. non-verbose output);
|
|
72
|
+
# fall back to parsing the pytest summary line.
|
|
73
|
+
summary = re.search(r"(\d+) passed(?:.*?(\d+) failed)?", raw_result.stdout)
|
|
74
|
+
if summary:
|
|
75
|
+
passed_tests = int(summary.group(1))
|
|
76
|
+
failed_tests = int(summary.group(2)) if summary.group(2) else 0
|
|
77
|
+
num_tests = passed_tests + failed_tests
|
|
70
78
|
tr.metrics["tests"] = passed_tests / num_tests if num_tests else 0
|
|
71
79
|
tr.details = tests_found
|
|
72
80
|
return tr
|
py_cq/tool_registry.py
CHANGED
|
@@ -24,7 +24,7 @@ def load_tool_configs() -> dict[str, ToolConfig]:
|
|
|
24
24
|
name=tool_data["name"],
|
|
25
25
|
command=tool_data["command"],
|
|
26
26
|
parser_class=parser_class,
|
|
27
|
-
|
|
27
|
+
order=tool_data["order"],
|
|
28
28
|
warning_threshold=tool_data["warning_threshold"],
|
|
29
29
|
error_threshold=tool_data["error_threshold"],
|
|
30
30
|
run_in_target_env=tool_data.get("run_in_target_env", False),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-code-quality
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
4
4
|
Summary: Python Code Quality Analysis Tool - feed the results from 11 CQ tools straight into an LLM. Minimal tokens.
|
|
5
5
|
Project-URL: Homepage, https://github.com/rhiza-fr/py-cq
|
|
6
6
|
Project-URL: Repository, https://github.com/rhiza-fr/py-cq
|
|
@@ -34,7 +34,13 @@ The primary workflow is:
|
|
|
34
34
|
# get the single most critical defect as markdown
|
|
35
35
|
cq check . -o llm
|
|
36
36
|
```
|
|
37
|
-
|
|
37
|
+
Selects the single most critical defect using this priority order:
|
|
38
|
+
|
|
39
|
+
1. **Severity** — tools with score below `error_threshold` come before those only below `warning_threshold`
|
|
40
|
+
2. **Order** — among tools at the same severity, lower-order tools win (compile before lint before style)
|
|
41
|
+
3. **Score** — among ties, the lower score wins
|
|
42
|
+
|
|
43
|
+
The code context is expanded if available.
|
|
38
44
|
```md
|
|
39
45
|
`data/problems/travelling_salesman/ts_bad.py:21` — **F841**: Local variable `unused_variable` is assigned to but never used
|
|
40
46
|
|
|
@@ -51,8 +57,10 @@ Please fix only this issue. After fixing, run `cq check . -o llm` to verify.
|
|
|
51
57
|
```
|
|
52
58
|
Feed to an LLM with edit tools and repeat until there are no issues, e.g.
|
|
53
59
|
|
|
54
|
-
```
|
|
60
|
+
```python
|
|
55
61
|
cq check . -o llm | claude -p "fix this"
|
|
62
|
+
# or
|
|
63
|
+
cq check . -o llm | ollama gpt-oss:20b "Explain how to fix this"
|
|
56
64
|
```
|
|
57
65
|
|
|
58
66
|
## Install
|
|
@@ -69,9 +77,9 @@ uv tool install .
|
|
|
69
77
|
|
|
70
78
|
## Tools
|
|
71
79
|
|
|
72
|
-
These tools are run in **parallel
|
|
80
|
+
These tools are run in **parallel** except when looking for the first error in -o llm mode:
|
|
73
81
|
|
|
74
|
-
|
|
|
82
|
+
| Order | Tool | Measures |
|
|
75
83
|
|----------|------|----------|
|
|
76
84
|
| 1 | compileall | Syntax errors |
|
|
77
85
|
| 2 | bandit | Security vulnerabilities |
|
|
@@ -91,31 +99,15 @@ Diskcache is used to cache tool output for lightning fast re-runs. Sane defaults
|
|
|
91
99
|
## Usage
|
|
92
100
|
|
|
93
101
|
```bash
|
|
94
|
-
|
|
95
|
-
cq check -o llm
|
|
96
|
-
|
|
97
|
-
#
|
|
98
|
-
cq check .
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
cq check . -
|
|
102
|
-
|
|
103
|
-
# Full JSON output, including raw test results
|
|
104
|
-
cq check . -o json
|
|
105
|
-
|
|
106
|
-
# Explicit path
|
|
107
|
-
cq check path/to/project/
|
|
108
|
-
cq check path/to/file.py
|
|
109
|
-
|
|
110
|
-
# Run sequentially if you like things slow
|
|
111
|
-
cq check . --workers 1
|
|
112
|
-
|
|
113
|
-
# Clear cached results before running (rarely needed)
|
|
114
|
-
cq check . --clear-cache
|
|
115
|
-
|
|
116
|
-
# Show effective tool configuration (thresholds, enabled/disabled status)
|
|
117
|
-
cq config
|
|
118
|
-
cq config path/to/project/
|
|
102
|
+
cq check . # Table overview of scores for humans
|
|
103
|
+
cq check -o llm # Top defect as markdown for LLMs
|
|
104
|
+
cq check . -o score # Numeric score only for CI
|
|
105
|
+
cq check . -o json # Detailed parsed JSON output for jq
|
|
106
|
+
cq check . -o raw # Raw tool output for debug
|
|
107
|
+
cq check path/to/file.py # Just one file (skips pytest and coverage)
|
|
108
|
+
cq check . --workers 1 # Run sequentially if you like things slow
|
|
109
|
+
cq check . --clear-cache # Clear cached results before running (rarely needed)
|
|
110
|
+
cq config path/to/project/ # Show effective tool configuration
|
|
119
111
|
```
|
|
120
112
|
|
|
121
113
|
## Table output
|
|
@@ -160,30 +152,36 @@ cq config path/to/project/
|
|
|
160
152
|
```
|
|
161
153
|
|
|
162
154
|
```json
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
},
|
|
169
|
-
"details": {},
|
|
170
|
-
"raw": {
|
|
171
|
-
"tool_name": "compile",
|
|
172
|
-
"command": ".venv\\Scripts\\python.exe -m compileall -r 10 -j 8 . -x .*venv",
|
|
173
|
-
"stdout": "Compiling './src/project/file.py'...",
|
|
174
|
-
"stderr": "",
|
|
175
|
-
"return_code": 0,
|
|
176
|
-
"timestamp": "2026-02-19 05:03:11"
|
|
177
|
-
},
|
|
178
|
-
"duration_s": 0.08294440002646297
|
|
155
|
+
[
|
|
156
|
+
{
|
|
157
|
+
"tool_name": "compile",
|
|
158
|
+
"metrics": {
|
|
159
|
+
"compile": 1.0
|
|
179
160
|
},
|
|
180
|
-
{
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
161
|
+
"details": {},
|
|
162
|
+
"duration_s": 0.05611889995634556
|
|
163
|
+
}
|
|
164
|
+
...
|
|
165
|
+
]
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Raw output
|
|
169
|
+
```bash
|
|
170
|
+
> cq check -o raw
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
[
|
|
175
|
+
{
|
|
176
|
+
"tool_name": "compile",
|
|
177
|
+
"command": "D:\\ai\\py-cq\\.venv\\Scripts\\python.exe -m compileall -r 10 -j 8 . -x .*venv",
|
|
178
|
+
"stdout": "",
|
|
179
|
+
"stderr": "",
|
|
180
|
+
"return_code": 0,
|
|
181
|
+
"timestamp": "2026-02-20 10:01:22"
|
|
182
|
+
}
|
|
183
|
+
...
|
|
184
|
+
]
|
|
187
185
|
```
|
|
188
186
|
|
|
189
187
|
## Configuration
|
|
@@ -213,7 +211,7 @@ tools:
|
|
|
213
211
|
name: "compile"
|
|
214
212
|
command: "{python} -m compileall -r 10 -j 8 {context_path} -x .*venv"
|
|
215
213
|
parser: "CompileParser"
|
|
216
|
-
|
|
214
|
+
order: 1
|
|
217
215
|
warning_threshold: 0.9999
|
|
218
216
|
error_threshold: 0.9999
|
|
219
217
|
|
|
@@ -221,7 +219,7 @@ tools:
|
|
|
221
219
|
name: "bandit"
|
|
222
220
|
command: "{python} -m bandit -r {context_path} -f json -q -s B101 --severity-level medium --exclude {input_path_posix}/.venv,{input_path_posix}/tests"
|
|
223
221
|
parser: "BanditParser"
|
|
224
|
-
|
|
222
|
+
order: 2
|
|
225
223
|
warning_threshold: 0.9999
|
|
226
224
|
error_threshold: 0.8
|
|
227
225
|
|
|
@@ -229,7 +227,7 @@ tools:
|
|
|
229
227
|
name: "ruff"
|
|
230
228
|
command: "{python} -m ruff check --output-format concise --no-cache {context_path}"
|
|
231
229
|
parser: "RuffParser"
|
|
232
|
-
|
|
230
|
+
order: 3
|
|
233
231
|
warning_threshold: 0.9999
|
|
234
232
|
error_threshold: 0.9
|
|
235
233
|
|
|
@@ -237,7 +235,7 @@ tools:
|
|
|
237
235
|
name: "ty"
|
|
238
236
|
command: "{python} -m ty check --output-format concise --color never {context_path}"
|
|
239
237
|
parser: "TyParser"
|
|
240
|
-
|
|
238
|
+
order: 4
|
|
241
239
|
warning_threshold: 0.9999
|
|
242
240
|
error_threshold: 0.8
|
|
243
241
|
run_in_target_env: true
|
|
@@ -248,16 +246,16 @@ tools:
|
|
|
248
246
|
name: "pytest"
|
|
249
247
|
command: "{python} -m pytest -v {context_path}"
|
|
250
248
|
parser: "PytestParser"
|
|
251
|
-
|
|
249
|
+
order: 5
|
|
252
250
|
warning_threshold: 0.7
|
|
253
251
|
error_threshold: 0.5
|
|
254
252
|
run_in_target_env: true
|
|
255
253
|
|
|
256
254
|
coverage:
|
|
257
255
|
name: "coverage"
|
|
258
|
-
command: "{python} -m coverage run -m pytest {context_path} && {python} -m coverage report"
|
|
256
|
+
command: "{python} -m coverage run --omit=*/tests/*,*/test_*.py -m pytest {context_path} && {python} -m coverage report --omit=*/tests/*,*/test_*.py"
|
|
259
257
|
parser: "CoverageParser"
|
|
260
|
-
|
|
258
|
+
order: 6
|
|
261
259
|
warning_threshold: 0.9
|
|
262
260
|
error_threshold: 0.5
|
|
263
261
|
run_in_target_env: true
|
|
@@ -269,7 +267,7 @@ tools:
|
|
|
269
267
|
name: "radon cc"
|
|
270
268
|
command: "{python} -m radon cc --json {context_path}"
|
|
271
269
|
parser: "ComplexityParser"
|
|
272
|
-
|
|
270
|
+
order: 7
|
|
273
271
|
warning_threshold: 0.6
|
|
274
272
|
error_threshold: 0.4
|
|
275
273
|
|
|
@@ -277,7 +275,7 @@ tools:
|
|
|
277
275
|
name: "radon mi"
|
|
278
276
|
command: "{python} -m radon mi -s --json {context_path}"
|
|
279
277
|
parser: "MaintainabilityParser"
|
|
280
|
-
|
|
278
|
+
order: 8
|
|
281
279
|
warning_threshold: 0.6
|
|
282
280
|
error_threshold: 0.4
|
|
283
281
|
|
|
@@ -285,7 +283,7 @@ tools:
|
|
|
285
283
|
name: "radon hal"
|
|
286
284
|
command: "{python} -m radon hal -f --json {context_path}"
|
|
287
285
|
parser: "HalsteadParser"
|
|
288
|
-
|
|
286
|
+
order: 9
|
|
289
287
|
warning_threshold: 0.5
|
|
290
288
|
error_threshold: 0.3
|
|
291
289
|
|
|
@@ -293,7 +291,7 @@ tools:
|
|
|
293
291
|
name: "vulture"
|
|
294
292
|
command: "{python} -m vulture {context_path} --min-confidence 80 --exclude .venv,dist,.*_cache,docs,.git"
|
|
295
293
|
parser: "VultureParser"
|
|
296
|
-
|
|
294
|
+
order: 10
|
|
297
295
|
warning_threshold: 0.9999
|
|
298
296
|
error_threshold: 0.8
|
|
299
297
|
|
|
@@ -301,7 +299,7 @@ tools:
|
|
|
301
299
|
name: "interrogate"
|
|
302
300
|
command: "{python} -m interrogate {context_path} -v --fail-under 0"
|
|
303
301
|
parser: "InterrogateParser"
|
|
304
|
-
|
|
302
|
+
order: 11
|
|
305
303
|
warning_threshold: 0.8
|
|
306
304
|
error_threshold: 0.3
|
|
307
305
|
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
py_cq/__init__.py,sha256=rS7kf1RU1zZskvJlkbZaMqEpdRYPspwDPAFbxzF3tXg,373
|
|
2
|
-
py_cq/cli.py,sha256=
|
|
2
|
+
py_cq/cli.py,sha256=9rNdLdU2mcZVz3qdkczO4Rs_PU0-brZMmj5wJfv-Jcs,8688
|
|
3
3
|
py_cq/context_hash.py,sha256=h-i7Rhd7AUfLv9SkQvE79bjJvTsm_ZwoVwSmUKXWmfM,2977
|
|
4
|
-
py_cq/execution_engine.py,sha256=
|
|
5
|
-
py_cq/llm_formatter.py,sha256=
|
|
6
|
-
py_cq/localtypes.py,sha256=
|
|
4
|
+
py_cq/execution_engine.py,sha256=Q7Z8iibkE_E9VfkbUdnI_g5wA8GdwDbnJI4Mex-V8mE,7416
|
|
5
|
+
py_cq/llm_formatter.py,sha256=EdUMhvsnPLplSSUKDknMHiaLdKsd9B6aH-tTdpxukdY,1574
|
|
6
|
+
py_cq/localtypes.py,sha256=_PAx-F0cj03r_3YR1cyR9ilYYmYxUC14TkRtgLjH-Rc,5927
|
|
7
7
|
py_cq/main.py,sha256=VKoXI8R8rB2fEROBYoTVURfinLqyh8XTNIIWAOtH7dw,380
|
|
8
8
|
py_cq/metric_aggregator.py,sha256=M2ymo62S7p7qPUqjjoiPg4IVyXQhLMuTr9-jxLiFjCY,853
|
|
9
9
|
py_cq/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
py_cq/tool_registry.py,sha256=
|
|
10
|
+
py_cq/tool_registry.py,sha256=Ov5kQIRc5C5vkAq5Nc2Otp5kYiQzJuK5_nA-ZkY_-NQ,1529
|
|
11
11
|
py_cq/config/__init__.py,sha256=f0wc51O_3kGDTZUnCbGv8_zWnC5yYGl4NWcf2buSImQ,670
|
|
12
|
-
py_cq/config/tools.yaml,sha256=
|
|
12
|
+
py_cq/config/tools.yaml,sha256=cNs4h4sIJA-j28QhEFG0uWL9ELaPy_z8BNo4l5F3is4,2553
|
|
13
13
|
py_cq/parsers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
14
|
py_cq/parsers/banditparser.py,sha256=vj23tTbipaeVkhS_ldWI7GrpHGwlIkOuaEgszkrjzh0,2277
|
|
15
15
|
py_cq/parsers/common.py,sha256=lc9Chtr3H5l3vTk-vRVhptQVJfOeLax0UWTRjhA9IOU,4044
|
|
16
16
|
py_cq/parsers/compileparser.py,sha256=mVY8qh1oZQ8n9GJLW2ruF9j89G5GuxWb7fb6JeogTJ4,6207
|
|
17
17
|
py_cq/parsers/complexityparser.py,sha256=2t1-wmNjUu65fULcIm5jcgv7ZLWwjakyiY_r-Fx1QQg,3983
|
|
18
18
|
py_cq/parsers/coverageparser.py,sha256=xDNlLNEsA0U3z4GV02iEq97IL90-UJAQrhMlFzpIdy0,4013
|
|
19
|
-
py_cq/parsers/halsteadparser.py,sha256=
|
|
19
|
+
py_cq/parsers/halsteadparser.py,sha256=9z_abpPPuclUQBgq4P6u2vIfIB7ZShX2NbFnubTatqI,8980
|
|
20
20
|
py_cq/parsers/interrogateparser.py,sha256=eMROINtyZE2eHrRxVU0jA-nYTdvr0PZ8iERVn7kPH5o,2197
|
|
21
21
|
py_cq/parsers/maintainabilityparser.py,sha256=Ax0ZFA6zzqYIWZH1hP1_GUtdVn2LIJ8SKWtqVNdszYs,3411
|
|
22
|
-
py_cq/parsers/pytestparser.py,sha256=
|
|
22
|
+
py_cq/parsers/pytestparser.py,sha256=ERgS1aTTi7aB-Xk_Y9Xpo9h5jT9n0q3_vAfHCZwBTFE,4539
|
|
23
23
|
py_cq/parsers/ruffparser.py,sha256=Wgch9rDkR-6tJlfhDfG1CXXEZu0Gfk0qRpsI3KzjCZU,2226
|
|
24
24
|
py_cq/parsers/typarser.py,sha256=u7ktoH0TzmhB2saCJF1iY1LkfGui5ami2leLlYSCcns,2446
|
|
25
25
|
py_cq/parsers/vultureparser.py,sha256=X2fen6yQu-r_zoRt1qKfIGlGZKORkHCiZE4BFlxtzdE,1946
|
|
26
|
-
python_code_quality-0.1.
|
|
27
|
-
python_code_quality-0.1.
|
|
28
|
-
python_code_quality-0.1.
|
|
29
|
-
python_code_quality-0.1.
|
|
30
|
-
python_code_quality-0.1.
|
|
26
|
+
python_code_quality-0.1.8.dist-info/METADATA,sha256=2-E2SuWhsQMwYtv4NERKmE9CajsglC81tZY5DPPefrc,10266
|
|
27
|
+
python_code_quality-0.1.8.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
28
|
+
python_code_quality-0.1.8.dist-info/entry_points.txt,sha256=j5Q_gGr0b7389lddt1JlZ7gcL4Z7RHxuDhij_G-IhBY,39
|
|
29
|
+
python_code_quality-0.1.8.dist-info/licenses/LICENSE,sha256=Bpuh8tbf37so8M5NtRGTLmT5ue7diJ17223L9f9nsT0,1086
|
|
30
|
+
python_code_quality-0.1.8.dist-info/RECORD,,
|
|
File without changes
|
{python_code_quality-0.1.7.dist-info → python_code_quality-0.1.8.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{python_code_quality-0.1.7.dist-info → python_code_quality-0.1.8.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|