Skip to content

Commit 2566101

Browse files
authored
Add helper-script to get complexity metrics using lizard (#7)
1 parent d1c8568 commit 2566101

File tree

1 file changed

+130
-0
lines changed

1 file changed

+130
-0
lines changed

scripts/lizard_complexity.py

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
A script to run the Lizard code complexity analyzer and output results in CSV format.
5+
Usage:
6+
python lizard_complexity.py -l cpp -l c -t 8 path/to/code --output complexity.csv
7+
"""
8+
9+
import argparse
10+
import csv
11+
import os
12+
import sys
13+
from typing import List, Dict, Any
14+
15+
# Import Lizard as a library
16+
try:
17+
import lizard
18+
except ImportError:
19+
print("Error: Lizard library not found. Install with 'pip install lizard'")
20+
sys.exit(1)
21+
22+
23+
def parse_arguments() -> argparse.Namespace:
24+
"""Parse command line arguments."""
25+
parser = argparse.ArgumentParser(
26+
description="Generate code complexity CSV using Lizard"
27+
)
28+
parser.add_argument(
29+
"path", help="Path to analyze"
30+
)
31+
parser.add_argument(
32+
"-l", "--language", action="append", default=[],
33+
help="Programming language to include (can be specified multiple times)"
34+
)
35+
parser.add_argument(
36+
"-t", "--threads", type=int, default=1,
37+
help="Number of threads to use for analysis"
38+
)
39+
parser.add_argument(
40+
"-m", "--modified", action="store_true",
41+
help="Include only modified files"
42+
)
43+
parser.add_argument(
44+
"--output", default="complexity.csv",
45+
help="Output CSV file path"
46+
)
47+
parser.add_argument(
48+
"--exclude", action="append", default=[],
49+
help="File patterns to exclude (can be specified multiple times)"
50+
)
51+
parser.add_argument(
52+
"--verbose", action="store_true",
53+
help="Enable verbose output"
54+
)
55+
56+
return parser.parse_args()
57+
58+
59+
def analyze_code(args: argparse.Namespace) -> List[Dict[str, Any]]:
60+
"""Run Lizard analysis and return results."""
61+
lizard_args = []
62+
63+
for lang in args.language:
64+
lizard_args.extend(["-l", lang])
65+
66+
for pattern in args.exclude:
67+
lizard_args.extend(["--exclude", pattern])
68+
69+
if args.threads > 1:
70+
lizard_args.extend(["-t", str(args.threads)])
71+
72+
lizard_args.append(args.path)
73+
74+
if args.verbose:
75+
print(f"Analyzing code in {args.path}...")
76+
print(f"Lizard arguments: {lizard_args}")
77+
78+
analyzer = lizard.analyze(lizard_args)
79+
results = []
80+
81+
for source_file in analyzer:
82+
file_path = os.path.relpath(source_file.filename, os.getcwd())
83+
84+
for func in source_file.function_list:
85+
results.append({
86+
"file": file_path,
87+
"function": func.name,
88+
"length": func.length,
89+
"complexity": func.cyclomatic_complexity,
90+
"line": func.start_line,
91+
})
92+
93+
return results
94+
95+
96+
def write_csv(results: List[Dict[str, Any]], output_path: str, verbose: bool) -> None:
97+
"""Write analysis results to CSV file."""
98+
with open(output_path, 'w', newline='') as csv_file:
99+
writer = csv.writer(csv_file)
100+
101+
# Write data rows
102+
for result in results:
103+
writer.writerow([
104+
result["file"],
105+
result["function"],
106+
result["length"],
107+
result["complexity"],
108+
result["line"]
109+
])
110+
111+
if verbose:
112+
print(f"Wrote {len(results)} functions to {output_path}")
113+
114+
115+
def main() -> None:
116+
"""Main function."""
117+
args = parse_arguments()
118+
119+
# Run analysis
120+
results = analyze_code(args)
121+
122+
# Write results to CSV
123+
write_csv(results, args.output, args.verbose)
124+
125+
if args.verbose:
126+
print(f"Analysis complete. Found {len(results)} functions.")
127+
128+
129+
if __name__ == "__main__":
130+
main()

0 commit comments

Comments
 (0)