mktestdocs 0.1.2__py2.py3-none-any.whl → 0.2.1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mktestdocs/__init__.py +3 -1
- mktestdocs/__main__.py +75 -22
- {mktestdocs-0.1.2.dist-info → mktestdocs-0.2.1.dist-info}/METADATA +2 -8
- mktestdocs-0.2.1.dist-info/RECORD +7 -0
- {mktestdocs-0.1.2.dist-info → mktestdocs-0.2.1.dist-info}/WHEEL +1 -1
- {mktestdocs-0.1.2.dist-info → mktestdocs-0.2.1.dist-info}/top_level.txt +0 -1
- mktestdocs-0.1.2.dist-info/RECORD +0 -12
- tests/__init__.py +0 -0
- tests/test_actual_docstrings.py +0 -60
- tests/test_class.py +0 -73
- tests/test_codeblock.py +0 -56
- tests/test_markdown.py +0 -27
- {mktestdocs-0.1.2.dist-info → mktestdocs-0.2.1.dist-info}/LICENSE +0 -0
mktestdocs/__init__.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
from mktestdocs.__main__ import (
|
2
|
+
register_executor,
|
2
3
|
check_codeblock,
|
3
4
|
grab_code_blocks,
|
4
5
|
check_docstring,
|
@@ -6,10 +7,11 @@ from mktestdocs.__main__ import (
|
|
6
7
|
get_codeblock_members,
|
7
8
|
)
|
8
9
|
|
9
|
-
__version__ = "0.1
|
10
|
+
__version__ = "0.2.1"
|
10
11
|
|
11
12
|
__all__ = [
|
12
13
|
"__version__",
|
14
|
+
"register_executor",
|
13
15
|
"check_codeblock",
|
14
16
|
"grab_code_blocks",
|
15
17
|
"check_docstring",
|
mktestdocs/__main__.py
CHANGED
@@ -1,8 +1,56 @@
|
|
1
1
|
import inspect
|
2
2
|
import pathlib
|
3
|
+
import subprocess
|
3
4
|
import textwrap
|
4
5
|
|
5
6
|
|
7
|
+
_executors = {}
|
8
|
+
|
9
|
+
|
10
|
+
def register_executor(lang, executor):
|
11
|
+
"""Add a new executor for markdown code blocks
|
12
|
+
|
13
|
+
lang should be the tag used after the opening ```
|
14
|
+
executor should be a callable that takes one argument:
|
15
|
+
the code block found
|
16
|
+
"""
|
17
|
+
_executors[lang] = executor
|
18
|
+
|
19
|
+
|
20
|
+
def exec_bash(source):
|
21
|
+
"""Exec the bash source given in a new subshell
|
22
|
+
|
23
|
+
Does not return anything, but if any command returns not-0 an error
|
24
|
+
will be raised
|
25
|
+
"""
|
26
|
+
command = ["bash", "-e", "-u", "-c", source]
|
27
|
+
try:
|
28
|
+
subprocess.run(command, check=True)
|
29
|
+
except Exception:
|
30
|
+
print(source)
|
31
|
+
raise
|
32
|
+
|
33
|
+
|
34
|
+
register_executor("bash", exec_bash)
|
35
|
+
|
36
|
+
|
37
|
+
def exec_python(source):
|
38
|
+
"""Exec the python source given in a new module namespace
|
39
|
+
|
40
|
+
Does not return anything, but exceptions raised by the source
|
41
|
+
will propagate out unmodified
|
42
|
+
"""
|
43
|
+
try:
|
44
|
+
exec(source, {"__MODULE__": "__main__"})
|
45
|
+
except Exception:
|
46
|
+
print(source)
|
47
|
+
raise
|
48
|
+
|
49
|
+
|
50
|
+
register_executor("", exec_python)
|
51
|
+
register_executor("python", exec_python)
|
52
|
+
|
53
|
+
|
6
54
|
def get_codeblock_members(*classes):
|
7
55
|
"""
|
8
56
|
Grabs the docstrings of any methods of any classes that are passed in.
|
@@ -61,49 +109,54 @@ def check_docstring(obj, lang=""):
|
|
61
109
|
"""
|
62
110
|
Given a function, test the contents of the docstring.
|
63
111
|
"""
|
112
|
+
if lang not in _executors:
|
113
|
+
raise LookupError(
|
114
|
+
f"{lang} is not a supported language to check\n"
|
115
|
+
"\tHint: you can add support for any language by using register_executor"
|
116
|
+
)
|
117
|
+
executor = _executors[lang]
|
64
118
|
for b in grab_code_blocks(obj.__doc__, lang=lang):
|
65
|
-
|
66
|
-
exec(b, {"__MODULE__": "__main__"})
|
67
|
-
except Exception:
|
68
|
-
print(f"Error Encountered in `{obj.__name__}`. Caused by:\n")
|
69
|
-
print(b)
|
70
|
-
raise
|
119
|
+
executor(b)
|
71
120
|
|
72
121
|
|
73
122
|
def check_raw_string(raw, lang="python"):
|
74
123
|
"""
|
75
124
|
Given a raw string, test the contents.
|
76
125
|
"""
|
126
|
+
if lang not in _executors:
|
127
|
+
raise LookupError(
|
128
|
+
f"{lang} is not a supported language to check\n"
|
129
|
+
"\tHint: you can add support for any language by using register_executor"
|
130
|
+
)
|
131
|
+
executor = _executors[lang]
|
77
132
|
for b in grab_code_blocks(raw, lang=lang):
|
78
|
-
|
79
|
-
exec(b, {"__MODULE__": "__main__"})
|
80
|
-
except Exception:
|
81
|
-
print(b)
|
82
|
-
raise
|
133
|
+
executor(b)
|
83
134
|
|
84
135
|
|
85
136
|
def check_raw_file_full(raw, lang="python"):
|
137
|
+
if lang not in _executors:
|
138
|
+
raise LookupError(
|
139
|
+
f"{lang} is not a supported language to check\n"
|
140
|
+
"\tHint: you can add support for any language by using register_executor"
|
141
|
+
)
|
142
|
+
executor = _executors[lang]
|
86
143
|
all_code = ""
|
87
144
|
for b in grab_code_blocks(raw, lang=lang):
|
88
145
|
all_code = f"{all_code}\n{b}"
|
89
|
-
|
90
|
-
|
91
|
-
except Exception:
|
92
|
-
print(all_code)
|
93
|
-
raise
|
94
|
-
|
146
|
+
executor(all_code)
|
147
|
+
|
95
148
|
|
96
|
-
def check_md_file(fpath, memory=False):
|
149
|
+
def check_md_file(fpath, memory=False, lang="python"):
|
97
150
|
"""
|
98
151
|
Given a markdown file, parse the contents for python code blocks
|
99
|
-
and check that each
|
152
|
+
and check that each independent block does not cause an error.
|
100
153
|
|
101
154
|
Arguments:
|
102
155
|
fpath: path to markdown file
|
103
|
-
memory:
|
156
|
+
memory: whether or not previous code-blocks should be remembered
|
104
157
|
"""
|
105
158
|
text = pathlib.Path(fpath).read_text()
|
106
159
|
if not memory:
|
107
|
-
check_raw_string(text, lang=
|
160
|
+
check_raw_string(text, lang=lang)
|
108
161
|
else:
|
109
|
-
check_raw_file_full(text, lang=
|
162
|
+
check_raw_file_full(text, lang=lang)
|
@@ -1,13 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: mktestdocs
|
3
|
-
Version: 0.1
|
4
|
-
|
5
|
-
Home-page: UNKNOWN
|
6
|
-
License: UNKNOWN
|
7
|
-
Platform: UNKNOWN
|
3
|
+
Version: 0.2.1
|
4
|
+
License-File: LICENSE
|
8
5
|
Provides-Extra: test
|
9
6
|
Requires-Dist: pytest (>=4.0.2) ; extra == 'test'
|
10
7
|
|
11
|
-
UNKNOWN
|
12
|
-
|
13
|
-
|
@@ -0,0 +1,7 @@
|
|
1
|
+
mktestdocs/__init__.py,sha256=_iVQPmcuxkjOr-bEOP4DEygx6mnG_6fP4wJBhbc2G8E,371
|
2
|
+
mktestdocs/__main__.py,sha256=BO5LopXLAeKFFuKcT0KaeErUeFXt8ekjIiyrTymBG3k,4508
|
3
|
+
mktestdocs-0.2.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
4
|
+
mktestdocs-0.2.1.dist-info/METADATA,sha256=67xAXa_sIfpXAHDaOiKJPxRUqXQekbdMhZDqXQzL5Ec,148
|
5
|
+
mktestdocs-0.2.1.dist-info/WHEEL,sha256=a-zpFRIJzOq5QfuhBzbhiA1eHTzNCJn8OdRvhdNX0Rk,110
|
6
|
+
mktestdocs-0.2.1.dist-info/top_level.txt,sha256=1XGYsQSl3FsAtilWThIet3WOJQSuzQXXn6sQA7hxlho,11
|
7
|
+
mktestdocs-0.2.1.dist-info/RECORD,,
|
@@ -1,12 +0,0 @@
|
|
1
|
-
mktestdocs/__init__.py,sha256=OFT05l99yabbzwBSEyoxcy6EOeQ8OJZ-Aj42-6DaB2U,323
|
2
|
-
mktestdocs/__main__.py,sha256=xZoRTfWCTJltef-katbq9XY_OK0GDaFggwhcXIBfMTk,3069
|
3
|
-
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
-
tests/test_actual_docstrings.py,sha256=N1yIuHOBNhv2qR2yO1DkqiBNvHK3_o_pbLJCHLKUa68,940
|
5
|
-
tests/test_class.py,sha256=lkZ73We8Hb4IvPbQVn8w5LX5zMHptFHkUcJ3xfBJqgc,1220
|
6
|
-
tests/test_codeblock.py,sha256=FxyPZZw1lVLFWXB1BErciHP6h-kFNBLLPU9UX_6uBfE,903
|
7
|
-
tests/test_markdown.py,sha256=ndriPDsL5rI0mPhDJDeTRwmDWod6DXXlm05CRNKhDdk,827
|
8
|
-
mktestdocs-0.1.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
9
|
-
mktestdocs-0.1.2.dist-info/METADATA,sha256=e0ET9ESs91i_AtXs_TifyTbZa0aGledTBv_TTzXO-ss,207
|
10
|
-
mktestdocs-0.1.2.dist-info/WHEEL,sha256=Z-nyYpwrcSqxfdux5Mbn_DQ525iP7J2DG3JgGvOYyTQ,110
|
11
|
-
mktestdocs-0.1.2.dist-info/top_level.txt,sha256=Wh9mCrbRZsALS8VKzSi8ifKBj95gf-BHeWQCoTTNBKc,17
|
12
|
-
mktestdocs-0.1.2.dist-info/RECORD,,
|
tests/__init__.py
DELETED
File without changes
|
tests/test_actual_docstrings.py
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
import pytest
|
2
|
-
from mktestdocs import check_docstring
|
3
|
-
|
4
|
-
|
5
|
-
def foobar_good(a, b):
|
6
|
-
"""
|
7
|
-
Returns a + b.
|
8
|
-
|
9
|
-
Examples:
|
10
|
-
|
11
|
-
```python
|
12
|
-
import random
|
13
|
-
|
14
|
-
random.random()
|
15
|
-
assert 'a' + 'b' == 'ab'
|
16
|
-
assert 1 + 2 == 3
|
17
|
-
```
|
18
|
-
"""
|
19
|
-
return a + b
|
20
|
-
|
21
|
-
|
22
|
-
def foobar_also_good(a, b):
|
23
|
-
"""
|
24
|
-
Returns a + b.
|
25
|
-
|
26
|
-
Examples:
|
27
|
-
|
28
|
-
```python
|
29
|
-
import random
|
30
|
-
|
31
|
-
assert random.random() < 10
|
32
|
-
```
|
33
|
-
"""
|
34
|
-
return a + b
|
35
|
-
|
36
|
-
|
37
|
-
def foobar_bad(a, b):
|
38
|
-
"""
|
39
|
-
Returns a + b.
|
40
|
-
|
41
|
-
Examples:
|
42
|
-
|
43
|
-
```python
|
44
|
-
assert foobar(1, 2) == 4
|
45
|
-
```
|
46
|
-
"""
|
47
|
-
return a + b
|
48
|
-
|
49
|
-
|
50
|
-
@pytest.mark.parametrize("func", [foobar_good, foobar_also_good])
|
51
|
-
def test_base_docstrings(func):
|
52
|
-
check_docstring(func)
|
53
|
-
|
54
|
-
|
55
|
-
@pytest.mark.parametrize("func", [foobar_bad])
|
56
|
-
def test_base_docstrings_bad(func, capsys):
|
57
|
-
with pytest.raises(Exception):
|
58
|
-
check_docstring(func)
|
59
|
-
capsys.readouterr()
|
60
|
-
assert func.__name__ in capsys.readouterr().out
|
tests/test_class.py
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
import pytest
|
2
|
-
|
3
|
-
from mktestdocs import get_codeblock_members, check_docstring
|
4
|
-
|
5
|
-
|
6
|
-
class Dinosaur:
|
7
|
-
"""
|
8
|
-
This is a dino.
|
9
|
-
|
10
|
-
```python
|
11
|
-
from dinosaur import Dinosaur
|
12
|
-
|
13
|
-
assert Dinosaur().name == 'trex'
|
14
|
-
```
|
15
|
-
"""
|
16
|
-
|
17
|
-
def __init__(self):
|
18
|
-
self.name = "trex"
|
19
|
-
|
20
|
-
@staticmethod
|
21
|
-
def a(value):
|
22
|
-
"""
|
23
|
-
Returns value
|
24
|
-
|
25
|
-
Example:
|
26
|
-
|
27
|
-
```python
|
28
|
-
from dinosaur import Dinosaur
|
29
|
-
|
30
|
-
dino = Dinosaur()
|
31
|
-
assert dino.a(1) == 1
|
32
|
-
```
|
33
|
-
"""
|
34
|
-
return value
|
35
|
-
|
36
|
-
@classmethod
|
37
|
-
def b(cls, value):
|
38
|
-
"""
|
39
|
-
Returns value
|
40
|
-
|
41
|
-
Example:
|
42
|
-
|
43
|
-
```python
|
44
|
-
from dinosaur import Dinosaur
|
45
|
-
assert Dinosaur.b(1) == 1
|
46
|
-
```
|
47
|
-
"""
|
48
|
-
return value
|
49
|
-
|
50
|
-
def hello(self):
|
51
|
-
"""
|
52
|
-
Returns value
|
53
|
-
|
54
|
-
Example:
|
55
|
-
|
56
|
-
```python
|
57
|
-
from dinosaur import Dinosaur
|
58
|
-
assert Dinosaur().name == 'trex'
|
59
|
-
```
|
60
|
-
"""
|
61
|
-
return self.name
|
62
|
-
|
63
|
-
|
64
|
-
members = get_codeblock_members(Dinosaur)
|
65
|
-
|
66
|
-
|
67
|
-
def test_grab_methods():
|
68
|
-
assert len(get_codeblock_members(Dinosaur)) == 4
|
69
|
-
|
70
|
-
|
71
|
-
@pytest.mark.parametrize("obj", members, ids=lambda d: d.__qualname__)
|
72
|
-
def test_member(obj):
|
73
|
-
check_docstring(obj)
|
tests/test_codeblock.py
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
import pytest
|
2
|
-
|
3
|
-
from mktestdocs import check_codeblock, grab_code_blocks
|
4
|
-
|
5
|
-
exibit_a = """
|
6
|
-
This is an example docstring.
|
7
|
-
|
8
|
-
Arguments:
|
9
|
-
a: a parameter
|
10
|
-
|
11
|
-
There is no example
|
12
|
-
"""
|
13
|
-
|
14
|
-
exibit_b = """
|
15
|
-
This is an example docstring.
|
16
|
-
|
17
|
-
Arguments:
|
18
|
-
a: a parameter
|
19
|
-
|
20
|
-
```python
|
21
|
-
assert 1 == 1
|
22
|
-
```
|
23
|
-
"""
|
24
|
-
|
25
|
-
exibit_c = """
|
26
|
-
This is an example docstring.
|
27
|
-
|
28
|
-
Arguments:
|
29
|
-
a: a parameter
|
30
|
-
|
31
|
-
```
|
32
|
-
assert 1 == 1
|
33
|
-
```
|
34
|
-
|
35
|
-
```python
|
36
|
-
assert 1 == 1
|
37
|
-
```
|
38
|
-
"""
|
39
|
-
|
40
|
-
|
41
|
-
@pytest.mark.parametrize(
|
42
|
-
"doc, n",
|
43
|
-
[(exibit_a, 0), (exibit_b, 1), (exibit_c, 1)],
|
44
|
-
ids=["exibit_a", "exibit_b", "exibit_c"],
|
45
|
-
)
|
46
|
-
def test_number_of_codeblocks(doc, n):
|
47
|
-
assert len(grab_code_blocks(doc, lang="python")) == n
|
48
|
-
|
49
|
-
|
50
|
-
@pytest.mark.parametrize(
|
51
|
-
"doc, n",
|
52
|
-
[(exibit_a, 0), (exibit_b, 1), (exibit_c, 2)],
|
53
|
-
ids=["exibit_a", "exibit_b", "exibit_c"],
|
54
|
-
)
|
55
|
-
def test_number_of_codeblocks_any(doc, n):
|
56
|
-
assert len(grab_code_blocks(doc, lang=None)) == n
|
tests/test_markdown.py
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
import pathlib
|
2
|
-
import pytest
|
3
|
-
|
4
|
-
from mktestdocs import check_md_file
|
5
|
-
|
6
|
-
|
7
|
-
@pytest.mark.parametrize("fpath", pathlib.Path("tests/data/good").glob("*.md"), ids=str)
|
8
|
-
def test_files_good(fpath):
|
9
|
-
check_md_file(fpath=fpath)
|
10
|
-
|
11
|
-
|
12
|
-
@pytest.mark.parametrize("fpath", pathlib.Path("tests/data/bad").glob("*.md"), ids=str)
|
13
|
-
def test_files_bad(fpath):
|
14
|
-
with pytest.raises(Exception):
|
15
|
-
check_md_file(fpath=fpath)
|
16
|
-
|
17
|
-
|
18
|
-
def test_big_files_good():
|
19
|
-
"""Confirm that we can deal with multi-cell markdown cells."""
|
20
|
-
check_md_file(fpath="tests/data/big-good.md", memory=True)
|
21
|
-
|
22
|
-
|
23
|
-
def test_big_file_independant():
|
24
|
-
"""Confirm that different files don't influence eachother."""
|
25
|
-
check_md_file(fpath="tests/data/big-good.md", memory=True)
|
26
|
-
with pytest.raises(Exception):
|
27
|
-
check_md_file(fpath="tests/data/big-bad.md", memory=True)
|
File without changes
|