Spaces:
Sleeping
Sleeping
| #!/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() | |