mirror of
https://github.com/harvard-edge/cs249r_book.git
synced 2026-05-01 18:19:18 -05:00
Consolidated 21 root-level scripts into logical subdirectories: New structure: - images/: All image management scripts (10 files consolidated from 3 locations) - infrastructure/: CI/CD and container scripts (3 files) - content/: Added formatting scripts (3 files moved from root) - testing/: All test scripts (5 files consolidated) - glossary/: Added standardize_glossaries.py - maintenance/: Added generate_release_notes.py, preflight.py - utilities/: Added validation scripts Benefits: - Reduced root-level clutter (21 → 2 files) - Related scripts grouped logically - Easier to find and maintain scripts - Follows standard project organization patterns Changes: - Created new subdirectories: images/, infrastructure/ - Moved scripts from root to appropriate subdirectories - Consolidated scattered scripts (images were in 3 places) - Updated all pre-commit hook references - Created README files for new directories - Included backup file for rollback if needed Tool: tools/scripts/reorganize_scripts.py (for future reference)
116 lines
3.8 KiB
Python
Executable File
116 lines
3.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Format Python code blocks in .qmd files using Black."""
|
|
|
|
import ast
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import List
|
|
import subprocess
|
|
import tempfile
|
|
|
|
|
|
def is_valid_python(code: str) -> bool:
|
|
"""Check if code string is valid Python syntax."""
|
|
try:
|
|
ast.parse(code)
|
|
return True
|
|
except SyntaxError:
|
|
return False
|
|
|
|
|
|
def format_python_blocks(content: str, line_length: int = 70) -> str:
|
|
"""Find and format Python code blocks in markdown using Black."""
|
|
lines = content.split('\n')
|
|
result = []
|
|
in_python_block = False
|
|
python_lines = []
|
|
block_indent = ""
|
|
|
|
for line in lines:
|
|
# Detect start of Python block
|
|
if re.match(r'^```(\{\.)?python', line):
|
|
in_python_block = True
|
|
result.append(line)
|
|
python_lines = []
|
|
continue
|
|
|
|
# Detect end of Python block
|
|
if in_python_block and line.strip() == '```':
|
|
# Format accumulated Python code with Black
|
|
if python_lines:
|
|
code = '\n'.join(python_lines)
|
|
|
|
# Validate Python syntax before attempting to format
|
|
if not is_valid_python(code):
|
|
# Skip formatting for invalid Python (e.g., shell, pseudocode, etc.)
|
|
result.extend(python_lines)
|
|
else:
|
|
try:
|
|
# Write to temp file
|
|
with tempfile.NamedTemporaryFile(
|
|
mode='w', suffix='.py', delete=False
|
|
) as f:
|
|
f.write(code)
|
|
temp_path = f.name
|
|
|
|
# Run Black with stderr suppressed
|
|
subprocess.run(
|
|
['black', '--line-length', str(line_length),
|
|
'--quiet', temp_path],
|
|
check=True,
|
|
stderr=subprocess.DEVNULL,
|
|
stdout=subprocess.DEVNULL
|
|
)
|
|
|
|
# Read formatted code
|
|
with open(temp_path, 'r') as f:
|
|
formatted = f.read().rstrip()
|
|
|
|
result.extend(formatted.split('\n'))
|
|
|
|
# Cleanup
|
|
Path(temp_path).unlink()
|
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
# If Black fails or isn't installed, keep original
|
|
result.extend(python_lines)
|
|
|
|
python_lines = []
|
|
in_python_block = False
|
|
result.append(line)
|
|
continue
|
|
|
|
# Accumulate Python code
|
|
if in_python_block:
|
|
python_lines.append(line)
|
|
else:
|
|
result.append(line)
|
|
|
|
return '\n'.join(result)
|
|
|
|
|
|
def main(files: List[str], line_length: int = 70) -> int:
|
|
"""Format Python blocks in .qmd files."""
|
|
changed = 0
|
|
for filepath in files:
|
|
path = Path(filepath)
|
|
if path.suffix == '.qmd':
|
|
try:
|
|
content = path.read_text(encoding='utf-8')
|
|
formatted = format_python_blocks(content, line_length)
|
|
|
|
if formatted != content:
|
|
path.write_text(formatted, encoding='utf-8')
|
|
print(f"Formatted: {filepath}")
|
|
changed += 1
|
|
except Exception as e:
|
|
print(f"Error processing {filepath}: {e}",
|
|
file=sys.stderr)
|
|
return 1
|
|
|
|
return 0 if changed == 0 else 1 # Return 1 if changes made
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main(sys.argv[1:]))
|