synapse 2.224.0__py311-none-any.whl → 2.226.0__py311-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.
Potentially problematic release.
This version of synapse might be problematic. Click here for more details.
- synapse/axon.py +10 -5
- synapse/cortex.py +6 -8
- synapse/lib/agenda.py +28 -15
- synapse/lib/ast.py +4 -8
- synapse/lib/cell.py +1 -1
- synapse/lib/const.py +4 -0
- synapse/lib/multislabseqn.py +36 -1
- synapse/lib/nexus.py +67 -8
- synapse/lib/platforms/linux.py +2 -0
- synapse/lib/queue.py +4 -1
- synapse/lib/rstorm.py +2 -2
- synapse/lib/schemas.py +11 -1
- synapse/lib/slabseqn.py +28 -0
- synapse/lib/storm.py +16 -4
- synapse/lib/stormhttp.py +7 -1
- synapse/lib/stormlib/aha.py +3 -3
- synapse/lib/stormtypes.py +10 -3
- synapse/lib/types.py +20 -0
- synapse/lib/version.py +2 -2
- synapse/models/base.py +3 -0
- synapse/models/inet.py +62 -5
- synapse/models/infotech.py +18 -0
- synapse/models/media.py +4 -0
- synapse/models/risk.py +3 -0
- synapse/tests/test_cortex.py +115 -2
- synapse/tests/test_lib_agenda.py +141 -28
- synapse/tests/test_lib_cell.py +1 -1
- synapse/tests/test_lib_certdir.py +1 -1
- synapse/tests/test_lib_httpapi.py +1 -1
- synapse/tests/test_lib_layer.py +1 -1
- synapse/tests/test_lib_lmdbslab.py +2 -0
- synapse/tests/test_lib_multislabseqn.py +22 -0
- synapse/tests/test_lib_nexus.py +42 -1
- synapse/tests/test_lib_platforms_linux.py +4 -0
- synapse/tests/test_lib_slabseqn.py +30 -1
- synapse/tests/test_lib_storm.py +65 -1
- synapse/tests/test_lib_stormhttp.py +16 -0
- synapse/tests/test_lib_stormlib_aha.py +6 -2
- synapse/tests/test_lib_stormlib_oauth.py +1 -1
- synapse/tests/test_lib_stormsvc.py +1 -1
- synapse/tests/test_lib_trigger.py +1 -1
- synapse/tests/test_model_inet.py +37 -0
- synapse/tests/test_model_infotech.py +15 -1
- synapse/tests/test_model_media.py +4 -1
- synapse/tests/test_model_risk.py +2 -0
- synapse/tests/test_tools_aha.py +2 -2
- synapse/tests/{test_tools_axon2axon.py → test_tools_axon_copy.py} +4 -4
- synapse/tests/{test_tools_pullfile.py → test_tools_axon_get.py} +4 -4
- synapse/tests/{test_tools_pushfile.py → test_tools_axon_put.py} +7 -7
- synapse/tests/{test_tools_csvtool.py → test_tools_cortex_csv.py} +12 -3
- synapse/tests/{test_tools_feed.py → test_tools_cortex_feed.py} +2 -2
- synapse/tests/{test_tools_apikey.py → test_tools_service_apikey.py} +1 -4
- synapse/tests/{test_tools_backup.py → test_tools_service_backup.py} +5 -5
- synapse/tests/{test_tools_demote.py → test_tools_service_demote.py} +1 -1
- synapse/tests/{test_tools_healthcheck.py → test_tools_service_healthcheck.py} +1 -1
- synapse/tests/{test_tools_livebackup.py → test_tools_service_livebackup.py} +1 -1
- synapse/tests/{test_tools_modrole.py → test_tools_service_modrole.py} +1 -1
- synapse/tests/{test_tools_moduser.py → test_tools_service_moduser.py} +1 -1
- synapse/tests/{test_tools_promote.py → test_tools_service_promote.py} +1 -1
- synapse/tests/{test_tools_reload.py → test_tools_service_reload.py} +1 -1
- synapse/tests/{test_tools_shutdown.py → test_tools_service_shutdown.py} +1 -1
- synapse/tests/{test_tools_snapshot.py → test_tools_service_snapshot.py} +1 -1
- synapse/tests/{test_tools_storm.py → test_tools_storm_cli.py} +1 -1
- synapse/tests/{test_tools_pkgs_gendocs.py → test_tools_storm_pkg_doc.py} +12 -3
- synapse/tests/{test_tools_genpkg.py → test_tools_storm_pkg_gen.py} +1 -1
- synapse/tests/{test_tools_autodoc.py → test_tools_utils_autodoc.py} +1 -1
- synapse/tests/test_tools_utils_changelog.py +454 -0
- synapse/tests/{test_tools_easycert.py → test_tools_utils_easycert.py} +48 -46
- synapse/tests/{test_tools_guid.py → test_tools_utils_guid.py} +3 -3
- synapse/tests/{test_tools_json2mpk.py → test_tools_utils_json2mpk.py} +3 -3
- synapse/tests/{test_tools_rstorm.py → test_tools_utils_rstorm.py} +6 -1
- synapse/tests/utils.py +15 -1
- synapse/tools/aha/mirror.py +1 -1
- synapse/tools/apikey.py +4 -83
- synapse/tools/autodoc.py +3 -1031
- synapse/tools/axon/copy.py +44 -0
- synapse/tools/axon/get.py +64 -0
- synapse/tools/axon/put.py +122 -0
- synapse/tools/axon2axon.py +3 -36
- synapse/tools/backup.py +6 -176
- synapse/tools/changelog.py +3 -1098
- synapse/tools/cortex/csv.py +236 -0
- synapse/tools/cortex/feed.py +151 -0
- synapse/tools/csvtool.py +3 -227
- synapse/tools/demote.py +4 -40
- synapse/tools/docker/validate.py +3 -3
- synapse/tools/easycert.py +4 -129
- synapse/tools/feed.py +3 -140
- synapse/tools/genpkg.py +3 -307
- synapse/tools/guid.py +7 -6
- synapse/tools/healthcheck.py +3 -101
- synapse/tools/json2mpk.py +6 -38
- synapse/tools/livebackup.py +4 -27
- synapse/tools/modrole.py +3 -108
- synapse/tools/moduser.py +3 -179
- synapse/tools/pkgs/gendocs.py +3 -164
- synapse/tools/promote.py +4 -41
- synapse/tools/pullfile.py +3 -56
- synapse/tools/pushfile.py +3 -114
- synapse/tools/reload.py +4 -61
- synapse/tools/rstorm.py +3 -26
- synapse/tools/service/__init__.py +0 -0
- synapse/tools/service/apikey.py +90 -0
- synapse/tools/service/backup.py +181 -0
- synapse/tools/service/demote.py +47 -0
- synapse/tools/service/healthcheck.py +109 -0
- synapse/tools/service/livebackup.py +34 -0
- synapse/tools/service/modrole.py +116 -0
- synapse/tools/service/moduser.py +184 -0
- synapse/tools/service/promote.py +48 -0
- synapse/tools/service/reload.py +68 -0
- synapse/tools/service/shutdown.py +51 -0
- synapse/tools/service/snapshot.py +64 -0
- synapse/tools/shutdown.py +5 -45
- synapse/tools/snapshot.py +4 -57
- synapse/tools/storm/__init__.py +0 -0
- synapse/tools/storm/__main__.py +5 -0
- synapse/tools/{storm.py → storm/_cli.py} +0 -3
- synapse/tools/storm/pkg/__init__.py +0 -0
- synapse/tools/{pkgs/pandoc_filter.py → storm/pkg/_pandoc_filter.py} +1 -1
- synapse/tools/storm/pkg/doc.py +176 -0
- synapse/tools/storm/pkg/gen.py +315 -0
- synapse/tools/utils/__init__.py +0 -0
- synapse/tools/utils/autodoc.py +1040 -0
- synapse/tools/utils/changelog.py +1124 -0
- synapse/tools/utils/easycert.py +136 -0
- synapse/tools/utils/guid.py +11 -0
- synapse/tools/utils/json2mpk.py +46 -0
- synapse/tools/utils/rstorm.py +35 -0
- {synapse-2.224.0.dist-info → synapse-2.226.0.dist-info}/METADATA +1 -1
- {synapse-2.224.0.dist-info → synapse-2.226.0.dist-info}/RECORD +135 -106
- synapse/tests/test_tools_changelog.py +0 -196
- /synapse/tests/{test_tools_axon.py → test_tools_axon_dump_load.py} +0 -0
- {synapse-2.224.0.dist-info → synapse-2.226.0.dist-info}/WHEEL +0 -0
- {synapse-2.224.0.dist-info → synapse-2.226.0.dist-info}/licenses/LICENSE +0 -0
- {synapse-2.224.0.dist-info → synapse-2.226.0.dist-info}/top_level.txt +0 -0
synapse/tools/autodoc.py
CHANGED
|
@@ -1,1039 +1,11 @@
|
|
|
1
|
-
import copy
|
|
2
|
-
import logging
|
|
3
|
-
import collections
|
|
4
|
-
|
|
5
|
-
from typing import List, Tuple, Dict, Union
|
|
6
|
-
|
|
7
|
-
import synapse.exc as s_exc
|
|
8
1
|
import synapse.common as s_common
|
|
9
|
-
import synapse.cortex as s_cortex
|
|
10
|
-
import synapse.telepath as s_telepath
|
|
11
2
|
|
|
12
3
|
import synapse.lib.cmd as s_cmd
|
|
13
|
-
import synapse.lib.json as s_json
|
|
14
|
-
import synapse.lib.storm as s_storm
|
|
15
|
-
import synapse.lib.config as s_config
|
|
16
|
-
import synapse.lib.output as s_output
|
|
17
|
-
import synapse.lib.autodoc as s_autodoc
|
|
18
|
-
import synapse.lib.dyndeps as s_dyndeps
|
|
19
|
-
import synapse.lib.version as s_version
|
|
20
|
-
import synapse.lib.stormsvc as s_stormsvc
|
|
21
|
-
import synapse.lib.stormtypes as s_stormtypes
|
|
22
|
-
|
|
23
|
-
import synapse.tools.genpkg as s_genpkg
|
|
24
|
-
|
|
25
|
-
logger = logging.getLogger(__name__)
|
|
26
|
-
|
|
27
|
-
# src / name / target
|
|
28
|
-
EdgeDef = Tuple[Union[str, None], str, Union[str, None]]
|
|
29
|
-
EdgeDict = Dict[str, str]
|
|
30
|
-
Edge = Tuple[EdgeDef, EdgeDict]
|
|
31
|
-
Edges = List[Edge]
|
|
32
|
-
|
|
33
|
-
poptsToWords = {
|
|
34
|
-
'ex': 'Example',
|
|
35
|
-
'ro': 'Read Only',
|
|
36
|
-
'deprecated': 'Deprecated',
|
|
37
|
-
'disp': 'Display',
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
info_ignores = (
|
|
41
|
-
'stortype',
|
|
42
|
-
'bases',
|
|
43
|
-
'custom',
|
|
44
|
-
'template',
|
|
45
|
-
'display',
|
|
46
|
-
'deprecated',
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
raw_back_slash_colon = r'\:'
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
class DocHelp:
|
|
53
|
-
'''
|
|
54
|
-
Helper to pre-compute all doc strings hierarchically
|
|
55
|
-
'''
|
|
56
|
-
|
|
57
|
-
def __init__(self, ctors, types, forms, props, univs):
|
|
58
|
-
self.ctors = {c[0]: c[3].get('doc', 'BaseType has no doc string.') for c in ctors}
|
|
59
|
-
self.types = {t[0]: t[2].get('doc', self.ctors.get(t[1][0])) for t in types}
|
|
60
|
-
self.forms = {f[0]: f[1].get('doc', self.types.get(f[0], self.ctors.get(f[0]))) for f in forms}
|
|
61
|
-
self.univs = {}
|
|
62
|
-
for unam, utyp, unfo in univs:
|
|
63
|
-
tn = utyp[0]
|
|
64
|
-
doc = unfo.get('doc', self.forms.get(tn, self.types.get(tn, self.ctors.get(tn))))
|
|
65
|
-
self.univs[unam] = doc
|
|
66
|
-
self.props = {}
|
|
67
|
-
for form, props in props.items():
|
|
68
|
-
for prop in props:
|
|
69
|
-
tn = prop[1][0]
|
|
70
|
-
doc = prop[2].get('doc', self.forms.get(tn, self.types.get(tn, self.ctors.get(tn))))
|
|
71
|
-
self.props[(form, prop[0])] = doc
|
|
72
|
-
typed = {t[0]: t for t in types}
|
|
73
|
-
ctord = {c[0]: c for c in ctors}
|
|
74
|
-
self.formhelp = {} # form name -> ex string for a given type
|
|
75
|
-
for form in forms:
|
|
76
|
-
formname = form[0]
|
|
77
|
-
tnfo = typed.get(formname)
|
|
78
|
-
ctor = ctord.get(formname)
|
|
79
|
-
if tnfo:
|
|
80
|
-
tnfo = tnfo[2]
|
|
81
|
-
example = tnfo.get('ex')
|
|
82
|
-
self.formhelp[formname] = example
|
|
83
|
-
elif ctor:
|
|
84
|
-
ctor = ctor[3]
|
|
85
|
-
example = ctor.get('ex')
|
|
86
|
-
self.formhelp[formname] = example
|
|
87
|
-
else: # pragma: no cover
|
|
88
|
-
logger.warning(f'No ctor/type available for [{formname}]')
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def processCtors(rst, dochelp, ctors):
|
|
92
|
-
'''
|
|
93
|
-
|
|
94
|
-
Args:
|
|
95
|
-
rst (RstHelp):
|
|
96
|
-
dochelp (DocHelp):
|
|
97
|
-
ctors (list):
|
|
98
|
-
|
|
99
|
-
Returns:
|
|
100
|
-
None
|
|
101
|
-
'''
|
|
102
|
-
rst.addHead('Base Types', lvl=1, link='.. _dm-base-types:')
|
|
103
|
-
rst.addLines('',
|
|
104
|
-
'Base types are defined via Python classes.',
|
|
105
|
-
'')
|
|
106
|
-
|
|
107
|
-
for name, ctor, opts, info in ctors:
|
|
108
|
-
|
|
109
|
-
doc = dochelp.ctors.get(name)
|
|
110
|
-
if not doc.endswith('.'):
|
|
111
|
-
logger.warning(f'Docstring for ctor {name} does not end with a period.]')
|
|
112
|
-
doc = doc + '.'
|
|
113
|
-
|
|
114
|
-
# Break implicit links to nowhere
|
|
115
|
-
hname = name
|
|
116
|
-
if ':' in name:
|
|
117
|
-
hname = name.replace(':', raw_back_slash_colon)
|
|
118
|
-
|
|
119
|
-
link = f'.. _dm-type-{name.replace(":", "-")}:'
|
|
120
|
-
rst.addHead(hname, lvl=2, link=link)
|
|
121
|
-
|
|
122
|
-
rst.addLines(doc, f'It is implemented by the following class{raw_back_slash_colon} ``{ctor}``.')
|
|
123
|
-
_ = info.pop('doc', None)
|
|
124
|
-
ex = info.pop('ex', None)
|
|
125
|
-
if ex:
|
|
126
|
-
rst.addLines('',
|
|
127
|
-
f'An example of ``{name}``{raw_back_slash_colon}',
|
|
128
|
-
'',
|
|
129
|
-
f' * ``{ex}``',
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
if opts:
|
|
133
|
-
rst.addLines('',
|
|
134
|
-
f'The base type ``{name}`` has the following default options set:',
|
|
135
|
-
''
|
|
136
|
-
)
|
|
137
|
-
for k, v in opts.items():
|
|
138
|
-
rst.addLines(f' * {k}: ``{v}``')
|
|
139
|
-
|
|
140
|
-
for key in info_ignores:
|
|
141
|
-
info.pop(key, None)
|
|
142
|
-
|
|
143
|
-
if info:
|
|
144
|
-
logger.warning(f'Base type {name} has unhandled info: {info}')
|
|
145
|
-
|
|
146
|
-
def processTypes(rst, dochelp, types):
|
|
147
|
-
'''
|
|
148
|
-
|
|
149
|
-
Args:
|
|
150
|
-
rst (RstHelp):
|
|
151
|
-
dochelp (DocHelp):
|
|
152
|
-
ctors (list):
|
|
153
|
-
|
|
154
|
-
Returns:
|
|
155
|
-
None
|
|
156
|
-
'''
|
|
157
|
-
rst.addHead('Types', lvl=1, link='.. _dm-types:')
|
|
158
|
-
|
|
159
|
-
rst.addLines('',
|
|
160
|
-
'Regular types are derived from BaseTypes.',
|
|
161
|
-
'')
|
|
162
|
-
|
|
163
|
-
for name, (ttyp, topt), info in types:
|
|
164
|
-
|
|
165
|
-
doc = dochelp.types.get(name)
|
|
166
|
-
if not doc.endswith('.'):
|
|
167
|
-
logger.warning(f'Docstring for type {name} does not end with a period.]')
|
|
168
|
-
doc = doc + '.'
|
|
169
|
-
|
|
170
|
-
# Break implicit links to nowhere
|
|
171
|
-
hname = name
|
|
172
|
-
if ':' in name:
|
|
173
|
-
hname = name.replace(':', raw_back_slash_colon)
|
|
174
|
-
|
|
175
|
-
link = f'.. _dm-type-{name.replace(":", "-")}:'
|
|
176
|
-
rst.addHead(hname, lvl=2, link=link)
|
|
177
|
-
|
|
178
|
-
rst.addLines(doc,
|
|
179
|
-
f'The ``{name}`` type is derived from the base type: ``{ttyp}``.')
|
|
180
|
-
|
|
181
|
-
ifaces = info.pop('interfaces', None)
|
|
182
|
-
if ifaces:
|
|
183
|
-
rst.addLines('', 'This type implements the following interfaces:', '')
|
|
184
|
-
for iface in ifaces:
|
|
185
|
-
rst.addLines(f' * ``{iface}``')
|
|
186
|
-
|
|
187
|
-
_ = info.pop('doc', None)
|
|
188
|
-
ex = info.pop('ex', None)
|
|
189
|
-
if ex:
|
|
190
|
-
rst.addLines('',
|
|
191
|
-
f'An example of ``{name}``{raw_back_slash_colon}',
|
|
192
|
-
'',
|
|
193
|
-
f' * ``{ex}``',
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
if topt:
|
|
197
|
-
rst.addLines('',
|
|
198
|
-
f'This type has the following options set:',
|
|
199
|
-
''
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
for key, valu in sorted(topt.items(), key=lambda x: x[0]):
|
|
203
|
-
if key == 'enums':
|
|
204
|
-
if valu is None:
|
|
205
|
-
continue
|
|
206
|
-
lines = [f' * {key}:\n']
|
|
207
|
-
elines = []
|
|
208
|
-
if isinstance(valu, str):
|
|
209
|
-
# handle str
|
|
210
|
-
enums = valu.split(',')
|
|
211
|
-
header = 'valu'
|
|
212
|
-
maxa = max((len(enum) for enum in enums))
|
|
213
|
-
maxa = max(maxa, len(header))
|
|
214
|
-
|
|
215
|
-
seprline = f'+{"-" * maxa}+'
|
|
216
|
-
elines.append(seprline)
|
|
217
|
-
line = f'+{header}{" " * (maxa - len(header))}+'
|
|
218
|
-
elines.append(line)
|
|
219
|
-
line = f'+{"=" * maxa}+'
|
|
220
|
-
elines.append(line)
|
|
221
|
-
for enum in enums:
|
|
222
|
-
line = f'+{enum}{" " * (maxa - len(enum))}+'
|
|
223
|
-
elines.append(line)
|
|
224
|
-
elines.append(seprline)
|
|
225
|
-
|
|
226
|
-
elif isinstance(valu, (list, tuple)):
|
|
227
|
-
# handle enum list
|
|
228
|
-
valu = sorted(valu, key=lambda x: x[0])
|
|
229
|
-
|
|
230
|
-
maxa, maxb = len('int'), len('valu')
|
|
231
|
-
for (a, b) in valu:
|
|
232
|
-
maxa = max(len(str(a)), maxa)
|
|
233
|
-
maxb = max(len(b), maxb)
|
|
234
|
-
line = f'{"=" * maxa} {"=" * maxb}'
|
|
235
|
-
elines.append(line)
|
|
236
|
-
line = f'int{" " * (maxa - 3)} valu{" " * (maxb - 4)}'
|
|
237
|
-
elines.append(line)
|
|
238
|
-
line = f'{"=" * maxa} {"=" * maxb}'
|
|
239
|
-
elines.append(line)
|
|
240
|
-
|
|
241
|
-
for (a, b) in valu:
|
|
242
|
-
line = f'{a}{" " * (maxa - len(str(a)))} {b}{" " * (maxb - len(b))}'
|
|
243
|
-
elines.append(line)
|
|
244
|
-
|
|
245
|
-
line = f'{"=" * maxa} {"=" * maxb}'
|
|
246
|
-
elines.append(line)
|
|
247
|
-
|
|
248
|
-
else: # pragma: no cover
|
|
249
|
-
raise ValueError(f'Unknown enum type {type(valu)} for {name}')
|
|
250
|
-
|
|
251
|
-
elines = [' ' + line for line in elines]
|
|
252
|
-
lines.extend(elines)
|
|
253
|
-
lines.append('\n')
|
|
254
|
-
rst.addLines(*lines)
|
|
255
|
-
|
|
256
|
-
elif key in ('fields',
|
|
257
|
-
'schema',
|
|
258
|
-
):
|
|
259
|
-
if len(str(valu)) < 80:
|
|
260
|
-
rst.addLines(f' * {key}: ``{valu}``')
|
|
261
|
-
continue
|
|
262
|
-
lines = [f' * {key}:\n', ' ::\n\n']
|
|
263
|
-
json_lines = s_json.dumps(valu, indent=True, sort_keys=True).decode()
|
|
264
|
-
json_lines = [' ' + line for line in json_lines.split('\n')]
|
|
265
|
-
lines.extend(json_lines)
|
|
266
|
-
lines.append('\n')
|
|
267
|
-
rst.addLines(*lines)
|
|
268
|
-
else:
|
|
269
|
-
rst.addLines(f' * {key}: ``{valu}``')
|
|
270
|
-
|
|
271
|
-
for key in info_ignores:
|
|
272
|
-
info.pop(key, None)
|
|
273
|
-
|
|
274
|
-
if info:
|
|
275
|
-
logger.warning(f'Type {name} has unhandled info: {info}')
|
|
276
|
-
|
|
277
|
-
def has_popts_data(props):
|
|
278
|
-
# Props contain "doc" which we pop out
|
|
279
|
-
# Check if a list of props has any keys
|
|
280
|
-
# which are not 'doc'
|
|
281
|
-
for _, _, popts in props:
|
|
282
|
-
keys = set(popts.keys())
|
|
283
|
-
if 'doc' in keys:
|
|
284
|
-
keys.remove('doc')
|
|
285
|
-
if keys:
|
|
286
|
-
return True
|
|
287
|
-
|
|
288
|
-
return False
|
|
289
|
-
|
|
290
|
-
def processFormsProps(rst, dochelp, forms, univ_names, alledges):
|
|
291
|
-
rst.addHead('Forms', lvl=1, link='.. _dm-forms:')
|
|
292
|
-
rst.addLines('',
|
|
293
|
-
'Forms are derived from types, or base types. Forms represent node types in the graph.'
|
|
294
|
-
'')
|
|
295
|
-
|
|
296
|
-
for name, info, props in forms:
|
|
297
|
-
|
|
298
|
-
formedges = lookupedgesforform(name, alledges)
|
|
299
|
-
|
|
300
|
-
doc = dochelp.forms.get(name)
|
|
301
|
-
if not doc.endswith('.'):
|
|
302
|
-
logger.warning(f'Docstring for form {name} does not end with a period.]')
|
|
303
|
-
doc = doc + '.'
|
|
304
|
-
|
|
305
|
-
hname = name
|
|
306
|
-
if ':' in name:
|
|
307
|
-
hname = name.replace(':', raw_back_slash_colon)
|
|
308
|
-
link = f'.. _dm-form-{name.replace(":", "-")}:'
|
|
309
|
-
rst.addHead(hname, lvl=2, link=link)
|
|
310
|
-
|
|
311
|
-
baseline = f'The base type for the form can be found at :ref:`dm-type-{name.replace(":", "-")}`.'
|
|
312
|
-
rst.addLines(doc,
|
|
313
|
-
'',
|
|
314
|
-
baseline,
|
|
315
|
-
'')
|
|
316
|
-
|
|
317
|
-
ex = dochelp.formhelp.get(name)
|
|
318
|
-
if ex:
|
|
319
|
-
rst.addLines('',
|
|
320
|
-
f'An example of ``{name}``{raw_back_slash_colon}',
|
|
321
|
-
'',
|
|
322
|
-
f' * ``{ex}``',
|
|
323
|
-
''
|
|
324
|
-
)
|
|
325
|
-
|
|
326
|
-
props = [blob for blob in props if blob[0] not in univ_names]
|
|
327
|
-
|
|
328
|
-
if props:
|
|
329
|
-
|
|
330
|
-
has_popts = has_popts_data(props)
|
|
331
|
-
|
|
332
|
-
rst.addLines('', '', f' Properties:', )
|
|
333
|
-
rst.addLines(' .. list-table::',
|
|
334
|
-
' :header-rows: 1',
|
|
335
|
-
' :widths: auto',
|
|
336
|
-
' :class: tight-table',
|
|
337
|
-
'')
|
|
338
|
-
header = (' * - name',
|
|
339
|
-
' - type',
|
|
340
|
-
' - doc',
|
|
341
|
-
)
|
|
342
|
-
if has_popts:
|
|
343
|
-
header = header + (' - opts',)
|
|
344
|
-
rst.addLines(*header)
|
|
345
|
-
|
|
346
|
-
for pname, (ptname, ptopts), popts in props:
|
|
347
|
-
|
|
348
|
-
_ = popts.pop('doc', None)
|
|
349
|
-
doc = dochelp.props.get((name, pname))
|
|
350
|
-
if not doc.endswith('.'):
|
|
351
|
-
logger.warning(f'Docstring for prop ({name}, {pname}) does not end with a period.]')
|
|
352
|
-
doc = doc + '.'
|
|
353
|
-
|
|
354
|
-
hptlink = f'dm-type-{ptname.replace(":", "-")}'
|
|
355
|
-
|
|
356
|
-
rst.addLines(f' * - ``:{pname}``',)
|
|
357
|
-
if ptopts:
|
|
358
|
-
|
|
359
|
-
rst.addLines(f' - | :ref:`{hptlink}`', )
|
|
360
|
-
for k, v in ptopts.items():
|
|
361
|
-
if ptname == 'array' and k == 'type':
|
|
362
|
-
tlink = f'dm-type-{v.replace(":", "-")}'
|
|
363
|
-
rst.addLines(f' | {k}: :ref:`{tlink}`', )
|
|
364
|
-
else:
|
|
365
|
-
rst.addLines(f' | {k}: ``{v}``', )
|
|
366
|
-
|
|
367
|
-
else:
|
|
368
|
-
rst.addLines(f' - :ref:`{hptlink}`',)
|
|
369
|
-
|
|
370
|
-
rst.addLines(f' - {doc}',)
|
|
371
|
-
|
|
372
|
-
if has_popts:
|
|
373
|
-
if popts:
|
|
374
|
-
if len(popts) == 1:
|
|
375
|
-
for k, v in popts.items():
|
|
376
|
-
k = poptsToWords.get(k, k.replace(':', raw_back_slash_colon))
|
|
377
|
-
rst.addLines(f' - {k}: ``{v}``')
|
|
378
|
-
else:
|
|
379
|
-
for i, (k, v) in enumerate(popts.items()):
|
|
380
|
-
k = poptsToWords.get(k, k.replace(':', raw_back_slash_colon))
|
|
381
|
-
if i == 0:
|
|
382
|
-
rst.addLines(f' - | {k}: ``{v}``')
|
|
383
|
-
else:
|
|
384
|
-
rst.addLines(f' | {k}: ``{v}``')
|
|
385
|
-
else:
|
|
386
|
-
rst.addLines(f' - ')
|
|
387
|
-
|
|
388
|
-
if formedges:
|
|
389
|
-
|
|
390
|
-
source_edges = formedges.pop('source', None)
|
|
391
|
-
dst_edges = formedges.pop('target', None)
|
|
392
|
-
generic_edges = formedges.pop('generic', None)
|
|
393
|
-
|
|
394
|
-
if source_edges:
|
|
395
|
-
if generic_edges:
|
|
396
|
-
source_edges.extend(generic_edges)
|
|
397
|
-
|
|
398
|
-
rst.addLines(f' Source Edges:',)
|
|
399
|
-
rst.addLines(' .. list-table::',
|
|
400
|
-
' :header-rows: 1',
|
|
401
|
-
' :widths: auto',
|
|
402
|
-
' :class: tight-table',
|
|
403
|
-
'',
|
|
404
|
-
' * - source',
|
|
405
|
-
' - verb',
|
|
406
|
-
' - target',
|
|
407
|
-
' - doc',
|
|
408
|
-
)
|
|
409
|
-
|
|
410
|
-
_edges = []
|
|
411
|
-
for (edef, enfo) in source_edges:
|
|
412
|
-
src, enam, dst = edef
|
|
413
|
-
doc = enfo.pop('doc', None)
|
|
414
|
-
|
|
415
|
-
if src is None:
|
|
416
|
-
src = '*'
|
|
417
|
-
if dst is None:
|
|
418
|
-
dst = '*'
|
|
419
|
-
|
|
420
|
-
for key in info_ignores:
|
|
421
|
-
enfo.pop(key, None)
|
|
422
|
-
|
|
423
|
-
if enfo:
|
|
424
|
-
logger.warning(f'{name} => Light edge {enam} has unhandled info: {enfo}')
|
|
425
|
-
_edges.append((src, enam, dst, doc))
|
|
426
|
-
_edges.sort(key=lambda x: x[:2])
|
|
427
|
-
|
|
428
|
-
for src, enam, dst, doc in _edges:
|
|
429
|
-
rst.addLines(f' * - ``{src}``',
|
|
430
|
-
f' - ``-({enam})>``',
|
|
431
|
-
f' - ``{dst}``',
|
|
432
|
-
f' - {doc}',
|
|
433
|
-
)
|
|
434
|
-
|
|
435
|
-
if dst_edges:
|
|
436
|
-
if generic_edges:
|
|
437
|
-
dst_edges.extend(generic_edges)
|
|
438
|
-
|
|
439
|
-
rst.addLines(f' Target Edges:', )
|
|
440
|
-
rst.addLines(' .. list-table::',
|
|
441
|
-
' :header-rows: 1',
|
|
442
|
-
' :widths: auto',
|
|
443
|
-
' :class: tight-table',
|
|
444
|
-
'',
|
|
445
|
-
' * - source',
|
|
446
|
-
' - verb',
|
|
447
|
-
' - target',
|
|
448
|
-
' - doc',
|
|
449
|
-
)
|
|
450
|
-
|
|
451
|
-
_edges = []
|
|
452
|
-
for (edef, enfo) in dst_edges:
|
|
453
|
-
src, enam, dst = edef
|
|
454
|
-
doc = enfo.pop('doc', None)
|
|
455
|
-
if src is None:
|
|
456
|
-
src = '*'
|
|
457
|
-
if dst is None:
|
|
458
|
-
dst = '*'
|
|
459
|
-
|
|
460
|
-
for key in info_ignores:
|
|
461
|
-
enfo.pop(key, None)
|
|
462
|
-
|
|
463
|
-
if enfo:
|
|
464
|
-
logger.warning(f'{name} => Light edge {enam} has unhandled info: {enfo}')
|
|
465
|
-
|
|
466
|
-
_edges.append((src, enam, dst, doc))
|
|
467
|
-
_edges.sort(key=lambda x: x[:2])
|
|
468
|
-
|
|
469
|
-
for src, enam, dst, doc in _edges:
|
|
470
|
-
rst.addLines(f' * - ``{src}``',
|
|
471
|
-
f' - ``-({enam})>``',
|
|
472
|
-
f' - ``{dst}``',
|
|
473
|
-
f' - {doc}',
|
|
474
|
-
)
|
|
475
|
-
|
|
476
|
-
rst.addLines('', '')
|
|
477
|
-
|
|
478
|
-
if formedges:
|
|
479
|
-
logger.warning(f'{name} has unhandled light edges: {formedges}')
|
|
480
|
-
|
|
481
|
-
def processUnivs(rst, dochelp, univs):
|
|
482
|
-
rst.addHead('Universal Properties', lvl=1, link='.. _dm-universal-props:')
|
|
483
|
-
|
|
484
|
-
rst.addLines('',
|
|
485
|
-
'Universal props are system level properties which may be present on every node.',
|
|
486
|
-
'',
|
|
487
|
-
'These properties are not specific to a particular form and exist outside of a particular',
|
|
488
|
-
'namespace.',
|
|
489
|
-
'')
|
|
490
|
-
|
|
491
|
-
for name, (utyp, uopt), info in univs:
|
|
492
|
-
|
|
493
|
-
_ = info.pop('doc', None)
|
|
494
|
-
doc = dochelp.univs.get(name)
|
|
495
|
-
if not doc.endswith('.'):
|
|
496
|
-
logger.warning(f'Docstring for form {name} does not end with a period.]')
|
|
497
|
-
doc = doc + '.'
|
|
498
|
-
|
|
499
|
-
hname = name
|
|
500
|
-
if ':' in name:
|
|
501
|
-
hname = name.replace(':', raw_back_slash_colon)
|
|
502
|
-
|
|
503
|
-
rst.addHead(hname, lvl=2, link=f'.. _dm-univ-{name.replace(":", "-")}:')
|
|
504
|
-
|
|
505
|
-
rst.addLines('',
|
|
506
|
-
doc,
|
|
507
|
-
)
|
|
508
|
-
|
|
509
|
-
if info:
|
|
510
|
-
rst.addLines('It has the following property options set:',
|
|
511
|
-
''
|
|
512
|
-
)
|
|
513
|
-
for k, v in info.items():
|
|
514
|
-
k = poptsToWords.get(k, k.replace(':', raw_back_slash_colon))
|
|
515
|
-
rst.addLines(' ' + f'* {k}: ``{v}``')
|
|
516
|
-
|
|
517
|
-
hptlink = f'dm-type-{utyp.replace(":", "-")}'
|
|
518
|
-
tdoc = f'The universal property type is :ref:`{hptlink}`.'
|
|
519
|
-
|
|
520
|
-
rst.addLines('',
|
|
521
|
-
tdoc,
|
|
522
|
-
)
|
|
523
|
-
if uopt:
|
|
524
|
-
rst.addLines("Its type has the following options set:",
|
|
525
|
-
'')
|
|
526
|
-
for k, v in uopt.items():
|
|
527
|
-
rst.addLines(' ' + f'* {k}: ``{v}``')
|
|
528
|
-
|
|
529
|
-
async def processStormCmds(rst, pkgname, commands):
|
|
530
|
-
'''
|
|
531
|
-
|
|
532
|
-
Args:
|
|
533
|
-
rst (RstHelp):
|
|
534
|
-
pkgname (str):
|
|
535
|
-
commands (list):
|
|
536
|
-
|
|
537
|
-
Returns:
|
|
538
|
-
None
|
|
539
|
-
'''
|
|
540
|
-
rst.addHead('Storm Commands', lvl=2)
|
|
541
|
-
|
|
542
|
-
rst.addLines(f'This package implements the following Storm Commands.\n')
|
|
543
|
-
|
|
544
|
-
commands = sorted(commands, key=lambda x: x.get('name'))
|
|
545
|
-
|
|
546
|
-
for cdef in commands:
|
|
547
|
-
|
|
548
|
-
cname = cdef.get('name')
|
|
549
|
-
cdesc = cdef.get('descr')
|
|
550
|
-
cargs = cdef.get('cmdargs')
|
|
551
|
-
|
|
552
|
-
# command names cannot have colons in them thankfully
|
|
553
|
-
cref = f'.. _stormcmd-{pkgname.replace(":", "-")}-{cname.replace(".", "-")}:'
|
|
554
|
-
rst.addHead(cname, lvl=3, link=cref)
|
|
555
|
-
|
|
556
|
-
# Form the description
|
|
557
|
-
lines = ['::\n']
|
|
558
|
-
|
|
559
|
-
# Generate help from args
|
|
560
|
-
pars = s_storm.Parser(prog=cname, descr=cdesc)
|
|
561
|
-
if cargs:
|
|
562
|
-
for (argname, arginfo) in cargs:
|
|
563
|
-
pars.add_argument(argname, **arginfo)
|
|
564
|
-
pars.help()
|
|
565
|
-
|
|
566
|
-
for line in pars.mesgs:
|
|
567
|
-
if '\n' in line:
|
|
568
|
-
for subl in line.split('\n'):
|
|
569
|
-
lines.append(f' {subl}')
|
|
570
|
-
else:
|
|
571
|
-
lines.append(f' {line}')
|
|
572
|
-
|
|
573
|
-
lines.append('\n')
|
|
574
|
-
|
|
575
|
-
forms = cdef.get('forms', {})
|
|
576
|
-
iforms = forms.get('input')
|
|
577
|
-
oforms = forms.get('output')
|
|
578
|
-
nodedata = forms.get('nodedata')
|
|
579
|
-
|
|
580
|
-
if iforms:
|
|
581
|
-
line = 'The command is aware of how to automatically handle the following forms as input nodes:\n'
|
|
582
|
-
lines.append(line)
|
|
583
|
-
for form in iforms:
|
|
584
|
-
lines.append(f'- ``{form}``')
|
|
585
|
-
lines.append('\n')
|
|
586
|
-
|
|
587
|
-
if oforms:
|
|
588
|
-
line = 'The command may make the following types of nodes in the graph as a result of its execution:\n'
|
|
589
|
-
lines.append(line)
|
|
590
|
-
for form in oforms:
|
|
591
|
-
lines.append(f'- ``{form}``')
|
|
592
|
-
lines.append('\n')
|
|
593
|
-
|
|
594
|
-
if nodedata:
|
|
595
|
-
line = 'The command may add nodedata with the following keys to the corresponding forms:\n'
|
|
596
|
-
lines.append(line)
|
|
597
|
-
for key, form in nodedata:
|
|
598
|
-
lines.append(f'- ``{key}`` on ``{form}``')
|
|
599
|
-
lines.append('\n')
|
|
600
|
-
|
|
601
|
-
rst.addLines(*lines)
|
|
602
|
-
|
|
603
|
-
async def processStormModules(rst, pkgname, modules):
|
|
604
|
-
|
|
605
|
-
rst.addHead('Storm Modules', lvl=2)
|
|
606
|
-
|
|
607
|
-
hasapi = False
|
|
608
|
-
modules = sorted(modules, key=lambda x: x.get('name'))
|
|
609
|
-
|
|
610
|
-
for mdef in modules:
|
|
611
|
-
|
|
612
|
-
apidefs = mdef.get('apidefs')
|
|
613
|
-
if not apidefs:
|
|
614
|
-
continue
|
|
615
|
-
|
|
616
|
-
if not hasapi:
|
|
617
|
-
rst.addLines('This package implements the following Storm Modules.\n')
|
|
618
|
-
hasapi = True
|
|
619
|
-
|
|
620
|
-
mname = mdef['name']
|
|
621
|
-
|
|
622
|
-
mref = f'.. _stormmod-{pkgname.replace(":", "-")}-{mname.replace(".", "-")}:'
|
|
623
|
-
rst.addHead(mname, lvl=3, link=mref)
|
|
624
|
-
|
|
625
|
-
for apidef in apidefs:
|
|
626
|
-
|
|
627
|
-
apiname = apidef['name']
|
|
628
|
-
apidesc = apidef['desc']
|
|
629
|
-
apitype = apidef['type']
|
|
630
|
-
|
|
631
|
-
callsig = s_autodoc.genCallsig(apitype)
|
|
632
|
-
rst.addHead(f'{apiname}{callsig}', lvl=4)
|
|
633
|
-
if depr := apidef.get('deprecated'):
|
|
634
|
-
rst.addLines(*s_autodoc.genDeprecationWarning(apiname, depr, True))
|
|
635
|
-
rst.addLines(*s_autodoc.prepareRstLines(apidesc))
|
|
636
|
-
rst.addLines(*s_autodoc.getArgLines(apitype))
|
|
637
|
-
rst.addLines(*s_autodoc.getReturnLines(apitype))
|
|
638
|
-
|
|
639
|
-
if not hasapi:
|
|
640
|
-
rst.addLines('This package does not export any Storm APIs.\n')
|
|
641
|
-
|
|
642
|
-
def lookupedgesforform(form: str, edges: Edges) -> Dict[str, Edges]:
|
|
643
|
-
ret = collections.defaultdict(list)
|
|
644
|
-
|
|
645
|
-
for edge in edges:
|
|
646
|
-
src, name, dst = edge[0]
|
|
647
|
-
|
|
648
|
-
# src and dst may be None, form==name, or form!=name.
|
|
649
|
-
# This gives us 9 possible states to consider.
|
|
650
|
-
# src | dst | -> ret
|
|
651
|
-
# ===================================
|
|
652
|
-
# none | none | -> generic
|
|
653
|
-
# none | != | -> source
|
|
654
|
-
# none | = | -> target
|
|
655
|
-
# != | none | -> target
|
|
656
|
-
# = | none | -> source
|
|
657
|
-
# != | = | -> target
|
|
658
|
-
# = | != | -> source
|
|
659
|
-
# != | != | -> no-op
|
|
660
|
-
# = | = | -> source, target
|
|
661
|
-
|
|
662
|
-
if src is None and dst is None:
|
|
663
|
-
ret['generic'].append(edge)
|
|
664
|
-
continue
|
|
665
|
-
if src is None and dst != form:
|
|
666
|
-
ret['source'].append(edge)
|
|
667
|
-
continue
|
|
668
|
-
if src is None and dst == form:
|
|
669
|
-
ret['target'].append(edge)
|
|
670
|
-
continue
|
|
671
|
-
if src != form and dst is None:
|
|
672
|
-
ret['target'].append(edge)
|
|
673
|
-
continue
|
|
674
|
-
if src == form and dst is None:
|
|
675
|
-
ret['source'].append(edge)
|
|
676
|
-
continue
|
|
677
|
-
if src != form and dst == form:
|
|
678
|
-
ret['target'].append(edge)
|
|
679
|
-
continue
|
|
680
|
-
if src == form and dst != form:
|
|
681
|
-
ret['source'].append(edge)
|
|
682
|
-
continue
|
|
683
|
-
if src != form and dst != form:
|
|
684
|
-
# no-op
|
|
685
|
-
continue
|
|
686
|
-
if src == form and dst == form:
|
|
687
|
-
ret['source'].append(edge)
|
|
688
|
-
ret['target'].append(edge)
|
|
689
|
-
|
|
690
|
-
return copy.deepcopy(dict(ret))
|
|
691
|
-
|
|
692
|
-
async def docModel(outp,
|
|
693
|
-
core):
|
|
694
|
-
coreinfo = await core.getCoreInfo()
|
|
695
|
-
_, model = coreinfo.get('modeldef')[0]
|
|
696
|
-
|
|
697
|
-
ctors = model.get('ctors')
|
|
698
|
-
types = model.get('types')
|
|
699
|
-
forms = model.get('forms')
|
|
700
|
-
univs = model.get('univs')
|
|
701
|
-
edges = model.get('edges')
|
|
702
|
-
props = collections.defaultdict(list)
|
|
703
|
-
|
|
704
|
-
ctors = sorted(ctors, key=lambda x: x[0])
|
|
705
|
-
univs = sorted(univs, key=lambda x: x[0])
|
|
706
|
-
types = sorted(types, key=lambda x: x[0])
|
|
707
|
-
forms = sorted(forms, key=lambda x: x[0])
|
|
708
|
-
univ_names = {univ[0] for univ in univs}
|
|
709
|
-
|
|
710
|
-
for fname, fnfo, fprops in forms:
|
|
711
|
-
for prop in fprops:
|
|
712
|
-
props[fname].append(prop)
|
|
713
|
-
|
|
714
|
-
[v.sort() for k, v in props.items()]
|
|
715
|
-
|
|
716
|
-
dochelp = DocHelp(ctors, types, forms, props, univs)
|
|
717
|
-
|
|
718
|
-
# Validate examples
|
|
719
|
-
for form, example in dochelp.formhelp.items():
|
|
720
|
-
if example is None:
|
|
721
|
-
continue
|
|
722
|
-
if example.startswith('('):
|
|
723
|
-
q = f"[{form}={example}]"
|
|
724
|
-
else:
|
|
725
|
-
q = f"[{form}='{example}']"
|
|
726
|
-
node = False
|
|
727
|
-
async for (mtyp, mnfo) in core.storm(q, {'editformat': 'none'}):
|
|
728
|
-
if mtyp in ('init', 'fini'):
|
|
729
|
-
continue
|
|
730
|
-
if mtyp == 'err': # pragma: no cover
|
|
731
|
-
raise s_exc.SynErr(mesg='Invalid example', form=form, example=example, info=mnfo)
|
|
732
|
-
if mtyp == 'node':
|
|
733
|
-
node = True
|
|
734
|
-
if not node: # pragma: no cover
|
|
735
|
-
raise s_exc.SynErr(mesg='Unable to make a node from example.', form=form, example=example)
|
|
736
|
-
|
|
737
|
-
rst = s_autodoc.RstHelp()
|
|
738
|
-
rst.addHead('Synapse Data Model - Types', lvl=0)
|
|
739
|
-
|
|
740
|
-
processCtors(rst, dochelp, ctors)
|
|
741
|
-
processTypes(rst, dochelp, types)
|
|
742
|
-
|
|
743
|
-
rst2 = s_autodoc.RstHelp()
|
|
744
|
-
rst2.addHead('Synapse Data Model - Forms', lvl=0)
|
|
745
|
-
|
|
746
|
-
processFormsProps(rst2, dochelp, forms, univ_names, edges)
|
|
747
|
-
processUnivs(rst2, dochelp, univs)
|
|
748
|
-
|
|
749
|
-
return rst, rst2
|
|
750
|
-
|
|
751
|
-
async def docConfdefs(ctor):
|
|
752
|
-
cls = s_dyndeps.tryDynLocal(ctor)
|
|
753
|
-
|
|
754
|
-
if not hasattr(cls, 'confdefs'):
|
|
755
|
-
raise Exception('ctor must have a confdefs attr')
|
|
756
|
-
|
|
757
|
-
rst = s_autodoc.RstHelp()
|
|
758
|
-
|
|
759
|
-
clsname = cls.__name__
|
|
760
|
-
|
|
761
|
-
conf = cls.initCellConf() # type: s_config.Config
|
|
762
|
-
|
|
763
|
-
# access raw config data
|
|
764
|
-
|
|
765
|
-
# Get envar and argparse mapping
|
|
766
|
-
name2envar = conf.getEnvarMapping()
|
|
767
|
-
|
|
768
|
-
schema = conf.json_schema.get('properties', {})
|
|
769
|
-
|
|
770
|
-
for name, conf in sorted(schema.items(), key=lambda x: x[0]):
|
|
771
|
-
|
|
772
|
-
if conf.get('hideconf'):
|
|
773
|
-
continue
|
|
774
|
-
|
|
775
|
-
if conf.get('hidedocs'):
|
|
776
|
-
continue
|
|
777
|
-
|
|
778
|
-
nodesc = f'No description available for ``{name}``.'
|
|
779
|
-
|
|
780
|
-
desc = conf.get('description', nodesc)
|
|
781
|
-
if not desc.endswith('.'): # pragma: no cover
|
|
782
|
-
logger.warning(f'Description for [{name}] is missing a period.')
|
|
783
|
-
|
|
784
|
-
hname = name.replace(':', raw_back_slash_colon)
|
|
785
|
-
lines = []
|
|
786
|
-
lines.append(hname)
|
|
787
|
-
lines.append('~' * len(hname))
|
|
788
|
-
lines.append('')
|
|
789
|
-
lines.append(desc)
|
|
790
|
-
|
|
791
|
-
extended_description = conf.get('extended_description')
|
|
792
|
-
if extended_description:
|
|
793
|
-
lines.append('\n')
|
|
794
|
-
lines.append(extended_description)
|
|
795
|
-
|
|
796
|
-
# Type/additional information
|
|
797
|
-
|
|
798
|
-
lines.append('\n')
|
|
799
|
-
|
|
800
|
-
ctyp = conf.get('type')
|
|
801
|
-
lines.append('Type')
|
|
802
|
-
lines.append(f' ``{ctyp}``\n')
|
|
803
|
-
|
|
804
|
-
if ctyp == 'object':
|
|
805
|
-
if conf.get('properties'):
|
|
806
|
-
lines.append('Properties')
|
|
807
|
-
lines.append(' The object expects the following properties:')
|
|
808
|
-
data = {k: v for k, v in conf.items() if k not in (
|
|
809
|
-
'description', 'default', 'type', 'hideconf', 'hidecmdl',
|
|
810
|
-
)}
|
|
811
|
-
parts = s_json.dumps(data, sort_keys=True, indent=True).decode().split('\n')
|
|
812
|
-
lines.append(' ::')
|
|
813
|
-
lines.append('\n')
|
|
814
|
-
lines.extend([f' {p}' for p in parts])
|
|
815
|
-
lines.append('\n')
|
|
816
|
-
|
|
817
|
-
defval = conf.get('default', s_common.novalu)
|
|
818
|
-
if defval is not s_common.novalu:
|
|
819
|
-
lines.append('Default Value')
|
|
820
|
-
lines.append(f' ``{repr(defval)}``\n')
|
|
821
|
-
|
|
822
|
-
envar = name2envar.get(name)
|
|
823
|
-
if envar:
|
|
824
|
-
lines.append('Environment Variable')
|
|
825
|
-
lines.append(f' ``{envar}``\n')
|
|
826
|
-
|
|
827
|
-
rst.addLines(*lines)
|
|
828
|
-
|
|
829
|
-
return rst, clsname
|
|
830
|
-
|
|
831
|
-
async def docStormsvc(ctor):
|
|
832
|
-
cls = s_dyndeps.tryDynLocal(ctor)
|
|
833
|
-
|
|
834
|
-
if not hasattr(cls, 'cellapi'):
|
|
835
|
-
raise Exception('ctor must have a cellapi attr')
|
|
836
|
-
|
|
837
|
-
clsname = cls.__name__
|
|
838
|
-
|
|
839
|
-
cellapi = cls.cellapi
|
|
840
|
-
|
|
841
|
-
if not issubclass(cellapi, s_stormsvc.StormSvc):
|
|
842
|
-
raise Exception('cellapi must be a StormSvc implementation')
|
|
843
|
-
|
|
844
|
-
# Make a dummy object
|
|
845
|
-
class MockSess:
|
|
846
|
-
def __init__(self):
|
|
847
|
-
self.user = None
|
|
848
|
-
|
|
849
|
-
class DummyLink:
|
|
850
|
-
def __init__(self):
|
|
851
|
-
self.info = {'sess': MockSess()}
|
|
852
|
-
|
|
853
|
-
def get(self, key):
|
|
854
|
-
return self.info.get(key)
|
|
855
|
-
|
|
856
|
-
async with await cellapi.anit(s_common.novalu, DummyLink(), s_common.novalu) as obj:
|
|
857
|
-
svcinfo = await obj.getStormSvcInfo()
|
|
858
|
-
|
|
859
|
-
rst = s_autodoc.RstHelp()
|
|
860
|
-
|
|
861
|
-
# Disable default python highlighting
|
|
862
|
-
rst.addLines('.. highlight:: none\n')
|
|
863
|
-
|
|
864
|
-
rst.addHead(f'{clsname} Storm Service')
|
|
865
|
-
lines = ['The following Storm Packages and Commands are available from this service.',
|
|
866
|
-
f'This documentation is generated for version '
|
|
867
|
-
f'{s_version.fmtVersion(*svcinfo.get("vers"))} of the service.',
|
|
868
|
-
f'The Storm Service name is ``{svcinfo.get("name")}``.',
|
|
869
|
-
]
|
|
870
|
-
rst.addLines(*lines)
|
|
871
|
-
|
|
872
|
-
for pkg in svcinfo.get('pkgs'):
|
|
873
|
-
pname = pkg.get('name')
|
|
874
|
-
pver = pkg.get('version')
|
|
875
|
-
commands = pkg.get('commands')
|
|
876
|
-
|
|
877
|
-
hname = pname
|
|
878
|
-
if ':' in pname:
|
|
879
|
-
hname = pname.replace(':', raw_back_slash_colon)
|
|
880
|
-
|
|
881
|
-
rst.addHead(f'Storm Package\\: {hname}', lvl=1)
|
|
882
|
-
|
|
883
|
-
rst.addLines(f'This documentation for {pname} is generated for version {s_version.fmtVersion(*pver)}')
|
|
884
|
-
|
|
885
|
-
if commands:
|
|
886
|
-
await processStormCmds(rst, pname, commands)
|
|
887
|
-
|
|
888
|
-
if modules := pkg.get('modules'):
|
|
889
|
-
await processStormModules(rst, pname, modules)
|
|
890
|
-
|
|
891
|
-
return rst, clsname
|
|
892
|
-
|
|
893
|
-
async def docStormpkg(pkgpath):
|
|
894
|
-
pkgdef = s_genpkg.loadPkgProto(pkgpath)
|
|
895
|
-
pkgname = pkgdef.get('name')
|
|
896
|
-
|
|
897
|
-
rst = s_autodoc.RstHelp()
|
|
898
|
-
|
|
899
|
-
# Disable default python highlighting
|
|
900
|
-
rst.addLines('.. highlight:: none\n')
|
|
901
|
-
|
|
902
|
-
hname = pkgname
|
|
903
|
-
if ':' in pkgname:
|
|
904
|
-
hname = pkgname.replace(':', raw_back_slash_colon)
|
|
905
|
-
|
|
906
|
-
rst.addHead(f'Storm Package\\: {hname}')
|
|
907
|
-
lines = ['The following Commands are available from this package.',
|
|
908
|
-
f'This documentation is generated for version '
|
|
909
|
-
f'{s_version.fmtVersion(pkgdef.get("version"))} of the package.',
|
|
910
|
-
]
|
|
911
|
-
rst.addLines(*lines)
|
|
912
|
-
|
|
913
|
-
commands = pkgdef.get('commands')
|
|
914
|
-
if commands:
|
|
915
|
-
await processStormCmds(rst, pkgname, commands)
|
|
916
|
-
|
|
917
|
-
if modules := pkgdef.get('modules'):
|
|
918
|
-
await processStormModules(rst, pkgname, modules)
|
|
919
|
-
|
|
920
|
-
return rst, pkgname
|
|
921
|
-
|
|
922
|
-
async def docStormTypes():
|
|
923
|
-
registry = s_stormtypes.registry
|
|
924
|
-
|
|
925
|
-
libsinfo = registry.getLibDocs()
|
|
926
|
-
|
|
927
|
-
libspage = s_autodoc.RstHelp()
|
|
928
|
-
|
|
929
|
-
libspage.addHead('Storm Libraries', lvl=0, link='.. _stormtypes-libs-header:')
|
|
930
|
-
|
|
931
|
-
lines = (
|
|
932
|
-
'',
|
|
933
|
-
'Storm Libraries represent powerful tools available inside of the Storm query language.',
|
|
934
|
-
''
|
|
935
|
-
)
|
|
936
|
-
libspage.addLines(*lines)
|
|
937
|
-
|
|
938
|
-
# This value is appended to the end of the ref to the first level header of a type.
|
|
939
|
-
# This prevents accidental cross linking between parts of the docs; which can happen
|
|
940
|
-
# when secondary properties of a type may overlap with the main name of the type.
|
|
941
|
-
types_suffix = 'f527'
|
|
942
|
-
|
|
943
|
-
s_autodoc.docStormTypes(libspage, libsinfo, linkprefix='stormlibs', islib=True,
|
|
944
|
-
known_types=registry.known_types, types_prefix='stormprims', types_suffix=types_suffix)
|
|
945
|
-
|
|
946
|
-
priminfo = registry.getTypeDocs()
|
|
947
|
-
typespage = s_autodoc.RstHelp()
|
|
948
|
-
|
|
949
|
-
typespage.addHead('Storm Types', lvl=0, link='.. _stormtypes-prim-header:')
|
|
950
|
-
|
|
951
|
-
lines = (
|
|
952
|
-
'',
|
|
953
|
-
'Storm Objects are used as view objects for manipulating data in the Storm Runtime and in the Cortex itself.'
|
|
954
|
-
''
|
|
955
|
-
)
|
|
956
|
-
typespage.addLines(*lines)
|
|
957
|
-
s_autodoc.docStormTypes(typespage, priminfo, linkprefix='stormprims', known_types=registry.known_types,
|
|
958
|
-
types_prefix='stormprims', types_suffix=types_suffix)
|
|
959
|
-
|
|
960
|
-
return libspage, typespage
|
|
961
|
-
|
|
962
|
-
async def main(argv, outp=s_output.stdout):
|
|
963
|
-
pars = getArgParser(outp)
|
|
964
|
-
opts = pars.parse_args(argv)
|
|
965
|
-
|
|
966
|
-
if opts.doc_model:
|
|
967
|
-
|
|
968
|
-
if opts.cortex:
|
|
969
|
-
async with s_telepath.withTeleEnv():
|
|
970
|
-
async with await s_telepath.openurl(opts.cortex) as core:
|
|
971
|
-
rsttypes, rstforms = await docModel(outp, core)
|
|
972
|
-
|
|
973
|
-
else:
|
|
974
|
-
async with s_cortex.getTempCortex() as core:
|
|
975
|
-
rsttypes, rstforms = await docModel(outp, core)
|
|
976
|
-
|
|
977
|
-
if opts.savedir:
|
|
978
|
-
with open(s_common.genpath(opts.savedir, 'datamodel_types.rst'), 'wb') as fd:
|
|
979
|
-
fd.write(rsttypes.getRstText().encode())
|
|
980
|
-
with open(s_common.genpath(opts.savedir, 'datamodel_forms.rst'), 'wb') as fd:
|
|
981
|
-
fd.write(rstforms.getRstText().encode())
|
|
982
|
-
|
|
983
|
-
if opts.doc_conf:
|
|
984
|
-
confdocs, cname = await docConfdefs(opts.doc_conf)
|
|
985
|
-
|
|
986
|
-
if opts.savedir:
|
|
987
|
-
with open(s_common.genpath(opts.savedir, f'conf_{cname.lower()}.rst'), 'wb') as fd:
|
|
988
|
-
fd.write(confdocs.getRstText().encode())
|
|
989
|
-
|
|
990
|
-
if opts.doc_storm:
|
|
991
|
-
confdocs, svcname = await docStormsvc(opts.doc_storm)
|
|
992
|
-
|
|
993
|
-
if opts.savedir:
|
|
994
|
-
with open(s_common.genpath(opts.savedir, f'stormsvc_{svcname.lower()}.rst'), 'wb') as fd:
|
|
995
|
-
fd.write(confdocs.getRstText().encode())
|
|
996
|
-
|
|
997
|
-
if opts.doc_stormpkg:
|
|
998
|
-
pkgdocs, pkgname = await docStormpkg(opts.doc_stormpkg)
|
|
999
|
-
|
|
1000
|
-
if opts.savedir:
|
|
1001
|
-
with open(s_common.genpath(opts.savedir, f'stormpkg_{pkgname.lower()}.rst'), 'wb') as fd:
|
|
1002
|
-
fd.write(pkgdocs.getRstText().encode())
|
|
1003
|
-
|
|
1004
|
-
if opts.doc_stormtypes:
|
|
1005
|
-
libdocs, typedocs = await docStormTypes()
|
|
1006
|
-
if opts.savedir:
|
|
1007
|
-
with open(s_common.genpath(opts.savedir, f'stormtypes_libs.rst'), 'wb') as fd:
|
|
1008
|
-
fd.write(libdocs.getRstText().encode())
|
|
1009
|
-
with open(s_common.genpath(opts.savedir, f'stormtypes_prims.rst'), 'wb') as fd:
|
|
1010
|
-
fd.write(typedocs.getRstText().encode())
|
|
1011
|
-
|
|
1012
|
-
return 0
|
|
1013
|
-
|
|
1014
|
-
def getArgParser(outp):
|
|
1015
|
-
desc = 'Command line tool to generate various synapse documentation.'
|
|
1016
|
-
pars = s_cmd.Parser(prog='synapse.tools.autodoc', outp=outp, description=desc)
|
|
1017
|
-
|
|
1018
|
-
pars.add_argument('--cortex', '-c', default=None,
|
|
1019
|
-
help='Cortex URL for model inspection')
|
|
1020
|
-
pars.add_argument('--savedir', default=None,
|
|
1021
|
-
help='Save output to the given directory')
|
|
1022
|
-
doc_type = pars.add_mutually_exclusive_group()
|
|
1023
|
-
doc_type.add_argument('--doc-model', action='store_true', default=False,
|
|
1024
|
-
help='Generate RST docs for the DataModel within a cortex')
|
|
1025
|
-
doc_type.add_argument('--doc-conf', default=None,
|
|
1026
|
-
help='Generate RST docs for the Confdefs for a given Cell ctor')
|
|
1027
|
-
doc_type.add_argument('--doc-storm', default=None,
|
|
1028
|
-
help='Generate RST docs for a stormssvc implemented by a given Cell')
|
|
1029
|
-
|
|
1030
|
-
doc_type.add_argument('--doc-stormpkg', default=None,
|
|
1031
|
-
help='Generate RST docs for the specified Storm package YAML file.')
|
|
1032
4
|
|
|
1033
|
-
|
|
1034
|
-
help='Generate RST docs for StormTypes')
|
|
5
|
+
from synapse.tools.utils.autodoc import logger, main, docStormpkg
|
|
1035
6
|
|
|
1036
|
-
|
|
7
|
+
s_common.deprecated('synapse.tools.autodoc is deprecated. Please use synapse.tools.utils.autodoc instead.',
|
|
8
|
+
curv='v2.225.0')
|
|
1037
9
|
|
|
1038
10
|
if __name__ == '__main__': # pragma: no cover
|
|
1039
11
|
s_common.setlogging(logger, 'DEBUG')
|