-
Notifications
You must be signed in to change notification settings - Fork 36
/
build_livedocs.py
143 lines (104 loc) · 3.27 KB
/
build_livedocs.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
#!/usr/bin/env python
import io
import re
def parse(fname):
"""Return blocks of code as list of dicts
Arguments:
fname (str): Relative name of caveats file
"""
blocks = list()
with io.open(fname, "r", encoding="utf-8") as f:
in_block = False
current_block = None
current_header = ""
for number, line in enumerate(f):
number += 1
# Doctests are within a quadruple hashtag header.
if line.startswith("### "):
current_header = line.rstrip()
# The actuat test is within a fenced block.
if line.startswith("```"):
in_block = False
if in_block:
current_block.append(line)
if line.startswith("```python"):
in_block = True
current_block = list()
current_block.append(current_header + " L%d" % number)
blocks.append(current_block)
tests = list()
for block in blocks:
header = (
block[0].strip("# ") # Remove Markdown
.rstrip() # Remove newline
.lower() # PEP08
)
# Remove unsupported characters
header = re.sub(r"\W", "_", header)
# Adding "untested" anywhere in the first line of
# the doctest excludes it from the test.
if "untested" in block[1].lower():
continue
tests.append({
"header": header,
"body": block[1:]
})
return tests
def format_(blocks):
"""Produce Python module from blocks of tests
Arguments:
blocks (list): Blocks of tests from func:`parse()`
"""
tests = list()
function_count = 0 # For each test to have a unique name
for block in blocks:
# Validate docstring format of body
if not any(line[:3] == ">>>" for line in block["body"]):
# A doctest requires at least one `>>>` directive.
continue
function_count += 1
block["header"] = block["header"]
block["count"] = str(function_count)
block["body"] = " ".join(block["body"])
tests.append(u"""\
def test_{count}_{header}():
'''Test {header}
{body}
'''
""".format(**block))
return tests
if __name__ == '__main__':
blocks = parse("README.md")
tests = format_(blocks)
# Write formatted tests
# with open("test_docs.py", "w") as f:
with io.open("test_docs.py", "w", encoding="utf-8") as f:
f.write(u"""\
# -*- coding: utf-8 -*-
import os
import sys
import nose
from nose.tools import assert_raises
if __name__ == "__main__":
print("Initialising Maya..")
from maya import standalone
standalone.initialize()
# For nose
if sys.version_info[0] == 3:
import collections
collections.Callable = collections.abc.Callable
from maya import cmds
import cmdx
argv = sys.argv[:]
argv.extend([
"--verbose",
"--with-doctest",
"test_docs.py",
])
result = nose.main(argv=argv, exit=False)
if os.name == "nt":
# Graceful exit, only Windows seems to like this consistently
standalone.uninitialize()
os._exit(0 if result.success else 1)
""")
f.write("".join(tests))