modal 0.62.115__py3-none-any.whl → 0.72.13__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 +13 -9
  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 +402 -398
  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 -60
  11. modal/_resources.py +26 -7
  12. modal/_runtime/__init__.py +1 -0
  13. modal/_runtime/asgi.py +519 -0
  14. modal/_runtime/container_io_manager.py +1025 -0
  15. modal/{execution_context.py → _runtime/execution_context.py} +11 -2
  16. modal/_runtime/telemetry.py +169 -0
  17. modal/_runtime/user_code_imports.py +356 -0
  18. modal/_serialization.py +123 -6
  19. modal/_traceback.py +47 -187
  20. modal/_tunnel.py +50 -14
  21. modal/_tunnel.pyi +19 -36
  22. modal/_utils/app_utils.py +3 -17
  23. modal/_utils/async_utils.py +386 -104
  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 +299 -98
  29. modal/_utils/grpc_testing.py +47 -34
  30. modal/_utils/grpc_utils.py +54 -21
  31. modal/_utils/hash_utils.py +51 -10
  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 +3 -3
  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 +12 -10
  43. modal/app.py +561 -323
  44. modal/app.pyi +474 -262
  45. modal/call_graph.py +7 -6
  46. modal/cli/_download.py +22 -6
  47. modal/cli/_traceback.py +200 -0
  48. modal/cli/app.py +203 -42
  49. modal/cli/config.py +12 -5
  50. modal/cli/container.py +61 -13
  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 +21 -48
  55. modal/cli/launch.py +28 -14
  56. modal/cli/network_file_system.py +57 -21
  57. modal/cli/profile.py +1 -1
  58. modal/cli/programs/run_jupyter.py +34 -9
  59. modal/cli/programs/vscode.py +58 -8
  60. modal/cli/queues.py +131 -0
  61. modal/cli/run.py +199 -96
  62. modal/cli/secret.py +5 -4
  63. modal/cli/token.py +7 -2
  64. modal/cli/utils.py +74 -8
  65. modal/cli/volume.py +97 -56
  66. modal/client.py +248 -144
  67. modal/client.pyi +156 -124
  68. modal/cloud_bucket_mount.py +43 -30
  69. modal/cloud_bucket_mount.pyi +32 -25
  70. modal/cls.py +528 -141
  71. modal/cls.pyi +189 -145
  72. modal/config.py +32 -15
  73. modal/container_process.py +177 -0
  74. modal/container_process.pyi +82 -0
  75. modal/dict.py +50 -54
  76. modal/dict.pyi +120 -164
  77. modal/environments.py +106 -5
  78. modal/environments.pyi +77 -25
  79. modal/exception.py +30 -43
  80. modal/experimental.py +62 -2
  81. modal/file_io.py +537 -0
  82. modal/file_io.pyi +235 -0
  83. modal/file_pattern_matcher.py +196 -0
  84. modal/functions.py +846 -428
  85. modal/functions.pyi +446 -387
  86. modal/gpu.py +57 -44
  87. modal/image.py +943 -417
  88. modal/image.pyi +584 -245
  89. modal/io_streams.py +434 -0
  90. modal/io_streams.pyi +122 -0
  91. modal/mount.py +223 -90
  92. modal/mount.pyi +241 -243
  93. modal/network_file_system.py +85 -86
  94. modal/network_file_system.pyi +151 -110
  95. modal/object.py +66 -36
  96. modal/object.pyi +166 -143
  97. modal/output.py +63 -0
  98. modal/parallel_map.py +73 -47
  99. modal/parallel_map.pyi +51 -63
  100. modal/partial_function.py +272 -107
  101. modal/partial_function.pyi +219 -120
  102. modal/proxy.py +15 -12
  103. modal/proxy.pyi +3 -8
  104. modal/queue.py +96 -72
  105. modal/queue.pyi +210 -135
  106. modal/requirements/2024.04.txt +2 -1
  107. modal/requirements/2024.10.txt +16 -0
  108. modal/requirements/README.md +21 -0
  109. modal/requirements/base-images.json +22 -0
  110. modal/retries.py +45 -4
  111. modal/runner.py +325 -203
  112. modal/runner.pyi +124 -110
  113. modal/running_app.py +27 -4
  114. modal/sandbox.py +509 -231
  115. modal/sandbox.pyi +396 -169
  116. modal/schedule.py +2 -2
  117. modal/scheduler_placement.py +20 -3
  118. modal/secret.py +41 -25
  119. modal/secret.pyi +62 -42
  120. modal/serving.py +39 -49
  121. modal/serving.pyi +37 -43
  122. modal/stream_type.py +15 -0
  123. modal/token_flow.py +5 -3
  124. modal/token_flow.pyi +37 -32
  125. modal/volume.py +123 -137
  126. modal/volume.pyi +228 -221
  127. {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/METADATA +5 -5
  128. modal-0.72.13.dist-info/RECORD +174 -0
  129. {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/top_level.txt +0 -1
  130. modal_docs/gen_reference_docs.py +3 -1
  131. modal_docs/mdmd/mdmd.py +0 -1
  132. modal_docs/mdmd/signatures.py +1 -2
  133. modal_global_objects/images/base_images.py +28 -0
  134. modal_global_objects/mounts/python_standalone.py +2 -2
  135. modal_proto/__init__.py +1 -1
  136. modal_proto/api.proto +1231 -531
  137. modal_proto/api_grpc.py +750 -430
  138. modal_proto/api_pb2.py +2102 -1176
  139. modal_proto/api_pb2.pyi +8859 -0
  140. modal_proto/api_pb2_grpc.py +1329 -675
  141. modal_proto/api_pb2_grpc.pyi +1416 -0
  142. modal_proto/modal_api_grpc.py +149 -0
  143. modal_proto/modal_options_grpc.py +3 -0
  144. modal_proto/options_pb2.pyi +20 -0
  145. modal_proto/options_pb2_grpc.pyi +7 -0
  146. modal_proto/py.typed +0 -0
  147. modal_version/__init__.py +1 -1
  148. modal_version/_version_generated.py +2 -2
  149. modal/_asgi.py +0 -370
  150. modal/_container_exec.py +0 -128
  151. modal/_container_io_manager.py +0 -646
  152. modal/_container_io_manager.pyi +0 -412
  153. modal/_sandbox_shell.py +0 -49
  154. modal/app_utils.py +0 -20
  155. modal/app_utils.pyi +0 -17
  156. modal/execution_context.pyi +0 -37
  157. modal/shared_volume.py +0 -23
  158. modal/shared_volume.pyi +0 -24
  159. modal-0.62.115.dist-info/RECORD +0 -207
  160. modal_global_objects/images/conda.py +0 -15
  161. modal_global_objects/images/debian_slim.py +0 -15
  162. modal_global_objects/images/micromamba.py +0 -15
  163. test/__init__.py +0 -1
  164. test/aio_test.py +0 -12
  165. test/async_utils_test.py +0 -279
  166. test/blob_test.py +0 -67
  167. test/cli_imports_test.py +0 -149
  168. test/cli_test.py +0 -674
  169. test/client_test.py +0 -203
  170. test/cloud_bucket_mount_test.py +0 -22
  171. test/cls_test.py +0 -636
  172. test/config_test.py +0 -149
  173. test/conftest.py +0 -1485
  174. test/container_app_test.py +0 -50
  175. test/container_test.py +0 -1405
  176. test/cpu_test.py +0 -23
  177. test/decorator_test.py +0 -85
  178. test/deprecation_test.py +0 -34
  179. test/dict_test.py +0 -51
  180. test/e2e_test.py +0 -68
  181. test/error_test.py +0 -7
  182. test/function_serialization_test.py +0 -32
  183. test/function_test.py +0 -791
  184. test/function_utils_test.py +0 -101
  185. test/gpu_test.py +0 -159
  186. test/grpc_utils_test.py +0 -82
  187. test/helpers.py +0 -47
  188. test/image_test.py +0 -814
  189. test/live_reload_test.py +0 -80
  190. test/lookup_test.py +0 -70
  191. test/mdmd_test.py +0 -329
  192. test/mount_test.py +0 -162
  193. test/mounted_files_test.py +0 -327
  194. test/network_file_system_test.py +0 -188
  195. test/notebook_test.py +0 -66
  196. test/object_test.py +0 -41
  197. test/package_utils_test.py +0 -25
  198. test/queue_test.py +0 -115
  199. test/resolver_test.py +0 -59
  200. test/retries_test.py +0 -67
  201. test/runner_test.py +0 -85
  202. test/sandbox_test.py +0 -191
  203. test/schedule_test.py +0 -15
  204. test/scheduler_placement_test.py +0 -57
  205. test/secret_test.py +0 -89
  206. test/serialization_test.py +0 -50
  207. test/stub_composition_test.py +0 -10
  208. test/stub_test.py +0 -361
  209. test/test_asgi_wrapper.py +0 -234
  210. test/token_flow_test.py +0 -18
  211. test/traceback_test.py +0 -135
  212. test/tunnel_test.py +0 -29
  213. test/utils_test.py +0 -88
  214. test/version_test.py +0 -14
  215. test/volume_test.py +0 -397
  216. test/watcher_test.py +0 -58
  217. test/webhook_test.py +0 -145
  218. {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/LICENSE +0 -0
  219. {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/WHEEL +0 -0
  220. {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/entry_points.txt +0 -0
modal/parallel_map.py CHANGED
@@ -1,15 +1,21 @@
1
1
  # Copyright Modal Labs 2024
2
2
  import asyncio
3
+ import time
3
4
  import typing
4
5
  from dataclasses import dataclass
5
- from typing import Any, Callable, Dict, Optional, Set, Tuple
6
+ from typing import Any, Callable, Optional
6
7
 
7
- from aiostream import pipe, stream
8
- from grpclib import Status
8
+ from grpclib import GRPCError, Status
9
9
 
10
+ from modal._runtime.execution_context import current_input_id
10
11
  from modal._utils.async_utils import (
11
- AsyncOrSyncIteratable,
12
+ AsyncOrSyncIterable,
13
+ aclosing,
14
+ async_map_ordered,
15
+ async_merge,
16
+ async_zip,
12
17
  queue_batch_iterator,
18
+ sync_or_async_iter,
13
19
  synchronize_api,
14
20
  synchronizer,
15
21
  warn_if_generator_is_not_consumed,
@@ -23,7 +29,6 @@ from modal._utils.function_utils import (
23
29
  )
24
30
  from modal._utils.grpc_utils import retry_transient_errors
25
31
  from modal.config import logger
26
- from modal.execution_context import current_input_id
27
32
  from modal_proto import api_pb2
28
33
 
29
34
  if typing.TYPE_CHECKING:
@@ -59,9 +64,12 @@ class _OutputValue:
59
64
 
60
65
  MAP_INVOCATION_CHUNK_SIZE = 49
61
66
 
67
+ if typing.TYPE_CHECKING:
68
+ import modal.functions
69
+
62
70
 
63
71
  async def _map_invocation(
64
- function_id: str,
72
+ function: "modal.functions._Function",
65
73
  raw_input_queue: _SynchronizedQueue,
66
74
  client: "modal.client._Client",
67
75
  order_outputs: bool,
@@ -70,7 +78,7 @@ async def _map_invocation(
70
78
  ):
71
79
  assert client.stub
72
80
  request = api_pb2.FunctionMapRequest(
73
- function_id=function_id,
81
+ function_id=function.object_id,
74
82
  parent_input_id=current_input_id() or "",
75
83
  function_call_type=api_pb2.FUNCTION_CALL_TYPE_MAP,
76
84
  return_exceptions=return_exceptions,
@@ -87,8 +95,8 @@ async def _map_invocation(
87
95
  if count_update_callback is not None:
88
96
  count_update_callback(num_outputs, num_inputs)
89
97
 
90
- pending_outputs: Dict[str, int] = {} # Map input_id -> next expected gen_index value
91
- completed_outputs: Set[str] = set() # Set of input_ids whose outputs are complete (expecting no more values)
98
+ pending_outputs: dict[str, int] = {} # Map input_id -> next expected gen_index value
99
+ completed_outputs: set[str] = set() # Set of input_ids whose outputs are complete (expecting no more values)
92
100
 
93
101
  input_queue: asyncio.Queue = asyncio.Queue()
94
102
 
@@ -97,23 +105,20 @@ async def _map_invocation(
97
105
  idx = num_inputs
98
106
  num_inputs += 1
99
107
  (args, kwargs) = argskwargs
100
- return await _create_input(args, kwargs, client, idx)
108
+ return await _create_input(args, kwargs, client, idx=idx, method_name=function._use_method_name)
101
109
 
102
110
  async def input_iter():
103
111
  while 1:
104
112
  raw_input = await raw_input_queue.get()
105
113
  if raw_input is None: # end of input sentinel
106
- return
114
+ break
107
115
  yield raw_input # args, kwargs
108
116
 
109
117
  async def drain_input_generator():
110
118
  # Parallelize uploading blobs
111
- proto_input_stream = stream.iterate(input_iter()) | pipe.map(
112
- create_input, # type: ignore[reportArgumentType]
113
- ordered=True,
114
- task_limit=BLOB_MAX_PARALLELISM,
115
- )
116
- async with proto_input_stream.stream() as streamer:
119
+ async with aclosing(
120
+ async_map_ordered(input_iter(), create_input, concurrency=BLOB_MAX_PARALLELISM)
121
+ ) as streamer:
117
122
  async for item in streamer:
118
123
  await input_queue.put(item)
119
124
 
@@ -126,23 +131,36 @@ async def _map_invocation(
126
131
  nonlocal have_all_inputs, num_inputs
127
132
  async for items in queue_batch_iterator(input_queue, MAP_INVOCATION_CHUNK_SIZE):
128
133
  request = api_pb2.FunctionPutInputsRequest(
129
- function_id=function_id, inputs=items, function_call_id=function_call_id
134
+ function_id=function.object_id, inputs=items, function_call_id=function_call_id
130
135
  )
131
136
  logger.debug(
132
137
  f"Pushing {len(items)} inputs to server. Num queued inputs awaiting push is {input_queue.qsize()}."
133
138
  )
134
- resp = await retry_transient_errors(
135
- client.stub.FunctionPutInputs,
136
- request,
137
- max_retries=None,
138
- max_delay=10,
139
- additional_status_codes=[Status.RESOURCE_EXHAUSTED],
140
- )
139
+ while True:
140
+ try:
141
+ resp = await retry_transient_errors(
142
+ client.stub.FunctionPutInputs,
143
+ request,
144
+ # with 8 retries we log the warning below about every 30 secondswhich isn't too spammy.
145
+ max_retries=8,
146
+ max_delay=15,
147
+ additional_status_codes=[Status.RESOURCE_EXHAUSTED],
148
+ )
149
+ break
150
+ except GRPCError as err:
151
+ if err.status != Status.RESOURCE_EXHAUSTED:
152
+ raise err
153
+ logger.warning(
154
+ "Warning: map progress is limited. Common bottlenecks "
155
+ "include slow iteration over results, or function backlogs."
156
+ )
157
+
141
158
  count_update()
142
159
  for item in resp.inputs:
143
160
  pending_outputs.setdefault(item.input_id, 0)
144
161
  logger.debug(
145
- f"Successfully pushed {len(items)} inputs to server. Num queued inputs awaiting push is {input_queue.qsize()}."
162
+ f"Successfully pushed {len(items)} inputs to server. "
163
+ f"Num queued inputs awaiting push is {input_queue.qsize()}."
146
164
  )
147
165
 
148
166
  have_all_inputs = True
@@ -158,6 +176,7 @@ async def _map_invocation(
158
176
  timeout=OUTPUTS_TIMEOUT,
159
177
  last_entry_id=last_entry_id,
160
178
  clear_on_success=False,
179
+ requested_at=time.time(),
161
180
  )
162
181
  response = await retry_transient_errors(
163
182
  client.stub.FunctionGetOutputs,
@@ -183,8 +202,9 @@ async def _map_invocation(
183
202
  async def get_all_outputs_and_clean_up():
184
203
  assert client.stub
185
204
  try:
186
- async for item in get_all_outputs():
187
- yield item
205
+ async with aclosing(get_all_outputs()) as output_items:
206
+ async for item in output_items:
207
+ yield item
188
208
  finally:
189
209
  # "ack" that we have all outputs we are interested in and let backend clear results
190
210
  request = api_pb2.FunctionGetOutputsRequest(
@@ -192,10 +212,11 @@ async def _map_invocation(
192
212
  timeout=0,
193
213
  last_entry_id="0-0",
194
214
  clear_on_success=True,
215
+ requested_at=time.time(),
195
216
  )
196
217
  await retry_transient_errors(client.stub.FunctionGetOutputs, request)
197
218
 
198
- async def fetch_output(item: api_pb2.FunctionGetOutputsItem) -> Tuple[int, Any]:
219
+ async def fetch_output(item: api_pb2.FunctionGetOutputsItem) -> tuple[int, Any]:
199
220
  try:
200
221
  output = await _process_result(item.result, item.data_format, client.stub, client)
201
222
  except Exception as e:
@@ -206,14 +227,13 @@ async def _map_invocation(
206
227
  return (item.idx, output)
207
228
 
208
229
  async def poll_outputs():
209
- outputs = stream.iterate(get_all_outputs_and_clean_up())
210
- outputs_fetched = outputs | pipe.map(fetch_output, ordered=True, task_limit=BLOB_MAX_PARALLELISM) # type: ignore
211
-
212
230
  # map to store out-of-order outputs received
213
231
  received_outputs = {}
214
232
  output_idx = 0
215
233
 
216
- async with outputs_fetched.stream() as streamer:
234
+ async with aclosing(
235
+ async_map_ordered(get_all_outputs_and_clean_up(), fetch_output, concurrency=BLOB_MAX_PARALLELISM)
236
+ ) as streamer:
217
237
  async for idx, output in streamer:
218
238
  count_update()
219
239
  if not order_outputs:
@@ -228,9 +248,7 @@ async def _map_invocation(
228
248
 
229
249
  assert len(received_outputs) == 0
230
250
 
231
- response_gen = stream.merge(drain_input_generator(), pump_inputs(), poll_outputs())
232
-
233
- async with response_gen.stream() as streamer:
251
+ async with aclosing(async_merge(drain_input_generator(), pump_inputs(), poll_outputs())) as streamer:
234
252
  async for response in streamer:
235
253
  if response is not None:
236
254
  yield response.value
@@ -243,7 +261,7 @@ def _map_sync(
243
261
  kwargs={}, # any extra keyword arguments for the function
244
262
  order_outputs: bool = True, # return outputs in order
245
263
  return_exceptions: bool = False, # propagate exceptions (False) or aggregate them in the results list (True)
246
- ) -> AsyncOrSyncIteratable:
264
+ ) -> AsyncOrSyncIterable:
247
265
  """Parallel map over a set of inputs.
248
266
 
249
267
  Takes one iterator argument per argument in the function being mapped over.
@@ -281,11 +299,14 @@ def _map_sync(
281
299
  ```
282
300
  """
283
301
 
284
- return AsyncOrSyncIteratable(
302
+ return AsyncOrSyncIterable(
285
303
  _map_async(
286
304
  self, *input_iterators, kwargs=kwargs, order_outputs=order_outputs, return_exceptions=return_exceptions
287
305
  ),
288
- nested_async_message="You can't iter(Function.map()) or Function.for_each() from an async function. Use async for ... Function.map.aio() or Function.for_each.aio() instead.",
306
+ nested_async_message=(
307
+ "You can't iter(Function.map()) or Function.for_each() from an async function. "
308
+ "Use async for ... Function.map.aio() or Function.for_each.aio() instead."
309
+ ),
289
310
  )
290
311
 
291
312
 
@@ -314,7 +335,7 @@ async def _map_async(
314
335
 
315
336
  async def feed_queue():
316
337
  # This runs in a main thread event loop, so it doesn't block the synchronizer loop
317
- async with stream.zip(*[stream.iterate(it) for it in input_iterators]).stream() as streamer:
338
+ async with aclosing(async_zip(*[sync_or_async_iter(it) for it in input_iterators])) as streamer:
318
339
  async for args in streamer:
319
340
  await raw_input_queue.put.aio((args, kwargs))
320
341
  await raw_input_queue.put.aio(None) # end-of-input sentinel
@@ -322,11 +343,13 @@ async def _map_async(
322
343
  feed_input_task = asyncio.create_task(feed_queue())
323
344
 
324
345
  try:
325
- # note that `map()` and `map.aio()` are not synchronicity-wrapped, since they accept executable code in the form of
346
+ # note that `map()` and `map.aio()` are not synchronicity-wrapped, since
347
+ # they accept executable code in the form of
326
348
  # iterators that we don't want to run inside the synchronicity thread.
327
349
  # Instead, we delegate to `._map()` with a safer Queue as input
328
- async for output in self._map.aio(raw_input_queue, order_outputs, return_exceptions): # type: ignore[reportFunctionMemberAccess]
329
- yield output
350
+ async with aclosing(self._map.aio(raw_input_queue, order_outputs, return_exceptions)) as map_output_stream:
351
+ async for output in map_output_stream:
352
+ yield output
330
353
  finally:
331
354
  feed_input_task.cancel() # should only be needed in case of exceptions
332
355
 
@@ -363,7 +386,7 @@ async def _starmap_async(
363
386
 
364
387
  async def feed_queue():
365
388
  # This runs in a main thread event loop, so it doesn't block the synchronizer loop
366
- async with stream.iterate(input_iterator).stream() as streamer:
389
+ async with aclosing(sync_or_async_iter(input_iterator)) as streamer:
367
390
  async for args in streamer:
368
391
  await raw_input_queue.put.aio((args, kwargs))
369
392
  await raw_input_queue.put.aio(None) # end-of-input sentinel
@@ -383,7 +406,7 @@ def _starmap_sync(
383
406
  kwargs={},
384
407
  order_outputs: bool = True,
385
408
  return_exceptions: bool = False,
386
- ) -> AsyncOrSyncIteratable:
409
+ ) -> AsyncOrSyncIterable:
387
410
  """Like `map`, but spreads arguments over multiple function arguments.
388
411
 
389
412
  Assumes every input is a sequence (e.g. a tuple).
@@ -400,9 +423,12 @@ def _starmap_sync(
400
423
  assert list(my_func.starmap([(1, 2), (3, 4)])) == [3, 7]
401
424
  ```
402
425
  """
403
- return AsyncOrSyncIteratable(
426
+ return AsyncOrSyncIterable(
404
427
  _starmap_async(
405
428
  self, input_iterator, kwargs=kwargs, order_outputs=order_outputs, return_exceptions=return_exceptions
406
429
  ),
407
- nested_async_message="You can't run Function.map() or Function.for_each() from an async function. Use Function.map.aio()/Function.for_each.aio() instead.",
430
+ nested_async_message=(
431
+ "You can't run Function.map() or Function.for_each() from an async function. "
432
+ "Use Function.map.aio()/Function.for_each.aio() instead."
433
+ ),
408
434
  )
modal/parallel_map.pyi CHANGED
@@ -1,87 +1,75 @@
1
1
  import modal._utils.async_utils
2
2
  import modal.client
3
+ import modal.functions
3
4
  import typing
4
5
  import typing_extensions
5
6
 
6
7
  class _SynchronizedQueue:
7
- async def init(self):
8
- ...
9
-
10
- async def put(self, item):
11
- ...
12
-
13
- async def get(self):
14
- ...
15
-
8
+ async def init(self): ...
9
+ async def put(self, item): ...
10
+ async def get(self): ...
16
11
 
17
12
  class SynchronizedQueue:
18
- def __init__(self, /, *args, **kwargs):
19
- ...
13
+ def __init__(self, /, *args, **kwargs): ...
20
14
 
21
15
  class __init_spec(typing_extensions.Protocol):
22
- def __call__(self):
23
- ...
24
-
25
- async def aio(self, *args, **kwargs):
26
- ...
16
+ def __call__(self): ...
17
+ async def aio(self): ...
27
18
 
28
19
  init: __init_spec
29
20
 
30
21
  class __put_spec(typing_extensions.Protocol):
31
- def __call__(self, item):
32
- ...
33
-
34
- async def aio(self, *args, **kwargs):
35
- ...
22
+ def __call__(self, item): ...
23
+ async def aio(self, item): ...
36
24
 
37
25
  put: __put_spec
38
26
 
39
27
  class __get_spec(typing_extensions.Protocol):
40
- def __call__(self):
41
- ...
42
-
43
- async def aio(self, *args, **kwargs):
44
- ...
28
+ def __call__(self): ...
29
+ async def aio(self): ...
45
30
 
46
31
  get: __get_spec
47
32
 
48
-
49
33
  class _OutputValue:
50
34
  value: typing.Any
51
35
 
52
- def __init__(self, value: typing.Any) -> None:
53
- ...
54
-
55
- def __repr__(self):
56
- ...
57
-
58
- def __eq__(self, other):
59
- ...
60
-
61
-
62
- def _map_invocation(function_id: str, raw_input_queue: _SynchronizedQueue, client: modal.client._Client, order_outputs: bool, return_exceptions: bool, count_update_callback: typing.Union[typing.Callable[[int, int], None], None]):
63
- ...
64
-
65
-
66
- def _map_sync(self, *input_iterators, kwargs={}, order_outputs: bool = True, return_exceptions: bool = False) -> modal._utils.async_utils.AsyncOrSyncIteratable:
67
- ...
68
-
69
-
70
- def _map_async(self, *input_iterators: typing.Union[typing.Iterable[typing.Any], typing.AsyncIterable[typing.Any]], kwargs={}, order_outputs: bool = True, return_exceptions: bool = False) -> typing.AsyncGenerator[typing.Any, None]:
71
- ...
72
-
73
-
74
- def _for_each_sync(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False):
75
- ...
76
-
77
-
78
- async def _for_each_async(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False):
79
- ...
80
-
81
-
82
- def _starmap_async(self, input_iterator: typing.Union[typing.Iterable[typing.Sequence[typing.Any]], typing.AsyncIterable[typing.Sequence[typing.Any]]], kwargs={}, order_outputs: bool = True, return_exceptions: bool = False) -> typing.AsyncIterable[typing.Any]:
83
- ...
84
-
85
-
86
- def _starmap_sync(self, input_iterator: typing.Iterable[typing.Sequence[typing.Any]], kwargs={}, order_outputs: bool = True, return_exceptions: bool = False) -> modal._utils.async_utils.AsyncOrSyncIteratable:
87
- ...
36
+ def __init__(self, value: typing.Any) -> None: ...
37
+ def __repr__(self): ...
38
+ def __eq__(self, other): ...
39
+
40
+ def _map_invocation(
41
+ function: modal.functions._Function,
42
+ raw_input_queue: _SynchronizedQueue,
43
+ client: modal.client._Client,
44
+ order_outputs: bool,
45
+ return_exceptions: bool,
46
+ count_update_callback: typing.Optional[typing.Callable[[int, int], None]],
47
+ ): ...
48
+ def _map_sync(
49
+ self, *input_iterators, kwargs={}, order_outputs: bool = True, return_exceptions: bool = False
50
+ ) -> modal._utils.async_utils.AsyncOrSyncIterable: ...
51
+ def _map_async(
52
+ self,
53
+ *input_iterators: typing.Union[typing.Iterable[typing.Any], typing.AsyncIterable[typing.Any]],
54
+ kwargs={},
55
+ order_outputs: bool = True,
56
+ return_exceptions: bool = False,
57
+ ) -> typing.AsyncGenerator[typing.Any, None]: ...
58
+ def _for_each_sync(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False): ...
59
+ async def _for_each_async(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False): ...
60
+ def _starmap_async(
61
+ self,
62
+ input_iterator: typing.Union[
63
+ typing.Iterable[typing.Sequence[typing.Any]], typing.AsyncIterable[typing.Sequence[typing.Any]]
64
+ ],
65
+ kwargs={},
66
+ order_outputs: bool = True,
67
+ return_exceptions: bool = False,
68
+ ) -> typing.AsyncIterable[typing.Any]: ...
69
+ def _starmap_sync(
70
+ self,
71
+ input_iterator: typing.Iterable[typing.Sequence[typing.Any]],
72
+ kwargs={},
73
+ order_outputs: bool = True,
74
+ return_exceptions: bool = False,
75
+ ) -> modal._utils.async_utils.AsyncOrSyncIterable: ...