-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconvert.py
More file actions
126 lines (89 loc) · 3.26 KB
/
convert.py
File metadata and controls
126 lines (89 loc) · 3.26 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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# Converts the original markdown for the course in `orig-source` into
# lesson-builder formtted assignments
from pathlib import Path
import yaml
from textwrap import dedent
dst = Path(Path.cwd().joinpath('assignments'))
if not dst.exists():
# Create if it does not exist
dst.mkdir(parents=True)
import re
def extract(source: str, base_name: str):
# Regex pattern to find python.run blocks with optional height and width
pattern = re.compile(r"```python\.run(?:\:height='?(\d+)'?)?(?:,width='?(\d+)%?'?)?\n(.*?)```",
re.DOTALL)
counter = [1]
code = {}
# Function to replace matched objects
def replacer(match):
m = match.group(0).strip('```')
lines = m.split('\n')
first = lines[0]
py_code = '\n'.join(lines[1:])
if ':' in first:
_, spec = first.split(':')
spec = spec.strip()
_ , height = spec.split('=')
height = int(height.strip("'"))
else:
height = 800
prog_name = f"{base_name}_{counter[0]}.py"
code[prog_name] = py_code
# Construct the replacement string
replacement = f"{{{{ trinket(\"{prog_name}\", width=\"100%\", height=\"{height}\", embed_type=\"python\") | safe }}}}"
counter[0] += 1
return replacement
# Replace matched blocks in the source with the template string
modified_source = pattern.sub(replacer, source)
return modified_source, code
def convert(source_dir, dst_root):
from collections import defaultdict
def mklesson():
return {
'text': '',
'resources': [],
'assignments': []
}
lessons = defaultdict(mklesson)
for f in source_dir.glob('**/*.md'):
e = f.relative_to(source_dir)
source = f.read_text()
p = e.parent
d = e.stem
md, code = extract(source, d)
lesson_path = p.joinpath(d)
dest = dst_root.joinpath(lesson_path)
if not dest.exists():
dest.mkdir(parents=True)
ack = dedent("""
---
Thanks to Trinket.io for providing this assignment,
part of their [Hour of Python](https://hourofpython.com/a-visual-introduction-to-python/)
course.\n""").strip()
(dest.joinpath('trinket.md')).write_text(md+"\n\n"+ack)
for k, v in code.items():
(dest.joinpath(k)).write_text(v)
title = d.replace('-',' ').title()
asgn = {'title': title, 'description':title}
(dest.joinpath('_assignment.yaml')).write_text(yaml.dump(asgn))
l = lessons[str(p)]
l['text'] = str(p.joinpath(str(p)+'.md'))
lesson_title = str(p).replace('-',' ').title()
lesson_text= dedent(f"""
---
title: {lesson_title}
---
# {lesson_title}
""").strip()
(dst.joinpath(p).joinpath(str(p)+'.md')).write_text(lesson_text)
l['assignments'].append(str(lesson_path))
plan = {
'title': '',
'description': '',
'pages': [],
'resources': [],
'sidebar': [],
'lessons': dict(lessons)
}
dst_root.joinpath('lesson-plan.yaml').write_text(yaml.dump(dict(plan)))
convert(Path.cwd().joinpath('orig-source'), dst)