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/object.pyi CHANGED
@@ -1,3 +1,4 @@
1
+ import collections.abc
1
2
  import google.protobuf.message
2
3
  import modal._resolver
3
4
  import modal.client
@@ -8,189 +9,211 @@ O = typing.TypeVar("O", bound="_Object")
8
9
 
9
10
  _BLOCKING_O = typing.TypeVar("_BLOCKING_O", bound="Object")
10
11
 
11
- def _get_environment_name(environment_name: typing.Union[str, None], resolver: typing.Union[modal._resolver.Resolver, None] = None) -> typing.Union[str, None]:
12
- ...
13
-
12
+ def _get_environment_name(
13
+ environment_name: typing.Optional[str] = None, resolver: typing.Optional[modal._resolver.Resolver] = None
14
+ ) -> typing.Optional[str]: ...
14
15
 
15
16
  class _Object:
16
- _type_prefix: typing.ClassVar[typing.Union[str, None]]
17
- _prefix_to_type: typing.ClassVar[typing.Dict[str, type]]
18
- _load: typing.Union[typing.Callable[[O, modal._resolver.Resolver, typing.Union[str, None]], typing.Awaitable[None]], None]
19
- _preload: typing.Union[typing.Callable[[O, modal._resolver.Resolver, typing.Union[str, None]], typing.Awaitable[None]], None]
17
+ _type_prefix: typing.ClassVar[typing.Optional[str]]
18
+ _prefix_to_type: typing.ClassVar[dict[str, type]]
19
+ _load: typing.Optional[
20
+ typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
21
+ ]
22
+ _preload: typing.Optional[
23
+ typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
24
+ ]
20
25
  _rep: str
21
26
  _is_another_app: bool
22
27
  _hydrate_lazily: bool
23
- _deps: typing.Union[typing.Callable[..., typing.List[_Object]], None]
24
- _deduplication_key: typing.Union[typing.Callable[[], typing.Awaitable[typing.Hashable]], None]
28
+ _deps: typing.Optional[typing.Callable[..., list[_Object]]]
29
+ _deduplication_key: typing.Optional[typing.Callable[[], collections.abc.Awaitable[collections.abc.Hashable]]]
25
30
  _object_id: str
26
31
  _client: modal.client._Client
27
32
  _is_hydrated: bool
33
+ _is_rehydrated: bool
28
34
 
29
35
  @classmethod
30
- def __init_subclass__(cls, type_prefix: typing.Union[str, None] = None):
31
- ...
32
-
33
- def __init__(self, *args, **kwargs):
34
- ...
35
-
36
- def _init(self, rep: str, load: typing.Union[typing.Callable[[O, modal._resolver.Resolver, typing.Union[str, None]], typing.Awaitable[None]], None] = None, is_another_app: bool = False, preload: typing.Union[typing.Callable[[O, modal._resolver.Resolver, typing.Union[str, None]], typing.Awaitable[None]], None] = None, hydrate_lazily: bool = False, deps: typing.Union[typing.Callable[..., typing.List[_Object]], None] = None, deduplication_key: typing.Union[typing.Callable[[], typing.Awaitable[typing.Hashable]], None] = None):
37
- ...
38
-
39
- def _unhydrate(self):
40
- ...
41
-
42
- def _initialize_from_empty(self):
43
- ...
44
-
45
- def _initialize_from_other(self, other):
46
- ...
47
-
48
- def _hydrate(self, object_id: str, client: modal.client._Client, metadata: typing.Union[google.protobuf.message.Message, None]):
49
- ...
50
-
51
- def _hydrate_metadata(self, metadata: typing.Union[google.protobuf.message.Message, None]):
52
- ...
53
-
54
- def _get_metadata(self) -> typing.Union[google.protobuf.message.Message, None]:
55
- ...
56
-
57
- def _init_from_other(self, other: O):
58
- ...
59
-
60
- def clone(self: O) -> O:
61
- ...
62
-
36
+ def __init_subclass__(cls, type_prefix: typing.Optional[str] = None): ...
37
+ def __init__(self, *args, **kwargs): ...
38
+ def _init(
39
+ self,
40
+ rep: str,
41
+ load: typing.Optional[
42
+ typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
43
+ ] = None,
44
+ is_another_app: bool = False,
45
+ preload: typing.Optional[
46
+ typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
47
+ ] = None,
48
+ hydrate_lazily: bool = False,
49
+ deps: typing.Optional[typing.Callable[..., list[_Object]]] = None,
50
+ deduplication_key: typing.Optional[
51
+ typing.Callable[[], collections.abc.Awaitable[collections.abc.Hashable]]
52
+ ] = None,
53
+ ): ...
54
+ def _unhydrate(self): ...
55
+ def _initialize_from_empty(self): ...
56
+ def _initialize_from_other(self, other): ...
57
+ def _hydrate(
58
+ self, object_id: str, client: modal.client._Client, metadata: typing.Optional[google.protobuf.message.Message]
59
+ ): ...
60
+ def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
61
+ def _get_metadata(self) -> typing.Optional[google.protobuf.message.Message]: ...
62
+ def _validate_is_hydrated(self: O): ...
63
+ def clone(self: O) -> O: ...
63
64
  @classmethod
