mirror of
https://github.com/sstent/FitTrack_GarminSync.git
synced 2026-01-26 09:01:53 +00:00
129 lines
4.1 KiB
Python
Executable File
129 lines
4.1 KiB
Python
Executable File
import os
|
|
import ast
|
|
from pathlib import Path
|
|
|
|
def get_docstring(node):
|
|
"""Extract docstring from a node."""
|
|
return ast.get_docstring(node) or ""
|
|
|
|
def analyze_file(filepath):
|
|
"""Analyze a Python file and extract structure."""
|
|
try:
|
|
with open(filepath, 'r', encoding='utf-8') as f:
|
|
tree = ast.parse(f.read())
|
|
except Exception as e:
|
|
return {'error': str(e)}
|
|
|
|
result = {
|
|
'classes': [],
|
|
'functions': [],
|
|
'imports': []
|
|
}
|
|
|
|
for node in ast.walk(tree):
|
|
if isinstance(node, ast.ClassDef):
|
|
methods = []
|
|
for item in node.body:
|
|
if isinstance(item, ast.FunctionDef):
|
|
methods.append({
|
|
'name': item.name,
|
|
'docstring': get_docstring(item)
|
|
})
|
|
|
|
result['classes'].append({
|
|
'name': node.name,
|
|
'docstring': get_docstring(node),
|
|
'methods': methods
|
|
})
|
|
|
|
elif isinstance(node, ast.FunctionDef) and node.col_offset == 0:
|
|
# Only top-level functions
|
|
result['functions'].append({
|
|
'name': node.name,
|
|
'docstring': get_docstring(node)
|
|
})
|
|
|
|
return result
|
|
|
|
def generate_project_map(root_dir, output_file='project_map.txt', exclude_dirs=None):
|
|
"""Generate a project map for LLM consumption."""
|
|
if exclude_dirs is None:
|
|
exclude_dirs = {'__pycache__', '.git', 'venv', 'env', '.venv', 'node_modules', '.pytest_cache'}
|
|
|
|
root_path = Path(root_dir)
|
|
lines = []
|
|
|
|
lines.append("=" * 80)
|
|
lines.append(f"PROJECT MAP: {root_path.name}")
|
|
lines.append("=" * 80)
|
|
lines.append("")
|
|
|
|
# Collect all Python files
|
|
py_files = []
|
|
for root, dirs, files in os.walk(root_path):
|
|
# Remove excluded directories
|
|
dirs[:] = [d for d in dirs if d not in exclude_dirs]
|
|
|
|
for file in sorted(files):
|
|
if file.endswith('.py'):
|
|
py_files.append(Path(root) / file)
|
|
|
|
# Analyze each file
|
|
for filepath in sorted(py_files):
|
|
rel_path = filepath.relative_to(root_path)
|
|
lines.append(f"\n{'─' * 80}")
|
|
lines.append(f"FILE: {rel_path}")
|
|
lines.append('─' * 80)
|
|
|
|
analysis = analyze_file(filepath)
|
|
|
|
if 'error' in analysis:
|
|
lines.append(f" ⚠ Error parsing file: {analysis['error']}")
|
|
continue
|
|
|
|
# Classes
|
|
if analysis['classes']:
|
|
lines.append("\n CLASSES:")
|
|
for cls in analysis['classes']:
|
|
lines.append(f" • {cls['name']}")
|
|
if cls['docstring']:
|
|
doc_preview = cls['docstring'].split('\n')[0][:60]
|
|
lines.append(f" └─ {doc_preview}")
|
|
|
|
if cls['methods']:
|
|
lines.append(f" Methods:")
|
|
for method in cls['methods']:
|
|
lines.append(f" - {method['name']}()")
|
|
|
|
# Functions
|
|
if analysis['functions']:
|
|
lines.append("\n FUNCTIONS:")
|
|
for func in analysis['functions']:
|
|
lines.append(f" • {func['name']}()")
|
|
if func['docstring']:
|
|
doc_preview = func['docstring'].split('\n')[0][:60]
|
|
lines.append(f" └─ {doc_preview}")
|
|
|
|
if not analysis['classes'] and not analysis['functions']:
|
|
lines.append(" (No classes or functions found)")
|
|
|
|
# Write to file
|
|
output = '\n'.join(lines)
|
|
with open(output_file, 'w', encoding='utf-8') as f:
|
|
f.write(output)
|
|
|
|
print(f"Project map generated: {output_file}")
|
|
print(f"Total files analyzed: {len(py_files)}")
|
|
return output
|
|
|
|
# Usage
|
|
if __name__ == "__main__":
|
|
# Change this to your project directory
|
|
project_dir = "."
|
|
|
|
# Generate the map
|
|
generate_project_map(project_dir, output_file="project_map.txt")
|
|
|
|
# Also print to console
|
|
with open("project_map.txt", 'r') as f:
|
|
print(f.read()) |