modal 0.62.16__py3-none-any.whl → 0.72.11__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.
Files changed (220) hide show
  1. modal/__init__.py +17 -13
  2. modal/__main__.py +41 -3
  3. modal/_clustered_functions.py +80 -0
  4. modal/_clustered_functions.pyi +22 -0
  5. modal/_container_entrypoint.py +420 -937
  6. modal/_ipython.py +3 -13
  7. modal/_location.py +17 -10
  8. modal/_output.py +243 -99
  9. modal/_pty.py +2 -2
  10. modal/_resolver.py +55 -59
  11. modal/_resources.py +51 -0
  12. modal/_runtime/__init__.py +1 -0
  13. modal/_runtime/asgi.py +519 -0
  14. modal/_runtime/container_io_manager.py +1036 -0
  15. modal/_runtime/execution_context.py +89 -0
  16. modal/_runtime/telemetry.py +169 -0
  17. modal/_runtime/user_code_imports.py +356 -0
  18. modal/_serialization.py +134 -9
  19. modal/_traceback.py +47 -187
  20. modal/_tunnel.py +52 -16
  21. modal/_tunnel.pyi +19 -36
  22. modal/_utils/app_utils.py +3 -17
  23. modal/_utils/async_utils.py +479 -100
  24. modal/_utils/blob_utils.py +157 -186
  25. modal/_utils/bytes_io_segment_payload.py +97 -0
  26. modal/_utils/deprecation.py +89 -0
  27. modal/_utils/docker_utils.py +98 -0
  28. modal/_utils/function_utils.py +460 -171
  29. modal/_utils/grpc_testing.py +47 -31
  30. modal/_utils/grpc_utils.py +62 -109
  31. modal/_utils/hash_utils.py +61 -19
  32. modal/_utils/http_utils.py +39 -9
  33. modal/_utils/logger.py +2 -1
  34. modal/_utils/mount_utils.py +34 -16
  35. modal/_utils/name_utils.py +58 -0
  36. modal/_utils/package_utils.py +14 -1
  37. modal/_utils/pattern_utils.py +205 -0
  38. modal/_utils/rand_pb_testing.py +5 -7
  39. modal/_utils/shell_utils.py +15 -49
  40. modal/_vendor/a2wsgi_wsgi.py +62 -72
  41. modal/_vendor/cloudpickle.py +1 -1
  42. modal/_watcher.py +14 -12
  43. modal/app.py +1003 -314
  44. modal/app.pyi +540 -264
  45. modal/call_graph.py +7 -6
  46. modal/cli/_download.py +63 -53
  47. modal/cli/_traceback.py +200 -0
  48. modal/cli/app.py +205 -45
  49. modal/cli/config.py +12 -5
  50. modal/cli/container.py +62 -14
  51. modal/cli/dict.py +128 -0
  52. modal/cli/entry_point.py +26 -13
  53. modal/cli/environment.py +40 -9
  54. modal/cli/import_refs.py +64 -58
  55. modal/cli/launch.py +32 -18
  56. modal/cli/network_file_system.py +64 -83
  57. modal/cli/profile.py +1 -1
  58. modal/cli/programs/run_jupyter.py +35 -10
  59. modal/cli/programs/vscode.py +60 -10
  60. modal/cli/queues.py +131 -0
  61. modal/cli/run.py +234 -131
  62. modal/cli/secret.py +8 -7
  63. modal/cli/token.py +7 -2
  64. modal/cli/utils.py +79 -10
  65. modal/cli/volume.py +110 -109
  66. modal/client.py +250 -144
  67. modal/client.pyi +157 -118
  68. modal/cloud_bucket_mount.py +108 -34
  69. modal/cloud_bucket_mount.pyi +32 -38
  70. modal/cls.py +535 -148
  71. modal/cls.pyi +190 -146
  72. modal/config.py +41 -19
  73. modal/container_process.py +177 -0
  74. modal/container_process.pyi +82 -0
  75. modal/dict.py +111 -65
  76. modal/dict.pyi +136 -131
  77. modal/environments.py +106 -5
  78. modal/environments.pyi +77 -25
  79. modal/exception.py +34 -43
  80. modal/experimental.py +61 -2
  81. modal/extensions/ipython.py +5 -5
  82. modal/file_io.py +537 -0
  83. modal/file_io.pyi +235 -0
  84. modal/file_pattern_matcher.py +197 -0
  85. modal/functions.py +906 -911
  86. modal/functions.pyi +466 -430
  87. modal/gpu.py +57 -44
  88. modal/image.py +1089 -479
  89. modal/image.pyi +584 -228
  90. modal/io_streams.py +434 -0
  91. modal/io_streams.pyi +122 -0
  92. modal/mount.py +314 -101
  93. modal/mount.pyi +241 -235
  94. modal/network_file_system.py +92 -92
  95. modal/network_file_system.pyi +152 -110
  96. modal/object.py +67 -36
  97. modal/object.pyi +166 -143
  98. modal/output.py +63 -0
  99. modal/parallel_map.py +434 -0
  100. modal/parallel_map.pyi +75 -0
  101. modal/partial_function.py +282 -117
  102. modal/partial_function.pyi +222 -129
  103. modal/proxy.py +15 -12
  104. modal/proxy.pyi +3 -8
  105. modal/queue.py +182 -65
  106. modal/queue.pyi +218 -118
  107. modal/requirements/2024.04.txt +29 -0
  108. modal/requirements/2024.10.txt +16 -0
  109. modal/requirements/README.md +21 -0
  110. modal/requirements/base-images.json +22 -0
  111. modal/retries.py +48 -7
  112. modal/runner.py +459 -156
  113. modal/runner.pyi +135 -71
  114. modal/running_app.py +38 -0
  115. modal/sandbox.py +514 -236
  116. modal/sandbox.pyi +397 -169
  117. modal/schedule.py +4 -4
  118. modal/scheduler_placement.py +20 -3
  119. modal/secret.py +56 -31
  120. modal/secret.pyi +62 -42
  121. modal/serving.py +51 -56
  122. modal/serving.pyi +44 -36
  123. modal/stream_type.py +15 -0
  124. modal/token_flow.py +5 -3
  125. modal/token_flow.pyi +37 -32
  126. modal/volume.py +285 -157
  127. modal/volume.pyi +249 -184
  128. {modal-0.62.16.dist-info → modal-0.72.11.dist-info}/METADATA +7 -7
  129. modal-0.72.11.dist-info/RECORD +174 -0
  130. {modal-0.62.16.dist-info → modal-0.72.11.dist-info}/top_level.txt +0 -1
  131. modal_docs/gen_reference_docs.py +3 -1
  132. modal_docs/mdmd/mdmd.py +0 -1
  133. modal_docs/mdmd/signatures.py +5 -2
  134. modal_global_objects/images/base_images.py +28 -0
  135. modal_global_objects/mounts/python_standalone.py +2 -2
  136. modal_proto/__init__.py +1 -1
  137. modal_proto/api.proto +1288 -533
  138. modal_proto/api_grpc.py +856 -456
  139. modal_proto/api_pb2.py +2165 -1157
  140. modal_proto/api_pb2.pyi +8859 -0
  141. modal_proto/api_pb2_grpc.py +1674 -855
  142. modal_proto/api_pb2_grpc.pyi +1416 -0
  143. modal_proto/modal_api_grpc.py +149 -0
  144. modal_proto/modal_options_grpc.py +3 -0
  145. modal_proto/options_pb2.pyi +20 -0
  146. modal_proto/options_pb2_grpc.pyi +7 -0
  147. modal_proto/py.typed +0 -0
  148. modal_version/__init__.py +1 -1
  149. modal_version/_version_generated.py +2 -2
  150. modal/_asgi.py +0 -370
  151. modal/_container_entrypoint.pyi +0 -378
  152. modal/_container_exec.py +0 -128
  153. modal/_sandbox_shell.py +0 -49
  154. modal/shared_volume.py +0 -23
  155. modal/shared_volume.pyi +0 -24
  156. modal/stub.py +0 -783
  157. modal/stub.pyi +0 -332
  158. modal-0.62.16.dist-info/RECORD +0 -198
  159. modal_global_objects/images/conda.py +0 -15
  160. modal_global_objects/images/debian_slim.py +0 -15
  161. modal_global_objects/images/micromamba.py +0 -15
  162. test/__init__.py +0 -1
  163. test/aio_test.py +0 -12
  164. test/async_utils_test.py +0 -262
  165. test/blob_test.py +0 -67
  166. test/cli_imports_test.py +0 -149
  167. test/cli_test.py +0 -659
  168. test/client_test.py +0 -194
  169. test/cls_test.py +0 -630
  170. test/config_test.py +0 -137
  171. test/conftest.py +0 -1420
  172. test/container_app_test.py +0 -32
  173. test/container_test.py +0 -1389
  174. test/cpu_test.py +0 -23
  175. test/decorator_test.py +0 -85
  176. test/deprecation_test.py +0 -34
  177. test/dict_test.py +0 -33
  178. test/e2e_test.py +0 -68
  179. test/error_test.py +0 -7
  180. test/function_serialization_test.py +0 -32
  181. test/function_test.py +0 -653
  182. test/function_utils_test.py +0 -101
  183. test/gpu_test.py +0 -159
  184. test/grpc_utils_test.py +0 -141
  185. test/helpers.py +0 -42
  186. test/image_test.py +0 -669
  187. test/live_reload_test.py +0 -80
  188. test/lookup_test.py +0 -70
  189. test/mdmd_test.py +0 -329
  190. test/mount_test.py +0 -162
  191. test/mounted_files_test.py +0 -329
  192. test/network_file_system_test.py +0 -181
  193. test/notebook_test.py +0 -66
  194. test/object_test.py +0 -41
  195. test/package_utils_test.py +0 -25
  196. test/queue_test.py +0 -97
  197. test/resolver_test.py +0 -58
  198. test/retries_test.py +0 -67
  199. test/runner_test.py +0 -85
  200. test/sandbox_test.py +0 -191
  201. test/schedule_test.py +0 -15
  202. test/scheduler_placement_test.py +0 -29
  203. test/secret_test.py +0 -78
  204. test/serialization_test.py +0 -42
  205. test/stub_composition_test.py +0 -10
  206. test/stub_test.py +0 -360
  207. test/test_asgi_wrapper.py +0 -234
  208. test/token_flow_test.py +0 -18
  209. test/traceback_test.py +0 -135
  210. test/tunnel_test.py +0 -29
  211. test/utils_test.py +0 -88
  212. test/version_test.py +0 -14
  213. test/volume_test.py +0 -341
  214. test/watcher_test.py +0 -30
  215. test/webhook_test.py +0 -146
  216. /modal/{requirements.312.txt → requirements/2023.12.312.txt} +0 -0
  217. /modal/{requirements.txt → requirements/2023.12.txt} +0 -0
  218. {modal-0.62.16.dist-info → modal-0.72.11.dist-info}/LICENSE +0 -0
  219. {modal-0.62.16.dist-info → modal-0.72.11.dist-info}/WHEEL +0 -0
  220. {modal-0.62.16.dist-info → modal-0.72.11.dist-info}/entry_points.txt +0 -0
