complexipy 0.2.2__tar.gz → 0.3.1__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-0.2.2 → complexipy-0.3.1}/Cargo.lock +89 -1
- {complexipy-0.2.2 → complexipy-0.3.1}/Cargo.toml +4 -2
- complexipy-0.3.1/PKG-INFO +244 -0
- complexipy-0.3.1/README.md +225 -0
- complexipy-0.3.1/complexipy/main.py +113 -0
- complexipy-0.3.1/complexipy/types.py +17 -0
- complexipy-0.3.1/complexipy/utils.py +139 -0
- complexipy-0.3.1/docs/index.md +225 -0
- {complexipy-0.2.2 → complexipy-0.3.1}/pyproject.toml +1 -1
- {complexipy-0.2.2 → complexipy-0.3.1}/src/classes/mod.rs +2 -1
- complexipy-0.3.1/src/cognitive_complexity/mod.rs +361 -0
- complexipy-0.3.1/src/cognitive_complexity/utils.rs +162 -0
- complexipy-0.3.1/src/lib.rs +18 -0
- complexipy-0.2.2/PKG-INFO +0 -173
- complexipy-0.2.2/README.md +0 -154
- complexipy-0.2.2/complexipy/main.py +0 -87
- complexipy-0.2.2/docs/index.md +0 -154
- complexipy-0.2.2/src/cognitive_complexity/mod.rs +0 -237
- complexipy-0.2.2/src/cognitive_complexity/utils.rs +0 -70
- complexipy-0.2.2/src/lib.rs +0 -16
- {complexipy-0.2.2 → complexipy-0.3.1}/LICENSE +0 -0
- {complexipy-0.2.2 → complexipy-0.3.1}/complexipy/__init__.py +0 -0
- {complexipy-0.2.2 → complexipy-0.3.1}/docs/img/favicon.svg +0 -0
- {complexipy-0.2.2 → complexipy-0.3.1}/docs/img/icon.svg +0 -0
- {complexipy-0.2.2 → complexipy-0.3.1}/docs/img/logo-vector.svg +0 -0
- {complexipy-0.2.2 → complexipy-0.3.1}/mkdocs.yml +0 -0
|
@@ -119,10 +119,12 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
|
|
119
119
|
|
|
120
120
|
[[package]]
|
|
121
121
|
name = "complexipy"
|
|
122
|
-
version = "0.
|
|
122
|
+
version = "0.3.1"
|
|
123
123
|
dependencies = [
|
|
124
|
+
"csv",
|
|
124
125
|
"env_logger",
|
|
125
126
|
"ignore",
|
|
127
|
+
"indicatif",
|
|
126
128
|
"log",
|
|
127
129
|
"pyo3",
|
|
128
130
|
"rayon",
|
|
@@ -130,6 +132,19 @@ dependencies = [
|
|
|
130
132
|
"tempfile",
|
|
131
133
|
]
|
|
132
134
|
|
|
135
|
+
[[package]]
|
|
136
|
+
name = "console"
|
|
137
|
+
version = "0.15.8"
|
|
138
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
139
|
+
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
|
|
140
|
+
dependencies = [
|
|
141
|
+
"encode_unicode",
|
|
142
|
+
"lazy_static",
|
|
143
|
+
"libc",
|
|
144
|
+
"unicode-width",
|
|
145
|
+
"windows-sys",
|
|
146
|
+
]
|
|
147
|
+
|
|
133
148
|
[[package]]
|
|
134
149
|
name = "convert_case"
|
|
135
150
|
version = "0.4.0"
|
|
@@ -167,6 +182,27 @@ version = "0.2.2"
|
|
|
167
182
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
168
183
|
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
|
169
184
|
|
|
185
|
+
[[package]]
|
|
186
|
+
name = "csv"
|
|
187
|
+
version = "1.3.0"
|
|
188
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
189
|
+
checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe"
|
|
190
|
+
dependencies = [
|
|
191
|
+
"csv-core",
|
|
192
|
+
"itoa",
|
|
193
|
+
"ryu",
|
|
194
|
+
"serde",
|
|
195
|
+
]
|
|
196
|
+
|
|
197
|
+
[[package]]
|
|
198
|
+
name = "csv-core"
|
|
199
|
+
version = "0.1.11"
|
|
200
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
201
|
+
checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70"
|
|
202
|
+
dependencies = [
|
|
203
|
+
"memchr",
|
|
204
|
+
]
|
|
205
|
+
|
|
170
206
|
[[package]]
|
|
171
207
|
name = "derive_more"
|
|
172
208
|
version = "0.99.17"
|
|
@@ -198,6 +234,12 @@ dependencies = [
|
|
|
198
234
|
"syn 1.0.109",
|
|
199
235
|
]
|
|
200
236
|
|
|
237
|
+
[[package]]
|
|
238
|
+
name = "encode_unicode"
|
|
239
|
+
version = "0.3.6"
|
|
240
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
241
|
+
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
|
242
|
+
|
|
201
243
|
[[package]]
|
|
202
244
|
name = "env_filter"
|
|
203
245
|
version = "0.1.0"
|
|
@@ -292,12 +334,34 @@ dependencies = [
|
|
|
292
334
|
"winapi-util",
|
|
293
335
|
]
|
|
294
336
|
|
|
337
|
+
[[package]]
|
|
338
|
+
name = "indicatif"
|
|
339
|
+
version = "0.17.8"
|
|
340
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
341
|
+
checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3"
|
|
342
|
+
dependencies = [
|
|
343
|
+
"console",
|
|
344
|
+
"instant",
|
|
345
|
+
"number_prefix",
|
|
346
|
+
"portable-atomic",
|
|
347
|
+
"unicode-width",
|
|
348
|
+
]
|
|
349
|
+
|
|
295
350
|
[[package]]
|
|
296
351
|
name = "indoc"
|
|
297
352
|
version = "1.0.9"
|
|
298
353
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
299
354
|
checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306"
|
|
300
355
|
|
|
356
|
+
[[package]]
|
|
357
|
+
name = "instant"
|
|
358
|
+
version = "0.1.12"
|
|
359
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
360
|
+
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
|
361
|
+
dependencies = [
|
|
362
|
+
"cfg-if",
|
|
363
|
+
]
|
|
364
|
+
|
|
301
365
|
[[package]]
|
|
302
366
|
name = "is-macro"
|
|
303
367
|
version = "0.3.5"
|
|
@@ -319,12 +383,24 @@ dependencies = [
|
|
|
319
383
|
"either",
|
|
320
384
|
]
|
|
321
385
|
|
|
386
|
+
[[package]]
|
|
387
|
+
name = "itoa"
|
|
388
|
+
version = "1.0.10"
|
|
389
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
390
|
+
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
|
391
|
+
|
|
322
392
|
[[package]]
|
|
323
393
|
name = "lalrpop-util"
|
|
324
394
|
version = "0.20.0"
|
|
325
395
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
326
396
|
checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d"
|
|
327
397
|
|
|
398
|
+
[[package]]
|
|
399
|
+
name = "lazy_static"
|
|
400
|
+
version = "1.4.0"
|
|
401
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
402
|
+
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|
403
|
+
|
|
328
404
|
[[package]]
|
|
329
405
|
name = "libc"
|
|
330
406
|
version = "0.2.153"
|
|
@@ -442,6 +518,12 @@ dependencies = [
|
|
|
442
518
|
"autocfg",
|
|
443
519
|
]
|
|
444
520
|
|
|
521
|
+
[[package]]
|
|
522
|
+
name = "number_prefix"
|
|
523
|
+
version = "0.4.0"
|
|
524
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
525
|
+
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
|
526
|
+
|
|
445
527
|
[[package]]
|
|
446
528
|
name = "once_cell"
|
|
447
529
|
version = "1.19.0"
|
|
@@ -515,6 +597,12 @@ dependencies = [
|
|
|
515
597
|
"siphasher",
|
|
516
598
|
]
|
|
517
599
|
|
|
600
|
+
[[package]]
|
|
601
|
+
name = "portable-atomic"
|
|
602
|
+
version = "1.6.0"
|
|
603
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
604
|
+
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
|
|
605
|
+
|
|
518
606
|
[[package]]
|
|
519
607
|
name = "ppv-lite86"
|
|
520
608
|
version = "0.2.17"
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "complexipy"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.1"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
authors = ["Robin Quintero <rohaquinlop301@gmail.com>"]
|
|
6
6
|
license = "MIT"
|
|
7
|
-
description = "An extremely fast Python library to calculate the cognitive complexity of
|
|
7
|
+
description = "An extremely fast Python library to calculate the cognitive complexity of Python files, written in Rust."
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
homepage = "https://github.com/rohaquinlop/complexipy"
|
|
10
10
|
documentation = "https://rohaquinlop.github.io/complexipy/"
|
|
@@ -17,8 +17,10 @@ name = "complexipy"
|
|
|
17
17
|
crate-type = ["cdylib"]
|
|
18
18
|
|
|
19
19
|
[dependencies]
|
|
20
|
+
csv = "1.3.0"
|
|
20
21
|
env_logger = "0.11.1"
|
|
21
22
|
ignore = "0.4.22"
|
|
23
|
+
indicatif = "0.17.8"
|
|
22
24
|
log = "0.4.20"
|
|
23
25
|
pyo3 = "0.19.0"
|
|
24
26
|
rayon = "1.8.1"
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: complexipy
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Classifier: Programming Language :: Rust
|
|
5
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
7
|
+
Requires-Dist: typer[all]
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Summary: An extremely fast Python library to calculate the cognitive complexity of Python files, written in Rust.
|
|
10
|
+
Keywords: cognitive,complexity,cognitive complexity,rust,fast
|
|
11
|
+
Home-Page: https://github.com/rohaquinlop/complexipy
|
|
12
|
+
Author: Robin Quintero <rohaquinlop301@gmail.com>
|
|
13
|
+
Author-email: Robin Quintero <rohaquinlop301@gmail.com>
|
|
14
|
+
License: MIT
|
|
15
|
+
Requires-Python: >=3.8
|
|
16
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
17
|
+
Project-URL: Source Code, https://github.com/rohaquinlop/complexipy
|
|
18
|
+
|
|
19
|
+
# complexipy
|
|
20
|
+
|
|
21
|
+
<p align="center">
|
|
22
|
+
<a href="https://rohaquinlop.github.io/complexipy/"><img src="https://raw.githubusercontent.com/rohaquinlop/complexipy/main/docs/img/logo-vector.svg" alt="complexipy"></a>
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
<p align="center">
|
|
26
|
+
<em>An extremely fast Python library to calculate the cognitive complexity of Python files, written in Rust.</em>
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
<p align="center">
|
|
30
|
+
<a href="https://sonarcloud.io/summary/new_code?id=rohaquinlop_complexipy" target="_blank">
|
|
31
|
+
<img src="https://sonarcloud.io/api/project_badges/measure?project=rohaquinlop_complexipy&metric=alert_status" alt="Quality Gate">
|
|
32
|
+
</a>
|
|
33
|
+
<a href="https://pypi.org/project/complexipy" target="_blank">
|
|
34
|
+
<img src="https://img.shields.io/pypi/v/complexipy?color=%2334D058&label=pypi%20package" alt="Package version">
|
|
35
|
+
</a>
|
|
36
|
+
</p>
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
Cognitive Complexity breaks from using mathematical models to assess software
|
|
40
|
+
maintainability by combining Cyclomatic Complexity precedents with human
|
|
41
|
+
assessment. It yields method complexity scores that align well with how
|
|
42
|
+
developers perceive maintainability. Read the white paper here: [Cognitive Complexity, a new way of measuring understandability](https://www.sonarsource.com/resources/cognitive-complexity/)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
**Documentation**: <a href="https://rohaquinlop.github.io/complexipy/" target="_blank">https://rohaquinlop.github.io/complexipy/</a>
|
|
48
|
+
|
|
49
|
+
**Source Code**: <a href="https://github.com/rohaquinlop/complexipy" target="_blank">https://github.com/rohaquinlop/complexipy</a>
|
|
50
|
+
|
|
51
|
+
**PyPI**: <a href="https://pypi.org/project/complexipy/" target="_blank">https://pypi.org/project/complexipy/</a>
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
## Contributors
|
|
57
|
+
|
|
58
|
+
<p align="center">
|
|
59
|
+
<a href = "https://github.com/rohaquinlop/complexipy/graphs/contributors">
|
|
60
|
+
<img src = "https://contrib.rocks/image?repo=rohaquinlop/complexipy"/>
|
|
61
|
+
</a>
|
|
62
|
+
</p>
|
|
63
|
+
|
|
64
|
+
Made with [contributors-img](https://contrib.rocks)
|
|
65
|
+
|
|
66
|
+
## Requirements
|
|
67
|
+
|
|
68
|
+
- Python >= 3.8
|
|
69
|
+
- You also need to install `git` in your computer if you want to analyze a git repository.
|
|
70
|
+
|
|
71
|
+
## Installation
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install complexipy
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Usage
|
|
78
|
+
|
|
79
|
+
To run **complexipy** you can use the following command:
|
|
80
|
+
|
|
81
|
+
```shell
|
|
82
|
+
complexipy . # Use complexipy to analyze the current directory and any subdirectories
|
|
83
|
+
complexipy path/to/directory # Use complexipy to analyze a specific directory and any subdirectories
|
|
84
|
+
complexipy git_repository_url # Use complexipy to analyze a git repository
|
|
85
|
+
complexipy path/to/file.py # Use complexipy to analyze a specific file
|
|
86
|
+
complexipy path/to/file.py -c 20 # Use the -c option to set the maximum congnitive complexity, default is 15
|
|
87
|
+
complexipy path/to/directory -c 0 # Set the maximum cognitive complexity to 0 to disable the exit with error
|
|
88
|
+
complexipy path/to/directory -o # Use the -o option to output the results to a CSV file, default is False
|
|
89
|
+
complexipy path/to/directory -d low # Use the -d option to set detail level, default is "normal". If set to "low" will show only files with complexity greater than the maximum complexity
|
|
90
|
+
complexipy path/to/directory -l file # Use the -l option to set the level of measurement, default is "function". If set to "file" will measure the complexity of the file and will validate the maximum complexity according to the file complexity.
|
|
91
|
+
complexipy path/to/directory -q # Use the -q option to disable the output to the console, default is False.
|
|
92
|
+
complexipy path/to/directory -s desc # Use the -s option to set the sort order, default is "asc". If set to "desc" will sort the results in descending order. If set to "asc" will sort the results in ascending order. If set to "name" will sort the results by name.
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Options
|
|
96
|
+
|
|
97
|
+
- `-c` or `--max-complexity`: Set the maximum cognitive complexity, default is 15.
|
|
98
|
+
If the cognitive complexity of a file is greater than the maximum cognitive,
|
|
99
|
+
then the return code will be 1 and exit with error, otherwise it will be 0.
|
|
100
|
+
If set to 0, the exit with error will be disabled.
|
|
101
|
+
- `-o` or `--output`: Output the results to a CSV file, default is False. The
|
|
102
|
+
filename will be `complexipy.csv` and will be saved in the invocation directory.
|
|
103
|
+
- `-d` or `--detail`: Set the detail level, default is "normal". If set to "low"
|
|
104
|
+
will show only files or functions with complexity greater than the maximum
|
|
105
|
+
complexity.
|
|
106
|
+
- `-l` or `--level` Set the level of measurement, default is "function". If set
|
|
107
|
+
to "file" will measure the complexity of the file and will validate the maximum
|
|
108
|
+
complexity according to the file complexity. If set to "function" will measure
|
|
109
|
+
the complexity of the functions and will validate the maximum complexity
|
|
110
|
+
according to the function complexity. This option is useful if you want to set
|
|
111
|
+
a maximum complexity according for each file or for each function in the file
|
|
112
|
+
(or files).
|
|
113
|
+
- `-q` or `--quiet`: Disable the output to the console, default is False.
|
|
114
|
+
- `-s` or `--sort`: Set the sort order, default is "asc". If set to "desc" will
|
|
115
|
+
sort the results in descending order. If set to "asc" will sort the results in
|
|
116
|
+
ascending order. If set to "name" will sort the results by name. This option will
|
|
117
|
+
affect the output to the console and the output to the CSV file.
|
|
118
|
+
|
|
119
|
+
If the cognitive complexity of a file or a function is greater than the maximum
|
|
120
|
+
cognitive cognitive complexity, then the return code will be 1 and exit with
|
|
121
|
+
error, otherwise it will be 0.
|
|
122
|
+
|
|
123
|
+
## Example
|
|
124
|
+
|
|
125
|
+
### Analyzing a file
|
|
126
|
+
|
|
127
|
+
For example, given the following file:
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
def a_decorator(a, b):
|
|
131
|
+
def inner(func):
|
|
132
|
+
return func
|
|
133
|
+
return inner
|
|
134
|
+
|
|
135
|
+
def b_decorator(a, b):
|
|
136
|
+
def inner(func):
|
|
137
|
+
if func:
|
|
138
|
+
return None
|
|
139
|
+
return func
|
|
140
|
+
return inner
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The cognitive complexity of the file is 1, and the output of the command
|
|
144
|
+
`complexipy path/to/file.py` will be:
|
|
145
|
+
|
|
146
|
+
```txt
|
|
147
|
+
───────────────────────────── 🐙 complexipy 0.3.1 ──────────────────────────────
|
|
148
|
+
Summary
|
|
149
|
+
┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
|
|
150
|
+
┃ Path ┃ File ┃ Function ┃ Complexity ┃
|
|
151
|
+
┡━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
|
|
152
|
+
│ test_decorator.py │ test_decorator.py │ a_decorator │ 0 │
|
|
153
|
+
├───────────────────┼───────────────────┼─────────────┼────────────┤
|
|
154
|
+
│ test_decorator.py │ test_decorator.py │ b_decorator │ 1 │
|
|
155
|
+
└───────────────────┴───────────────────┴─────────────┴────────────┘
|
|
156
|
+
🧠 Total Cognitive Complexity in ./tests/src/test_decorator.py: 1
|
|
157
|
+
1 file analyzed in 0.0032 seconds
|
|
158
|
+
────────────────────────── 🎉 Analysis completed! 🎉 ───────────────────────────
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### Explaining the results of the analysis
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
def a_decorator(a, b): # 0
|
|
165
|
+
def inner(func): # 0
|
|
166
|
+
return func # 0
|
|
167
|
+
return inner # 0
|
|
168
|
+
|
|
169
|
+
def b_decorator(a, b): # 0
|
|
170
|
+
def inner(func): # 0
|
|
171
|
+
if func: # 1 (nested = 0), total 1
|
|
172
|
+
return None # 0
|
|
173
|
+
return func # 0
|
|
174
|
+
return inner # 0
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
The cognitive complexity of the file is 1, and the cognitive complexity of the
|
|
178
|
+
function `b_decorator` is 1. This example is simple, but it shows how
|
|
179
|
+
**complexipy** calculates the cognitive complexity according to the specifications
|
|
180
|
+
of the paper "Cognitive Complexity a new way to measure understandability",
|
|
181
|
+
considering the decorators and the if statement.
|
|
182
|
+
|
|
183
|
+
#### Output to a CSV file
|
|
184
|
+
|
|
185
|
+
If you want to output the results to a CSV file, you can use the `-o` option,
|
|
186
|
+
this is really useful if you want to integrate **complexipy** with other tools,
|
|
187
|
+
for example, a CI/CD pipeline. You will get the output in the console and will
|
|
188
|
+
create a CSV file with the results of the analysis.
|
|
189
|
+
|
|
190
|
+
The filename will be `complexipy.csv` and will be saved in the current directory.
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
$ complexipy path/to/file.py -o
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The output will be:
|
|
197
|
+
|
|
198
|
+
```csv
|
|
199
|
+
Path,File Name,Function Name,Cognitive Complexity
|
|
200
|
+
test_decorator.py,test_decorator.py,a_decorator,0
|
|
201
|
+
test_decorator.py,test_decorator.py,b_decorator,1
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Analyzing a directory
|
|
205
|
+
|
|
206
|
+
You can also analyze a directory, for example:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
$ complexipy .
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
And **complexipy** will analyze all the files in the current directory and any
|
|
213
|
+
subdirectories.
|
|
214
|
+
|
|
215
|
+
### Analyzing a git repository
|
|
216
|
+
|
|
217
|
+
You can also analyze a git repository, for example:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
$ complexipy https://github.com/rohaquinlop/complexipy
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
And to generate the output to a CSV file:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
$ complexipy https://github.com/rohaquinlop/complexipy -o
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
This project is licensed under the MIT License - see the [LICENSE](https://github.com/rohaquinlop/complexipy/blob/main/LICENSE) file
|
|
232
|
+
for details.
|
|
233
|
+
|
|
234
|
+
## Acknowledgments
|
|
235
|
+
|
|
236
|
+
- Thanks to G. Ann Campbell for publishing the paper "Cognitive Complexity a new
|
|
237
|
+
way to measure understandability".
|
|
238
|
+
- This project is inspired by the Sonar way to calculate the cognitive
|
|
239
|
+
complexity.
|
|
240
|
+
|
|
241
|
+
## References
|
|
242
|
+
|
|
243
|
+
- [Cognitive Complexity](https://www.sonarsource.com/resources/cognitive-complexity/)
|
|
244
|
+
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# complexipy
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://rohaquinlop.github.io/complexipy/"><img src="https://raw.githubusercontent.com/rohaquinlop/complexipy/main/docs/img/logo-vector.svg" alt="complexipy"></a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<em>An extremely fast Python library to calculate the cognitive complexity of Python files, written in Rust.</em>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://sonarcloud.io/summary/new_code?id=rohaquinlop_complexipy" target="_blank">
|
|
13
|
+
<img src="https://sonarcloud.io/api/project_badges/measure?project=rohaquinlop_complexipy&metric=alert_status" alt="Quality Gate">
|
|
14
|
+
</a>
|
|
15
|
+
<a href="https://pypi.org/project/complexipy" target="_blank">
|
|
16
|
+
<img src="https://img.shields.io/pypi/v/complexipy?color=%2334D058&label=pypi%20package" alt="Package version">
|
|
17
|
+
</a>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
Cognitive Complexity breaks from using mathematical models to assess software
|
|
22
|
+
maintainability by combining Cyclomatic Complexity precedents with human
|
|
23
|
+
assessment. It yields method complexity scores that align well with how
|
|
24
|
+
developers perceive maintainability. Read the white paper here: [Cognitive Complexity, a new way of measuring understandability](https://www.sonarsource.com/resources/cognitive-complexity/)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
**Documentation**: <a href="https://rohaquinlop.github.io/complexipy/" target="_blank">https://rohaquinlop.github.io/complexipy/</a>
|
|
30
|
+
|
|
31
|
+
**Source Code**: <a href="https://github.com/rohaquinlop/complexipy" target="_blank">https://github.com/rohaquinlop/complexipy</a>
|
|
32
|
+
|
|
33
|
+
**PyPI**: <a href="https://pypi.org/project/complexipy/" target="_blank">https://pypi.org/project/complexipy/</a>
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
## Contributors
|
|
39
|
+
|
|
40
|
+
<p align="center">
|
|
41
|
+
<a href = "https://github.com/rohaquinlop/complexipy/graphs/contributors">
|
|
42
|
+
<img src = "https://contrib.rocks/image?repo=rohaquinlop/complexipy"/>
|
|
43
|
+
</a>
|
|
44
|
+
</p>
|
|
45
|
+
|
|
46
|
+
Made with [contributors-img](https://contrib.rocks)
|
|
47
|
+
|
|
48
|
+
## Requirements
|
|
49
|
+
|
|
50
|
+
- Python >= 3.8
|
|
51
|
+
- You also need to install `git` in your computer if you want to analyze a git repository.
|
|
52
|
+
|
|
53
|
+
## Installation
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install complexipy
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Usage
|
|
60
|
+
|
|
61
|
+
To run **complexipy** you can use the following command:
|
|
62
|
+
|
|
63
|
+
```shell
|
|
64
|
+
complexipy . # Use complexipy to analyze the current directory and any subdirectories
|
|
65
|
+
complexipy path/to/directory # Use complexipy to analyze a specific directory and any subdirectories
|
|
66
|
+
complexipy git_repository_url # Use complexipy to analyze a git repository
|
|
67
|
+
complexipy path/to/file.py # Use complexipy to analyze a specific file
|
|
68
|
+
complexipy path/to/file.py -c 20 # Use the -c option to set the maximum congnitive complexity, default is 15
|
|
69
|
+
complexipy path/to/directory -c 0 # Set the maximum cognitive complexity to 0 to disable the exit with error
|
|
70
|
+
complexipy path/to/directory -o # Use the -o option to output the results to a CSV file, default is False
|
|
71
|
+
complexipy path/to/directory -d low # Use the -d option to set detail level, default is "normal". If set to "low" will show only files with complexity greater than the maximum complexity
|
|
72
|
+
complexipy path/to/directory -l file # Use the -l option to set the level of measurement, default is "function". If set to "file" will measure the complexity of the file and will validate the maximum complexity according to the file complexity.
|
|
73
|
+
complexipy path/to/directory -q # Use the -q option to disable the output to the console, default is False.
|
|
74
|
+
complexipy path/to/directory -s desc # Use the -s option to set the sort order, default is "asc". If set to "desc" will sort the results in descending order. If set to "asc" will sort the results in ascending order. If set to "name" will sort the results by name.
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Options
|
|
78
|
+
|
|
79
|
+
- `-c` or `--max-complexity`: Set the maximum cognitive complexity, default is 15.
|
|
80
|
+
If the cognitive complexity of a file is greater than the maximum cognitive,
|
|
81
|
+
then the return code will be 1 and exit with error, otherwise it will be 0.
|
|
82
|
+
If set to 0, the exit with error will be disabled.
|
|
83
|
+
- `-o` or `--output`: Output the results to a CSV file, default is False. The
|
|
84
|
+
filename will be `complexipy.csv` and will be saved in the invocation directory.
|
|
85
|
+
- `-d` or `--detail`: Set the detail level, default is "normal". If set to "low"
|
|
86
|
+
will show only files or functions with complexity greater than the maximum
|
|
87
|
+
complexity.
|
|
88
|
+
- `-l` or `--level` Set the level of measurement, default is "function". If set
|
|
89
|
+
to "file" will measure the complexity of the file and will validate the maximum
|
|
90
|
+
complexity according to the file complexity. If set to "function" will measure
|
|
91
|
+
the complexity of the functions and will validate the maximum complexity
|
|
92
|
+
according to the function complexity. This option is useful if you want to set
|
|
93
|
+
a maximum complexity according for each file or for each function in the file
|
|
94
|
+
(or files).
|
|
95
|
+
- `-q` or `--quiet`: Disable the output to the console, default is False.
|
|
96
|
+
- `-s` or `--sort`: Set the sort order, default is "asc". If set to "desc" will
|
|
97
|
+
sort the results in descending order. If set to "asc" will sort the results in
|
|
98
|
+
ascending order. If set to "name" will sort the results by name. This option will
|
|
99
|
+
affect the output to the console and the output to the CSV file.
|
|
100
|
+
|
|
101
|
+
If the cognitive complexity of a file or a function is greater than the maximum
|
|
102
|
+
cognitive cognitive complexity, then the return code will be 1 and exit with
|
|
103
|
+
error, otherwise it will be 0.
|
|
104
|
+
|
|
105
|
+
## Example
|
|
106
|
+
|
|
107
|
+
### Analyzing a file
|
|
108
|
+
|
|
109
|
+
For example, given the following file:
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
def a_decorator(a, b):
|
|
113
|
+
def inner(func):
|
|
114
|
+
return func
|
|
115
|
+
return inner
|
|
116
|
+
|
|
117
|
+
def b_decorator(a, b):
|
|
118
|
+
def inner(func):
|
|
119
|
+
if func:
|
|
120
|
+
return None
|
|
121
|
+
return func
|
|
122
|
+
return inner
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The cognitive complexity of the file is 1, and the output of the command
|
|
126
|
+
`complexipy path/to/file.py` will be:
|
|
127
|
+
|
|
128
|
+
```txt
|
|
129
|
+
───────────────────────────── 🐙 complexipy 0.3.1 ──────────────────────────────
|
|
130
|
+
Summary
|
|
131
|
+
┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
|
|
132
|
+
┃ Path ┃ File ┃ Function ┃ Complexity ┃
|
|
133
|
+
┡━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
|
|
134
|
+
│ test_decorator.py │ test_decorator.py │ a_decorator │ 0 │
|
|
135
|
+
├───────────────────┼───────────────────┼─────────────┼────────────┤
|
|
136
|
+
│ test_decorator.py │ test_decorator.py │ b_decorator │ 1 │
|
|
137
|
+
└───────────────────┴───────────────────┴─────────────┴────────────┘
|
|
138
|
+
🧠 Total Cognitive Complexity in ./tests/src/test_decorator.py: 1
|
|
139
|
+
1 file analyzed in 0.0032 seconds
|
|
140
|
+
────────────────────────── 🎉 Analysis completed! 🎉 ───────────────────────────
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
#### Explaining the results of the analysis
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
def a_decorator(a, b): # 0
|
|
147
|
+
def inner(func): # 0
|
|
148
|
+
return func # 0
|
|
149
|
+
return inner # 0
|
|
150
|
+
|
|
151
|
+
def b_decorator(a, b): # 0
|
|
152
|
+
def inner(func): # 0
|
|
153
|
+
if func: # 1 (nested = 0), total 1
|
|
154
|
+
return None # 0
|
|
155
|
+
return func # 0
|
|
156
|
+
return inner # 0
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
The cognitive complexity of the file is 1, and the cognitive complexity of the
|
|
160
|
+
function `b_decorator` is 1. This example is simple, but it shows how
|
|
161
|
+
**complexipy** calculates the cognitive complexity according to the specifications
|
|
162
|
+
of the paper "Cognitive Complexity a new way to measure understandability",
|
|
163
|
+
considering the decorators and the if statement.
|
|
164
|
+
|
|
165
|
+
#### Output to a CSV file
|
|
166
|
+
|
|
167
|
+
If you want to output the results to a CSV file, you can use the `-o` option,
|
|
168
|
+
this is really useful if you want to integrate **complexipy** with other tools,
|
|
169
|
+
for example, a CI/CD pipeline. You will get the output in the console and will
|
|
170
|
+
create a CSV file with the results of the analysis.
|
|
171
|
+
|
|
172
|
+
The filename will be `complexipy.csv` and will be saved in the current directory.
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
$ complexipy path/to/file.py -o
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
The output will be:
|
|
179
|
+
|
|
180
|
+
```csv
|
|
181
|
+
Path,File Name,Function Name,Cognitive Complexity
|
|
182
|
+
test_decorator.py,test_decorator.py,a_decorator,0
|
|
183
|
+
test_decorator.py,test_decorator.py,b_decorator,1
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Analyzing a directory
|
|
187
|
+
|
|
188
|
+
You can also analyze a directory, for example:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
$ complexipy .
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
And **complexipy** will analyze all the files in the current directory and any
|
|
195
|
+
subdirectories.
|
|
196
|
+
|
|
197
|
+
### Analyzing a git repository
|
|
198
|
+
|
|
199
|
+
You can also analyze a git repository, for example:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
$ complexipy https://github.com/rohaquinlop/complexipy
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
And to generate the output to a CSV file:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
$ complexipy https://github.com/rohaquinlop/complexipy -o
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## License
|
|
212
|
+
|
|
213
|
+
This project is licensed under the MIT License - see the [LICENSE](https://github.com/rohaquinlop/complexipy/blob/main/LICENSE) file
|
|
214
|
+
for details.
|
|
215
|
+
|
|
216
|
+
## Acknowledgments
|
|
217
|
+
|
|
218
|
+
- Thanks to G. Ann Campbell for publishing the paper "Cognitive Complexity a new
|
|
219
|
+
way to measure understandability".
|
|
220
|
+
- This project is inspired by the Sonar way to calculate the cognitive
|
|
221
|
+
complexity.
|
|
222
|
+
|
|
223
|
+
## References
|
|
224
|
+
|
|
225
|
+
- [Cognitive Complexity](https://www.sonarsource.com/resources/cognitive-complexity/)
|