From 484e6cd34f0b01e1f92e11284f6becde7cc29112 Mon Sep 17 00:00:00 2001 From: spark Date: Thu, 29 Oct 2026 04:11:46 +0000 Subject: [PATCH] spark: py_stats.py - quick Python file analyzer with AST parsing --- wizard-work/spark/output.txt | 7 +++ wizard-work/spark/py_stats.py | 107 ++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 wizard-work/spark/output.txt create mode 100644 wizard-work/spark/py_stats.py diff --git a/wizard-work/spark/output.txt b/wizard-work/spark/output.txt new file mode 100644 index 0000000..e879bd1 --- /dev/null +++ b/wizard-work/spark/output.txt @@ -0,0 +1,7 @@ +Python File Statistics for: /root/.hermes/profiles/spark/ +================================================== +Total .py files: 50 +Total lines: 11590 +Total imports: 434 +Total functions: 415 +Total classes: 10 diff --git a/wizard-work/spark/py_stats.py b/wizard-work/spark/py_stats.py new file mode 100644 index 0000000..6a743e2 --- /dev/null +++ b/wizard-work/spark/py_stats.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +"""Quick Python file statistics reporter. +Usage: python py_stats.py [output_file] +Reports: number of .py files, total lines, imports, functions, classes. +""" +import os +import sys +import ast +from pathlib import Path + +def analyze_py_file(filepath): + """Analyze a single Python file.""" + result = { + 'lines': 0, + 'imports': 0, + 'functions': 0, + 'classes': 0 + } + + try: + with open(filepath, 'r', encoding='utf-8') as f: + content = f.read() + result['lines'] = len(content.splitlines()) + + tree = ast.parse(content) + for node in ast.walk(tree): + if isinstance(node, (ast.Import, ast.ImportFrom)): + result['imports'] += 1 + elif isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): + result['functions'] += 1 + elif isinstance(node, ast.ClassDef): + result['classes'] += 1 + except Exception as e: + result['error'] = str(e) + + return result + +def scan_directory(directory): + """Scan directory for Python files and report statistics.""" + stats = { + 'files': 0, + 'total_lines': 0, + 'total_imports': 0, + 'total_functions': 0, + 'total_classes': 0, + 'file_details': [] + } + + for root, dirs, files in os.walk(directory): + # Skip hidden directories and common non-source folders + dirs[:] = [d for d in dirs if not d.startswith('.') and d not in ('__pycache__', 'venv', '.venv', 'node_modules')] + + for file in files: + if file.endswith('.py'): + filepath = os.path.join(root, file) + relpath = os.path.relpath(filepath, directory) + fstats = analyze_py_file(filepath) + fstats['path'] = relpath + stats['file_details'].append(fstats) + stats['files'] += 1 + stats['total_lines'] += fstats['lines'] + stats['total_imports'] += fstats['imports'] + stats['total_functions'] += fstats['functions'] + stats['total_classes'] += fstats['classes'] + + return stats + +def main(): + if len(sys.argv) < 2: + print("Usage: python py_stats.py [output_file]") + sys.exit(1) + + directory = sys.argv[1] + output_file = sys.argv[2] if len(sys.argv) > 2 else None + + if not os.path.isdir(directory): + print(f"Error: {directory} is not a directory") + sys.exit(1) + + stats = scan_directory(directory) + + output = [] + output.append(f"Python File Statistics for: {directory}") + output.append("=" * 50) + output.append(f"Total .py files: {stats['files']}") + output.append(f"Total lines: {stats['total_lines']}") + output.append(f"Total imports: {stats['total_imports']}") + output.append(f"Total functions: {stats['total_functions']}") + output.append(f"Total classes: {stats['total_classes']}") + output.append("") + + if stats['files'] <= 20: # Show details for small projects + output.append("File details:") + output.append("-" * 50) + for f in stats['file_details']: + output.append(f" {f['path']}: {f['lines']} lines, {f['imports']} imports, {f['functions']} funcs, {f['classes']} classes") + + result = "\n".join(output) + print(result) + + if output_file: + with open(output_file, 'w') as f: + f.write(result) + print(f"\nResults written to: {output_file}") + +if __name__ == '__main__': + main() \ No newline at end of file