modal/app.pyi CHANGED
@@ -1,287 +1,563 @@
1
- import google.protobuf.message
2
- import modal._output
1
+ import collections.abc
2
+ import modal._utils.function_utils
3
3
  import modal.client
4
+ import modal.cloud_bucket_mount
5
+ import modal.cls
6
+ import modal.functions
7
+ import modal.gpu
8
+ import modal.image
9
+ import modal.mount
10
+ import modal.network_file_system
4
11
  import modal.object
12
+ import modal.partial_function
13
+ import modal.proxy
14
+ import modal.retries
15
+ import modal.running_app
16
+ import modal.schedule
17
+ import modal.scheduler_placement
18
+ import modal.secret
19
+ import modal.volume
5
20
  import modal_proto.api_pb2
21
+ import pathlib
22
+ import synchronicity.combined_types
6
23
  import typing
7
24
  import typing_extensions
8
25
 
9
- _Function = typing.TypeVar("_Function")
10
-
11
- class _LocalApp:
12
- _tag_to_object_id: typing.Dict[str, str]
13
- _client: modal.client._Client
14
- _app_id: str
15
- _app_page_url: str
16
- _environment_name: str
17
- _interactive: bool
18
-
19
- def __init__(self, client: modal.client._Client, app_id: str, app_page_url: str, tag_to_object_id: typing.Union[typing.Dict[str, str], None] = None, environment_name: typing.Union[str, None] = None, interactive: bool = False):
20
- ...
26
+ class _LocalEntrypoint:
27
+ _info: modal._utils.function_utils.FunctionInfo
28
+ _app: _App
21
29
 
