#!/usr/bin/env python3 """ Check import organization in Python files and identify files that need manual standardization. """ import ast import os from pathlib import Path from typing import List, Tuple def analyze_imports(file_path: str) -> Tuple[bool, List[str]]: """Analyze imports in a file and return (is_standardized, issues)""" try: with open(file_path, 'r', encoding='utf-8') as f: content = f.read() tree = ast.parse(content) except (SyntaxError, UnicodeDecodeError) as e: return False, [f"Parse error: {e}"] issues = [] stdlib_imports = [] third_party_imports = [] local_imports = [] # Standard library modules (common ones) stdlib_modules = { 'os', 'sys', 'json', 'logging', 'datetime', 'time', 'asyncio', 'typing', 'functools', 'collections', 'itertools', 'pathlib', 'unittest', 'argparse', 'subprocess', 're', 'uuid', 'ssl', 'threading', 'ast', 'shutil', 'tempfile' } for node in ast.walk(tree): if isinstance(node, ast.Import): for alias in node.names: module_root = alias.name.split('.')[0] if module_root in stdlib_modules: stdlib_imports.append((node.lineno, f"import {alias.name}")) elif module_root in ['analytics', 'tests', 'scripts']: local_imports.append((node.lineno, f"import {alias.name}")) else: third_party_imports.append((node.lineno, f"import {alias.name}")) elif isinstance(node, ast.ImportFrom): if node.module: module_root = node.module.split('.')[0] names = [alias.name for alias in node.names] import_str = f"from {node.module} import {', '.join(names)}" if module_root in stdlib_modules: stdlib_imports.append((node.lineno, import_str)) elif module_root in ['analytics', 'tests', 'scripts'] or node.module.startswith('.'): local_imports.append((node.lineno, import_str)) else: third_party_imports.append((node.lineno, import_str)) # Check if imports are properly ordered all_imports = stdlib_imports + third_party_imports + local_imports all_imports.sort(key=lambda x: x[0]) # Sort by line number # Check ordering current_section = 'stdlib' for line_no, import_str in all_imports: if import_str.split()[1].split('.')[0] in stdlib_modules: if current_section not in ['stdlib']: issues.append(f"Line {line_no}: stdlib import after non-stdlib imports") current_section = 'stdlib' elif any(import_str.startswith(f"from {mod}") or import_str.startswith(f"import {mod}") for mod in ['analytics', 'tests', 'scripts']) or '.database' in import_str: if current_section not in ['stdlib', 'third_party', 'local']: issues.append(f"Line {line_no}: local import in wrong position") current_section = 'local' else: if current_section not in ['stdlib', 'third_party']: issues.append(f"Line {line_no}: third-party import after local imports") current_section = 'third_party' return len(issues) == 0, issues def main(): """Check import organization across the codebase""" project_root = Path(__file__).parent.parent.parent files_to_check = [] # Collect Python files for pattern in ['*.py', 'analytics/*.py', 'tests/*.py', 'scripts/**/*.py', 'archive/*.py']: files_to_check.extend(project_root.glob(pattern)) # Also check subdirectories for subdir in ['tests/unit', 'tests/integration', 'tests/utilities', 'tests/performance']: subdir_path = project_root / subdir if subdir_path.exists(): files_to_check.extend(subdir_path.glob('*.py')) print("šŸ” Checking import organization...") needs_attention = [] well_organized = [] for file_path in files_to_check: if 'backup' in str(file_path): continue # Skip backup files is_standardized, issues = analyze_imports(str(file_path)) if is_standardized: well_organized.append(str(file_path)) else: needs_attention.append((str(file_path), issues)) print(f"\nāœ… Well-organized files: {len(well_organized)}") for file_path in well_organized: rel_path = os.path.relpath(file_path, project_root) print(f" āœ“ {rel_path}") print(f"\nāš ļø Files needing attention: {len(needs_attention)}") for file_path, issues in needs_attention: rel_path = os.path.relpath(file_path, project_root) print(f" šŸ“ {rel_path}") for issue in issues[:3]: # Show first 3 issues print(f" - {issue}") if len(issues) > 3: print(f" - ... and {len(issues) - 3} more issues") print(f"\nšŸ“Š Summary:") print(f" Total files checked: {len(well_organized) + len(needs_attention)}") print(f" Well-organized: {len(well_organized)}") print(f" Need attention: {len(needs_attention)}") if __name__ == "__main__": main()