final-python-env / utils /complexity.py
uvpatel7271's picture
Upload folder using huggingface_hub
019e7db verified
raw
history blame
2.21 kB
"""Complexity heuristics for Python code review."""
from __future__ import annotations
import ast
from typing import Any
def _clamp_unit(value: float) -> float:
return max(0.0, min(1.0, float(value)))
def _estimate_time_complexity(loop_depth: int, uses_recursion: bool) -> str:
if uses_recursion and loop_depth >= 1:
return "O(n^2)"
if loop_depth >= 3:
return "O(n^3)"
if loop_depth == 2:
return "O(n^2)"
if loop_depth == 1:
return "O(n)"
if uses_recursion:
return "O(n)"
return "O(1)"
def _estimate_space_complexity(code: str, uses_recursion: bool) -> str:
if uses_recursion:
return "O(n)"
if any(token in code for token in ("[]", "{}", "set(", "dict(", "list(", "Counter(")):
return "O(n)"
return "O(1)"
def _cyclomatic_complexity(code: str) -> int:
try:
tree = ast.parse(code or "\n")
except SyntaxError:
return 1
decision_points = sum(
isinstance(node, (ast.If, ast.For, ast.AsyncFor, ast.While, ast.Try, ast.ExceptHandler, ast.Match, ast.BoolOp))
for node in ast.walk(tree)
)
return max(1, 1 + decision_points)
def estimate_complexity(parsed: dict[str, Any], code: str) -> dict[str, Any]:
"""Estimate Python complexity signals from parsed structure plus source text."""
cyclomatic_complexity = _cyclomatic_complexity(code)
loop_depth = int(parsed.get("max_loop_depth", 0) or 0)
max_nesting_depth = int(parsed.get("max_nesting_depth", 0) or 0)
uses_recursion = bool(parsed.get("uses_recursion", False))
line_count = int(parsed.get("line_count", 0) or 0)
complexity_penalty = _clamp_unit(
0.08
+ min(cyclomatic_complexity, 12) * 0.045
+ min(loop_depth, 4) * 0.11
+ min(max_nesting_depth, 4) * 0.06
+ (0.06 if uses_recursion else 0.0)
+ min(line_count, 200) * 0.0009
)
return {
"cyclomatic_complexity": cyclomatic_complexity,
"time_complexity": _estimate_time_complexity(loop_depth, uses_recursion),
"space_complexity": _estimate_space_complexity(code, uses_recursion),
"complexity_penalty": round(complexity_penalty, 4),
}