30
+ def __init__(self, info: modal._utils.function_utils.FunctionInfo, app: _App) -> None: ...
31
+ def __call__(self, *args: typing.Any, **kwargs: typing.Any) -> typing.Any: ...
22
32
  @property
23
- def client(self) -> modal.client._Client:
24
- ...
25
-
33
+ def info(self) -> modal._utils.function_utils.FunctionInfo: ...
26
34
  @property
27
- def app_id(self) -> str:
28
- ...
29
-
35
+ def app(self) -> _App: ...
30
36
  @property
31
- def is_interactive(self) -> bool:
32
- ...
33
-
34
- async def _create_all_objects(self, indexed_objects: typing.Dict[str, modal.object._Object], new_app_state: int, environment_name: str, output_mgr: typing.Union[modal._output.OutputManager, None] = None):
35
- ...
36
-
37
- async def disconnect(self, reason: typing.Union[int, None] = None, exc_str: typing.Union[str, None] = None):
38
- ...
39
-
40
- async def stop(self):
41
- ...
37
+ def stub(self) -> _App: ...
42
38
 
43
- def log_url(self):
44
- ...
45
-
46
- @staticmethod
47
- async def _init_existing(client: modal.client._Client, existing_app_id: str) -> _LocalApp:
48
- ...
49
-
50
- @staticmethod
51
- async def _init_new(client: modal.client._Client, description: str, app_state: int, environment_name: str = '', interactive=False) -> _LocalApp:
52
- ...
53
-
54
- @staticmethod
55
- async def _init_from_name(client: modal.client._Client, name: str, namespace, environment_name: str = ''):
56
- ...
57
-
58
- async def deploy(self, name: str, namespace, public: bool) -> str:
59
- ...
60
-
61
-
62
- class _ContainerApp:
63
- _client: typing.Union[modal.client._Client, None]
64
- _app_id: typing.Union[str, None]
65
- _environment_name: typing.Union[str, None]
66
- _tag_to_object_id: typing.Dict[str, str]
67
- _object_handle_metadata: typing.Dict[str, typing.Union[google.protobuf.message.Message, None]]
68
- _is_interactivity_enabled: bool
69
- _function_def: typing.Union[modal_proto.api_pb2.Function, None]
70
- _fetching_inputs: bool
71
-
72
- def __init__(self):
73
- ...
39
+ class LocalEntrypoint:
40
+ _info: modal._utils.function_utils.FunctionInfo
41
+ _app: App
74
42
 
43
+ def __init__(self, info: modal._utils.function_utils.FunctionInfo, app: App) -> None: ...
44
+ def __call__(self, *args: typing.Any, **kwargs: typing.Any) -> typing.Any: ...
75
45
  @property
76
- def client(self) -> typing.Union[modal.client._Client, None]:
77
- ...
78
-
46
+ def info(self) -> modal._utils.function_utils.FunctionInfo: ...
79
47
  @property
80
- def app_id(self) -> typing.Union[str, None]:
81
- ...
82
-
48
+ def app(self) -> App: ...
83
49
  @property
84
- def fetching_inputs(self) -> bool:
85
- ...
86
-
87
- def associate_stub_container(self, stub):
88
- ...
89
-
90
- def _has_object(self, tag: str) -> bool:
91
- ...
92
-
93
- def _hydrate_object(self, obj, tag: str):
94
- ...
95
-
96
- def hydrate_function_deps(self, function: _Function, dep_object_ids: typing.List[str]):
97
- ...
98
-
99
- async def init(self, client: modal.client._Client, app_id: str, environment_name: str = '', function_def: typing.Union[modal_proto.api_pb2.Function, None] = None):
100
- ...
101
-
50
+ def stub(self) -> App: ...
51
+
52
+ def check_sequence(items: typing.Sequence[typing.Any], item_type: type[typing.Any], error_msg: str) -> None: ...
53
+
54
+ CLS_T = typing.TypeVar("CLS_T", bound="type[typing.Any]")
55
+
56
+ P = typing_extensions.ParamSpec("P")
57
+
58
+ ReturnType = typing.TypeVar("ReturnType")
59
+
60
+ OriginalReturnType = typing.TypeVar("OriginalReturnType")
61
+
62
+ class _FunctionDecoratorType:
63
+ @typing.overload
64
+ def __call__(
65
+ self, func: modal.partial_function.PartialFunction[P, ReturnType, OriginalReturnType]
66
+ ) -> modal.functions.Function[P, ReturnType, OriginalReturnType]: ...
67
+ @typing.overload
68
+ def __call__(
69
+ self, func: typing.Callable[P, collections.abc.Coroutine[typing.Any, typing.Any, ReturnType]]
70
+ ) -> modal.functions.Function[P, ReturnType, collections.abc.Coroutine[typing.Any, typing.Any, ReturnType]]: ...
71
+ @typing.overload
72
+ def __call__(self, func: typing.Callable[P, ReturnType]) -> modal.functions.Function[P, ReturnType, ReturnType]: ...
73
+
74
+ class _App:
75
+ _all_apps: typing.ClassVar[dict[typing.Optional[str], list[_App]]]
76
+ _container_app: typing.ClassVar[typing.Optional[_App]]
77
+ _name: typing.Optional[str]
78
+ _description: typing.Optional[str]
79
+ _functions: dict[str, modal.functions._Function]
80
+ _classes: dict[str, modal.cls._Cls]
81
+ _image: typing.Optional[modal.image._Image]
82
+ _mounts: collections.abc.Sequence[modal.mount._Mount]
83
+ _secrets: collections.abc.Sequence[modal.secret._Secret]
84
+ _volumes: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume._Volume]
85
+ _web_endpoints: list[str]
86
+ _local_entrypoints: dict[str, _LocalEntrypoint]
87
+ _app_id: typing.Optional[str]
88
+ _running_app: typing.Optional[modal.running_app.RunningApp]
89
+ _client: typing.Optional[modal.client._Client]
90
+
91
+ def __init__(
92
+ self,
93
+ name: typing.Optional[str] = None,
94
+ *,
95
+ image: typing.Optional[modal.image._Image] = None,
96
+ mounts: collections.abc.Sequence[modal.mount._Mount] = [],
97
+ secrets: collections.abc.Sequence[modal.secret._Secret] = [],
98
+ volumes: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume._Volume] = {},
99
+ ) -> None: ...
100
+ @property
101
+ def name(self) -> typing.Optional[str]: ...
102
+ @property
103
+ def is_interactive(self) -> bool: ...
104
+ @property
105
+ def app_id(self) -> typing.Optional[str]: ...
106
+ @property
107
+ def description(self) -> typing.Optional[str]: ...
102
108
  @staticmethod
