Files
metabuilder/python/summary.py
2026-03-09 22:30:41 +00:00

290 lines
7.8 KiB
Python
Executable File

#!/usr/bin/env python3
"""
MetaBuilder Project Summary Generator
Self-documenting argparse script to generate project summaries
"""
import argparse
import subprocess
import json
from pathlib import Path
from datetime import datetime
def run_cmd(cmd, capture=True):
"""Run shell command and optionally capture output"""
if capture:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
return result.stdout.strip()
else:
subprocess.run(cmd, shell=True)
return None
def count_files(pattern):
"""Count files matching glob pattern"""
try:
result = run_cmd(f"find . -type f -name '{pattern}' | wc -l")
return int(result)
except:
return 0
def get_git_stats():
"""Get Git repository statistics"""
return {
'branch': run_cmd('git branch --show-current'),
'commits': run_cmd('git rev-list --count HEAD'),
'contributors': run_cmd('git shortlog -sn --all | wc -l'),
'last_commit': run_cmd('git log -1 --format="%h - %s (%ar)"'),
}
def get_code_stats():
"""Get code statistics by language"""
stats = {}
languages = {
'TypeScript': '*.ts',
'JavaScript': '*.js',
'Python': '*.py',
'C++': '*.cpp',
'QML': '*.qml',
'SCSS': '*.scss',
'JSON': '*.json',
'YAML': '*.yaml',
}
for lang, pattern in languages.items():
count = count_files(pattern)
if count > 0:
stats[lang] = count
return stats
def get_docker_status():
"""Get Docker container status"""
try:
containers = run_cmd("docker ps --format '{{.Names}}: {{.Status}}'")
return containers.split('\n') if containers else []
except:
return []
def get_npm_packages():
"""Get npm workspace packages"""
try:
result = run_cmd('npm ls --json --depth=0')
data = json.loads(result)
return list(data.get('dependencies', {}).keys())
except:
return []
def get_subproject_info():
"""Get information about subprojects"""
subprojects = {
'dbal': 'Database Abstraction Layer',
'workflow': 'DAG Workflow Engine',
'workflowui': 'Workflow UI (Next.js)',
'fakemui': 'Material Design 3 Components',
'codegen': 'CodeForge IDE',
'pastebin': 'Code Snippet Sharing',
'postgres': 'PostgreSQL Admin Dashboard',
'gameengine': 'SDL3/bgfx Game Engine',
'mojo': 'Mojo Compiler Implementation',
}
info = {}
for name, description in subprojects.items():
path = Path(name)
if path.exists():
ts_files = count_files(f'{name}/*.ts')
py_files = count_files(f'{name}/*.py')
info[name] = {
'description': description,
'typescript': ts_files,
'python': py_files,
}
return info
def generate_summary_markdown():
"""Generate full project summary in markdown"""
git = get_git_stats()
code = get_code_stats()
docker = get_docker_status()
packages = get_npm_packages()
subprojects = get_subproject_info()
output = [
f"# MetaBuilder Project Summary",
f"**Generated**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
"",
"## Git Repository",
f"- **Branch**: {git['branch']}",
f"- **Commits**: {git['commits']}",
f"- **Contributors**: {git['contributors']}",
f"- **Last Commit**: {git['last_commit']}",
"",
"## Code Statistics",
]
for lang, count in sorted(code.items(), key=lambda x: x[1], reverse=True):
output.append(f"- **{lang}**: {count:,} files")
output.extend([
"",
"## Subprojects",
])
for name, info in sorted(subprojects.items()):
output.append(f"### {name}")
output.append(f"**Description**: {info['description']}")
if info['typescript'] > 0:
output.append(f"- TypeScript files: {info['typescript']}")
if info['python'] > 0:
output.append(f"- Python files: {info['python']}")
output.append("")
if docker:
output.extend([
"## Docker Containers",
])
for container in docker:
output.append(f"- {container}")
output.append("")
if packages:
output.extend([
"## NPM Dependencies",
f"**Total**: {len(packages)} packages",
"",
])
for pkg in sorted(packages[:20]): # Top 20
output.append(f"- {pkg}")
if len(packages) > 20:
output.append(f"- ... and {len(packages) - 20} more")
output.append("")
output.extend([
"## Quick Commands",
"```bash",
"# Start everything",
"./metabuilder.py quick-start",
"",
"# C++ development",
"./metabuilder.py dev start --build --shell",
"",
"# Run tests",
"./metabuilder.py test run comprehensive",
"",
"# Check status",
"./metabuilder.py status",
"```",
])
return '\n'.join(output)
def generate_summary_json():
"""Generate project summary in JSON format"""
return json.dumps({
'timestamp': datetime.now().isoformat(),
'git': get_git_stats(),
'code': get_code_stats(),
'docker': get_docker_status(),
'subprojects': get_subproject_info(),
}, indent=2)
def generate_summary_compact():
"""Generate compact one-line summary"""
git = get_git_stats()
code = get_code_stats()
total_files = sum(code.values())
return f"MetaBuilder [{git['branch']}] {git['commits']} commits, {total_files:,} files across {len(code)} languages"
def main():
parser = argparse.ArgumentParser(
description='MetaBuilder Project Summary Generator',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
# Generate markdown summary
%(prog)s --format markdown
# Generate JSON summary
%(prog)s --format json
# Generate compact summary
%(prog)s --format compact
# Save to file
%(prog)s --format markdown --output summary.md
# Show git stats only
%(prog)s --git
# Show code stats only
%(prog)s --code
# Show Docker status
%(prog)s --docker
"""
)
parser.add_argument(
'--format',
choices=['markdown', 'json', 'compact'],
default='markdown',
help='Output format (default: markdown)'
)
parser.add_argument(
'--output', '-o',
type=str,
help='Output file (default: stdout)'
)
parser.add_argument(
'--git',
action='store_true',
help='Show only Git statistics'
)
parser.add_argument(
'--code',
action='store_true',
help='Show only code statistics'
)
parser.add_argument(
'--docker',
action='store_true',
help='Show only Docker status'
)
args = parser.parse_args()
# Handle specific stats requests
if args.git:
git = get_git_stats()
output = '\n'.join([f"{k}: {v}" for k, v in git.items()])
elif args.code:
code = get_code_stats()
output = '\n'.join([f"{k}: {v}" for k, v in sorted(code.items(), key=lambda x: x[1], reverse=True)])
elif args.docker:
docker = get_docker_status()
output = '\n'.join(docker) if docker else "No Docker containers running"
else:
# Generate full summary
if args.format == 'markdown':
output = generate_summary_markdown()
elif args.format == 'json':
output = generate_summary_json()
else: # compact
output = generate_summary_compact()
# Write output
if args.output:
Path(args.output).write_text(output)
print(f"✅ Summary written to {args.output}")
else:
print(output)
if __name__ == '__main__':
main()