smartbiz_ai / analyze_code_quality.py
Muhammad7865253's picture
SmartBiz AI — clean release (guardrails, UI polish, repo cleanup)
8ce1429
Raw
History Blame Contribute Delete
6.37 kB
#!/usr/bin/env python3
"""
Code quality analyzer: find duplicates, dead code, unused imports, inconsistencies.
"""
import os
import re
import json
from pathlib import Path
from collections import defaultdict
BACKEND_PATH = Path("d:/FYP_SmartBIZ/smartbiz-ai/backend")
ROUTES_PATH = BACKEND_PATH / "routes"
PIPELINE_PATH = BACKEND_PATH / "pipeline"
def find_function_definitions():
"""Find all function definitions in Python files."""
functions = defaultdict(list)
for py_file in BACKEND_PATH.rglob("*.py"):
rel_path = py_file.relative_to(BACKEND_PATH)
with open(py_file, 'r', encoding='utf-8', errors='ignore') as f:
lines = f.readlines()
for i, line in enumerate(lines, 1):
# Find function definitions
if re.match(r'^\s*(?:async\s+)?def\s+\w+', line):
func_name = re.search(r'def\s+(\w+)', line).group(1)
functions[func_name].append({
'file': str(rel_path),
'line': i,
'is_private': func_name.startswith('_')
})
return functions
def find_imports():
"""Find all imports and identify unused ones."""
all_imports = defaultdict(list)
for py_file in BACKEND_PATH.rglob("*.py"):
rel_path = py_file.relative_to(BACKEND_PATH)
with open(py_file, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
# Find imports
imports = re.findall(r'(?:from|import)\s+[\w\.]+', content)
for imp in imports:
all_imports[imp].append(str(rel_path))
return all_imports
def find_duplicate_functions():
"""Find duplicate function definitions."""
functions = find_function_definitions()
duplicates = {}
for func_name, locations in functions.items():
if len(locations) > 1 and not func_name.startswith('__'):
duplicates[func_name] = locations
return duplicates
def analyze_code_quality():
"""Run comprehensive code analysis."""
print("=" * 80)
print("SMARTBIZ CODE QUALITY ANALYSIS")
print("=" * 80)
# 1. Find duplicate functions
print("\n[1] DUPLICATE FUNCTIONS")
print("-" * 80)
duplicates = find_duplicate_functions()
if duplicates:
for func_name, locations in sorted(duplicates.items()):
print(f"\n ⚠️ {func_name}")
for loc in locations:
print(f" - {loc['file']} (line {loc['line']})")
else:
print(" ✓ No duplicate functions found")
# 2. Check for unused private functions
print("\n[2] PRIVATE FUNCTIONS (potential cleanup targets)")
print("-" * 80)
functions = find_function_definitions()
private_funcs = {k: v for k, v in functions.items() if k.startswith('_') and not k.startswith('__')}
if private_funcs:
print(f" Found {len(private_funcs)} private functions:")
# Show only the problematic ones (duplicates)
for func_name, locations in sorted(private_funcs.items()):
if len(locations) > 1:
print(f" ⚠️ DUPLICATE: {func_name}")
for loc in locations:
print(f" - {loc['file']} (line {loc['line']})")
else:
print(" ✓ No private functions found")
# 3. File count and structure
print("\n[3] CODEBASE STRUCTURE")
print("-" * 80)
py_files = list(BACKEND_PATH.rglob("*.py"))
routes_files = list(ROUTES_PATH.rglob("*.py"))
pipeline_files = list(PIPELINE_PATH.rglob("*.py"))
print(f" Total Python files: {len(py_files)}")
print(f" - Routes: {len(routes_files)}")
print(f" - Pipeline: {len(pipeline_files)}")
print(f" - Other: {len(py_files) - len(routes_files) - len(pipeline_files)}")
# 4. Check for test files that might be redundant
print("\n[4] TEST FILES (root level)")
print("-" * 80)
root_path = Path("d:/FYP_SmartBIZ/smartbiz-ai")
test_files = sorted(root_path.glob("test_*.py"))
if test_files:
print(f" Found {len(test_files)} test files:")
for tf in test_files:
size_kb = tf.stat().st_size / 1024
with open(tf, 'r', encoding='utf-8', errors='ignore') as f:
lines = len(f.readlines())
print(f" - {tf.name} ({lines} lines, {size_kb:.1f} KB)")
# 5. Check for endpoints consistency
print("\n[5] API ENDPOINTS")
print("-" * 80)
endpoints = {}
for py_file in ROUTES_PATH.glob("*.py"):
with open(py_file, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
routes = re.findall(r'@router\.(\w+)\("([^"]+)"', content)
if routes:
endpoints[py_file.stem] = routes
for route_file, routes_list in sorted(endpoints.items()):
print(f" {route_file}.py:")
for method, path in routes_list:
print(f" - {method.upper()} {path}")
# 6. Summary statistics
print("\n[6] STATISTICS")
print("-" * 80)
all_functions = find_function_definitions()
print(f" Total function definitions: {len(all_functions)}")
print(f" Total locations across codebase: {sum(len(v) for v in all_functions.values())}")
duplicate_count = sum(1 for v in all_functions.values() if len(v) > 1)
print(f" Function names with multiple definitions: {duplicate_count}")
print("\n" + "=" * 80)
print("RECOMMENDATIONS FOR MVP OPTIMIZATION")
print("=" * 80)
print("""
1. CONSOLIDATION
✓ Created backend/pipeline/query/utils.py with shared utilities
✓ Updated dashboard.py and report.py to use shared guess_x_axis/guess_y_axis
2. UNUSED TEST FILES (consider archiving or consolidating)
- test_pipeline_duckdb.py
- test_pipeline_comprehensive.py
- test_multi_dataset.py
- test_multi_api.py
- check_db.py
→ Keep test_system_checkup.py and test_query_cars.py as validation suite
3. ROUTE PREFIX FIX
✓ Added /api prefix to process and upload routers for consistency
4. NEXT STEPS
- Run full integration test with updated endpoints
- Measure report generation performance
- Archive or consolidate test files into single validation suite
""")
if __name__ == "__main__":
analyze_code_quality()