An extremely fast Python library to calculate the cognitive complexity of Python files, written in Rust.
- complexipy
Cognitive Complexity breaks from using mathematical models to assess software maintainability by combining Cyclomatic Complexity precedents with human assessment. It yields method complexity scores that align well with how developers perceive maintainability.
Unlike traditional complexity metrics, cognitive complexity focuses on how difficult code is to understand by humans, making it more relevant for maintaining and reviewing code.
Key benefits:
- Identifies hard-to-understand code sections
- Helps improve code quality and maintainability
- Provides a more intuitive metric than traditional complexity measures
📄 Read the white paper: Cognitive Complexity, a new way of measuring understandability
Documentation: https://rohaquinlop.github.io/complexipy/
Source Code: https://github.com/rohaquinlop/complexipy
PyPI: https://pypi.org/project/complexipy/
- Python >= 3.8
- Git (optional) - required only if you want to analyze a git repository
pip install complexipy
# Analyze the current directory and subdirectories
complexipy .
# Analyze a specific directory and subdirectories
complexipy path/to/directory
# Analyze a git repository
complexipy git_repository_url
# Analyze a specific file
complexipy path/to/file.py
# Ignore complexity threshold and show all functions
complexipy path/to/file.py -i
# Output results to a CSV file
complexipy path/to/directory -c
# Output results to a JSON file
complexipy path/to/directory -j
# Show only files exceeding maximum complexity
complexipy path/to/directory -d low
# Disable console output
complexipy path/to/directory -q
# Sort results in descending order
complexipy path/to/directory -s desc
You can use complexipy as a GitHub Action to automatically check code complexity in your CI/CD pipeline:
name: Check Code Complexity
on: [push, pull_request]
jobs:
complexity:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check Python Code Complexity
uses: rohaquinlop/complexipy-action@v1
with:
paths: '.' # Analyze the entire repository
Input | Description | Required | Default |
---|---|---|---|
paths | Paths to analyze. Can be local paths or a git repository URL. | Yes | ${{ github.workspace }} |
output_csv | Generate results in a CSV file. | No | false |
output_json | Generate results in a JSON file. | No | false |
details | Output detail level (low or normal). | No | normal |
quiet | Suppress console output. | No | false |
sort | Sort results by complexity (asc, desc, or name). | No | asc |
Basic Usage:
- uses: rohaquinlop/complexipy-action@v1
with:
paths: '.'
Generate CSV Report:
- uses: rohaquinlop/complexipy-action@v1
with:
paths: '.'
output_csv: true
Generate JSON Report:
- uses: rohaquinlop/complexipy-action@v1
with:
paths: '.'
output_json: true
Analyze Specific Directory with Low Detail Output:
- uses: rohaquinlop/complexipy-action@v1
with:
paths: './src/python'
details: 'low'
sort: 'desc'
You can use complexipy as a pre-commit hook to automatically check code complexity before each commit. This helps maintain code quality by preventing complex code from being committed.
To use complexipy with pre-commit, add the following to your .pre-commit-config.yaml
:
repos:
- repo: https://github.com/rohaquinlop/complexipy-pre-commit
rev: v3.0.0 # Use the latest version
hooks:
- id: complexipy
To exclude Jupyter Notebooks from the analysis, you can specify the file types:
repos:
- repo: https://github.com/rohaquinlop/complexipy-pre-commit
rev: v3.0.0
hooks:
- id: complexipy
types_or: [ python, pyi ] # Only analyze Python files
The pre-commit hook will:
- Run automatically before each commit
- Check the cognitive complexity of your Python files
- Prevent commits if any function exceeds the complexity threshold
- Help maintain code quality standards in your repository
You can also use complexipy directly in Visual Studio Code through our official extension:
- Open VS Code
- Go to the Extensions view (Ctrl+Shift+X / Cmd+Shift+X)
- Search for "complexipy"
- Click Install
The extension provides:
- Real-time complexity analysis as you type
- Visual complexity indicators:
- Function complexity shown with ƒ symbol
- Line-level complexity shown with + symbol
- Color-coded indicators:
- Green: Low complexity (functions < 15, lines ≤ 5)
- Red: High complexity (functions ≥ 15, lines > 5)
- Automatic updates on:
- File save
- Active editor change
- Text changes
You can also trigger a manual analysis by:
- Opening the Command Palette (Ctrl+Shift+P / Cmd+Shift+P)
- Typing "complexipy"
- Selecting the "complexipy" command
-
-c
or--output-csv
: Output results to a CSV file namedcomplexipy.csv
in the current directory. -
-j
or--output-json
: Output results to a JSON file namedcomplexipy.json
in the current directory. -
-i
or--ignore-complexity
: Ignore the complexity threshold and show all functions. -
-d
or--details
: Set detail level:normal
(default): Show all files and functionslow
: Show only files/functions exceeding the maximum complexity
-
-q
or--quiet
: Disable console output. -
-s
or--sort
: Set sort order:asc
(default): Sort by complexity (ascending)desc
: Sort by complexity (descending)name
: Sort by name (ascending)
Note: The program will exit with error code 1 if any function has a cognitive complexity greater than or equal to 15. Use the -i
option to ignore this behavior.
The library provides two main functions:
complexipy.file_complexity
: Analyze a Python file at a specified pathcomplexipy.code_complexity
: Analyze a string containing Python code
# Analyze a file
from complexipy import file_complexity
result = file_complexity("path/to/your/file.py")
print(f"File complexity: {result.complexity}")
# Analyze a code snippet
from complexipy import code_complexity
code = """
def example_function(x):
if x > 0:
for i in range(x):
print(i)
"""
result = code_complexity(code)
print(f"Code complexity: {result.complexity}")
Given the following Python file:
def a_decorator(a, b):
def inner(func):
return func
return inner
def b_decorator(a, b):
def inner(func):
if func:
return None
return func
return inner
Running complexipy path/to/file.py
produces:
───────────────────────────── 🐙 complexipy 3.0.0 ──────────────────────────────
Summary
┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Path ┃ File ┃ Function ┃ Complexity ┃
┡━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ test_decorator.py │ test_decorator.py │ a_decorator │ 0 │
├───────────────────┼───────────────────┼─────────────┼────────────┤
│ test_decorator.py │ test_decorator.py │ b_decorator │ 1 │
└───────────────────┴───────────────────┴─────────────┴────────────┘
🧠 Total Cognitive Complexity: 1
1 file analyzed in 0.0092 seconds
────────────────────────── 🎉 Analysis completed! 🎉 ───────────────────────────
With file_complexity
:
>>> from complexipy import file_complexity
>>> fc = file_complexity("path/to/file.py")
>>> fc.complexity
1
With code_complexity
:
>>> from complexipy import code_complexity
>>> snippet = """for x in range(0, 10):
print(x)
"""
>>> cc = code_complexity(snippet)
>>> cc.complexity
1
def a_decorator(a, b): # 0
def inner(func): # 0
return func # 0
return inner # 0
def b_decorator(a, b): # 0
def inner(func): # 0
if func: # 1 (nested = 0), total 1
return None # 0
return func # 0
return inner # 0
The cognitive complexity of the file is 1, with function b_decorator
having a complexity of 1 due to the if statement.
Using the -o
option outputs results to complexipy.csv
in the current directory:
complexipy path/to/file.py -o
CSV content:
Path,File Name,Function Name,Cognitive Complexity
test_decorator.py,test_decorator.py,a_decorator,0
test_decorator.py,test_decorator.py,b_decorator,1
Analyze all Python files in the current directory and subdirectories:
complexipy .
Analyze a remote repository:
# Analyze repository
complexipy https://github.com/rohaquinlop/complexipy
# With CSV output
complexipy https://github.com/rohaquinlop/complexipy -o
Made with contributors-img
This project is licensed under the MIT License - see the LICENSE file for details.
- Thanks to G. Ann Campbell for publishing the paper "Cognitive Complexity a new way to measure understandability".
- This project is inspired by the Sonar way to calculate cognitive complexity.