modal 1.0.4.dev10__py3-none-any.whl → 1.0.5__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 (67) hide show
  1. modal/_clustered_functions.pyi +13 -3
  2. modal/_functions.py +84 -46
  3. modal/_partial_function.py +1 -1
  4. modal/_runtime/container_io_manager.pyi +222 -40
  5. modal/_runtime/execution_context.pyi +60 -6
  6. modal/_serialization.py +25 -2
  7. modal/_tunnel.pyi +380 -12
  8. modal/_utils/async_utils.py +1 -1
  9. modal/_utils/blob_utils.py +56 -19
  10. modal/_utils/function_utils.py +33 -7
  11. modal/_utils/grpc_utils.py +11 -4
  12. modal/app.py +5 -5
  13. modal/app.pyi +658 -48
  14. modal/cli/run.py +2 -1
  15. modal/client.pyi +224 -36
  16. modal/cloud_bucket_mount.pyi +192 -4
  17. modal/cls.py +57 -16
  18. modal/cls.pyi +442 -34
  19. modal/container_process.pyi +103 -14
  20. modal/dict.py +4 -4
  21. modal/dict.pyi +453 -51
  22. modal/environments.pyi +41 -9
  23. modal/exception.py +6 -2
  24. modal/experimental/__init__.py +90 -0
  25. modal/experimental/ipython.py +11 -7
  26. modal/file_io.pyi +236 -45
  27. modal/functions.pyi +573 -65
  28. modal/gpu.py +1 -1
  29. modal/image.py +1 -1
  30. modal/image.pyi +1256 -74
  31. modal/io_streams.py +8 -4
  32. modal/io_streams.pyi +348 -38
  33. modal/mount.pyi +261 -31
  34. modal/network_file_system.py +3 -3
  35. modal/network_file_system.pyi +307 -26
  36. modal/object.pyi +48 -9
  37. modal/parallel_map.py +93 -19
  38. modal/parallel_map.pyi +160 -15
  39. modal/partial_function.pyi +255 -14
  40. modal/proxy.py +1 -1
  41. modal/proxy.pyi +28 -3
  42. modal/queue.py +4 -4
  43. modal/queue.pyi +447 -30
  44. modal/runner.pyi +160 -22
  45. modal/sandbox.py +8 -7
  46. modal/sandbox.pyi +310 -50
  47. modal/schedule.py +1 -1
  48. modal/secret.py +2 -2
  49. modal/secret.pyi +164 -15
  50. modal/snapshot.pyi +25 -4
  51. modal/token_flow.pyi +28 -8
  52. modal/volume.py +41 -4
  53. modal/volume.pyi +693 -59
  54. {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/METADATA +3 -3
  55. {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/RECORD +67 -67
  56. modal_proto/api.proto +57 -0
  57. modal_proto/api_grpc.py +48 -0
  58. modal_proto/api_pb2.py +874 -780
  59. modal_proto/api_pb2.pyi +198 -9
  60. modal_proto/api_pb2_grpc.py +100 -0
  61. modal_proto/api_pb2_grpc.pyi +32 -0
  62. modal_proto/modal_api_grpc.py +3 -0
  63. modal_version/__init__.py +1 -1
  64. {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/WHEEL +0 -0
  65. {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/entry_points.txt +0 -0
  66. {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/licenses/LICENSE +0 -0
  67. {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/top_level.txt +0 -0
modal/functions.pyi CHANGED
@@ -35,6 +35,12 @@ class Function(
35
35
  typing.Generic[modal._functions.P, modal._functions.ReturnType, modal._functions.OriginalReturnType],
36
36
  modal.object.Object,
37
37
  ):
38
+ """Functions are the basic units of serverless execution on Modal.
39
+
40
+ Generally, you will not construct a `Function` directly. Instead, use the
41
+ `App.function()` decorator to register your Python functions with your App.
42
+ """
43
+
38
44
  _info: typing.Optional[modal._utils.function_utils.FunctionInfo]
39
45
  _serve_mounts: frozenset[modal.mount.Mount]
40
46
  _app: typing.Optional[modal.app.App]
@@ -53,7 +59,10 @@ class Function(
53
59
  _method_handle_metadata: typing.Optional[dict[str, modal_proto.api_pb2.FunctionHandleMetadata]]
54
60
  _metadata: typing.Optional[modal_proto.api_pb2.FunctionHandleMetadata]
55
61
 
56
- def __init__(self, *args, **kwargs): ...
62
+ def __init__(self, *args, **kwargs):
63
+ """mdmd:hidden"""
64
+ ...
65
+
57
66
  @staticmethod
58
67
  def from_local(
59
68
  info: modal._utils.function_utils.FunctionInfo,
@@ -101,14 +110,22 @@ class Function(
101
110
  _experimental_proxy_ip: typing.Optional[str] = None,
102
111
  _experimental_custom_scaling_factor: typing.Optional[float] = None,
103
112
  _experimental_enable_gpu_snapshot: bool = False,
104
- ) -> Function: ...
113
+ ) -> Function:
114
+ """mdmd:hidden"""
115
+ ...
116
+
105
117
  def _bind_parameters(
106
118
  self,
107
119
  obj: modal.cls.Obj,
108
120
  options: typing.Optional[modal.cls._ServiceOptions],
109
121
  args: collections.abc.Sized,
110
122
  kwargs: dict[str, typing.Any],
111
- ) -> Function: ...
123
+ ) -> Function:
124
+ """mdmd:hidden
125
+
126
+ Binds a class-function to a specific instance of (init params, options) or a new workspace
127
+ """
128
+ ...
112
129
 
113
130
  class __update_autoscaler_spec(typing_extensions.Protocol[SUPERSELF]):
114
131
  def __call__(
@@ -119,7 +136,33 @@ class Function(
119
136
  max_containers: typing.Optional[int] = None,
120
137
  buffer_containers: typing.Optional[int] = None,
121
138
  scaledown_window: typing.Optional[int] = None,
122
- ) -> None: ...
139
+ ) -> None:
140
+ """Override the current autoscaler behavior for this Function.
141
+
142
+ Unspecified parameters will retain their current value, i.e. either the static value
143
+ from the function decorator, or an override value from a previous call to this method.
144
+
145
+ Subsequent deployments of the App containing this Function will reset the autoscaler back to
146
+ its static configuration.
147
+
148
+ Examples:
149
+
150
+ ```python notest
151
+ f = modal.Function.from_name("my-app", "function")
152
+
153
+ # Always have at least 2 containers running, with an extra buffer when the Function is active
154
+ f.update_autoscaler(min_containers=2, buffer_containers=1)
155
+
156
+ # Limit this Function to avoid spinning up more than 5 containers
157
+ f.update_autoscaler(max_containers=5)
158
+
159
+ # Extend the scaledown window to increase the amount of time that idle containers stay alive
160
+ f.update_autoscaler(scaledown_window=300)
161
+
162
+ ```
163
+ """
164
+ ...
165
+
123
166
  async def aio(
124
167
  self,
125
168
  /,
@@ -128,13 +171,71 @@ class Function(
128
171
  max_containers: typing.Optional[int] = None,
129
172
  buffer_containers: typing.Optional[int] = None,
130
173
  scaledown_window: typing.Optional[int] = None,
131
- ) -> None: ...
174
+ ) -> None:
175
+ """Override the current autoscaler behavior for this Function.
176
+
177
+ Unspecified parameters will retain their current value, i.e. either the static value
178
+ from the function decorator, or an override value from a previous call to this method.
179
+
180
+ Subsequent deployments of the App containing this Function will reset the autoscaler back to
181
+ its static configuration.
182
+
183
+ Examples:
184
+
185
+ ```python notest
186
+ f = modal.Function.from_name("my-app", "function")
187
+
188
+ # Always have at least 2 containers running, with an extra buffer when the Function is active
189
+ f.update_autoscaler(min_containers=2, buffer_containers=1)
190
+
191
+ # Limit this Function to avoid spinning up more than 5 containers
192
+ f.update_autoscaler(max_containers=5)
193
+
194
+ # Extend the scaledown window to increase the amount of time that idle containers stay alive
195
+ f.update_autoscaler(scaledown_window=300)
196
+
197
+ ```
198
+ """
199
+ ...
132
200
 
133
201
  update_autoscaler: __update_autoscaler_spec[typing_extensions.Self]
134
202
 
135
203
  class __keep_warm_spec(typing_extensions.Protocol[SUPERSELF]):
136
- def __call__(self, /, warm_pool_size: int) -> None: ...
137
- async def aio(self, /, warm_pool_size: int) -> None: ...
204
+ def __call__(self, /, warm_pool_size: int) -> None:
205
+ """mdmd:hidden
206
+ Set the warm pool size for the Function.
207
+
208
+ DEPRECATED: Please adapt your code to use the more general `update_autoscaler` method instead:
209
+
210
+ ```python notest
211
+ f = modal.Function.from_name("my-app", "function")
212
+
213
+ # Old pattern (deprecated)
214
+ f.keep_warm(2)
215
+
216
+ # New pattern
217
+ f.update_autoscaler(min_containers=2)
218
+ ```
219
+ """
220
+ ...
221
+
222
+ async def aio(self, /, warm_pool_size: int) -> None:
223
+ """mdmd:hidden
224
+ Set the warm pool size for the Function.
225
+
226
+ DEPRECATED: Please adapt your code to use the more general `update_autoscaler` method instead:
227
+
228
+ ```python notest
229
+ f = modal.Function.from_name("my-app", "function")
230
+
231
+ # Old pattern (deprecated)
232
+ f.keep_warm(2)
233
+
234
+ # New pattern
235
+ f.update_autoscaler(min_containers=2)
236
+ ```
237
+ """
238
+ ...
138
239
 
139
240
  keep_warm: __keep_warm_spec[typing_extensions.Self]
140
241
 
@@ -143,7 +244,18 @@ class Function(
143
244
  @classmethod
144
245
  def from_name(
145
246
  cls: type[Function], app_name: str, name: str, *, namespace=1, environment_name: typing.Optional[str] = None
146
- ) -> Function: ...
247
+ ) -> Function:
248
+ """Reference a Function from a deployed App by its name.
249
+
250
+ This is a lazy method that defers hydrating the local
251
+ object with metadata from Modal servers until the first
252
+ time it is actually used.
253
+
254
+ ```python
255
+ f = modal.Function.from_name("other-app", "function")
256
+ ```
257
+ """
258
+ ...
147
259
 
148
260
  class __lookup_spec(typing_extensions.Protocol):
149
261
  def __call__(
@@ -154,7 +266,21 @@ class Function(
154
266
  namespace=1,
155
267
  client: typing.Optional[modal.client.Client] = None,
156
268
  environment_name: typing.Optional[str] = None,
157
- ) -> Function: ...
269
+ ) -> Function:
270
+ """mdmd:hidden
271
+ Lookup a Function from a deployed App by its name.
272
+
273
+ DEPRECATED: This method is deprecated in favor of `modal.Function.from_name`.
274
+
275
+ In contrast to `modal.Function.from_name`, this is an eager method
276
+ that will hydrate the local object with metadata from Modal servers.
277
+
278
+ ```python notest
279
+ f = modal.Function.lookup("other-app", "function")
280
+ ```
281
+ """
282
+ ...
283
+
158
284
  async def aio(
159
285
  self,
160
286
  /,
@@ -163,45 +289,120 @@ class Function(
163
289
  namespace=1,
164
290
  client: typing.Optional[modal.client.Client] = None,
165
291
  environment_name: typing.Optional[str] = None,
166
- ) -> Function: ...
292
+ ) -> Function:
293
+ """mdmd:hidden
294
+ Lookup a Function from a deployed App by its name.
295
+
296
+ DEPRECATED: This method is deprecated in favor of `modal.Function.from_name`.
297
+
298
+ In contrast to `modal.Function.from_name`, this is an eager method
299
+ that will hydrate the local object with metadata from Modal servers.
300
+
301
+ ```python notest
302
+ f = modal.Function.lookup("other-app", "function")
303
+ ```
304
+ """
305
+ ...
167
306
 
168
307
  lookup: __lookup_spec
169
308
 
170
309
  @property
171
- def tag(self) -> str: ...
310
+ def tag(self) -> str:
311
+ """mdmd:hidden"""
312
+ ...
313
+
172
314
  @property
173
- def app(self) -> modal.app.App: ...
315
+ def app(self) -> modal.app.App:
316
+ """mdmd:hidden"""
317
+ ...
318
+
174
319
  @property
175
- def stub(self) -> modal.app.App: ...
320
+ def stub(self) -> modal.app.App:
321
+ """mdmd:hidden"""
322
+ ...
323
+
176
324
  @property
177
- def info(self) -> modal._utils.function_utils.FunctionInfo: ...
325
+ def info(self) -> modal._utils.function_utils.FunctionInfo:
326
+ """mdmd:hidden"""
327
+ ...
328
+
178
329
  @property
179
- def spec(self) -> modal._functions._FunctionSpec: ...
330
+ def spec(self) -> modal._functions._FunctionSpec:
331
+ """mdmd:hidden"""
332
+ ...
333
+
180
334
  def _is_web_endpoint(self) -> bool: ...
181
- def get_build_def(self) -> str: ...
335
+ def get_build_def(self) -> str:
336
+ """mdmd:hidden"""
337
+ ...
338
+
182
339
  def _initialize_from_empty(self): ...
183
340
  def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
184
341
  def _get_metadata(self): ...
185
342
  def _check_no_web_url(self, fn_name: str): ...
186
343
  @property
187
- def web_url(self) -> typing.Optional[str]: ...
344
+ def web_url(self) -> typing.Optional[str]:
345
+ """mdmd:hidden
346
+ Deprecated. Use the `Function.get_web_url()` method instead.
347
+
348
+ URL of a Function running as a web endpoint.
349
+ """
350
+ ...
188
351
 
189
352
  class __get_web_url_spec(typing_extensions.Protocol[SUPERSELF]):
190
- def __call__(self, /) -> typing.Optional[str]: ...
191
- async def aio(self, /) -> typing.Optional[str]: ...
353
+ def __call__(self, /) -> typing.Optional[str]:
354
+ """URL of a Function running as a web endpoint."""
355
+ ...
356
+
357
+ async def aio(self, /) -> typing.Optional[str]:
358
+ """URL of a Function running as a web endpoint."""
359
+ ...
192
360
 
193
361
  get_web_url: __get_web_url_spec[typing_extensions.Self]
194
362
 
195
363
  @property
196
- def is_generator(self) -> bool: ...
364
+ def is_generator(self) -> bool:
365
+ """mdmd:hidden"""
366
+ ...
197
367
 
198
368
  class ___map_spec(typing_extensions.Protocol[SUPERSELF]):
199
369
  def __call__(
200
- self, /, input_queue: modal.parallel_map.SynchronizedQueue, order_outputs: bool, return_exceptions: bool
201
- ) -> typing.Generator[typing.Any, None, None]: ...
370
+ self,
371
+ /,
372
+ input_queue: modal.parallel_map.SynchronizedQueue,
373
+ order_outputs: bool,
374
+ return_exceptions: bool,
375
+ wrap_returned_exceptions: bool,
376
+ ) -> typing.Generator[typing.Any, None, None]:
377
+ """mdmd:hidden
378
+
379
+ Synchronicity-wrapped map implementation. To be safe against invocations of user code in
380
+ the synchronicity thread it doesn't accept an [async]iterator, and instead takes a
381
+ _SynchronizedQueue instance that is fed by higher level functions like .map()
382
+
383
+ _SynchronizedQueue is used instead of asyncio.Queue so that the main thread can put
384
+ items in the queue safely.
385
+ """
386
+ ...
387
+
202
388
  def aio(
203
- self, /, input_queue: modal.parallel_map.SynchronizedQueue, order_outputs: bool, return_exceptions: bool
204
- ) -> collections.abc.AsyncGenerator[typing.Any, None]: ...
389
+ self,
390
+ /,
391
+ input_queue: modal.parallel_map.SynchronizedQueue,
392
+ order_outputs: bool,
393
+ return_exceptions: bool,
394
+ wrap_returned_exceptions: bool,
395
+ ) -> collections.abc.AsyncGenerator[typing.Any, None]:
396
+ """mdmd:hidden
397
+
398
+ Synchronicity-wrapped map implementation. To be safe against invocations of user code in
399
+ the synchronicity thread it doesn't accept an [async]iterator, and instead takes a
400
+ _SynchronizedQueue instance that is fed by higher level functions like .map()
401
+
402
+ _SynchronizedQueue is used instead of asyncio.Queue so that the main thread can put
403
+ items in the queue safely.
404
+ """
405
+ ...
205
406
 
206
407
  _map: ___map_spec[typing_extensions.Self]
207
408
 
@@ -227,15 +428,25 @@ class Function(
227
428
 
228
429
  _call_generator: ___call_generator_spec[typing_extensions.Self]
229
430
 
230
- class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
231
- def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
232
- async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
431
+ class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
432
+ def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
433
+ """Calls the function remotely, executing it with the given arguments and returning the execution's result."""
434
+ ...
233
435
 
234
- remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
436
+ async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
437
+ """Calls the function remotely, executing it with the given arguments and returning the execution's result."""
438
+ ...
439
+
440
+ remote: __remote_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
235
441
 
236
442
  class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
237
- def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
238
- def aio(self, /, *args, **kwargs) -> collections.abc.AsyncGenerator[typing.Any, None]: ...
443
+ def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
444
+ """Calls the generator remotely, executing it with the given arguments and returning the execution's result."""
445
+ ...
446
+
447
+ def aio(self, /, *args, **kwargs) -> collections.abc.AsyncGenerator[typing.Any, None]:
448
+ """Calls the generator remotely, executing it with the given arguments and returning the execution's result."""
449
+ ...
239
450
 
240
451
  remote_gen: __remote_gen_spec[typing_extensions.Self]
241
452
 
@@ -244,14 +455,40 @@ class Function(
244
455
  def _get_obj(self) -> typing.Optional[modal.cls.Obj]: ...
245
456
  def local(
246
457
  self, *args: modal._functions.P.args, **kwargs: modal._functions.P.kwargs
247
- ) -> modal._functions.OriginalReturnType: ...
458
+ ) -> modal._functions.OriginalReturnType:
459
+ """Calls the function locally, executing it with the given arguments and returning the execution's result.
460
+
461
+ The function will execute in the same environment as the caller, just like calling the underlying function
462
+ directly in Python. In particular, only secrets available in the caller environment will be available
463
+ through environment variables.
464
+ """
465
+ ...
466
+
467
+ class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
468
+ def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
469
+ """[Experimental] Calls the function with the given arguments, without waiting for the results.
470
+
471
+ This experimental version of the spawn method allows up to 1 million inputs to be spawned.
472
+
473
+ Returns a `modal.FunctionCall` object, that can later be polled or
474
+ waited for using `.get(timeout=...)`.
475
+ Conceptually similar to `multiprocessing.pool.apply_async`, or a Future/Promise in other contexts.
476
+ """
477
+ ...
248
478
 
249
- class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
250
- def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
251
- async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
479
+ async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
480
+ """[Experimental] Calls the function with the given arguments, without waiting for the results.
481
+
482
+ This experimental version of the spawn method allows up to 1 million inputs to be spawned.
483
+
484
+ Returns a `modal.FunctionCall` object, that can later be polled or
485
+ waited for using `.get(timeout=...)`.
486
+ Conceptually similar to `multiprocessing.pool.apply_async`, or a Future/Promise in other contexts.
487
+ """
488
+ ...
252
489
 
253
490
  _experimental_spawn: ___experimental_spawn_spec[
254
- modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
491
+ modal._functions.ReturnType, modal._functions.P, typing_extensions.Self
255
492
  ]
256
493
 
257
494
  class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER, SUPERSELF]):
@@ -260,30 +497,103 @@ class Function(
260
497
 
261
498
  _spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P, typing_extensions.Self]
262
499
 
263
- class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
264
- def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
265
- async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
500
+ class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
501
+ def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
502
+ """Calls the function with the given arguments, without waiting for the results.
503
+
504
+ Returns a [`modal.FunctionCall`](https://modal.com/docs/reference/modal.FunctionCall) object
505
+ that can later be polled or waited for using
506
+ [`.get(timeout=...)`](https://modal.com/docs/reference/modal.FunctionCall#get).
507
+ Conceptually similar to `multiprocessing.pool.apply_async`, or a Future/Promise in other contexts.
508
+ """
509
+ ...
510
+
511
+ async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
512
+ """Calls the function with the given arguments, without waiting for the results.
266
513
 
267
- spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
514
+ Returns a [`modal.FunctionCall`](https://modal.com/docs/reference/modal.FunctionCall) object
515
+ that can later be polled or waited for using
516
+ [`.get(timeout=...)`](https://modal.com/docs/reference/modal.FunctionCall#get).
517
+ Conceptually similar to `multiprocessing.pool.apply_async`, or a Future/Promise in other contexts.
518
+ """
519
+ ...
268
520
 
269
- def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]: ...
521
+ spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
522
+
523
+ def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
524
+ """Return the inner Python object wrapped by this Modal Function."""
525
+ ...
270
526
 
271
527
  class __get_current_stats_spec(typing_extensions.Protocol[SUPERSELF]):
272
- def __call__(self, /) -> modal._functions.FunctionStats: ...
273
- async def aio(self, /) -> modal._functions.FunctionStats: ...
528
+ def __call__(self, /) -> modal._functions.FunctionStats:
529
+ """Return a `FunctionStats` object describing the current function's queue and runner counts."""
530
+ ...
531
+
532
+ async def aio(self, /) -> modal._functions.FunctionStats:
533
+ """Return a `FunctionStats` object describing the current function's queue and runner counts."""
534
+ ...
274
535
 
275
536
  get_current_stats: __get_current_stats_spec[typing_extensions.Self]
276
537
 
277
538
  class ___get_schema_spec(typing_extensions.Protocol[SUPERSELF]):
278
- def __call__(self, /) -> modal_proto.api_pb2.FunctionSchema: ...
279
- async def aio(self, /) -> modal_proto.api_pb2.FunctionSchema: ...
539
+ def __call__(self, /) -> modal_proto.api_pb2.FunctionSchema:
540
+ """Returns recorded schema for function, internal use only for now"""
541
+ ...
542
+
543
+ async def aio(self, /) -> modal_proto.api_pb2.FunctionSchema:
544
+ """Returns recorded schema for function, internal use only for now"""
545
+ ...
280
546
 
281
547
  _get_schema: ___get_schema_spec[typing_extensions.Self]
282
548
 
283
549
  class __map_spec(typing_extensions.Protocol[SUPERSELF]):
284
550
  def __call__(
285
- self, /, *input_iterators, kwargs={}, order_outputs: bool = True, return_exceptions: bool = False
286
- ) -> modal._utils.async_utils.AsyncOrSyncIterable: ...
551
+ self,
552
+ /,
553
+ *input_iterators,
554
+ kwargs={},
555
+ order_outputs: bool = True,
556
+ return_exceptions: bool = False,
557
+ wrap_returned_exceptions: bool = True,
558
+ ) -> modal._utils.async_utils.AsyncOrSyncIterable:
559
+ """Parallel map over a set of inputs.
560
+
561
+ Takes one iterator argument per argument in the function being mapped over.
562
+
563
+ Example:
564
+ ```python
565
+ @app.function()
566
+ def my_func(a):
567
+ return a ** 2
568
+
569
+
570
+ @app.local_entrypoint()
571
+ def main():
572
+ assert list(my_func.map([1, 2, 3, 4])) == [1, 4, 9, 16]
573
+ ```
574
+
575
+ If applied to a `app.function`, `map()` returns one result per input and the output order
576
+ is guaranteed to be the same as the input order. Set `order_outputs=False` to return results
577
+ in the order that they are completed instead.
578
+
579
+ `return_exceptions` can be used to treat exceptions as successful results:
580
+
581
+ ```python
582
+ @app.function()
583
+ def my_func(a):
584
+ if a == 2:
585
+ raise Exception("ohno")
586
+ return a ** 2
587
+
588
+
589
+ @app.local_entrypoint()
590
+ def main():
591
+ # [0, 1, UserCodeException(Exception('ohno'))]
592
+ print(list(my_func.map(range(3), return_exceptions=True)))
593
+ ```
594
+ """
595
+ ...
596
+
287
597
  def aio(
288
598
  self,
289
599
  /,
@@ -291,6 +601,7 @@ class Function(
291
601
  kwargs={},
292
602
  order_outputs: bool = True,
293
603
  return_exceptions: bool = False,
604
+ wrap_returned_exceptions: bool = True,
294
605
  ) -> typing.AsyncGenerator[typing.Any, None]: ...
295
606
 
296
607
  map: __map_spec[typing_extensions.Self]
@@ -304,7 +615,26 @@ class Function(
304
615
  kwargs={},
305
616
  order_outputs: bool = True,
306
617
  return_exceptions: bool = False,
307
- ) -> modal._utils.async_utils.AsyncOrSyncIterable: ...
618
+ wrap_returned_exceptions: bool = True,
619
+ ) -> modal._utils.async_utils.AsyncOrSyncIterable:
620
+ """Like `map`, but spreads arguments over multiple function arguments.
621
+
622
+ Assumes every input is a sequence (e.g. a tuple).
623
+
624
+ Example:
625
+ ```python
626
+ @app.function()
627
+ def my_func(a, b):
628
+ return a + b
629
+
630
+
631
+ @app.local_entrypoint()
632
+ def main():
633
+ assert list(my_func.starmap([(1, 2), (3, 4)])) == [3, 7]
634
+ ```
635
+ """
636
+ ...
637
+
308
638
  def aio(
309
639
  self,
310
640
  /,
@@ -315,68 +645,246 @@ class Function(
315
645
  kwargs={},
316
646
  order_outputs: bool = True,
317
647
  return_exceptions: bool = False,
648
+ wrap_returned_exceptions: bool = True,
318
649
  ) -> typing.AsyncIterable[typing.Any]: ...
319
650
 
320
651
  starmap: __starmap_spec[typing_extensions.Self]
321
652
 
322
653
  class __for_each_spec(typing_extensions.Protocol[SUPERSELF]):
323
- def __call__(self, /, *input_iterators, kwargs={}, ignore_exceptions: bool = False): ...
654
+ def __call__(self, /, *input_iterators, kwargs={}, ignore_exceptions: bool = False):
655
+ """Execute function for all inputs, ignoring outputs. Waits for completion of the inputs.
656
+
657
+ Convenient alias for `.map()` in cases where the function just needs to be called.
658
+ as the caller doesn't have to consume the generator to process the inputs.
659
+ """
660
+ ...
661
+
324
662
  async def aio(self, /, *input_iterators, kwargs={}, ignore_exceptions: bool = False) -> None: ...
325
663
 
326
664
  for_each: __for_each_spec[typing_extensions.Self]
327
665
 
328
666
  class __spawn_map_spec(typing_extensions.Protocol[SUPERSELF]):
329
- def __call__(self, /, *input_iterators, kwargs={}) -> None: ...
330
- async def aio(self, /, *input_iterators, kwargs={}) -> None: ...
667
+ def __call__(self, /, *input_iterators, kwargs={}) -> None:
668
+ """Spawn parallel execution over a set of inputs, exiting as soon as the inputs are created (without waiting
669
+ for the map to complete).
670
+
671
+ Takes one iterator argument per argument in the function being mapped over.
672
+
673
+ Example:
674
+ ```python
675
+ @app.function()
676
+ def my_func(a):
677
+ return a ** 2
678
+
679
+
680
+ @app.local_entrypoint()
681
+ def main():
682
+ my_func.spawn_map([1, 2, 3, 4])
683
+ ```
684
+
685
+ Programmatic retrieval of results will be supported in a future update.
686
+ """
687
+ ...
688
+
689
+ async def aio(self, /, *input_iterators, kwargs={}) -> None:
690
+ """This runs in an event loop on the main thread. It consumes inputs from the input iterators and creates async
691
+ function calls for each.
692
+ """
693
+ ...
331
694
 
332
695
  spawn_map: __spawn_map_spec[typing_extensions.Self]
333
696
 
334
697
  class FunctionCall(typing.Generic[modal._functions.ReturnType], modal.object.Object):
698
+ """A reference to an executed function call.
699
+
700
+ Constructed using `.spawn(...)` on a Modal function with the same
701
+ arguments that a function normally takes. Acts as a reference to
702
+ an ongoing function call that can be passed around and used to
703
+ poll or fetch function results at some later time.
704
+
705
+ Conceptually similar to a Future/Promise/AsyncResult in other contexts and languages.
706
+ """
707
+
335
708
  _is_generator: bool
336
709
 
337
- def __init__(self, *args, **kwargs): ...
710
+ def __init__(self, *args, **kwargs):
711
+ """mdmd:hidden"""
712
+ ...
713
+
338
714
  def _invocation(self): ...
339
715
 
340
716
  class __get_spec(typing_extensions.Protocol[ReturnType_INNER, SUPERSELF]):
341
- def __call__(self, /, timeout: typing.Optional[float] = None) -> ReturnType_INNER: ...
342
- async def aio(self, /, timeout: typing.Optional[float] = None) -> ReturnType_INNER: ...
717
+ def __call__(self, /, timeout: typing.Optional[float] = None) -> ReturnType_INNER:
718
+ """Get the result of the function call.
719
+
720
+ This function waits indefinitely by default. It takes an optional
721
+ `timeout` argument that specifies the maximum number of seconds to wait,
722
+ which can be set to `0` to poll for an output immediately.
723
+
724
+ The returned coroutine is not cancellation-safe.
725
+ """
726
+ ...
727
+
728
+ async def aio(self, /, timeout: typing.Optional[float] = None) -> ReturnType_INNER:
729
+ """Get the result of the function call.
730
+
731
+ This function waits indefinitely by default. It takes an optional
732
+ `timeout` argument that specifies the maximum number of seconds to wait,
733
+ which can be set to `0` to poll for an output immediately.
734
+
735
+ The returned coroutine is not cancellation-safe.
736
+ """
737
+ ...
343
738
 
344
739
  get: __get_spec[modal._functions.ReturnType, typing_extensions.Self]
345
740
 
346
741
  class __get_call_graph_spec(typing_extensions.Protocol[SUPERSELF]):
347
- def __call__(self, /) -> list[modal.call_graph.InputInfo]: ...
348
- async def aio(self, /) -> list[modal.call_graph.InputInfo]: ...
742
+ def __call__(self, /) -> list[modal.call_graph.InputInfo]:
743
+ """Returns a structure representing the call graph from a given root
744
+ call ID, along with the status of execution for each node.
745
+
746
+ See [`modal.call_graph`](https://modal.com/docs/reference/modal.call_graph) reference page
747
+ for documentation on the structure of the returned `InputInfo` items.
748
+ """
749
+ ...
750
+
751
+ async def aio(self, /) -> list[modal.call_graph.InputInfo]:
752
+ """Returns a structure representing the call graph from a given root
753
+ call ID, along with the status of execution for each node.
754
+
755
+ See [`modal.call_graph`](https://modal.com/docs/reference/modal.call_graph) reference page
756
+ for documentation on the structure of the returned `InputInfo` items.
757
+ """
758
+ ...
349
759
 
350
760
  get_call_graph: __get_call_graph_spec[typing_extensions.Self]
351
761
 
352
762
  class __cancel_spec(typing_extensions.Protocol[SUPERSELF]):
353
- def __call__(self, /, terminate_containers: bool = False): ...
354
- async def aio(self, /, terminate_containers: bool = False): ...
763
+ def __call__(self, /, terminate_containers: bool = False):
764
+ """Cancels the function call, which will stop its execution and mark its inputs as
765
+ [`TERMINATED`](https://modal.com/docs/reference/modal.call_graph#modalcall_graphinputstatus).
766
+
767
+ If `terminate_containers=True` - the containers running the cancelled inputs are all terminated
768
+ causing any non-cancelled inputs on those containers to be rescheduled in new containers.
769
+ """
770
+ ...
771
+
772
+ async def aio(self, /, terminate_containers: bool = False):
773
+ """Cancels the function call, which will stop its execution and mark its inputs as
774
+ [`TERMINATED`](https://modal.com/docs/reference/modal.call_graph#modalcall_graphinputstatus).
775
+
776
+ If `terminate_containers=True` - the containers running the cancelled inputs are all terminated
777
+ causing any non-cancelled inputs on those containers to be rescheduled in new containers.
778
+ """
779
+ ...
355
780
 
356
781
  cancel: __cancel_spec[typing_extensions.Self]
357
782
 
358
783
  class __from_id_spec(typing_extensions.Protocol):
359
784
  def __call__(
360
785
  self, /, function_call_id: str, client: typing.Optional[modal.client.Client] = None
361
- ) -> FunctionCall[typing.Any]: ...
786
+ ) -> FunctionCall[typing.Any]:
787
+ """Instantiate a FunctionCall object from an existing ID.
788
+
789
+ Examples:
790
+
791
+ ```python notest
792
+ # Spawn a FunctionCall and keep track of its object ID
793
+ fc = my_func.spawn()
794
+ fc_id = fc.object_id
795
+
796
+ # Later, use the ID to re-instantiate the FunctionCall object
797
+ fc = _FunctionCall.from_id(fc_id)
798
+ result = fc.get()
799
+ ```
800
+
801
+ Note that it's only necessary to re-instantiate the `FunctionCall` with this method
802
+ if you no longer have access to the original object returned from `Function.spawn`.
803
+ """
804
+ ...
805
+
362
806
  async def aio(
363
807
  self, /, function_call_id: str, client: typing.Optional[modal.client.Client] = None
364
- ) -> FunctionCall[typing.Any]: ...
808
+ ) -> FunctionCall[typing.Any]:
809
+ """Instantiate a FunctionCall object from an existing ID.
810
+
811
+ Examples:
812
+
813
+ ```python notest
814
+ # Spawn a FunctionCall and keep track of its object ID
815
+ fc = my_func.spawn()
816
+ fc_id = fc.object_id
817
+
818
+ # Later, use the ID to re-instantiate the FunctionCall object
819
+ fc = _FunctionCall.from_id(fc_id)
820
+ result = fc.get()
821
+ ```
822
+
823
+ Note that it's only necessary to re-instantiate the `FunctionCall` with this method
824
+ if you no longer have access to the original object returned from `Function.spawn`.
825
+ """
826
+ ...
365
827
 
