-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathindexes.py
299 lines (260 loc) · 11.1 KB
/
indexes.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# Author: Toshio Kuratomi <[email protected]>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or
# https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2020, Ansible Project
"""Output indexes."""
from __future__ import annotations
import asyncio
import os
import os.path
from collections.abc import Mapping
import asyncio_pool # type: ignore[import]
from antsibull_core import app_context
from antsibull_core.logging import log
from antsibull_core.utils.io import write_file
from jinja2 import Template
from ..docs_parsing import AnsibleCollectionMetadata
from ..env_variables import EnvironmentVariableInfo
from ..jinja2 import FilenameGenerator, OutputFormat
from ..jinja2.environment import doc_environment, get_template_filename
from ..utils.collection_name_transformer import CollectionNameTransformer
from . import PluginCollectionInfoT, _render_template
mlog = log.fields(mod=__name__)
async def write_callback_type_index(
callback_type: str,
per_collection_plugins: Mapping[str, Mapping[str, str]],
template: Template,
dest_filename: str,
for_official_docsite: bool = False,
) -> None:
"""
Write an index page for each plugin type.
:arg callback_type: The callback plugin type to write the index for.
:arg per_collection_plugins: Mapping of collection_name to Mapping of plugin_name to
short_description.
:arg template: A template to render the plugin index.
:arg dest_filename: The destination filename.
:kwarg for_official_docsite: Default False. Set to True to use wording specific for the
official docsite on docs.ansible.com.
"""
index_contents = _render_template(
template,
dest_filename,
callback_type=callback_type,
per_collection_plugins=per_collection_plugins,
for_official_docsite=for_official_docsite,
)
await write_file(dest_filename, index_contents)
async def write_plugin_type_index(
plugin_type: str,
per_collection_plugins: Mapping[str, Mapping[str, str]],
collection_metadata: Mapping[str, AnsibleCollectionMetadata],
template: Template,
dest_filename: str,
for_official_docsite: bool = False,
) -> None:
"""
Write an index page for each plugin type.
:arg plugin_type: The plugin type to write the index for.
:arg per_collection_plugins: Mapping of collection_name to Mapping of plugin_name to
short_description.
:arg collection_metadata: Dictionary mapping collection names to collection metadata objects.
:arg template: A template to render the plugin index.
:arg dest_filename: The destination filename.
:kwarg for_official_docsite: Default False. Set to True to use wording specific for the
official docsite on docs.ansible.com.
"""
public_per_collection_plugins = {}
for collection_name, plugins in per_collection_plugins.items():
public_plugins = {}
collection_meta = collection_metadata[collection_name]
private_plugins = collection_meta.private_plugins.get(plugin_type) or []
for plugin_name, plugin_data in plugins.items():
if plugin_name not in private_plugins:
public_plugins[plugin_name] = plugin_data
if public_plugins:
public_per_collection_plugins[collection_name] = public_plugins
index_contents = _render_template(
template,
dest_filename,
plugin_type=plugin_type,
per_collection_plugins=public_per_collection_plugins,
for_official_docsite=for_official_docsite,
)
await write_file(dest_filename, index_contents)
async def output_callback_indexes(
plugin_info: PluginCollectionInfoT,
dest_dir: str,
collection_url: CollectionNameTransformer,
collection_install: CollectionNameTransformer,
output_format: OutputFormat,
filename_generator: FilenameGenerator,
for_official_docsite: bool = False,
referable_envvars: set[str] | None = None,
) -> None:
"""
Generate top-level callback plugin index pages for all callback plugins of a type in all
collections.
:arg plugin_info: Mapping of callback_type to Mapping of collection_name to Mapping of
plugin_name to short_description.
:arg dest_dir: The directory to place the documentation in.
:kwarg for_official_docsite: Default False. Set to True to use wording specific for the
official docsite on docs.ansible.com.
:kwarg referable_envvars: Optional set of environment variables that can be referenced.
:kwarg output_format: The output format to use.
"""
flog = mlog.fields(func="output_callback_indexes")
flog.debug("Enter")
env = doc_environment(
collection_url=collection_url,
collection_install=collection_install,
referable_envvars=referable_envvars,
output_format=output_format,
filename_generator=filename_generator,
)
# Get the templates
plugin_list_tmpl = env.get_template(
get_template_filename("list_of_callback_plugins", output_format)
)
collection_toplevel = os.path.join(dest_dir, "collections")
flog.fields(
toplevel=collection_toplevel, exists=os.path.isdir(collection_toplevel)
).debug("collection_toplevel exists?")
# This is only safe because we made sure that the top of the directory tree we're writing to
# (docs/docsite/rst) is only writable by us.
os.makedirs(collection_toplevel, mode=0o755, exist_ok=True)
writers = []
lib_ctx = app_context.lib_ctx.get()
async with asyncio_pool.AioPool(size=lib_ctx.thread_max) as pool:
for callback_type, per_collection_data in plugin_info.items():
filename = os.path.join(
collection_toplevel,
f"callback_index_{callback_type}{output_format.output_extension}",
)
writers.append(
await pool.spawn(
write_callback_type_index(
callback_type,
per_collection_data,
plugin_list_tmpl,
filename,
for_official_docsite=for_official_docsite,
)
)
)
await asyncio.gather(*writers)
flog.debug("Leave")
async def output_plugin_indexes(
plugin_info: PluginCollectionInfoT,
collection_metadata: Mapping[str, AnsibleCollectionMetadata],
dest_dir: str,
collection_url: CollectionNameTransformer,
collection_install: CollectionNameTransformer,
output_format: OutputFormat,
filename_generator: FilenameGenerator,
for_official_docsite: bool = False,
referable_envvars: set[str] | None = None,
) -> None:
"""
Generate top-level plugin index pages for all plugins of a type in all collections.
:arg plugin_info: Mapping of plugin_type to Mapping of collection_name to Mapping of
plugin_name to short_description.
:arg collection_metadata: Dictionary mapping collection names to collection metadata objects.
:arg dest_dir: The directory to place the documentation in.
:kwarg for_official_docsite: Default False. Set to True to use wording specific for the
official docsite on docs.ansible.com.
:kwarg referable_envvars: Optional set of environment variables that can be referenced.
:kwarg output_format: The output format to use.
"""
flog = mlog.fields(func="output_plugin_indexes")
flog.debug("Enter")
env = doc_environment(
collection_url=collection_url,
collection_install=collection_install,
referable_envvars=referable_envvars,
output_format=output_format,
filename_generator=filename_generator,
)
# Get the templates
plugin_list_tmpl = env.get_template(
get_template_filename("list_of_plugins", output_format)
)
collection_toplevel = os.path.join(dest_dir, "collections")
flog.fields(
toplevel=collection_toplevel, exists=os.path.isdir(collection_toplevel)
).debug("collection_toplevel exists?")
# This is only safe because we made sure that the top of the directory tree we're writing to
# (docs/docsite/rst) is only writable by us.
os.makedirs(collection_toplevel, mode=0o755, exist_ok=True)
writers = []
lib_ctx = app_context.lib_ctx.get()
async with asyncio_pool.AioPool(size=lib_ctx.thread_max) as pool:
for plugin_type, per_collection_data in plugin_info.items():
filename = os.path.join(
collection_toplevel,
f"index_{plugin_type}{output_format.output_extension}",
)
writers.append(
await pool.spawn(
write_plugin_type_index(
plugin_type,
per_collection_data,
collection_metadata,
plugin_list_tmpl,
filename,
for_official_docsite=for_official_docsite,
)
)
)
await asyncio.gather(*writers)
flog.debug("Leave")
async def output_environment_variables(
dest_dir: str,
env_variables: Mapping[str, EnvironmentVariableInfo],
output_format: OutputFormat,
filename_generator: FilenameGenerator,
squash_hierarchy: bool = False,
referable_envvars: set[str] | None = None,
) -> None:
"""
Write environment variable Generate collection-level index pages for the collections.
:arg dest_dir: The directory to place the documentation in.
:arg env_variables: Mapping of environment variable names to environment variable information.
:arg squash_hierarchy: If set to ``True``, no directory hierarchy will be used.
Undefined behavior if documentation for multiple collections are
created.
:kwarg referable_envvars: Optional set of environment variables that can be referenced.
:kwarg output_format: The output format to use.
"""
flog = mlog.fields(func="write_environment_variables")
flog.debug("Enter")
if not squash_hierarchy:
collection_toplevel = os.path.join(dest_dir, "collections")
else:
collection_toplevel = dest_dir
env = doc_environment(
referable_envvars=referable_envvars,
output_format=output_format,
filename_generator=filename_generator,
)
# Get the templates
env_var_list_tmpl = env.get_template(
get_template_filename("list_of_env_variables", output_format)
)
flog.fields(
toplevel=collection_toplevel, exists=os.path.isdir(collection_toplevel)
).debug("collection_toplevel exists?")
# This is only safe because we made sure that the top of the directory tree we're writing to
# (docs/docsite/rst) is only writable by us.
os.makedirs(collection_toplevel, mode=0o755, exist_ok=True)
index_file = os.path.join(
collection_toplevel, f"environment_variables{output_format.output_extension}"
)
index_contents = _render_template(
env_var_list_tmpl,
index_file,
env_variables=env_variables,
)
await write_file(index_file, index_contents)
flog.debug("Leave")