-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpythia-gallery.py
executable file
·147 lines (119 loc) · 4.12 KB
/
pythia-gallery.py
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env python3
import sys
import json
import urllib.request
import yaml
import concurrent.futures
import traceback
import argparse
from unist import *
LAYOUT_STYLE = {
"display": "inline-block",
"borderRadius": 8,
"color": "white",
"padding": 5,
"margin": 5,
}
DEFAULT_STYLE = {"background": "#4E66F6", **LAYOUT_STYLE}
styles = {
"domains": {"background": "#7A77B4", **LAYOUT_STYLE},
"packages": {"background": "#B83BC0", **LAYOUT_STYLE},
}
def fetch_yaml(url: str):
print(f"Fetching {url}", file=sys.stderr, flush=True)
with urllib.request.urlopen(url) as response:
body = response.read().decode()
return yaml.load(body, yaml.SafeLoader)
def render_cookbook(name: str):
try:
print(f"Rendering {name}", file=sys.stderr, flush=True)
raw_base_url = (
f"https://raw.githubusercontent.com/ProjectPythia-MystMD/{name}/main"
)
config_url = f"{raw_base_url}/myst.yml"
book_url = f"https://projectpythia-mystmd.github.io/{name}"
# Load JB data
config = fetch_yaml(config_url)
title = config["project"]["title"]
# Fetch gallery metadata
gallery_url = f"{raw_base_url}/_gallery_info.yml"
gallery_data = fetch_yaml(gallery_url)
image_name = gallery_data["thumbnail"]
image_url = f"{raw_base_url}/{image_name}"
# Build tags
tags = gallery_data["tags"]
return {
"type": "card",
"url": book_url,
"children": [
{"type": "cardTitle", "children": [text(title)]},
div(
[
image(image_url),
div(
[
span(
[text(item)],
style=styles.get(name, DEFAULT_STYLE),
)
for name, items in tags.items()
if items is not None
for item in items
]
),
],
),
],
}
except Exception as err:
print(f"\n\nError rendering {name}", file=sys.stderr)
traceback.print_exception(err, file=sys.stderr)
return None
def render_cookbooks(pool):
with open("cookbook_gallery.txt") as f:
body = f.read()
return [c for c in pool.map(render_cookbook, body.splitlines()) if c is not None]
def run_directive(name, data):
assert name == "pythia-cookbooks"
return [{"type": "pythia-cookbooks", "children": []}]
def run_transform(name, data):
with concurrent.futures.ThreadPoolExecutor() as pool:
# Find our cookbook nodes in the AST
cookbook_nodes = find_all_by_type(data, "pythia-cookbooks")
# In-place mutate the AST to replace cookbook nodes with card grids
children = render_cookbooks(pool)
# Mutate our cookbook nodes in-place
for node in cookbook_nodes:
node.clear()
node.update(grid([1, 1, 2, 3], children))
node["children"] = children
return data
pythiaGalleryDirective = {
"name": "pythia-cookbooks",
"doc": "An example directive for embedding a Pythia cookbook gallery.",
}
pythiaGalleryTransform = {
"stage": "document",
}
PLUGIN_SPEC = {
"name": "Pythia Gallery",
"directives": [pythiaGalleryDirective],
"transforms": [pythiaGalleryTransform],
}
if __name__ == "__main__":
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument("--role")
group.add_argument("--directive")
group.add_argument("--transform")
args = parser.parse_args()
if args.directive:
data = json.load(sys.stdin)
json.dump(run_directive(args.directive, data), sys.stdout)
elif args.transform:
data = json.load(sys.stdin)
json.dump(run_transform(args.transform, data), sys.stdout)
elif args.role:
raise NotImplementedError
else:
json.dump(PLUGIN_SPEC, sys.stdout)