64
- def _from_loader(cls, load: typing.Callable[[O, modal._resolver.Resolver, typing.Union[str, None]], typing.Awaitable[None]], rep: str, is_another_app: bool = False, preload: typing.Union[typing.Callable[[O, modal._resolver.Resolver, typing.Union[str, None]], typing.Awaitable[None]], None] = None, hydrate_lazily: bool = False, deps: typing.Union[typing.Callable[..., typing.List[_Object]], None] = None, deduplication_key: typing.Union[typing.Callable[[], typing.Awaitable[typing.Hashable]], None] = None):
65
- ...
66
-
65
+ def _from_loader(
66
+ cls,
67
+ load: typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]],
68
+ rep: str,
69
+ is_another_app: bool = False,
70
+ preload: typing.Optional[
71
+ typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
72
+ ] = None,
73
+ hydrate_lazily: bool = False,
74
+ deps: typing.Optional[typing.Callable[..., collections.abc.Sequence[_Object]]] = None,
75
+ deduplication_key: typing.Optional[
76
+ typing.Callable[[], collections.abc.Awaitable[collections.abc.Hashable]]
77
+ ] = None,
78
+ ): ...
67
79
  @classmethod
68
- def _new_hydrated(cls: typing.Type[O], object_id: str, client: modal.client._Client, handle_metadata: typing.Union[google.protobuf.message.Message, None], is_another_app: bool = False) -> O:
69
- ...
70
-
71
- def _hydrate_from_other(self, other: O):
72
- ...
73
-
74
- def __repr__(self):
75
- ...
76
-
80
+ def _get_type_from_id(cls: type[O], object_id: str) -> type[O]: ...
81
+ @classmethod
82
+ def _is_id_type(cls: type[O], object_id) -> bool: ...
83
+ @classmethod
84
+ def _new_hydrated(
85
+ cls: type[O],
86
+ object_id: str,
87
+ client: modal.client._Client,
88
+ handle_metadata: typing.Optional[google.protobuf.message.Message],
89
+ is_another_app: bool = False,
90
+ ) -> O: ...
91
+ def _hydrate_from_other(self, other: O): ...
92
+ def __repr__(self): ...
77
93
  @property
78
- def local_uuid(self):
79
- ...
80
-
94
+ def local_uuid(self): ...
81
95
  @property
82
- def object_id(self):
83
- ...
84
-
96
+ def object_id(self) -> str: ...
85
97
  @property
86
- def is_hydrated(self) -> bool:
87
- ...
88
-
98
+ def is_hydrated(self) -> bool: ...
89
99
  @property
90
- def deps(self) -> typing.Callable[..., typing.List[_Object]]:
91
- ...
92
-
93
- async def resolve(self):
94
- ...
95
-
100
+ def deps(self) -> typing.Callable[..., list[_Object]]: ...
101
+ async def resolve(self, client: typing.Optional[modal.client._Client] = None): ...
96
102
 
97
103
  class Object:
98
- _type_prefix: typing.ClassVar[typing.Union[str, None]]
99
- _prefix_to_type: typing.ClassVar[typing.Dict[str, type]]
100
- _load: typing.Union[typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Union[str, None]], None], None]
101
- _preload: typing.Union[typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Union[str, None]], None], None]
104
+ _type_prefix: typing.ClassVar[typing.Optional[str]]
105
+ _prefix_to_type: typing.ClassVar[dict[str, type]]
106
+ _load: typing.Optional[
107
+ typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
108
+ ]
109
+ _preload: typing.Optional[
110
+ typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
111
+ ]
102
112
  _rep: str
103
113
  _is_another_app: bool
104
114
  _hydrate_lazily: bool
105
- _deps: typing.Union[typing.Callable[..., typing.List[Object]], None]
106
- _deduplication_key: typing.Union[typing.Callable[[], typing.Hashable], None]
115
+ _deps: typing.Optional[typing.Callable[..., list[Object]]]
116
+ _deduplication_key: typing.Optional[typing.Callable[[], collections.abc.Awaitable[collections.abc.Hashable]]]
107
117
  _object_id: str
108
118
  _client: modal.client.Client
109
119
  _is_hydrated: bool
120
+ _is_rehydrated: bool
110
121
 
111
- def __init__(self, *args, **kwargs):
112
- ...
113
-
122
+ def __init__(self, *args, **kwargs): ...
114
123
  @classmethod
