modal 0.73.46__py3-none-any.whl → 0.73.47__py3-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.
- modal/client.pyi +2 -2
- modal/functions.pyi +6 -6
- {modal-0.73.46.dist-info → modal-0.73.47.dist-info}/METADATA +1 -1
- {modal-0.73.46.dist-info → modal-0.73.47.dist-info}/RECORD +12 -9
- {modal-0.73.46.dist-info → modal-0.73.47.dist-info}/top_level.txt +1 -0
- modal_docs/__init__.py +1 -0
- modal_docs/gen_cli_docs.py +117 -0
- modal_docs/gen_reference_docs.py +193 -0
- modal_version/_version_generated.py +1 -1
- {modal-0.73.46.dist-info → modal-0.73.47.dist-info}/LICENSE +0 -0
- {modal-0.73.46.dist-info → modal-0.73.47.dist-info}/WHEEL +0 -0
- {modal-0.73.46.dist-info → modal-0.73.47.dist-info}/entry_points.txt +0 -0
modal/client.pyi
CHANGED
@@ -27,7 +27,7 @@ class _Client:
|
|
27
27
|
_snapshotted: bool
|
28
28
|
|
29
29
|
def __init__(
|
30
|
-
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.
|
30
|
+
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.47"
|
31
31
|
): ...
|
32
32
|
def is_closed(self) -> bool: ...
|
33
33
|
@property
|
@@ -85,7 +85,7 @@ class Client:
|
|
85
85
|
_snapshotted: bool
|
86
86
|
|
87
87
|
def __init__(
|
88
|
-
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.
|
88
|
+
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.47"
|
89
89
|
): ...
|
90
90
|
def is_closed(self) -> bool: ...
|
91
91
|
@property
|
modal/functions.pyi
CHANGED
@@ -200,11 +200,11 @@ class Function(
|
|
200
200
|
|
201
201
|
_call_generator_nowait: ___call_generator_nowait_spec[typing_extensions.Self]
|
202
202
|
|
203
|
-
class __remote_spec(typing_extensions.Protocol[
|
203
|
+
class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
|
204
204
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
|
205
205
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
|
206
206
|
|
207
|
-
remote: __remote_spec[modal._functions.
|
207
|
+
remote: __remote_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
|
208
208
|
|
209
209
|
class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
|
210
210
|
def __call__(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
|
@@ -219,19 +219,19 @@ class Function(
|
|
219
219
|
self, *args: modal._functions.P.args, **kwargs: modal._functions.P.kwargs
|
220
220
|
) -> modal._functions.OriginalReturnType: ...
|
221
221
|
|
222
|
-
class ___experimental_spawn_spec(typing_extensions.Protocol[
|
222
|
+
class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
|
223
223
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
224
224
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
225
225
|
|
226
226
|
_experimental_spawn: ___experimental_spawn_spec[
|
227
|
-
modal._functions.
|
227
|
+
modal._functions.ReturnType, modal._functions.P, typing_extensions.Self
|
228
228
|
]
|
229
229
|
|
230
|
-
class __spawn_spec(typing_extensions.Protocol[
|
230
|
+
class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
|
231
231
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
232
232
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
233
233
|
|
234
|
-
spawn: __spawn_spec[modal._functions.
|
234
|
+
spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
|
235
235
|
|
236
236
|
def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]: ...
|
237
237
|
|
@@ -22,7 +22,7 @@ modal/app.py,sha256=rCOPD51gVyow8muyaqMuV65qfTnAZKf_w1OCZdSF_6o,44636
|
|
22
22
|
modal/app.pyi,sha256=0MMCgskIL4r3eq8oBcfm2lLyeao2gXjS3iXaIfmaJ-o,25959
|
23
23
|
modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
|
24
24
|
modal/client.py,sha256=8SQawr7P1PNUCq1UmJMUQXG2jIo4Nmdcs311XqrNLRE,15276
|
25
|
-
modal/client.pyi,sha256=
|
25
|
+
modal/client.pyi,sha256=5qG22FLFyDb4OjKfcnpVlfFwBYCVD6O_SzR9Rh2llaA,7593
|
26
26
|
modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
|
27
27
|
modal/cloud_bucket_mount.pyi,sha256=30T3K1a89l6wzmEJ_J9iWv9SknoGqaZDx59Xs-ZQcmk,1607
|
28
28
|
modal/cls.py,sha256=nJhJr-YuttOmdNWxtMHcBV-q6iQmY5qXkEy9yO43clY,31130
|
@@ -41,7 +41,7 @@ modal/file_io.py,sha256=lcMs_E9Xfm0YX1t9U2wNIBPnqHRxmImqjLW1GHqVmyg,20945
|
|
41
41
|
modal/file_io.pyi,sha256=NTRft1tbPSWf9TlWVeZmTlgB5AZ_Zhu2srWIrWr7brk,9445
|
42
42
|
modal/file_pattern_matcher.py,sha256=trosX-Bp7dOubudN1bLLhRAoidWy1TcoaR4Pv8CedWw,6497
|
43
43
|
modal/functions.py,sha256=kcNHvqeGBxPI7Cgd57NIBBghkfbeFJzXO44WW0jSmao,325
|
44
|
-
modal/functions.pyi,sha256=
|
44
|
+
modal/functions.pyi,sha256=Qx5RDsB-Ta9lixUz2kWZYzUBD0ZGDxQenzHFyq0DJr8,14395
|
45
45
|
modal/gpu.py,sha256=Kbhs_u49FaC2Zi0TjCdrpstpRtT5eZgecynmQi5IZVE,6752
|
46
46
|
modal/image.py,sha256=EtYt7_Rjgi71gt_SutqF8KSjnzWgP5P1Z7XsV-eIoFw,91470
|
47
47
|
modal/image.pyi,sha256=Oc2ndYHSdQTcRpZKHSfTdj-m_2oQAsnc2EWTthbNn-s,26380
|
@@ -144,6 +144,9 @@ modal/requirements/2024.04.txt,sha256=6NnrbIE-mflwMyKyQ0tsWeY8XFE1kSW9oE8DVDoD8Q
|
|
144
144
|
modal/requirements/2024.10.txt,sha256=qD-5cVIVM9wXesJ6JC89Ew-3m2KjEElUz3jaw_MddRo,296
|
145
145
|
modal/requirements/README.md,sha256=9tK76KP0Uph7O0M5oUgsSwEZDj5y-dcUPsnpR0Sc-Ik,854
|
146
146
|
modal/requirements/base-images.json,sha256=kLNo5Sqmnhp9H6Hr9IcaGJFrRaRg1yfuepUWkm-y8iQ,571
|
147
|
+
modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
|
148
|
+
modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
|
149
|
+
modal_docs/gen_reference_docs.py,sha256=aDcUSSDtAAZ4eeFWyroeIg2TOzyRoYcic-d9Zh9TdLY,6656
|
147
150
|
modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
148
151
|
modal_proto/api.proto,sha256=hM-iLwpYycp-wGyvoAieAEM_km42yI0jZTigPQLGPC0,86712
|
149
152
|
modal_proto/api_grpc.py,sha256=FYGqDegM_w_qxdtlxum8k31mDibKoMvmNxv_p9cKdKs,109056
|
@@ -162,10 +165,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
|
|
162
165
|
modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
163
166
|
modal_version/__init__.py,sha256=wiJQ53c-OMs0Xf1UeXOxQ7FwlV1VzIjnX6o-pRYZ_Pk,470
|
164
167
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
165
|
-
modal_version/_version_generated.py,sha256=
|
166
|
-
modal-0.73.
|
167
|
-
modal-0.73.
|
168
|
-
modal-0.73.
|
169
|
-
modal-0.73.
|
170
|
-
modal-0.73.
|
171
|
-
modal-0.73.
|
168
|
+
modal_version/_version_generated.py,sha256=5cj8cqKxfu-44XR4MQVL7vocSJ_677tLG2jtW72Zc7U,149
|
169
|
+
modal-0.73.47.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
170
|
+
modal-0.73.47.dist-info/METADATA,sha256=JSgSze5rgpMBFjrdIbIjQqqlzvFPjddyU-bPzU206I4,2452
|
171
|
+
modal-0.73.47.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
172
|
+
modal-0.73.47.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
173
|
+
modal-0.73.47.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
|
174
|
+
modal-0.73.47.dist-info/RECORD,,
|
modal_docs/__init__.py
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Copyright Modal Labs 2023
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# Copyright Modal Labs 2023
|
2
|
+
import inspect
|
3
|
+
import sys
|
4
|
+
from pathlib import Path
|
5
|
+
from typing import Optional, cast
|
6
|
+
|
7
|
+
from click import Command, Context, Group
|
8
|
+
|
9
|
+
from modal.cli.entry_point import entrypoint_cli
|
10
|
+
|
11
|
+
|
12
|
+
# Adapted from typer_cli, since it's incompatible with the latest version of typer
|
13
|
+
# (see https://github.com/tiangolo/typer-cli/issues/50)
|
14
|
+
def get_docs_for_click(
|
15
|
+
obj: Command,
|
16
|
+
ctx: Context,
|
17
|
+
*,
|
18
|
+
indent: int = 0,
|
19
|
+
name: str = "",
|
20
|
+
call_prefix: str = "",
|
21
|
+
) -> str:
|
22
|
+
docs = "#" * (1 + indent)
|
23
|
+
command_name = name or obj.name
|
24
|
+
if call_prefix:
|
25
|
+
command_name = f"{call_prefix} {command_name}"
|
26
|
+
title = f"`{command_name}`" if command_name else "CLI"
|
27
|
+
docs += f" {title}\n\n"
|
28
|
+
if obj.help:
|
29
|
+
docs += f"{inspect.cleandoc(obj.help)}\n\n"
|
30
|
+
usage_pieces = obj.collect_usage_pieces(ctx)
|
31
|
+
if usage_pieces:
|
32
|
+
docs += "**Usage**:\n\n"
|
33
|
+
docs += "```shell\n"
|
34
|
+
if command_name:
|
35
|
+
docs += f"{command_name} "
|
36
|
+
docs += f"{' '.join(usage_pieces)}\n"
|
37
|
+
docs += "```\n\n"
|
38
|
+
args = []
|
39
|
+
opts = []
|
40
|
+
for param in obj.get_params(ctx):
|
41
|
+
rv = param.get_help_record(ctx)
|
42
|
+
if rv is not None:
|
43
|
+
if getattr(param, "hidden", False):
|
44
|
+
continue
|
45
|
+
if param.param_type_name == "argument":
|
46
|
+
args.append(rv)
|
47
|
+
elif param.param_type_name == "option":
|
48
|
+
opts.append(rv)
|
49
|
+
if args:
|
50
|
+
docs += "**Arguments**:\n\n"
|
51
|
+
for arg_name, arg_help in args:
|
52
|
+
docs += f"* `{arg_name}`"
|
53
|
+
if arg_help:
|
54
|
+
docs += f": {arg_help}"
|
55
|
+
docs += "\n"
|
56
|
+
docs += "\n"
|
57
|
+
if opts:
|
58
|
+
docs += "**Options**:\n\n"
|
59
|
+
for opt_name, opt_help in opts:
|
60
|
+
docs += f"* `{opt_name}`"
|
61
|
+
if opt_help:
|
62
|
+
docs += f": {opt_help}"
|
63
|
+
docs += "\n"
|
64
|
+
docs += "\n"
|
65
|
+
if obj.epilog:
|
66
|
+
docs += f"{obj.epilog}\n\n"
|
67
|
+
if isinstance(obj, Group):
|
68
|
+
group: Group = cast(Group, obj)
|
69
|
+
commands = group.list_commands(ctx)
|
70
|
+
if commands:
|
71
|
+
docs += "**Commands**:\n\n"
|
72
|
+
for command in commands:
|
73
|
+
command_obj = group.get_command(ctx, command)
|
74
|
+
assert command_obj
|
75
|
+
if command_obj.hidden:
|
76
|
+
continue
|
77
|
+
docs += f"* `{command_obj.name}`"
|
78
|
+
command_help = command_obj.get_short_help_str(limit=250)
|
79
|
+
if command_help:
|
80
|
+
docs += f": {command_help}"
|
81
|
+
docs += "\n"
|
82
|
+
docs += "\n"
|
83
|
+
for command in commands:
|
84
|
+
command_obj = group.get_command(ctx, command)
|
85
|
+
if command_obj.hidden:
|
86
|
+
continue
|
87
|
+
assert command_obj
|
88
|
+
use_prefix = ""
|
89
|
+
if command_name:
|
90
|
+
use_prefix += f"{command_name}"
|
91
|
+
docs += get_docs_for_click(obj=command_obj, ctx=ctx, indent=indent + 1, call_prefix=use_prefix)
|
92
|
+
return docs
|
93
|
+
|
94
|
+
|
95
|
+
def run(output_dirname: Optional[str]) -> None:
|
96
|
+
entrypoint: Group = cast(Group, entrypoint_cli)
|
97
|
+
ctx = Context(entrypoint)
|
98
|
+
commands = entrypoint.list_commands(ctx)
|
99
|
+
|
100
|
+
for command in commands:
|
101
|
+
command_obj = entrypoint.get_command(ctx, command)
|
102
|
+
if command_obj.hidden:
|
103
|
+
continue
|
104
|
+
docs = get_docs_for_click(obj=command_obj, ctx=ctx, call_prefix="modal")
|
105
|
+
|
106
|
+
if output_dirname:
|
107
|
+
output_dir = Path(output_dirname)
|
108
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
109
|
+
output_file = output_dir / f"{command}.md"
|
110
|
+
print("Writing to", output_file)
|
111
|
+
output_file.write_text(docs)
|
112
|
+
else:
|
113
|
+
print(docs)
|
114
|
+
|
115
|
+
|
116
|
+
if __name__ == "__main__":
|
117
|
+
run(None if len(sys.argv) <= 1 else sys.argv[1])
|
@@ -0,0 +1,193 @@
|
|
1
|
+
# Copyright Modal Labs 2023
|
2
|
+
import importlib
|
3
|
+
import inspect
|
4
|
+
import json
|
5
|
+
import os
|
6
|
+
import sys
|
7
|
+
import warnings
|
8
|
+
from typing import NamedTuple
|
9
|
+
|
10
|
+
from synchronicity.synchronizer import FunctionWithAio
|
11
|
+
|
12
|
+
from .mdmd.mdmd import (
|
13
|
+
Category,
|
14
|
+
class_str,
|
15
|
+
default_filter,
|
16
|
+
function_str,
|
17
|
+
module_items,
|
18
|
+
module_str,
|
19
|
+
object_is_private,
|
20
|
+
package_filter,
|
21
|
+
)
|
22
|
+
|
23
|
+
|
24
|
+
class DocItem(NamedTuple):
|
25
|
+
label: str
|
26
|
+
category: Category
|
27
|
+
document: str
|
28
|
+
in_sidebar: bool = True
|
29
|
+
|
30
|
+
|
31
|
+
def validate_doc_item(docitem: DocItem) -> DocItem:
|
32
|
+
# Check that unwanted strings aren't leaking into our docs.
|
33
|
+
bad_strings = [
|
34
|
+
# Presence of a to-do inside a `DocItem` usually indicates it's been
|
35
|
+
# placed inside a function signature definition or right underneath it, before the body.
|
36
|
+
# Fix by moving the to-do into the body or above the signature.
|
37
|
+
"TODO:"
|
38
|
+
]
|
39
|
+
for line in docitem.document.splitlines():
|
40
|
+
for bad_str in bad_strings:
|
41
|
+
if bad_str in line:
|
42
|
+
msg = f"Found unwanted string '{bad_str}' in content for item '{docitem.label}'. Problem line: {line}"
|
43
|
+
raise ValueError(msg)
|
44
|
+
return docitem
|
45
|
+
|
46
|
+
|
47
|
+
def run(output_dir: str = None):
|
48
|
+
"""Generate Modal docs."""
|
49
|
+
import modal
|
50
|
+
|
51
|
+
ordered_doc_items: list[DocItem] = []
|
52
|
+
documented_items = set()
|
53
|
+
|
54
|
+
def filter_non_aio(module, name):
|
55
|
+
return not name.lower().startswith("aio")
|
56
|
+
|
57
|
+
def filter_already_documented(module, name):
|
58
|
+
item = getattr(module, name)
|
59
|
+
try:
|
60
|
+
if item in documented_items:
|
61
|
+
return False
|
62
|
+
except TypeError: # unhashable stuff
|
63
|
+
print(f"Warning: could not document item {name}: {item}:")
|
64
|
+
return False
|
65
|
+
documented_items.add(item)
|
66
|
+
return True
|
67
|
+
|
68
|
+
def modal_default_filter(module, name):
|
69
|
+
return default_filter(module, name) and filter_non_aio(module, name) and filter_already_documented(module, name)
|
70
|
+
|
71
|
+
def top_level_filter(module, name):
|
72
|
+
item = getattr(module, name)
|
73
|
+
if object_is_private(name, item) or inspect.ismodule(item):
|
74
|
+
return False
|
75
|
+
return package_filter("modal") and filter_already_documented(module, name) and filter_non_aio(module, name)
|
76
|
+
|
77
|
+
base_title_level = "#"
|
78
|
+
forced_module_docs = [
|
79
|
+
("modal.Function", "modal.functions"),
|
80
|
+
("modal.Secret", "modal.secret"),
|
81
|
+
("modal.Dict", "modal.dict"),
|
82
|
+
("modal.Queue", "modal.queue"),
|
83
|
+
("modal.call_graph", "modal.call_graph"),
|
84
|
+
("modal.gpu", "modal.gpu"),
|
85
|
+
("modal.runner", "modal.runner"),
|
86
|
+
("modal.Sandbox", "modal.sandbox"),
|
87
|
+
("modal.ContainerProcess", "modal.container_process"),
|
88
|
+
("modal.io_streams", "modal.io_streams"),
|
89
|
+
("modal.FileIO", "modal.file_io"),
|
90
|
+
]
|
91
|
+
# These aren't defined in `modal`, but should still be documented as top-level entries.
|
92
|
+
forced_members = {"web_endpoint", "asgi_app", "method", "wsgi_app", "forward"}
|
93
|
+
# These are excluded from the sidebar, typically to 'soft release' some documentation.
|
94
|
+
sidebar_excluded: set[str] = set()
|
95
|
+
|
96
|
+
for title, modulepath in forced_module_docs:
|
97
|
+
module = importlib.import_module(modulepath)
|
98
|
+
document = module_str(modulepath, module, title_level=base_title_level, filter_items=modal_default_filter)
|
99
|
+
if document:
|
100
|
+
ordered_doc_items.append(
|
101
|
+
validate_doc_item(
|
102
|
+
DocItem(
|
103
|
+
label=title,
|
104
|
+
category=Category.MODULE,
|
105
|
+
document=document,
|
106
|
+
in_sidebar=title not in sidebar_excluded,
|
107
|
+
)
|
108
|
+
)
|
109
|
+
)
|
110
|
+
|
111
|
+
def f(module, member_name):
|
112
|
+
return top_level_filter(module, member_name) or (member_name in forced_members)
|
113
|
+
|
114
|
+
# now add all remaining top level modal.X entries
|
115
|
+
for qual_name, item_name, item in module_items(modal, filter_items=f):
|
116
|
+
if object_is_private(item_name, item):
|
117
|
+
continue # skip stuff that's part of explicit `handle_objects` above
|
118
|
+
|
119
|
+
title = f"modal.{item_name}"
|
120
|
+
if inspect.isclass(item):
|
121
|
+
content = f"{base_title_level} {qual_name}\n\n" + class_str(item_name, item, base_title_level)
|
122
|
+
category = Category.CLASS
|
123
|
+
elif inspect.isroutine(item) or isinstance(item, FunctionWithAio):
|
124
|
+
content = f"{base_title_level} {qual_name}\n\n" + function_str(item_name, item)
|
125
|
+
category = Category.FUNCTION
|
126
|
+
elif inspect.ismodule(item):
|
127
|
+
continue # skipping imported modules
|
128
|
+
else:
|
129
|
+
warnings.warn(f"Not sure how to document: {item_name} ({item})")
|
130
|
+
continue
|
131
|
+
ordered_doc_items.append(
|
132
|
+
validate_doc_item(
|
133
|
+
DocItem(
|
134
|
+
label=title,
|
135
|
+
category=category,
|
136
|
+
document=content,
|
137
|
+
in_sidebar=title not in sidebar_excluded,
|
138
|
+
)
|
139
|
+
)
|
140
|
+
)
|
141
|
+
ordered_doc_items.sort()
|
142
|
+
|
143
|
+
for modulepath in ["modal.exception", "modal.config"]:
|
144
|
+
module = importlib.import_module(modulepath)
|
145
|
+
document = module_str(modulepath, module, title_level=base_title_level, filter_items=modal_default_filter)
|
146
|
+
ordered_doc_items.append(
|
147
|
+
DocItem(
|
148
|
+
label=modulepath,
|
149
|
+
category=Category.MODULE,
|
150
|
+
document=document,
|
151
|
+
)
|
152
|
+
)
|
153
|
+
|
154
|
+
# TODO: add some way of documenting our .aio sub-methods
|
155
|
+
|
156
|
+
make_markdown_docs(
|
157
|
+
ordered_doc_items,
|
158
|
+
output_dir,
|
159
|
+
)
|
160
|
+
|
161
|
+
|
162
|
+
def make_markdown_docs(items: list[DocItem], output_dir: str = None):
|
163
|
+
def _write_file(rel_path: str, data: str):
|
164
|
+
if output_dir is None:
|
165
|
+
print(f"<<< {rel_path}")
|
166
|
+
print(data)
|
167
|
+
print(f">>> {rel_path}")
|
168
|
+
return
|
169
|
+
|
170
|
+
filename = os.path.join(output_dir, rel_path)
|
171
|
+
print("Writing to", filename)
|
172
|
+
os.makedirs(os.path.dirname(filename), exist_ok=True)
|
173
|
+
with open(filename, "w") as fp:
|
174
|
+
fp.write(data)
|
175
|
+
|
176
|
+
sidebar_items = []
|
177
|
+
for item in items:
|
178
|
+
if item.in_sidebar:
|
179
|
+
sidebar_items.append(
|
180
|
+
{
|
181
|
+
"label": item.label,
|
182
|
+
"category": item.category.value,
|
183
|
+
}
|
184
|
+
)
|
185
|
+
_write_file(f"{item.label}.md", item.document)
|
186
|
+
|
187
|
+
sidebar_data = {"items": sidebar_items}
|
188
|
+
_write_file("sidebar.json", json.dumps(sidebar_data))
|
189
|
+
|
190
|
+
|
191
|
+
if __name__ == "__main__":
|
192
|
+
# running this module outputs docs to stdout for inspection, useful for debugging
|
193
|
+
run(None if len(sys.argv) <= 1 else sys.argv[1])
|
File without changes
|
File without changes
|
File without changes
|