Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
galaxyproject
GitHub Repository: galaxyproject/training-material
Path: blob/main/bin/knit.py
1677 views
1
#!/usr/bin/env python
2
import argparse
3
import re
4
import sys
5
import knittingneedles as knit
6
7
8
parser = argparse.ArgumentParser(
9
description="Extract specially formatted diffs from tutorials as a series of patches to apply"
10
)
11
parser.add_argument("tutorial", type=argparse.FileType("r+"), help="Input tutorial")
12
parser.add_argument(
13
"--patches", nargs='+', help="The patches to knit together with the tutorial"
14
)
15
args = parser.parse_args()
16
tutorial_contents = args.tutorial.read().split("\n")
17
chunks = []
18
19
20
# load patches
21
diffs = []
22
for patch in args.patches:
23
with open(patch, "r") as handle:
24
data = handle.readlines()
25
subject = [x for x in data[0:5] if x.startswith('Subject:')]
26
if len(subject) != 1:
27
commit = "MISSING"
28
else:
29
if subject[0].count(": ") >= 2:
30
commit = subject[0].split(": ")[2]
31
else:
32
commit = "MISSING"
33
34
indexindex = [idx for (idx, x) in enumerate(data) if x.startswith('index ')]
35
if len(indexindex) == 0:
36
# take a guess, it's our format?
37
data = [x.rstrip("\n") for x in data[5:-3]]
38
else:
39
# If 'index ' then we start at the next line
40
data = [x.rstrip("\n") for x in data[indexindex[0] + 1:-3]]
41
42
diffs.append((commit, data))
43
44
current = None
45
diff_idx = 0
46
prev_line = None
47
for line, text in enumerate(tutorial_contents):
48
m = re.match(knit.BOXES, text)
49
if m:
50
depth = m.group(1).count(">")
51
else:
52
depth = 0
53
(unprefixed, prefix) = knit.stripN(text, depth)
54
m0 = re.match(knit.BOX_PREFIX, unprefixed)
55
m1 = re.match(knit.BOX_OPEN, unprefixed)
56
m2 = re.match(knit.BOX_CLOSE, unprefixed)
57
58
if m0:
59
current = []
60
if m1 and current is None:
61
current = []
62
63
if current is not None:
64
current.append(unprefixed)
65
else:
66
chunks.append(text)
67
68
if current and len(current) > 2 and (current[-2].strip() == "```") and not m2:
69
chunks.extend([prefix + x for x in current])
70
# chunks.append('REJECT)')
71
current = None
72
73
if m2 and current and len(current) > 0:
74
(amount, _) = knit.removeWhitespacePrefix(current)
75
prefix_text = prefix + (amount * " ")
76
from_patch = diffs[diff_idx]
77
78
# Compare the diff messages
79
obs_msg = knit.extractCommitMsg(current).strip()
80
exp_msg = from_patch[0].strip()
81
obs_extra = m2.groups()[1]
82
if obs_msg != exp_msg:
83
# Most just got truncated
84
if exp_msg not in obs_msg:
85
print(f"WARNING: Diff messages do NOT line up: {obs_msg} != {exp_msg}")
86
# Replace with current message
87
exp_msg = obs_msg
88
89
# Knit it anyway
90
new_diff = from_patch[1]
91
chunks.append(prefix_text + "{% raw %}")
92
chunks.append(prefix_text + "```diff")
93
chunks.extend([f'{prefix}{amount * " "}{line}' for line in new_diff])
94
chunks.append(prefix_text + "{% endraw %}")
95
chunks.append(prefix_text + "```")
96
chunks.append(prefix_text + '{: data-commit="%s"%s}' % (exp_msg, obs_extra))
97
diff_idx += 1
98
current = None
99
100
prev_line = text
101
102
# Overwrite the original tutorial
103
args.tutorial.seek(0)
104
args.tutorial.truncate(0)
105
# The last chunk is a newline for some reason.
106
for c in chunks[0:-1]:
107
args.tutorial.write(c + "\n")
108
args.tutorial.close()
109
110