8
8
from os .path import getsize
9
9
from subprocess import run
10
10
from pathlib import Path
11
+ from sys import argv
11
12
12
13
# external
13
14
from yaml import safe_load , safe_dump
@@ -19,28 +20,37 @@ def _write_ref_content(source: Path, module_name: str, func_name: str):
19
20
"""Write content."""
20
21
with open (source , "at" ) as ref :
21
22
ref .write (
22
- (f"# { module_name } \n \n " if getsize (source ) == 0 else "" )
23
- + f"::: validators.{ module_name } .{ func_name } \n "
23
+ (
24
+ (f"# { module_name } \n \n " if getsize (source ) == 0 else "" )
25
+ + f"::: validators.{ module_name } .{ func_name } \n "
26
+ )
27
+ if f"{ source } " .endswith (".md" )
28
+ else (
29
+ (f"{ module_name } \n { len (module_name ) * '-' } \n \n " if getsize (source ) == 0 else "" )
30
+ + f".. module:: validators.{ module_name } \n "
31
+ + f".. autofunction:: { func_name } \n "
32
+ )
24
33
)
25
34
26
35
27
- def _generate_reference (source : Path , destination : Path ):
28
- """Generate reference."""
29
- nav_items : Dict [str , List [str ]] = {"Code Reference" : []}
30
- # clean destination
31
- if destination .exists () and destination .is_dir ():
32
- rmtree (destination )
33
- destination .mkdir (exist_ok = True )
34
- # parse source
36
+ def _parse_package (source : Path ):
37
+ """Parse validators package."""
35
38
v_ast = parse (source .read_text (), source )
36
- # generate reference content
37
39
for namespace in (node for node in v_ast .body if isinstance (node , ImportFrom )):
38
40
if not namespace .module :
39
41
continue
40
- for alias in namespace .names :
41
- ref_module = destination / f"{ namespace .module } .md"
42
- _write_ref_content (ref_module , namespace .module , alias .name )
43
- nav_items ["Code Reference" ].append (f"reference/{ namespace .module } .md" )
42
+ yield (namespace .module , namespace .names )
43
+
44
+
45
+ def _generate_reference (source : Path , destination : Path , ext : str ):
46
+ """Generate reference."""
47
+ nav_items : Dict [str , List [str ]] = {"Code Reference" : []}
48
+ # generate reference content
49
+ for module_name , aliases in _parse_package (source ):
50
+ for alias in aliases :
51
+ _write_ref_content (destination / f"{ module_name } .{ ext } " , module_name , alias .name )
52
+ if ext == "md" :
53
+ nav_items ["Code Reference" ].append (f"reference/{ module_name } .md" )
44
54
return nav_items
45
55
46
56
@@ -54,27 +64,70 @@ def _update_mkdocs_config(source: Path, destination: Path, nav_items: Dict[str,
54
64
safe_dump (mkdocs_conf , mkf , sort_keys = False )
55
65
56
66
57
- def generate_documentation (source : Path , discard_refs : bool = True ):
58
- """Generate documentation."""
59
- # copy readme as docs index file
60
- copy (source / "README.md" , source / "docs/index.md" )
61
- # generate reference documentation
62
- nav_items = _generate_reference (source / "validators/__init__.py" , source / "docs/reference" )
67
+ def _gen_md_docs (source : Path , refs_path : Path ):
68
+ """Generate Markdown docs."""
69
+ nav_items = _generate_reference (source / "validators/__init__.py" , refs_path , "md" )
63
70
# backup mkdocs config
64
- _update_mkdocs_config (source / "mkdocs.yaml" , source / "mkdocs.bak.yml " , nav_items )
65
- # build docs as subprocess
71
+ _update_mkdocs_config (source / "mkdocs.yaml" , source / "mkdocs.bak.yaml " , nav_items )
72
+ # build mkdocs as subprocess
66
73
print (run (("mkdocs" , "build" ), capture_output = True ).stderr .decode ())
67
74
# restore mkdocs config
68
- move (str (source / "mkdocs.bak.yml" ), source / "mkdocs.yaml" )
75
+ move (str (source / "mkdocs.bak.yaml" ), source / "mkdocs.yaml" )
76
+
77
+
78
+ def _gen_rst_docs (source : Path , refs_path : Path ):
79
+ """Generate reStructuredText docs.."""
80
+ # external
81
+ from pypandoc import convert_file # type: ignore
82
+
83
+ with open (source / "docs/index.rst" , "wt" ) as idx_f :
84
+ idx_f .write (
85
+ convert_file (source_file = source / "docs/index.md" , format = "md" , to = "rst" )
86
+ + "\n \n .. toctree::"
87
+ + "\n :hidden:"
88
+ + "\n :maxdepth: 2"
89
+ + "\n :caption: Reference:"
90
+ + "\n :glob:\n "
91
+ + "\n reference/*\n "
92
+ )
93
+ # generate RST reference documentation
94
+ _generate_reference (source / "validators/__init__.py" , refs_path , "rst" )
95
+ # build sphinx web pages as subprocess
96
+ web_build = run (("sphinx-build" , "docs" , "docs/_build/web" ), capture_output = True )
97
+ print (web_build .stderr .decode (), "\n " , web_build .stdout .decode (), sep = "" )
98
+ # build sphinx man pages as subprocess
99
+ man_build = run (("sphinx-build" , "-b" , "man" , "docs" , "docs/_build/man" ), capture_output = True )
100
+ print (man_build .stderr .decode (), "\n " , man_build .stdout .decode (), sep = "" )
101
+
102
+
103
+ def generate_documentation (
104
+ source : Path , only_md : bool = False , only_rst : bool = False , discard_refs : bool = True
105
+ ):
106
+ """Generate documentation."""
107
+ if only_md and only_rst :
108
+ return
109
+ # copy readme as docs index file
110
+ copy (source / "README.md" , source / "docs/index.md" )
111
+ # clean destination
112
+ refs_path = source / "docs/reference"
113
+ if refs_path .exists () and refs_path .is_dir ():
114
+ rmtree (refs_path )
115
+ refs_path .mkdir (exist_ok = True )
116
+ # documentation for each kind
117
+ if not only_rst :
118
+ _gen_md_docs (source , refs_path )
119
+ if not only_md :
120
+ _gen_rst_docs (source , refs_path )
69
121
# optionally discard reference folder
70
122
if discard_refs :
71
123
rmtree (source / "docs/reference" )
72
124
73
125
74
126
if __name__ == "__main__" :
75
127
project_root = Path (__file__ ).parent .parent
76
- generate_documentation (project_root )
77
- # NOTE: use following lines only for testing/debugging
78
- # generate_documentation(project_root, discard_refs=False)
79
- # from sys import argv
80
- # generate_documentation(project_root, len(argv) > 1 and argv[1] == "--keep")
128
+ generate_documentation (
129
+ project_root ,
130
+ only_md = True ,
131
+ only_rst = False ,
132
+ discard_refs = len (argv ) <= 1 or argv [1 ] != "--keep" ,
133
+ )
0 commit comments