mirror of
https://github.com/harvard-edge/cs249r_book.git
synced 2026-05-03 16:18:49 -05:00
refactor(tools): reorganize scripts directory structure for better maintainability
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)
This commit is contained in:
115
tools/scripts/content/format_python_in_qmd.py
Executable file
115
tools/scripts/content/format_python_in_qmd.py
Executable file
@@ -0,0 +1,115 @@
|
||||
#!/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:]))
|
||||
Reference in New Issue
Block a user