115
- def __init_subclass__(cls, type_prefix: typing.Union[str, None] = None):
116
- ...
124
+ def __init_subclass__(cls, type_prefix: typing.Optional[str] = None): ...
117
125
 
118
126
  class ___init_spec(typing_extensions.Protocol):
119
- def __call__(self, rep: str, load: typing.Union[typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Union[str, None]], None], None] = None, is_another_app: bool = False, preload: typing.Union[typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Union[str, None]], None], None] = None, hydrate_lazily: bool = False, deps: typing.Union[typing.Callable[..., typing.List[Object]], None] = None, deduplication_key: typing.Union[typing.Callable[[], typing.Hashable], None] = None):
120
- ...
121
-
122
- def aio(self, rep: str, load: typing.Union[typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Union[str, None]], typing.Awaitable[None]], None] = None, is_another_app: bool = False, preload: typing.Union[typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Union[str, None]], typing.Awaitable[None]], None] = None, hydrate_lazily: bool = False, deps: typing.Union[typing.Callable[..., typing.List[Object]], None] = None, deduplication_key: typing.Union[typing.Callable[[], typing.Awaitable[typing.Hashable]], None] = None):
123
- ...
127
+ def __call__(
128
+ self,
129
+ rep: str,
130
+ load: typing.Optional[
131
+ typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], None]
132
+ ] = None,
133
+ is_another_app: bool = False,
134
+ preload: typing.Optional[
135
+ typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], None]
136
+ ] = None,
137
+ hydrate_lazily: bool = False,
138
+ deps: typing.Optional[typing.Callable[..., list[Object]]] = None,
139
+ deduplication_key: typing.Optional[typing.Callable[[], collections.abc.Hashable]] = None,
140
+ ): ...
141
+ def aio(
142
+ self,
143
+ rep: str,
144
+ load: typing.Optional[
145
+ typing.Callable[
146
+ [_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]
147
+ ]
148
+ ] = None,
149
+ is_another_app: bool = False,
150
+ preload: typing.Optional[
151
+ typing.Callable[
152
+ [_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]
153
+ ]
154
+ ] = None,
155
+ hydrate_lazily: bool = False,
156
+ deps: typing.Optional[typing.Callable[..., list[Object]]] = None,
157
+ deduplication_key: typing.Optional[
158
+ typing.Callable[[], collections.abc.Awaitable[collections.abc.Hashable]]
159
+ ] = None,
160
+ ): ...
124
161
 
125
162
  _init: ___init_spec
126
163
 
127
- def _unhydrate(self):
128
- ...
129
-
130
- def _initialize_from_empty(self):
131
- ...
132
-
133
- def _initialize_from_other(self, other):
134
- ...
135
-
136
- def _hydrate(self, object_id: str, client: modal.client.Client, metadata: typing.Union[google.protobuf.message.Message, None]):
137
- ...
138
-
139
- def _hydrate_metadata(self, metadata: typing.Union[google.protobuf.message.Message, None]):
140
- ...
141
-
142
- def _get_metadata(self) -> typing.Union[google.protobuf.message.Message, None]:
143
- ...
144
-
145
- def _init_from_other(self, other: _BLOCKING_O):
146
- ...
147
-
148
- def clone(self: _BLOCKING_O) -> _BLOCKING_O:
149
- ...
150
-
164
+ def _unhydrate(self): ...
165
+ def _initialize_from_empty(self): ...
166
+ def _initialize_from_other(self, other): ...
167
+ def _hydrate(
168
+ self, object_id: str, client: modal.client.Client, metadata: typing.Optional[google.protobuf.message.Message]
169
+ ): ...
170
+ def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
171
+ def _get_metadata(self) -> typing.Optional[google.protobuf.message.Message]: ...
172
+ def _validate_is_hydrated(self: _BLOCKING_O): ...
173
+ def clone(self: _BLOCKING_O) -> _BLOCKING_O: ...
151
174
  @classmethod
152
- def _from_loader(cls, load: typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Union[str, None]], None], rep: str, is_another_app: bool = False, preload: typing.Union[typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Union[str, None]], None], None] = None, hydrate_lazily: bool = False, deps: typing.Union[typing.Callable[..., typing.List[Object]], None] = None, deduplication_key: typing.Union[typing.Callable[[], typing.Hashable], None] = None):
153
- ...
154
-
175
+ def _from_loader(
176
+ cls,
177
+ load: typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], None],
178
+ rep: str,
179
+ is_another_app: bool = False,
180
+ preload: typing.Optional[
181
+ typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], None]
182
+ ] = None,
183
+ hydrate_lazily: bool = False,
184
+ deps: typing.Optional[typing.Callable[..., collections.abc.Sequence[Object]]] = None,
185
+ deduplication_key: typing.Optional[typing.Callable[[], collections.abc.Hashable]] = None,
186
+ ): ...
155
187
  @classmethod
