-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnew_module.py
106 lines (84 loc) · 3.33 KB
/
new_module.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
'''
=============================================
Script to create boilerplate for a new module
=============================================
* Module file
* Unit test script
* Documentation stub and index entry
'''
from contextlib import suppress
import pathlib, re
app_name = 'tkds'
def checked_module_path(module_name, test=False):
rel_parts = ['tests' if test else app_name] + module_name.strip().split('.')
name_template = 'test_{}.py' if test else '{}.py'
rel_parts[-1] = name_template.format(rel_parts[-1])
result = pathlib.Path('.').joinpath(*rel_parts)
result.parent.mkdir(parents=True, exist_ok=True)
for n_parts in range(1, len(rel_parts)):
with suppress(FileExistsError):
pathlib.Path('.').joinpath(*rel_parts[:n_parts]).joinpath('__init__.py').touch(exist_ok=False)
return result
def as_heading(text, fill_char='=', overbar=True):
bar = fill_char * len(text)
lines = [bar] if overbar else []
lines.extend([text, bar])
return '\n'.join(lines)
module_template = '''
\'\'\'
{module_heading}
\'\'\'
if __name__ == '__main__':
import doctest
doctest.testmod()
'''
test_module_template = '''
\'\'\'
{test_module_heading}
Unit tests for {module_name}
\'\'\'
import unittest
from {module_location} import {module_short_name}
# From test_example.py:
#class Test_str_repeat(unittest.TestCase):
# def setUp(self):
# self.fun = example.str_repeat
# def test_retval_equal(self):
# for calc, retval in [(lambda: self.fun('a'), 'a'),
# (lambda: self.fun('abc', 0), ''),
# ]:
# self.assertEqual(calc(), retval)
if __name__ == '__main__':
unittest.main()
'''
doc_stub_template = '''
.. automodule:: {app_name}.{module_name}
:members:
'''
def make_new_module(module_name):
module_name = module_name.strip()
module_parts = [app_name] + module_name.split('.')
doc_source_path = pathlib.Path('./docs/source')
context = {'module_path': checked_module_path(module_name, test=False),
'test_module_path': checked_module_path(module_name, test=True),
'module_name': module_name,
'doc_stub_path': doc_source_path.joinpath('code_pages/{module_name}.rst'.format(**locals())),
'module_heading': as_heading(module_name),
'test_module_heading': as_heading('Unit tests for module {module_name}'.format(**locals())),
'module_location': '.'.join(module_parts[:-1]),
'module_short_name': module_parts[-1],
'module_name': module_name,
'app_name': app_name,
}
for mode, path_key, template in [('x', 'module_path', module_template),
('x', 'test_module_path', test_module_template),
('x', 'doc_stub_path', doc_stub_template),
]:
with context[path_key].open(mode=mode) as out_stream:
print(template.format(**context), file=out_stream)
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description='Add a new empty module and assoicated files')
parser.add_argument('module', help='Name of new module (can include package path. eg: my_pkg.my_module)')
args = parser.parse_args()
make_new_module(args.module)