CQ005: ComplexityCheck
Overview
| Property | Value |
|---|---|
| ID | CQ005 |
| Name | ComplexityCheck |
| Group | code-quality |
| Severity | WARNING |
Description
Checks code complexity using cyclomatic complexity metrics.
High complexity indicates code that is:
- Difficult to understand
- Hard to test thoroughly
- More likely to contain bugs
- Expensive to maintain
What it checks
The check analyzes cyclomatic complexity and:
- PASSED: All functions below complexity threshold (default 10)
- FAILED: Functions exceed complexity threshold (lists them)
- NOT_APPLICABLE: No complexity checker available
Cyclomatic complexity measures the number of independent paths through code. A function with:
- 1-5: Simple, easy to test
- 6-10: Moderate, consider refactoring
- 11-20: Complex, should refactor
- 21+: Very complex, must refactor
How to fix
Using ruff (recommended)
Ruff includes complexity checking. Enable it in pyproject.toml:
[tool.ruff.lint]
select = ["C901"] # McCabe complexity
[tool.ruff.lint.mccabe]
max-complexity = 10Run to see complex functions:
ruff check --select=C901 .Using radon
Install and run radon:
pip install radon
radon cc src/my_package -a -sUsing flake8
pip install flake8
flake8 --max-complexity=10 src/my_packageRefactoring strategies
Extract helper functions:
# Before: Complex function with many branches
def process_order(order):
if order.type == "retail":
# 20 lines of retail logic
...
elif order.type == "wholesale":
# 20 lines of wholesale logic
...
# more branches...
# After: Simplified with helpers
def process_order(order):
handlers = {
"retail": process_retail_order,
"wholesale": process_wholesale_order,
}
handler = handlers.get(order.type, process_default_order)
return handler(order)Use early returns:
# Before: Nested conditionals
def validate(data):
if data:
if data.get("name"):
if len(data["name"]) > 0:
return True
return False
# After: Early returns
def validate(data):
if not data:
return False
if not data.get("name"):
return False
return len(data["name"]) > 0Replace conditionals with polymorphism:
# Use classes or strategy pattern instead of long if/elif chainsWhy WARNING severity?
This check is a WARNING because:
- Complexity thresholds are subjective
- Some complex functions are unavoidable
- Context matters for complexity decisions
Configuration
Set complexity threshold
[tool.pycmdcheck]
max_complexity = 10Skip this check
[tool.pycmdcheck]
skip = ["CQ005"]CLI
pycmdcheck --skip CQ005