103
- def _reset_container():
104
- ...
105
-
106
- def stop_fetching_inputs(self):
107
- ...
108
-
109
-
110
- class LocalApp:
111
- _tag_to_object_id: typing.Dict[str, str]
112
- _client: modal.client.Client
113
- _app_id: str
114
- _app_page_url: str
115
- _environment_name: str
116
- _interactive: bool
117
-
118
- def __init__(self, client: modal.client.Client, app_id: str, app_page_url: str, tag_to_object_id: typing.Union[typing.Dict[str, str], None] = None, environment_name: typing.Union[str, None] = None, interactive: bool = False):
119
- ...
120
-
109
+ async def lookup(
110
+ name: str,
111
+ client: typing.Optional[modal.client._Client] = None,
112
+ environment_name: typing.Optional[str] = None,
113
+ create_if_missing: bool = False,
114
+ ) -> _App: ...
115
+ def set_description(self, description: str): ...
116
+ def _validate_blueprint_value(self, key: str, value: typing.Any): ...
117
+ def __getitem__(self, tag: str): ...
118
+ def __setitem__(self, tag: str, obj: modal.object._Object): ...
119
+ def __getattr__(self, tag: str): ...
120
+ def __setattr__(self, tag: str, obj: modal.object._Object): ...
121
121
  @property
122
- def client(self) -> modal.client.Client:
123
- ...
124
-
122
+ def image(self) -> modal.image._Image: ...
123
+ @image.setter
124
+ def image(self, value): ...
125
+ def _uncreate_all_objects(self): ...
126
+ def _set_local_app(
127
+ self, client: modal.client._Client, running_app: modal.running_app.RunningApp
128
+ ) -> typing.AsyncContextManager[None]: ...
129
+ def run(
130
+ self,
131
+ client: typing.Optional[modal.client._Client] = None,
132
+ show_progress: typing.Optional[bool] = None,
133
+ detach: bool = False,
134
+ interactive: bool = False,
135
+ ) -> typing.AsyncContextManager[_App]: ...
136
+ def _get_default_image(self): ...
137
+ def _get_watch_mounts(self): ...
138
+ def _add_function(self, function: modal.functions._Function, is_web_endpoint: bool): ...
139
+ def _add_class(self, tag: str, cls: modal.cls._Cls): ...
140
+ def _init_container(self, client: modal.client._Client, running_app: modal.running_app.RunningApp): ...
125
141
  @property
126
- def app_id(self) -> str:
127
- ...
128
-
142
+ def registered_functions(self) -> dict[str, modal.functions._Function]: ...
129
143
  @property
130
- def is_interactive(self) -> bool:
131
- ...
132
-
133
- class ___create_all_objects_spec(typing_extensions.Protocol):
134
- def __call__(self, indexed_objects: typing.Dict[str, modal.object.Object], new_app_state: int, environment_name: str, output_mgr: typing.Union[modal._output.OutputManager, None] = None):
135
- ...
136
-
137
- async def aio(self, *args, **kwargs):
138
- ...
139
-
140
- _create_all_objects: ___create_all_objects_spec
141
-
142
- class __disconnect_spec(typing_extensions.Protocol):
143
- def __call__(self, reason: typing.Union[int, None] = None, exc_str: typing.Union[str, None] = None):
144
- ...
145
-
146
- async def aio(self, *args, **kwargs):
147
- ...
148
-
149
- disconnect: __disconnect_spec
150
-
151
- class __stop_spec(typing_extensions.Protocol):
152
- def __call__(self):
153
- ...
154
-
155
- async def aio(self, *args, **kwargs):
156
- ...
157
-
158
- stop: __stop_spec
159
-
160
- def log_url(self):
161
- ...
162
-
163
- class ___init_existing_spec(typing_extensions.Protocol):
164
- def __call__(self, client: modal.client.Client, existing_app_id: str) -> LocalApp:
165
- ...
166
-
167
- async def aio(self, *args, **kwargs) -> LocalApp:
168
- ...
169
-
170
- _init_existing: ___init_existing_spec
171
-
172
- class ___init_new_spec(typing_extensions.Protocol):
173
- def __call__(self, client: modal.client.Client, description: str, app_state: int, environment_name: str = '', interactive=False) -> LocalApp:
174
- ...
175
-
176
- async def aio(self, *args, **kwargs) -> LocalApp:
177
- ...
178
-
179
- _init_new: ___init_new_spec
180
-
181
- class ___init_from_name_spec(typing_extensions.Protocol):
182
- def __call__(self, client: modal.client.Client, name: str, namespace, environment_name: str = ''):
183
- ...
184
-
185
- async def aio(self, *args, **kwargs):
186
- ...
187
-
188
- _init_from_name: ___init_from_name_spec
189
-
190
- class __deploy_spec(typing_extensions.Protocol):
191
- def __call__(self, name: str, namespace, public: bool) -> str:
192
- ...
193
-
194
- async def aio(self, *args, **kwargs) -> str:
195
- ...
196
-
197
- deploy: __deploy_spec
198
-
199
-
200
- class ContainerApp:
201
- _client: typing.Union[modal.client.Client, None]
202
- _app_id: typing.Union[str, None]
203
- _environment_name: typing.Union[str, None]
204
- _tag_to_object_id: typing.Dict[str, str]
205
- _object_handle_metadata: typing.Dict[str, typing.Union[google.protobuf.message.Message, None]]
206
- _is_interactivity_enabled: bool
207
- _function_def: typing.Union[modal_proto.api_pb2.Function, None]
208
- _fetching_inputs: bool
209
-
210
- def __init__(self):
211
- ...
212
-
144
+ def registered_classes(self) -> dict[str, modal.functions._Function]: ...
213
145
  @property
