complexipy 4.0.2__tar.gz → 4.2.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.
- {complexipy-4.0.2 → complexipy-4.2.0}/Cargo.lock +1 -1
- {complexipy-4.0.2 → complexipy-4.2.0}/Cargo.toml +1 -1
- {complexipy-4.0.2 → complexipy-4.2.0}/PKG-INFO +33 -4
- {complexipy-4.0.2 → complexipy-4.2.0}/README.md +32 -3
- {complexipy-4.0.2 → complexipy-4.2.0}/complexipy/__init__.py +2 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/complexipy/main.py +31 -1
- {complexipy-4.0.2 → complexipy-4.2.0}/complexipy/utils.py +33 -7
- {complexipy-4.0.2 → complexipy-4.2.0}/complexipy.toml +2 -1
- {complexipy-4.0.2 → complexipy-4.2.0}/docs/index.md +28 -2
- {complexipy-4.0.2 → complexipy-4.2.0}/src/cognitive_complexity/mod.rs +118 -37
- {complexipy-4.0.2 → complexipy-4.2.0}/src/cognitive_complexity/utils.rs +25 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/uv.lock +192 -146
- {complexipy-4.0.2 → complexipy-4.2.0}/vscode/complexipy/CHANGELOG.md +11 -1
- {complexipy-4.0.2 → complexipy-4.2.0}/vscode/complexipy/README.md +9 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/vscode/complexipy/package.json +2 -2
- {complexipy-4.0.2 → complexipy-4.2.0}/.pre-commit-config.yaml +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/LICENSE +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/build-wasm.sh +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/complexipy/_complexipy.pyi +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/complexipy/api.py +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/complexipy/error_handlers.py +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/complexipy/py.typed +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/complexipy/types.py +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/docs/img/complexipy_icon.svg +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/mkdocs.yml +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/pyproject.toml +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/serve-web-version.sh +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/src/classes/mod.rs +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/src/lib.rs +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/src/wasm.rs +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/vscode/complexipy/.vscode-test.mjs +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/vscode/complexipy/.vscodeignore +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/vscode/complexipy/LICENSE +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/vscode/complexipy/eslint.config.mjs +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/vscode/complexipy/extension.js +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/vscode/complexipy/img/complexipy.png +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/vscode/complexipy/img/complexipy_icon.png +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/vscode/complexipy/img/complexipy_icon.svg +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/vscode/complexipy/jsconfig.json +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/vscode/complexipy/package-lock.json +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/vscode/complexipy/test/extension.test.js +0 -0
- {complexipy-4.0.2 → complexipy-4.2.0}/vscode/complexipy/test/statusbar.test.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: complexipy
|
|
3
|
-
Version: 4.0
|
|
3
|
+
Version: 4.2.0
|
|
4
4
|
Classifier: Development Status :: 5 - Production/Stable
|
|
5
5
|
Classifier: Environment :: Console
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -33,7 +33,7 @@ Project-URL: Repository, https://github.com/rohaquinlop/complexipy
|
|
|
33
33
|
# complexipy
|
|
34
34
|
|
|
35
35
|
<div align="center">
|
|
36
|
-
<img src="docs/img/complexipy_icon.svg" alt="complexipy" width="120" height="120">
|
|
36
|
+
<img src="https://raw.githubusercontent.com/rohaquinlop/complexipy/refs/heads/main/docs/img/complexipy_icon.svg" alt="complexipy" width="120" height="120">
|
|
37
37
|
|
|
38
38
|
<p><em>Blazingly fast cognitive complexity analysis for Python, written in Rust.</em></p>
|
|
39
39
|
|
|
@@ -86,6 +86,9 @@ complexipy . --max-complexity-allowed 10
|
|
|
86
86
|
|
|
87
87
|
# Save results to JSON/CSV
|
|
88
88
|
complexipy . --output-json --output-csv
|
|
89
|
+
|
|
90
|
+
# Analyze current directory while excluding specific files
|
|
91
|
+
complexipy . --exclude path/to/exclude.py --exclude path/to/other/exclude.py
|
|
89
92
|
```
|
|
90
93
|
|
|
91
94
|
### Python API
|
|
@@ -168,6 +171,7 @@ quiet = false
|
|
|
168
171
|
ignore-complexity = false
|
|
169
172
|
details = "normal"
|
|
170
173
|
sort = "asc"
|
|
174
|
+
exclude = []
|
|
171
175
|
|
|
172
176
|
[output]
|
|
173
177
|
csv = true
|
|
@@ -183,6 +187,7 @@ quiet = false
|
|
|
183
187
|
ignore-complexity = false
|
|
184
188
|
details = "normal"
|
|
185
189
|
sort = "asc"
|
|
190
|
+
exclude = []
|
|
186
191
|
|
|
187
192
|
[tool.complexipy.output]
|
|
188
193
|
csv = true
|
|
@@ -193,6 +198,7 @@ json = true
|
|
|
193
198
|
|
|
194
199
|
| Flag | Description | Default |
|
|
195
200
|
|------|-------------|---------|
|
|
201
|
+
| `--exclude` | Exclude entries relative to each provided path. Entries resolve to existing directories (prefix match) or files (exact match). Non-existent entries are ignored. | |
|
|
196
202
|
| `--max-complexity-allowed` | Complexity threshold | `15` |
|
|
197
203
|
| `--output-json` | Save results as JSON | `false` |
|
|
198
204
|
| `--output-csv` | Save results as CSV | `false` |
|
|
@@ -200,6 +206,29 @@ json = true
|
|
|
200
206
|
| `--sort <asc\|desc\|name>` | Sort results | `asc` |
|
|
201
207
|
| `--quiet` | Suppress output | `false` |
|
|
202
208
|
| `--ignore-complexity` | Don't exit with error on threshold breach | `false` |
|
|
209
|
+
| `--version` | Show installed complexipy version and exit | - |
|
|
210
|
+
|
|
211
|
+
Example:
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
# Exclude only top-level 'tests' directory under the provided root
|
|
215
|
+
complexipy . --exclude tests
|
|
216
|
+
# This will not exclude './complexipy/utils.py' if you pass '--exclude utils' at repo root,
|
|
217
|
+
# because there is no './utils' directory or file at that level.
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Inline Ignores
|
|
221
|
+
|
|
222
|
+
You can explicitly ignore a known complex function inline, similar to Ruff's `C901` ignores:
|
|
223
|
+
|
|
224
|
+
```python
|
|
225
|
+
def legacy_adapter(x, y): # noqa: complexipy (safe wrapper)
|
|
226
|
+
if x and y:
|
|
227
|
+
return x + y
|
|
228
|
+
return 0
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Place `# noqa: complexipy` on the function definition line (or the line immediately above). An optional reason can be provided in parentheses or plain text, it’s ignored by the parser.
|
|
203
232
|
|
|
204
233
|
## API Reference
|
|
205
234
|
|
|
@@ -225,11 +254,11 @@ FunctionComplexity:
|
|
|
225
254
|
|
|
226
255
|
<div align="center">
|
|
227
256
|
|
|
257
|
+
<sub>Inspired by the <a href="https://www.sonarsource.com/resources/cognitive-complexity/">Cognitive Complexity</a> research by SonarSource, G. Ann Campbell</sub>
|
|
258
|
+
|
|
228
259
|
**[Documentation](https://rohaquinlop.github.io/complexipy/) • [PyPI](https://pypi.org/project/complexipy/) • [GitHub](https://github.com/rohaquinlop/complexipy)**
|
|
229
260
|
|
|
230
261
|
<sub>Built with ❤️ by <a href="https://github.com/rohaquinlop">@rohaquinlop</a> and <a href="https://github.com/rohaquinlop/complexipy/graphs/contributors">contributors</a></sub>
|
|
231
262
|
|
|
232
|
-
<sub>Inspired by the <a href="https://www.sonarsource.com/resources/cognitive-complexity/">Cognitive Complexity</a> research by SonarSource</sub>
|
|
233
|
-
|
|
234
263
|
</div>
|
|
235
264
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# complexipy
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
|
-
<img src="docs/img/complexipy_icon.svg" alt="complexipy" width="120" height="120">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/rohaquinlop/complexipy/refs/heads/main/docs/img/complexipy_icon.svg" alt="complexipy" width="120" height="120">
|
|
5
5
|
|
|
6
6
|
<p><em>Blazingly fast cognitive complexity analysis for Python, written in Rust.</em></p>
|
|
7
7
|
|
|
@@ -54,6 +54,9 @@ complexipy . --max-complexity-allowed 10
|
|
|
54
54
|
|
|
55
55
|
# Save results to JSON/CSV
|
|
56
56
|
complexipy . --output-json --output-csv
|
|
57
|
+
|
|
58
|
+
# Analyze current directory while excluding specific files
|
|
59
|
+
complexipy . --exclude path/to/exclude.py --exclude path/to/other/exclude.py
|
|
57
60
|
```
|
|
58
61
|
|
|
59
62
|
### Python API
|
|
@@ -136,6 +139,7 @@ quiet = false
|
|
|
136
139
|
ignore-complexity = false
|
|
137
140
|
details = "normal"
|
|
138
141
|
sort = "asc"
|
|
142
|
+
exclude = []
|
|
139
143
|
|
|
140
144
|
[output]
|
|
141
145
|
csv = true
|
|
@@ -151,6 +155,7 @@ quiet = false
|
|
|
151
155
|
ignore-complexity = false
|
|
152
156
|
details = "normal"
|
|
153
157
|
sort = "asc"
|
|
158
|
+
exclude = []
|
|
154
159
|
|
|
155
160
|
[tool.complexipy.output]
|
|
156
161
|
csv = true
|
|
@@ -161,6 +166,7 @@ json = true
|
|
|
161
166
|
|
|
162
167
|
| Flag | Description | Default |
|
|
163
168
|
|------|-------------|---------|
|
|
169
|
+
| `--exclude` | Exclude entries relative to each provided path. Entries resolve to existing directories (prefix match) or files (exact match). Non-existent entries are ignored. | |
|
|
164
170
|
| `--max-complexity-allowed` | Complexity threshold | `15` |
|
|
165
171
|
| `--output-json` | Save results as JSON | `false` |
|
|
166
172
|
| `--output-csv` | Save results as CSV | `false` |
|
|
@@ -168,6 +174,29 @@ json = true
|
|
|
168
174
|
| `--sort <asc\|desc\|name>` | Sort results | `asc` |
|
|
169
175
|
| `--quiet` | Suppress output | `false` |
|
|
170
176
|
| `--ignore-complexity` | Don't exit with error on threshold breach | `false` |
|
|
177
|
+
| `--version` | Show installed complexipy version and exit | - |
|
|
178
|
+
|
|
179
|
+
Example:
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
# Exclude only top-level 'tests' directory under the provided root
|
|
183
|
+
complexipy . --exclude tests
|
|
184
|
+
# This will not exclude './complexipy/utils.py' if you pass '--exclude utils' at repo root,
|
|
185
|
+
# because there is no './utils' directory or file at that level.
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Inline Ignores
|
|
189
|
+
|
|
190
|
+
You can explicitly ignore a known complex function inline, similar to Ruff's `C901` ignores:
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
def legacy_adapter(x, y): # noqa: complexipy (safe wrapper)
|
|
194
|
+
if x and y:
|
|
195
|
+
return x + y
|
|
196
|
+
return 0
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Place `# noqa: complexipy` on the function definition line (or the line immediately above). An optional reason can be provided in parentheses or plain text, it’s ignored by the parser.
|
|
171
200
|
|
|
172
201
|
## API Reference
|
|
173
202
|
|
|
@@ -193,10 +222,10 @@ FunctionComplexity:
|
|
|
193
222
|
|
|
194
223
|
<div align="center">
|
|
195
224
|
|
|
225
|
+
<sub>Inspired by the <a href="https://www.sonarsource.com/resources/cognitive-complexity/">Cognitive Complexity</a> research by SonarSource, G. Ann Campbell</sub>
|
|
226
|
+
|
|
196
227
|
**[Documentation](https://rohaquinlop.github.io/complexipy/) • [PyPI](https://pypi.org/project/complexipy/) • [GitHub](https://github.com/rohaquinlop/complexipy)**
|
|
197
228
|
|
|
198
229
|
<sub>Built with ❤️ by <a href="https://github.com/rohaquinlop">@rohaquinlop</a> and <a href="https://github.com/rohaquinlop/complexipy/graphs/contributors">contributors</a></sub>
|
|
199
230
|
|
|
200
|
-
<sub>Inspired by the <a href="https://www.sonarsource.com/resources/cognitive-complexity/">Cognitive Complexity</a> research by SonarSource</sub>
|
|
201
|
-
|
|
202
231
|
</div>
|
|
@@ -25,6 +25,10 @@ from typing import (
|
|
|
25
25
|
)
|
|
26
26
|
import time
|
|
27
27
|
import typer
|
|
28
|
+
from importlib.metadata import (
|
|
29
|
+
PackageNotFoundError,
|
|
30
|
+
version as pkg_version,
|
|
31
|
+
)
|
|
28
32
|
|
|
29
33
|
app = typer.Typer(name="complexipy")
|
|
30
34
|
console = Console()
|
|
@@ -32,12 +36,27 @@ INVOCATION_PATH = os.getcwd()
|
|
|
32
36
|
TOML_CONFIG = get_complexipy_toml_config(INVOCATION_PATH)
|
|
33
37
|
|
|
34
38
|
|
|
39
|
+
def _version_callback(value: bool):
|
|
40
|
+
if value:
|
|
41
|
+
try:
|
|
42
|
+
console.print(pkg_version("complexipy"))
|
|
43
|
+
except PackageNotFoundError:
|
|
44
|
+
console.print("Unknown version")
|
|
45
|
+
raise typer.Exit()
|
|
46
|
+
|
|
47
|
+
|
|
35
48
|
@app.command()
|
|
36
49
|
def main(
|
|
37
50
|
paths: Optional[List[str]] = typer.Argument(
|
|
38
51
|
None,
|
|
39
52
|
help="Paths to the directories or files to analyze, it can be a local paths or a git repository URL.",
|
|
40
53
|
),
|
|
54
|
+
exclude: Optional[List[str]] = typer.Option(
|
|
55
|
+
None,
|
|
56
|
+
"--exclude",
|
|
57
|
+
"-e",
|
|
58
|
+
help="Paths to the directories or files to exclude.",
|
|
59
|
+
),
|
|
41
60
|
max_complexity_allowed: Optional[int] = typer.Option(
|
|
42
61
|
None,
|
|
43
62
|
"--max-complexity-allowed",
|
|
@@ -80,6 +99,13 @@ def main(
|
|
|
80
99
|
"-j",
|
|
81
100
|
help="Output the results to a JSON file.",
|
|
82
101
|
),
|
|
102
|
+
version: bool = typer.Option( # type: ignore[assignment]
|
|
103
|
+
False,
|
|
104
|
+
"--version",
|
|
105
|
+
help="Show the complexipy version and exit.",
|
|
106
|
+
callback=_version_callback,
|
|
107
|
+
is_eager=True,
|
|
108
|
+
),
|
|
83
109
|
):
|
|
84
110
|
(
|
|
85
111
|
paths,
|
|
@@ -90,6 +116,7 @@ def main(
|
|
|
90
116
|
sort,
|
|
91
117
|
output_csv,
|
|
92
118
|
output_json,
|
|
119
|
+
exclude,
|
|
93
120
|
) = get_arguments_value(
|
|
94
121
|
TOML_CONFIG,
|
|
95
122
|
paths,
|
|
@@ -100,6 +127,7 @@ def main(
|
|
|
100
127
|
sort,
|
|
101
128
|
output_csv,
|
|
102
129
|
output_json,
|
|
130
|
+
exclude,
|
|
103
131
|
)
|
|
104
132
|
|
|
105
133
|
if not quiet:
|
|
@@ -108,7 +136,9 @@ def main(
|
|
|
108
136
|
else:
|
|
109
137
|
console.rule(":octopus: complexipy")
|
|
110
138
|
start_time = time.time()
|
|
111
|
-
result: Tuple[List[FileComplexity], List[str]] = _complexipy.main(
|
|
139
|
+
result: Tuple[List[FileComplexity], List[str]] = _complexipy.main(
|
|
140
|
+
paths, quiet, exclude
|
|
141
|
+
)
|
|
112
142
|
files_complexities, failed_paths = result
|
|
113
143
|
execution_time = time.time() - start_time
|
|
114
144
|
output_csv_path = f"{INVOCATION_PATH}/complexipy.csv"
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import os
|
|
2
4
|
import sys
|
|
3
5
|
from complexipy.types import DetailTypes, Sort, TOMLType
|
|
@@ -35,11 +37,32 @@ def get_brain_icon():
|
|
|
35
37
|
return ":brain:"
|
|
36
38
|
|
|
37
39
|
|
|
38
|
-
def load_values_from_toml_key(value:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
def load_values_from_toml_key(key: str, value: TOMLType) -> TOMLType:
|
|
41
|
+
"""Normalize TOML values to expected runtime types.
|
|
42
|
+
|
|
43
|
+
- Convert `details` and `sort` string values to their Enum variants.
|
|
44
|
+
- Ensure `paths` and `exclude` are lists when provided as strings.
|
|
45
|
+
"""
|
|
46
|
+
if key == "details":
|
|
47
|
+
# Accept either Enum or string in TOML
|
|
48
|
+
if isinstance(value, DetailTypes):
|
|
49
|
+
return value
|
|
50
|
+
if isinstance(value, str):
|
|
51
|
+
return DetailTypes(value)
|
|
52
|
+
return value
|
|
53
|
+
|
|
54
|
+
if key == "sort":
|
|
55
|
+
if isinstance(value, Sort):
|
|
56
|
+
return value
|
|
57
|
+
if isinstance(value, str):
|
|
58
|
+
return Sort(value)
|
|
59
|
+
return value
|
|
60
|
+
|
|
61
|
+
if key in ("paths", "exclude"):
|
|
62
|
+
# Allow a single string, normalize to list for downstream processing
|
|
63
|
+
if isinstance(value, str):
|
|
64
|
+
return [value]
|
|
65
|
+
return value
|
|
43
66
|
|
|
44
67
|
return value
|
|
45
68
|
|
|
@@ -69,7 +92,7 @@ def load_toml_config(invocation_path: str, config_file_name: str) -> TOMLType |
|
|
|
69
92
|
return None
|
|
70
93
|
|
|
71
94
|
for key, value in data.items():
|
|
72
|
-
data[key] = load_values_from_toml_key(value)
|
|
95
|
+
data[key] = load_values_from_toml_key(key, value)
|
|
73
96
|
|
|
74
97
|
return data
|
|
75
98
|
|
|
@@ -125,7 +148,8 @@ def get_arguments_value(
|
|
|
125
148
|
sort_arg: Sort | None,
|
|
126
149
|
output_csv: bool | None,
|
|
127
150
|
output_json: bool | None,
|
|
128
|
-
|
|
151
|
+
exclude: List[str] | None,
|
|
152
|
+
) -> Tuple[List[str], int, bool, bool, DetailTypes, Sort, bool, bool, List[str]]:
|
|
129
153
|
paths = get_argument_value(toml_config, "paths", paths)
|
|
130
154
|
max_complexity_allowed = get_argument_value(
|
|
131
155
|
toml_config, "max-complexity-allowed", max_complexity_allowed, 15
|
|
@@ -138,6 +162,7 @@ def get_arguments_value(
|
|
|
138
162
|
sort_arg = get_argument_value(toml_config, "sort", sort_arg, Sort.asc)
|
|
139
163
|
output_csv = get_argument_value(toml_config, "output-csv", output_csv, False)
|
|
140
164
|
output_json = get_argument_value(toml_config, "output-json", output_json, False)
|
|
165
|
+
exclude = get_argument_value(toml_config, "exclude", exclude, [])
|
|
141
166
|
|
|
142
167
|
return (
|
|
143
168
|
paths,
|
|
@@ -148,6 +173,7 @@ def get_arguments_value(
|
|
|
148
173
|
sort_arg,
|
|
149
174
|
output_csv,
|
|
150
175
|
output_json,
|
|
176
|
+
exclude,
|
|
151
177
|
)
|
|
152
178
|
|
|
153
179
|
|
|
@@ -67,6 +67,10 @@ complexipy . --max-complexity-allowed 10
|
|
|
67
67
|
|
|
68
68
|
# Generate reports
|
|
69
69
|
complexipy . --output-json --output-csv
|
|
70
|
+
|
|
71
|
+
# Analyze current directory while excluding specific files
|
|
72
|
+
complexipy . --exclude file_to_exclude.py --exclude path/to/other/exclude.py
|
|
73
|
+
|
|
70
74
|
```
|
|
71
75
|
|
|
72
76
|
### Python API
|
|
@@ -131,6 +135,7 @@ quiet = false
|
|
|
131
135
|
ignore-complexity = false
|
|
132
136
|
details = "normal"
|
|
133
137
|
sort = "asc"
|
|
138
|
+
exclude = []
|
|
134
139
|
|
|
135
140
|
[output]
|
|
136
141
|
csv = true
|
|
@@ -148,6 +153,7 @@ quiet = false
|
|
|
148
153
|
ignore-complexity = false
|
|
149
154
|
details = "normal"
|
|
150
155
|
sort = "asc"
|
|
156
|
+
exclude = []
|
|
151
157
|
|
|
152
158
|
[tool.complexipy.output]
|
|
153
159
|
csv = true
|
|
@@ -161,6 +167,7 @@ json = true
|
|
|
161
167
|
|
|
162
168
|
| Option | Description | Default |
|
|
163
169
|
|--------|-------------|---------|
|
|
170
|
+
| `--exclude` | Exclude entries relative to each provided path. Entries resolve to existing directories (prefix match) or files (exact match). Non-existent entries are ignored. | |
|
|
164
171
|
| `--max-complexity-allowed <N>` | Complexity threshold for warnings | `15` |
|
|
165
172
|
| `--output-json` | Export results to JSON | `false` |
|
|
166
173
|
| `--output-csv` | Export results to CSV | `false` |
|
|
@@ -168,6 +175,7 @@ json = true
|
|
|
168
175
|
| `--sort <asc\|desc\|name>` | Sort results by complexity or name | `asc` |
|
|
169
176
|
| `--quiet` | Suppress terminal output | `false` |
|
|
170
177
|
| `--ignore-complexity` | Don't exit with error on threshold breach | `false` |
|
|
178
|
+
| `--version` | Show installed complexipy version and exit | - |
|
|
171
179
|
|
|
172
180
|
### Examples
|
|
173
181
|
|
|
@@ -180,11 +188,29 @@ complexipy . --max-complexity-allowed 8 --output-json
|
|
|
180
188
|
|
|
181
189
|
# Silent analysis sorted by name
|
|
182
190
|
complexipy src/ --sort name --quiet
|
|
191
|
+
|
|
192
|
+
# Exclude specific paths relative to root
|
|
193
|
+
complexipy . --exclude tests --exclude utils
|
|
194
|
+
# Note: this excludes only './tests/**' and './utils/**' under '.',
|
|
195
|
+
# it does not exclude './complexipy/utils.py'.
|
|
183
196
|
```
|
|
184
197
|
|
|
185
198
|
!!! tip "Exit Codes"
|
|
186
199
|
complexipy returns exit code `1` when functions exceed the complexity threshold. Use `--ignore-complexity` to suppress this behavior in CI/CD pipelines.
|
|
187
200
|
|
|
201
|
+
### Inline Ignores
|
|
202
|
+
|
|
203
|
+
You can explicitly ignore a known complex function inline, similar to Ruff's `C901` ignores:
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
def legacy_adapter(x, y): # noqa: complexipy (safe wrapper)
|
|
207
|
+
if x and y:
|
|
208
|
+
return x + y
|
|
209
|
+
return 0
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Place `# noqa: complexipy` on the function definition line (or the line immediately above). An optional reason can be provided in parentheses or plain text, it’s ignored by the parser.
|
|
213
|
+
|
|
188
214
|
## API Reference
|
|
189
215
|
|
|
190
216
|
### Functions
|
|
@@ -365,7 +391,7 @@ def process_orders(orders): # Base: 0
|
|
|
365
391
|
```bash
|
|
366
392
|
$ complexipy example.py
|
|
367
393
|
|
|
368
|
-
───────────────────────────── 🐙 complexipy
|
|
394
|
+
───────────────────────────── 🐙 complexipy ──────────────────────────────
|
|
369
395
|
Summary
|
|
370
396
|
┏━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
|
|
371
397
|
┃ Path ┃ File ┃ Function ┃ Complexity ┃
|
|
@@ -384,7 +410,7 @@ $ complexipy example.py
|
|
|
384
410
|
|
|
385
411
|
## Links & Resources
|
|
386
412
|
|
|
387
|
-
- **📚 [Research Paper](https://www.sonarsource.com/resources/cognitive-complexity/)** - Original cognitive complexity research by SonarSource
|
|
413
|
+
- **📚 [Research Paper](https://www.sonarsource.com/resources/cognitive-complexity/)** - Original cognitive complexity research by SonarSource, G. Ann Campbell
|
|
388
414
|
- **🐙 [GitHub Repository](https://github.com/rohaquinlop/complexipy)** - Source code and issue tracking
|
|
389
415
|
- **📦 [PyPI Package](https://pypi.org/project/complexipy/)** - Installation and version history
|
|
390
416
|
- **🛠️ [GitHub Action](https://github.com/marketplace/actions/complexipy)** - CI/CD integration
|