Files
cs249r_book/tools/scripts/format_python_in_qmd.py
Vijay Janapa Reddi 9df531dd4e Enable full book PDF build and add Python formatting utility
- Uncomment all chapters in PDF config for complete book builds
- Add format_python_in_qmd.py script for code formatting
- Remove temporary working files (notes, footnote catalog)
- Update changelog (no new content changes since last publish)
2025-10-05 12:19:19 -04:00

98 lines
3.1 KiB
Python
Executable File

#!/usr/bin/env python3
"""Format Python code blocks in .qmd files using Black."""
import re
import sys
from pathlib import Path
from typing import List
import subprocess
import tempfile
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)
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
subprocess.run(
['black', '--line-length', str(line_length),
'--quiet', temp_path],
check=True
)
# 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:]))