-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathformat_examples.py
More file actions
executable file
·108 lines (88 loc) · 3.64 KB
/
Copy pathformat_examples.py
File metadata and controls
executable file
·108 lines (88 loc) · 3.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#!/usr/bin/env python3
"""Normalize Markdown example source files without changing prose or code."""
from __future__ import annotations
import argparse
import tomllib
from pathlib import Path
from typing import Any
ROOT = Path(__file__).resolve().parents[1]
SOURCE_DIR = ROOT / "src" / "example_sources"
FRONTMATTER_ORDER = ["slug", "title", "section", "summary", "doc_path", "scope_first_pass", "standalone_cells", "see_also", "expected_output", "min_python", "version_sensitive", "version_notes"]
def toml_value(value: Any) -> str:
if isinstance(value, bool):
return "true" if value else "false"
if isinstance(value, str):
return '"' + value.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\\n") + '"'
if isinstance(value, list) and all(isinstance(item, str) for item in value):
if len(value) == 0:
return "[]"
inner = "\n".join(f" {toml_value(item)}," for item in value)
return "[\n" + inner + "\n]"
raise TypeError(f"Unsupported TOML value: {value!r}")
def ordered_keys(data: dict[str, Any]) -> list[str]:
known = [key for key in FRONTMATTER_ORDER if key in data]
unknown = sorted(key for key in data if key not in FRONTMATTER_ORDER)
return known + unknown
def dump_toml(data: dict[str, Any]) -> str:
return "\n".join(f"{key} = {toml_value(data[key])}" for key in ordered_keys(data)) + "\n"
def normalize_body(text: str) -> str:
lines = [line.rstrip() for line in text.replace("\r\n", "\n").split("\n")]
out: list[str] = []
blank = False
in_fence = False
for line in lines:
if line.startswith("```"):
if line == "```py":
line = "```python"
in_fence = not in_fence
if not in_fence and line == "":
if blank:
continue
blank = True
else:
blank = False
out.append(line)
return "\n".join(out).strip()
def split_frontmatter(text: str, path: Path) -> tuple[dict[str, Any], str]:
normalized = text.replace("\r\n", "\n")
if not normalized.startswith("+++\n"):
raise ValueError(f"{path}: expected +++ frontmatter")
marker = "\n+++\n"
end = normalized.find(marker, 4)
if end < 0:
raise ValueError(f"{path}: missing closing +++")
frontmatter = tomllib.loads(normalized[4:end])
return frontmatter, normalized[end + len(marker) :]
def format_markdown(path: Path) -> str:
frontmatter, body = split_frontmatter(path.read_text(), path)
return "+++\n" + dump_toml(frontmatter) + "+++\n\n" + normalize_body(body) + "\n"
def format_manifest(path: Path) -> str:
data = tomllib.loads(path.read_text())
sections = [
f"python_version = {toml_value(data['python_version'])}",
f"docs_base_url = {toml_value(data['docs_base_url'])}",
"",
f"order = {toml_value(data['order'])}",
]
return "\n".join(sections) + "\n"
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--check", action="store_true")
args = parser.parse_args()
changed: list[Path] = []
paths = [SOURCE_DIR / "manifest.toml", *sorted(SOURCE_DIR.glob("*.md"))]
for path in paths:
original = path.read_text()
formatted = format_manifest(path) if path.name == "manifest.toml" else format_markdown(path)
if formatted != original:
changed.append(path)
if not args.check:
path.write_text(formatted)
if changed:
for path in changed:
print(path)
return 1 if args.check else 0
print("Example sources already formatted.")
return 0
if __name__ == "__main__":
raise SystemExit(main())