366
828
  from_id: __from_id_spec
367
829
 
368
830
  class __gather_spec(typing_extensions.Protocol):
369
- def __call__(
370
- self, /, *function_calls: FunctionCall[modal._functions.T]
371
- ) -> typing.Sequence[modal._functions.T]: ...
831
+ def __call__(self, /, *function_calls: FunctionCall[modal._functions.T]) -> typing.Sequence[modal._functions.T]:
832
+ """Wait until all Modal FunctionCall objects have results before returning.
833
+
834
+ Accepts a variable number of `FunctionCall` objects, as returned by `Function.spawn()`.
835
+
836
+ Returns a list of results from each FunctionCall, or raises an exception
837
+ from the first failing function call.
838
+
839
+ Examples:
840
+
841
+ ```python notest
842
+ fc1 = slow_func_1.spawn()
843
+ fc2 = slow_func_2.spawn()
844
+
845
+ result_1, result_2 = modal.FunctionCall.gather(fc1, fc2)
846
+ ```
847
+
848
+ *Added in v0.73.69*: This method replaces the deprecated `modal.functions.gather` function.
849
+ """
850
+ ...
851
+
372
852
  async def aio(
373
853
  self, /, *function_calls: FunctionCall[modal._functions.T]
374
- ) -> typing.Sequence[modal._functions.T]: ...
854
+ ) -> typing.Sequence[modal._functions.T]:
855
+ """Wait until all Modal FunctionCall objects have results before returning.
856
+
857
+ Accepts a variable number of `FunctionCall` objects, as returned by `Function.spawn()`.
858
+
859
+ Returns a list of results from each FunctionCall, or raises an exception
860
+ from the first failing function call.
861
+
862
+ Examples:
863
+
864
+ ```python notest
865
+ fc1 = slow_func_1.spawn()
866
+ fc2 = slow_func_2.spawn()
867
+
868
+ result_1, result_2 = modal.FunctionCall.gather(fc1, fc2)
869
+ ```
870
+
871
+ *Added in v0.73.69*: This method replaces the deprecated `modal.functions.gather` function.
872
+ """
873
+ ...
375
874
 
376
875
  gather: __gather_spec
377
876
 
378
877
  class __gather_spec(typing_extensions.Protocol):
379
- def __call__(self, /, *function_calls) -> typing.Sequence[modal._functions.T]: ...
380
- async def aio(self, /, *function_calls) -> typing.Sequence[modal._functions.T]: ...
878
+ def __call__(self, /, *function_calls) -> typing.Sequence[modal._functions.T]:
879
+ """mdmd:hidden
880
+ Deprecated: Please use `modal.FunctionCall.gather()` instead.
881
+ """
882
+ ...
883
+
884
+ async def aio(self, /, *function_calls) -> typing.Sequence[modal._functions.T]:
885
+ """mdmd:hidden
886
+ Deprecated: Please use `modal.FunctionCall.gather()` instead.
887
+ """
888
+ ...
381
889
 
382
890
  gather: __gather_spec