214
- def client(self) -> typing.Union[modal.client.Client, None]:
215
- ...
216
-
146
+ def registered_entrypoints(self) -> dict[str, _LocalEntrypoint]: ...
217
147
  @property
218
- def app_id(self) -> typing.Union[str, None]:
219
- ...
220
-
148
+ def indexed_objects(self) -> dict[str, modal.object._Object]: ...
221
149
  @property
222
- def fetching_inputs(self) -> bool:
223
- ...
224
-
225
- def associate_stub_container(self, stub):
226
- ...
227
-
228
- def _has_object(self, tag: str) -> bool:
229
- ...
230
-
231
- def _hydrate_object(self, obj, tag: str):
232
- ...
233
-
234
- def hydrate_function_deps(self, function: _Function, dep_object_ids: typing.List[str]):
235
- ...
236
-
237
- class __init_spec(typing_extensions.Protocol):
238
- def __call__(self, client: modal.client.Client, app_id: str, environment_name: str = '', function_def: typing.Union[modal_proto.api_pb2.Function, None] = None):
239
- ...
240
-
241
- async def aio(self, *args, **kwargs):
242
- ...
243
-
244
- init: __init_spec
245
-
150
+ def registered_web_endpoints(self) -> list[str]: ...
151
+ def local_entrypoint(
152
+ self, _warn_parentheses_missing: typing.Any = None, *, name: typing.Optional[str] = None
153
+ ) -> typing.Callable[[typing.Callable[..., typing.Any]], _LocalEntrypoint]: ...
154
+ def function(
155
+ self,
156
+ _warn_parentheses_missing: typing.Any = None,
157
+ *,
158
+ image: typing.Optional[modal.image._Image] = None,
159
+ schedule: typing.Optional[modal.schedule.Schedule] = None,
160
+ secrets: collections.abc.Sequence[modal.secret._Secret] = (),
161
+ gpu: typing.Union[
162
+ None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]
163
+ ] = None,
164
+ serialized: bool = False,
165
+ mounts: collections.abc.Sequence[modal.mount._Mount] = (),
166
+ network_file_systems: dict[
167
+ typing.Union[str, pathlib.PurePosixPath], modal.network_file_system._NetworkFileSystem
168
+ ] = {},
169
+ volumes: dict[
170
+ typing.Union[str, pathlib.PurePosixPath],
171
+ typing.Union[modal.volume._Volume, modal.cloud_bucket_mount._CloudBucketMount],
172
+ ] = {},
173
+ allow_cross_region_volumes: bool = False,
174
+ cpu: typing.Union[float, tuple[float, float], None] = None,
175
+ memory: typing.Union[int, tuple[int, int], None] = None,
176
+ ephemeral_disk: typing.Optional[int] = None,
177
+ proxy: typing.Optional[modal.proxy._Proxy] = None,
178
+ retries: typing.Union[int, modal.retries.Retries, None] = None,
179
+ concurrency_limit: typing.Optional[int] = None,
180
+ allow_concurrent_inputs: typing.Optional[int] = None,
181
+ container_idle_timeout: typing.Optional[int] = None,
182
+ timeout: typing.Optional[int] = None,
183
+ keep_warm: typing.Optional[int] = None,
184
+ name: typing.Optional[str] = None,
185
+ is_generator: typing.Optional[bool] = None,
186
+ cloud: typing.Optional[str] = None,
187
+ region: typing.Union[str, collections.abc.Sequence[str], None] = None,
188
+ enable_memory_snapshot: bool = False,
189
+ block_network: bool = False,
190
+ max_inputs: typing.Optional[int] = None,
191
+ i6pn: typing.Optional[bool] = None,
192
+ _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
193
+ _experimental_buffer_containers: typing.Optional[int] = None,
194
+ _experimental_proxy_ip: typing.Optional[str] = None,
195
+ _experimental_custom_scaling_factor: typing.Optional[float] = None,
196
+ ) -> _FunctionDecoratorType: ...
197
+ @typing_extensions.dataclass_transform(
198
+ field_specifiers=(modal.cls.parameter,),
199
+ kw_only_default=True,
200
+ )
201
+ def cls(
202
+ self,
203
+ _warn_parentheses_missing: typing.Optional[bool] = None,
204
+ *,
205
+ image: typing.Optional[modal.image._Image] = None,
206
+ secrets: collections.abc.Sequence[modal.secret._Secret] = (),
207
+ gpu: typing.Union[
208
+ None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]
209
+ ] = None,
210
+ serialized: bool = False,
211
+ mounts: collections.abc.Sequence[modal.mount._Mount] = (),
212
+ network_file_systems: dict[
213
+ typing.Union[str, pathlib.PurePosixPath], modal.network_file_system._NetworkFileSystem
214
+ ] = {},
215
+ volumes: dict[
216
+ typing.Union[str, pathlib.PurePosixPath],
217
+ typing.Union[modal.volume._Volume, modal.cloud_bucket_mount._CloudBucketMount],
218
+ ] = {},
219
+ allow_cross_region_volumes: bool = False,
220
+ cpu: typing.Union[float, tuple[float, float], None] = None,
221
+ memory: typing.Union[int, tuple[int, int], None] = None,
222
+ ephemeral_disk: typing.Optional[int] = None,
223
+ proxy: typing.Optional[modal.proxy._Proxy] = None,
224
+ retries: typing.Union[int, modal.retries.Retries, None] = None,
225
+ concurrency_limit: typing.Optional[int] = None,
226
+ allow_concurrent_inputs: typing.Optional[int] = None,
227
+ container_idle_timeout: typing.Optional[int] = None,
228
+ timeout: typing.Optional[int] = None,
229
+ keep_warm: typing.Optional[int] = None,
230
+ cloud: typing.Optional[str] = None,
231
+ region: typing.Union[str, collections.abc.Sequence[str], None] = None,
232
+ enable_memory_snapshot: bool = False,
233
+ block_network: bool = False,
234
+ max_inputs: typing.Optional[int] = None,
235
+ _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
236
+ _experimental_buffer_containers: typing.Optional[int] = None,
237
+ _experimental_proxy_ip: typing.Optional[str] = None,
238
+ _experimental_custom_scaling_factor: typing.Optional[float] = None,
239
+ ) -> typing.Callable[[CLS_T], CLS_T]: ...
240
+ async def spawn_sandbox(
241
+ self,
242
+ *entrypoint_args: str,
243
+ image: typing.Optional[modal.image._Image] = None,
244
+ mounts: collections.abc.Sequence[modal.mount._Mount] = (),
245
+ secrets: collections.abc.Sequence[modal.secret._Secret] = (),
246
+ network_file_systems: dict[
247
+ typing.Union[str, pathlib.PurePosixPath], modal.network_file_system._NetworkFileSystem
248
+ ] = {},
249
+ timeout: typing.Optional[int] = None,
250
+ workdir: typing.Optional[str] = None,
251
+ gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
252
+ cloud: typing.Optional[str] = None,
253
+ region: typing.Union[str, collections.abc.Sequence[str], None] = None,
254
+ cpu: typing.Union[float, tuple[float, float], None] = None,
255
+ memory: typing.Union[int, tuple[int, int], None] = None,
256
+ block_network: bool = False,
257
+ volumes: dict[
258
+ typing.Union[str, pathlib.PurePosixPath],
259
+ typing.Union[modal.volume._Volume, modal.cloud_bucket_mount._CloudBucketMount],
260
+ ] = {},
261
+ pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
262
+ _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
263
+ ) -> None: ...
264
+ def include(self, /, other_app: _App): ...
265
+ def _logs(
266
+ self, client: typing.Optional[modal.client._Client] = None
267
+ ) -> collections.abc.AsyncGenerator[str, None]: ...
268
+ @classmethod
269
+ def _get_container_app(cls) -> typing.Optional[_App]: ...
270
+ @classmethod
271
+ def _reset_container_app(cls): ...
272
+
273
+ class App:
274
+ _all_apps: typing.ClassVar[dict[typing.Optional[str], list[App]]]
275
+ _container_app: typing.ClassVar[typing.Optional[App]]
276
+ _name: typing.Optional[str]
277
+ _description: typing.Optional[str]
278
+ _functions: dict[str, modal.functions.Function]
279
+ _classes: dict[str, modal.cls.Cls]
280
+ _image: typing.Optional[modal.image.Image]
281
+ _mounts: collections.abc.Sequence[modal.mount.Mount]
282
+ _secrets: collections.abc.Sequence[modal.secret.Secret]
283
+ _volumes: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume.Volume]
284
+ _web_endpoints: list[str]
285
+ _local_entrypoints: dict[str, LocalEntrypoint]
286
+ _app_id: typing.Optional[str]
287
+ _running_app: typing.Optional[modal.running_app.RunningApp]
288
+ _client: typing.Optional[modal.client.Client]
289
+
290
+ def __init__(
291
+ self,
292
+ name: typing.Optional[str] = None,
293
+ *,
294
+ image: typing.Optional[modal.image.Image] = None,
295
+ mounts: collections.abc.Sequence[modal.mount.Mount] = [],
296
+ secrets: collections.abc.Sequence[modal.secret.Secret] = [],
297
+ volumes: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume.Volume] = {},
298
+ ) -> None: ...
299
+ @property
300
+ def name(self) -> typing.Optional[str]: ...
301
+ @property
302
+ def is_interactive(self) -> bool: ...
303
+ @property
304
+ def app_id(self) -> typing.Optional[str]: ...
305
+ @property
306
+ def description(self) -> typing.Optional[str]: ...
307
+
308
+ class __lookup_spec(typing_extensions.Protocol):
309
+ def __call__(
310
+ self,
311
+ name: str,
312
+ client: typing.Optional[modal.client.Client] = None,
313
+ environment_name: typing.Optional[str] = None,
314
+ create_if_missing: bool = False,
315
+ ) -> App: ...
316
+ async def aio(
317
+ self,
318
+ name: str,
319
+ client: typing.Optional[modal.client.Client] = None,
320
+ environment_name: typing.Optional[str] = None,
321
+ create_if_missing: bool = False,
322
+ ) -> App: ...
323
+
324
+ lookup: __lookup_spec
325
+
326
+ def set_description(self, description: str): ...
327
+ def _validate_blueprint_value(self, key: str, value: typing.Any): ...
328
+ def __getitem__(self, tag: str): ...
329
+ def __setitem__(self, tag: str, obj: modal.object.Object): ...
330
+ def __getattr__(self, tag: str): ...
331
+ def __setattr__(self, tag: str, obj: modal.object.Object): ...
332
+ @property
333
+ def image(self) -> modal.image.Image: ...
334
+ @image.setter
335
+ def image(self, value): ...
336
+ def _uncreate_all_objects(self): ...
337
+
338
+ class ___set_local_app_spec(typing_extensions.Protocol):
339
+ def __call__(
340
+ self, client: modal.client.Client, running_app: modal.running_app.RunningApp
341
+ ) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]: ...
342
+ def aio(
343
+ self, client: modal.client.Client, running_app: modal.running_app.RunningApp
344
+ ) -> typing.AsyncContextManager[None]: ...
345
+
346
+ _set_local_app: ___set_local_app_spec
347
+
348
+ class __run_spec(typing_extensions.Protocol):
349
+ def __call__(
350
+ self,
351
+ client: typing.Optional[modal.client.Client] = None,
352
+ show_progress: typing.Optional[bool] = None,
353
+ detach: bool = False,
354
+ interactive: bool = False,
355
+ ) -> synchronicity.combined_types.AsyncAndBlockingContextManager[App]: ...
356
+ def aio(
357
+ self,
358
+ client: typing.Optional[modal.client.Client] = None,
359
+ show_progress: typing.Optional[bool] = None,
360
+ detach: bool = False,
361
+ interactive: bool = False,
362
+ ) -> typing.AsyncContextManager[App]: ...
363
+
364
+ run: __run_spec
365
+
366
+ def _get_default_image(self): ...
367
+ def _get_watch_mounts(self): ...
368
+ def _add_function(self, function: modal.functions.Function, is_web_endpoint: bool): ...
369
+ def _add_class(self, tag: str, cls: modal.cls.Cls): ...
370
+ def _init_container(self, client: modal.client.Client, running_app: modal.running_app.RunningApp): ...
371
+ @property
372
+ def registered_functions(self) -> dict[str, modal.functions.Function]: ...
373
+ @property
374
+ def registered_classes(self) -> dict[str, modal.functions.Function]: ...
375
+ @property
376
+ def registered_entrypoints(self) -> dict[str, LocalEntrypoint]: ...
377
+ @property
378
+ def indexed_objects(self) -> dict[str, modal.object.Object]: ...
379
+ @property
380
+ def registered_web_endpoints(self) -> list[str]: ...
381
+ def local_entrypoint(
382
+ self, _warn_parentheses_missing: typing.Any = None, *, name: typing.Optional[str] = None
383
+ ) -> typing.Callable[[typing.Callable[..., typing.Any]], LocalEntrypoint]: ...
384
+ def function(
385
+ self,
386
+ _warn_parentheses_missing: typing.Any = None,
387
+ *,
388
+ image: typing.Optional[modal.image.Image] = None,
389
+ schedule: typing.Optional[modal.schedule.Schedule] = None,
390
+ secrets: collections.abc.Sequence[modal.secret.Secret] = (),
391
+ gpu: typing.Union[
392
+ None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]
393
+ ] = None,
394
+ serialized: bool = False,
395
+ mounts: collections.abc.Sequence[modal.mount.Mount] = (),
396
+ network_file_systems: dict[
397
+ typing.Union[str, pathlib.PurePosixPath], modal.network_file_system.NetworkFileSystem
398
+ ] = {},
399
+ volumes: dict[
400
+ typing.Union[str, pathlib.PurePosixPath],
401
+ typing.Union[modal.volume.Volume, modal.cloud_bucket_mount.CloudBucketMount],
402
+ ] = {},
403
+ allow_cross_region_volumes: bool = False,
404
+ cpu: typing.Union[float, tuple[float, float], None] = None,
405
+ memory: typing.Union[int, tuple[int, int], None] = None,
406
+ ephemeral_disk: typing.Optional[int] = None,
407
+ proxy: typing.Optional[modal.proxy.Proxy] = None,
408
+ retries: typing.Union[int, modal.retries.Retries, None] = None,
409
+ concurrency_limit: typing.Optional[int] = None,
410
+ allow_concurrent_inputs: typing.Optional[int] = None,
411
+ container_idle_timeout: typing.Optional[int] = None,
412
+ timeout: typing.Optional[int] = None,
413
+ keep_warm: typing.Optional[int] = None,
414
+ name: typing.Optional[str] = None,
415
+ is_generator: typing.Optional[bool] = None,
416
+ cloud: typing.Optional[str] = None,
417
+ region: typing.Union[str, collections.abc.Sequence[str], None] = None,
418
+ enable_memory_snapshot: bool = False,
419
+ block_network: bool = False,
420
+ max_inputs: typing.Optional[int] = None,
421
+ i6pn: typing.Optional[bool] = None,
422
+ _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
423
+ _experimental_buffer_containers: typing.Optional[int] = None,
424
+ _experimental_proxy_ip: typing.Optional[str] = None,
425
+ _experimental_custom_scaling_factor: typing.Optional[float] = None,
426
+ ) -> _FunctionDecoratorType: ...
427
+ @typing_extensions.dataclass_transform(
428
+ field_specifiers=(modal.cls.parameter,),
429
+ kw_only_default=True,
430
+ )
431
+ def cls(
432
+ self,
433
+ _warn_parentheses_missing: typing.Optional[bool] = None,
434
+ *,
435
+ image: typing.Optional[modal.image.Image] = None,
436
+ secrets: collections.abc.Sequence[modal.secret.Secret] = (),
437
+ gpu: typing.Union[
438
+ None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]
439
+ ] = None,
440
+ serialized: bool = False,
441
+ mounts: collections.abc.Sequence[modal.mount.Mount] = (),
442
+ network_file_systems: dict[
443
+ typing.Union[str, pathlib.PurePosixPath], modal.network_file_system.NetworkFileSystem
444
+ ] = {},
445
+ volumes: dict[
446
+ typing.Union[str, pathlib.PurePosixPath],
447
+ typing.Union[modal.volume.Volume, modal.cloud_bucket_mount.CloudBucketMount],
448
+ ] = {},
449
+ allow_cross_region_volumes: bool = False,
450
+ cpu: typing.Union[float, tuple[float, float], None] = None,
451
+ memory: typing.Union[int, tuple[int, int], None] = None,
452
+ ephemeral_disk: typing.Optional[int] = None,
453
+ proxy: typing.Optional[modal.proxy.Proxy] = None,
454
+ retries: typing.Union[int, modal.retries.Retries, None] = None,
455
+ concurrency_limit: typing.Optional[int] = None,
456
+ allow_concurrent_inputs: typing.Optional[int] = None,
457
+ container_idle_timeout: typing.Optional[int] = None,
458
+ timeout: typing.Optional[int] = None,
459
+ keep_warm: typing.Optional[int] = None,
460
+ cloud: typing.Optional[str] = None,
461
+ region: typing.Union[str, collections.abc.Sequence[str], None] = None,
462
+ enable_memory_snapshot: bool = False,
463
+ block_network: bool = False,
464
+ max_inputs: typing.Optional[int] = None,
465
+ _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
466
+ _experimental_buffer_containers: typing.Optional[int] = None,
467
+ _experimental_proxy_ip: typing.Optional[str] = None,
468
+ _experimental_custom_scaling_factor: typing.Optional[float] = None,
469
+ ) -> typing.Callable[[CLS_T], CLS_T]: ...
470
+
471
+ class __spawn_sandbox_spec(typing_extensions.Protocol):
472
+ def __call__(
473
+ self,
474
+ *entrypoint_args: str,
475
+ image: typing.Optional[modal.image.Image] = None,
476
+ mounts: collections.abc.Sequence[modal.mount.Mount] = (),
477
+ secrets: collections.abc.Sequence[modal.secret.Secret] = (),
478
+ network_file_systems: dict[
479
+ typing.Union[str, pathlib.PurePosixPath], modal.network_file_system.NetworkFileSystem
480
+ ] = {},
481
+ timeout: typing.Optional[int] = None,
482
+ workdir: typing.Optional[str] = None,
483
+ gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
484
+ cloud: typing.Optional[str] = None,
485
+ region: typing.Union[str, collections.abc.Sequence[str], None] = None,
486
+ cpu: typing.Union[float, tuple[float, float], None] = None,
487
+ memory: typing.Union[int, tuple[int, int], None] = None,
488
+ block_network: bool = False,
489
+ volumes: dict[
490
+ typing.Union[str, pathlib.PurePosixPath],
491
+ typing.Union[modal.volume.Volume, modal.cloud_bucket_mount.CloudBucketMount],
492
+ ] = {},
493
+ pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
494
+ _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
495
+ ) -> None: ...
496
+ async def aio(
497
+ self,
498
+ *entrypoint_args: str,
499
+ image: typing.Optional[modal.image.Image] = None,
500
+ mounts: collections.abc.Sequence[modal.mount.Mount] = (),
501
+ secrets: collections.abc.Sequence[modal.secret.Secret] = (),
502
+ network_file_systems: dict[
503
+ typing.Union[str, pathlib.PurePosixPath], modal.network_file_system.NetworkFileSystem
504
+ ] = {},
505
+ timeout: typing.Optional[int] = None,
506
+ workdir: typing.Optional[str] = None,
507
+ gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
508
+ cloud: typing.Optional[str] = None,
509
+ region: typing.Union[str, collections.abc.Sequence[str], None] = None,
510
+ cpu: typing.Union[float, tuple[float, float], None] = None,
511
+ memory: typing.Union[int, tuple[int, int], None] = None,
512
+ block_network: bool = False,
513
+ volumes: dict[
514
+ typing.Union[str, pathlib.PurePosixPath],
515
+ typing.Union[modal.volume.Volume, modal.cloud_bucket_mount.CloudBucketMount],
516
+ ] = {},
517
+ pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
518
+ _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
519
+ ) -> None: ...
520
+
521
+ spawn_sandbox: __spawn_sandbox_spec
522
+
523
+ def include(self, /, other_app: App): ...
524
+
525
+ class ___logs_spec(typing_extensions.Protocol):
526
+ def __call__(
527
+ self, client: typing.Optional[modal.client.Client] = None
528
+ ) -> typing.Generator[str, None, None]: ...
529
+ def aio(
530
+ self, client: typing.Optional[modal.client.Client] = None
531
+ ) -> collections.abc.AsyncGenerator[str, None]: ...
532
+
533
+ _logs: ___logs_spec
534
+
535
+ @classmethod
536
+ def _get_container_app(cls) -> typing.Optional[App]: ...
537
+ @classmethod
538
+ def _reset_container_app(cls): ...
539
+
540
+ class _Stub(_App):
246
541
  @staticmethod