156
- def _new_hydrated(cls: typing.Type[_BLOCKING_O], object_id: str, client: modal.client.Client, handle_metadata: typing.Union[google.protobuf.message.Message, None], is_another_app: bool = False) -> _BLOCKING_O:
157
- ...
158
-
159
- def _hydrate_from_other(self, other: _BLOCKING_O):
160
- ...
161
-
162
- def __repr__(self):
163
- ...
164
-
188
+ def _get_type_from_id(cls: type[_BLOCKING_O], object_id: str) -> type[_BLOCKING_O]: ...
189
+ @classmethod
190
+ def _is_id_type(cls: type[_BLOCKING_O], object_id) -> bool: ...
191
+ @classmethod
192
+ def _new_hydrated(
193
+ cls: type[_BLOCKING_O],
194
+ object_id: str,
195
+ client: modal.client.Client,
196
+ handle_metadata: typing.Optional[google.protobuf.message.Message],
197
+ is_another_app: bool = False,
198
+ ) -> _BLOCKING_O: ...
199
+ def _hydrate_from_other(self, other: _BLOCKING_O): ...
200
+ def __repr__(self): ...
165
201
  @property
166
- def local_uuid(self):
167
- ...
168
-
202
+ def local_uuid(self): ...
169
203
  @property
170
- def object_id(self):
171
- ...
172
-
204
+ def object_id(self) -> str: ...
173
205
  @property
174
- def is_hydrated(self) -> bool:
175
- ...
176
-
206
+ def is_hydrated(self) -> bool: ...
177
207
  @property
178
- def deps(self) -> typing.Callable[..., typing.List[Object]]:
179
- ...
208
+ def deps(self) -> typing.Callable[..., list[Object]]: ...
180
209
 
181
210
  class __resolve_spec(typing_extensions.Protocol):
182
- def __call__(self):
183
- ...
184
-
185
- async def aio(self, *args, **kwargs):
186
- ...
211
+ def __call__(self, client: typing.Optional[modal.client.Client] = None): ...
212
+ async def aio(self, client: typing.Optional[modal.client.Client] = None): ...
187
213
 
188
214
  resolve: __resolve_spec
189
215
 
216
+ def live_method(method): ...
217
+ def live_method_gen(method): ...
190
218
 
191
- def live_method(method):
192
- ...
193
-
194
-
195
- def live_method_gen(method):
196
- ...
219
+ EPHEMERAL_OBJECT_HEARTBEAT_SLEEP: int
modal/output.py ADDED
@@ -0,0 +1,63 @@
1
+ # Copyright Modal Labs 2024
2
+ """Interface to Modal's OutputManager functionality.
3
+
4
+ These functions live here so that Modal library code can import them without
5
+ transitively importing Rich, as we do in global scope in _output.py. This allows
6
+ us to avoid importing Rich for client code that runs in the container environment.
7
+
8
+ """
9
+ import contextlib
10
+ from collections.abc import Generator
11
+ from typing import TYPE_CHECKING, Optional
12
+
13
+ if TYPE_CHECKING:
14
+ from ._output import OutputManager
15
+
16
+
17
+ OUTPUT_ENABLED = False
18
+
19
+
20
+ @contextlib.contextmanager
21
+ def enable_output(show_progress: bool = True) -> Generator[None, None, None]:
22
+ """Context manager that enable output when using the Python SDK.
23
+
24
+ This will print to stdout and stderr things such as
25
+ 1. Logs from running functions
26
+ 2. Status of creating objects
27
+ 3. Map progress
28
+
29
+ Example:
30
+ ```python
31
+ app = modal.App()
32
+ with modal.enable_output():
33
+ with app.run():
34
+ ...
35
+ ```
36
+ """
37
+ from ._output import OutputManager
38
+
39
+ # Toggle the output flag from within this function so that we can
40
+ # call _get_output_manager from within the library and only import
41
+ # the _output module if output is explicitly enabled. That prevents
42
+ # us from trying to import rich inside a container environment where
43
+ # it might not be installed. This is sort of hacky and I would prefer
44
+ # a more thorough refactor where the OutputManager is fully useable
45
+ # without rich installed, but that's a larger project.
46
+ global OUTPUT_ENABLED
47
+
48
+ try:
49
+ with OutputManager.enable_output(show_progress):
50
+ OUTPUT_ENABLED = True
51
+ yield
52
+ finally:
53
+ OUTPUT_ENABLED = False
54
+
55
+
56
+ def _get_output_manager() -> Optional["OutputManager"]:
57
+ """Interface to the OutputManager that returns None when output is not enabled."""
58
+ if OUTPUT_ENABLED:
59
+ from ._output import OutputManager
60
+
61
+ return OutputManager.get()
62
+ else:
63
+ return None