1
1
#!/usr/bin/env python3
2
2
import logging
3
3
import os
4
-
5
- # This script is copy-pasted from a cookiecutter template (to be open sourced soon)
6
- # and therefore does not adhere to the code conventions for the remainder of sensAI
4
+ import shutil
7
5
8
6
9
7
log = logging .getLogger (os .path .basename (__file__ ))
10
8
11
9
12
- def module_template (module_path : str ):
13
- title = os .path .basename (module_path ).replace ("_" , r"\_" )
14
- title = title [:- 3 ] # removing trailing .py
15
- module_path = module_path [:- 3 ]
10
+ def module_template (module_qualname : str ):
11
+ module_name = module_qualname .split ("." )[- 1 ]
12
+ title = module_name .replace ("_" , r"\_" )
16
13
template = f"""{ title }
17
14
{ "=" * len (title )}
18
15
19
- .. automodule:: { module_path . replace ( os . path . sep , "." ) }
16
+ .. automodule:: { module_qualname }
20
17
:members:
21
18
:undoc-members:
22
19
"""
23
20
return template
24
21
25
22
26
- def package_template (package_path : str ):
27
- package_name = os . path . basename ( package_path )
23
+ def package_template (package_qualname : str ):
24
+ package_name = package_qualname . split ( "." )[ - 1 ]
28
25
title = package_name .replace ("_" , r"\_" )
29
26
template = f"""{ title }
30
27
{ "=" * len (title )}
31
28
32
- .. automodule:: { package_path . replace ( os . path . sep , "." ) }
29
+ .. automodule:: { package_qualname }
33
30
:members:
34
31
:undoc-members:
35
32
@@ -41,50 +38,80 @@ def package_template(package_path: str):
41
38
return template
42
39
43
40
41
+ def indexTemplate (package_name ):
42
+ title = "Modules"
43
+ template = \
44
+ f"""{ title }
45
+ { "=" * len (title )}
46
+
47
+ .. automodule:: { package_name }
48
+ :members:
49
+ :undoc-members:
50
+
51
+ .. toctree::
52
+ :glob:
53
+
54
+ *
55
+ """
56
+ return template
57
+
58
+
44
59
def write_to_file (content : str , path : str ):
60
+ os .makedirs (os .path .dirname (path ), exist_ok = True )
45
61
with open (path , "w" ) as f :
46
62
f .write (content )
47
63
os .chmod (path , 0o666 )
48
64
49
65
50
- def make_docu (basedir = os .path .join ("src" , "sensai" ), overwrite = False ):
66
+
67
+ def make_rst (src_root = os .path .join ("src" , "sensai" ), rst_root = os .path .join ("docs" , "sensai" ), clean = False , overwrite = False ):
51
68
"""
52
69
Creates/updates documentation in form of rst files for modules and packages.
53
70
Does not delete any existing rst files. Thus, rst files for packages or modules that have been removed or renamed
54
71
should be deleted by hand.
55
72
56
73
This method should be executed from the project's top-level directory
57
74
58
- :param basedir: path to library basedir, typically "src/<library_name>"
75
+ :param src_root: path to library base directory, typically "src/<library_name>"
76
+ :param clean: whether to completely clean the target directory beforehand, removing any existing .rst files
59
77
:param overwrite: whether to overwrite existing rst files. This should be used with caution as it will delete
60
78
all manual changes to documentation files
61
79
:return:
62
80
"""
63
- library_basedir = basedir .split (os .path .sep , 1 )[1 ] # splitting off the "src" part
64
- for file in os .listdir (basedir ):
65
- if file .startswith ("_" ):
66
- continue
81
+ rst_root = os .path .abspath (rst_root )
67
82
68
- library_file_path = os .path .join ( library_basedir , file )
69
- full_path = os . path . join ( basedir , file )
70
- file_name , ext = os . path . splitext ( file )
71
- docs_file_path = os .path .join ( "docs" , library_basedir , f" { file_name } .rst" )
72
- if os .path .exists ( docs_file_path ) and not overwrite :
73
- log . debug ( f" { docs_file_path } already exists, skipping it" )
74
- if os .path . isdir ( full_path ):
75
- make_docu ( basedir = full_path , overwrite = overwrite )
83
+ if clean and os .path .isdir ( rst_root ):
84
+ shutil . rmtree ( rst_root )
85
+
86
+ base_package_name = os .path .basename ( src_root )
87
+ write_to_file ( indexTemplate ( base_package_name ), os .path .join ( rst_root , "index.rst" ))
88
+
89
+ for root , dirnames , filenames in os .walk ( src_root ):
90
+ if os . path . basename ( root ). startswith ( "_" ):
76
91
continue
77
- os .makedirs (os .path .dirname (docs_file_path ), exist_ok = True )
92
+ base_package_relpath = os .path .relpath (root , start = src_root )
93
+ base_package_qualname = os .path .relpath (root , start = os .path .dirname (src_root )).replace (os .path .sep , "." )
94
+
95
+ for dirname in dirnames :
96
+ if not dirname .startswith ("_" ):
97
+ package_qualname = f"{ base_package_qualname } .{ dirname } "
98
+ package_rst_path = os .path .join (rst_root , base_package_relpath , f"{ dirname } .rst" )
99
+ log .info (f"Writing package documentation to { package_rst_path } " )
100
+ write_to_file (package_template (package_qualname ), package_rst_path )
101
+
102
+ for filename in filenames :
103
+ base_name , ext = os .path .splitext (filename )
104
+ if ext == ".py" and not filename .startswith ("_" ):
105
+ module_qualname = f"{ base_package_qualname } .{ filename [:- 3 ]} "
106
+
107
+ module_rst_path = os .path .join (rst_root , base_package_relpath , f"{ base_name } .rst" )
108
+ if os .path .exists (module_rst_path ) and not overwrite :
109
+ log .debug (f"{ module_rst_path } already exists, skipping it" )
78
110
79
- if ext == ".py" :
80
- log .info (f"writing module docu to { docs_file_path } " )
81
- write_to_file (module_template (library_file_path ), docs_file_path )
82
- elif os .path .isdir (full_path ):
83
- log .info (f"writing package docu to { docs_file_path } " )
84
- write_to_file (package_template (library_file_path ), docs_file_path )
85
- make_docu (basedir = full_path , overwrite = overwrite )
111
+ log .info (f"Writing module documentation to { module_rst_path } " )
112
+ write_to_file (module_template (module_qualname ), module_rst_path )
86
113
87
114
88
115
if __name__ == "__main__" :
89
116
logging .basicConfig (level = logging .INFO )
90
- make_docu ( )
117
+ make_rst ( clean = True )
0 commit comments