247
- def _reset_container():
248
- ...
249
-
250
- def stop_fetching_inputs(self):
251
- ...
252
-
253
-
254
- _container_app: _ContainerApp
255
-
256
- container_app: ContainerApp
257
-
258
- async def _interact(client: typing.Union[modal.client._Client, None] = None) -> None:
259
- ...
260
-
261
-
262
- class __interact_spec(typing_extensions.Protocol):
263
- def __call__(self, client: typing.Union[modal.client.Client, None] = None) -> None:
264
- ...
265
-
266
- async def aio(self, *args, **kwargs) -> None:
267
- ...
268
-
269
- interact: __interact_spec
270
-
271
-
272
- def is_local() -> bool:
273
- ...
274
-
275
-
276
- async def _list_apps(env: str, client: typing.Union[modal.client._Client, None] = None) -> typing.List[modal_proto.api_pb2.AppStats]:
277
- ...
278
-
279
-
280
- class __list_apps_spec(typing_extensions.Protocol):
281
- def __call__(self, env: str, client: typing.Union[modal.client.Client, None] = None) -> typing.List[modal_proto.api_pb2.AppStats]:
282
- ...
283
-
284
- async def aio(self, *args, **kwargs) -> typing.List[modal_proto.api_pb2.AppStats]:
285
- ...
286
-
287
- list_apps: __list_apps_spec
542
+ def __new__(
543
+ cls,
544
+ name: typing.Optional[str] = None,
545
+ *,
546
+ image: typing.Optional[modal.image._Image] = None,
547
+ mounts: collections.abc.Sequence[modal.mount._Mount] = [],
548
+ secrets: collections.abc.Sequence[modal.secret._Secret] = [],
549
+ volumes: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume._Volume] = {},
550
+ ): ...
551
+
552
+ class Stub(App):
553
+ def __init__(
554
+ self,
555
+ name: typing.Optional[str] = None,
556
+ *,
557
+ image: typing.Optional[modal.image.Image] = None,
558
+ mounts: collections.abc.Sequence[modal.mount.Mount] = [],
559
+ secrets: collections.abc.Sequence[modal.secret.Secret] = [],
560
+ volumes: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume.Volume] = {},
561
+ ) -> None: ...
562
+
563
+ _default_image: modal.image._Image