modal 1.0.5.dev11__py3-none-any.whl → 1.0.5.dev13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
modal/_functions.py CHANGED
@@ -356,12 +356,14 @@ class _InputPlaneInvocation:
356
356
  client: _Client,
357
357
  input_item: api_pb2.FunctionPutInputsItem,
358
358
  function_id: str,
359
+ input_plane_region: str,
359
360
  ):
360
361
  self.stub = stub
361
362
  self.client = client # Used by the deserializer.
362
363
  self.attempt_token = attempt_token
363
364
  self.input_item = input_item
364
365
  self.function_id = function_id
366
+ self.input_plane_region = input_plane_region
365
367
 
366
368
  @staticmethod
367
369
  async def create(
@@ -371,6 +373,7 @@ class _InputPlaneInvocation:
371
373
  *,
372
374
  client: _Client,
373
375
  input_plane_url: str,
376
+ input_plane_region: str,
374
377
  ) -> "_InputPlaneInvocation":
375
378
  stub = await client.get_stub(input_plane_url)
376
379
 
@@ -384,10 +387,13 @@ class _InputPlaneInvocation:
384
387
  parent_input_id=current_input_id() or "",
385
388
  input=input_item,
386
389
  )
387
- response = await retry_transient_errors(stub.AttemptStart, request)
390
+ metadata: list[tuple[str, str]] = []
391
+ if input_plane_region and input_plane_region != "":
392
+ metadata.append(("x-modal-input-plane-region", input_plane_region))
393
+ response = await retry_transient_errors(stub.AttemptStart, request, metadata=metadata)
388
394
  attempt_token = response.attempt_token
389
395
 
390
- return _InputPlaneInvocation(stub, attempt_token, client, input_item, function_id)
396
+ return _InputPlaneInvocation(stub, attempt_token, client, input_item, function_id, input_plane_region)
391
397
 
392
398
  async def run_function(self) -> Any:
393
399
  # This will retry when the server returns GENERIC_STATUS_INTERNAL_FAILURE, i.e. lost inputs or worker preemption
@@ -399,10 +405,14 @@ class _InputPlaneInvocation:
399
405
  timeout_secs=OUTPUTS_TIMEOUT,
400
406
  requested_at=time.time(),
401
407
  )
408
+ metadata: list[tuple[str, str]] = []
409
+ if self.input_plane_region and self.input_plane_region != "":
410
+ metadata.append(("x-modal-input-plane-region", self.input_plane_region))
402
411
  await_response: api_pb2.AttemptAwaitResponse = await retry_transient_errors(
403
412
  self.stub.AttemptAwait,
404
413
  await_request,
405
414
  attempt_timeout=OUTPUTS_TIMEOUT + ATTEMPT_TIMEOUT_GRACE_PERIOD,
415
+ metadata=metadata,
406
416
  )
407
417
 
408
418
  if await_response.HasField("output"):
@@ -419,7 +429,11 @@ class _InputPlaneInvocation:
419
429
  attempt_token=self.attempt_token,
420
430
  )
421
431
  # TODO(ryan): Add exponential backoff?
422
- retry_response = await retry_transient_errors(self.stub.AttemptRetry, retry_request)
432
+ retry_response = await retry_transient_errors(
433
+ self.stub.AttemptRetry,
434
+ retry_request,
435
+ metadata=metadata,
436
+ )
423
437
  self.attempt_token = retry_response.attempt_token
424
438
  continue
425
439
 
@@ -779,6 +793,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
779
793
  req.method_definitions[method_name].CopyFrom(method_definition)
780
794
  elif webhook_config:
781
795
  req.webhook_config.CopyFrom(webhook_config)
796
+
782
797
  response = await retry_transient_errors(resolver.client.stub.FunctionPrecreate, req)
783
798
  self._hydrate(response.function_id, resolver.client, response.handle_metadata)
784
799
 
@@ -1383,6 +1398,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1383
1398
  self._method_handle_metadata = dict(metadata.method_handle_metadata)
1384
1399
  self._definition_id = metadata.definition_id
1385
1400
  self._input_plane_url = metadata.input_plane_url
1401
+ self._input_plane_region = metadata.input_plane_region
1386
1402
 
1387
1403
  def _get_metadata(self):
1388
1404
  # Overridden concrete implementation of base class method
@@ -1398,6 +1414,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1398
1414
  method_handle_metadata=self._method_handle_metadata,
1399
1415
  function_schema=self._metadata.function_schema if self._metadata else None,
1400
1416
  input_plane_url=self._input_plane_url,
1417
+ input_plane_region=self._input_plane_region,
1401
1418
  )
1402
1419
 
1403
1420
  def _check_no_web_url(self, fn_name: str):
@@ -1493,6 +1510,7 @@ Use the `Function.get_web_url()` method instead.
1493
1510
  kwargs,
1494
1511
  client=self.client,
1495
1512
  input_plane_url=self._input_plane_url,
1513
+ input_plane_region=self._input_plane_region,
1496
1514
  )
1497
1515
  else:
1498
1516
  invocation = await _Invocation.create(
@@ -603,6 +603,14 @@ class FunctionCreationStatus:
603
603
  f"Custom domain for {self.tag} => [magenta underline]{custom_domain.url}[/magenta underline]"
604
604
  )
605
605
 
606
+ elif self.response.function.flash_service_urls:
607
+ for flash_service_url in self.response.function.flash_service_urls:
608
+ flash_service_url_status_row = self.resolver.add_status_row()
609
+ flash_service_url_status_row.finish(
610
+ f"Created flash service endpoint for {self.tag} => "
611
+ f"[magenta underline]{flash_service_url}[/magenta underline]"
612
+ )
613
+
606
614
  else:
607
615
  for warning in self.response.server_warnings:
608
616
  self.status_row.warning(warning)
@@ -198,6 +198,7 @@ async def retry_transient_errors(
198
198
  total_timeout: Optional[float] = None, # timeout for the entire function call
199
199
  attempt_timeout_floor=2.0, # always have at least this much timeout (only for total_timeout)
200
200
  retry_warning_message: Optional[RetryWarningMessage] = None,
201
+ metadata: list[tuple[str, str]] = [],
201
202
  ) -> ResponseType:
202
203
  """Retry on transient gRPC failures with back-off until max_retries is reached.
203
204
  If max_retries is None, retry forever."""
@@ -216,9 +217,13 @@ async def retry_transient_errors(
216
217
  total_deadline = None
217
218
 
218
219
  while True:
219
- metadata = [("x-idempotency-key", idempotency_key), ("x-retry-attempt", str(n_retries))]
220
+ attempt_metadata = [
221
+ ("x-idempotency-key", idempotency_key),
222
+ ("x-retry-attempt", str(n_retries)),
223
+ *metadata,
224
+ ]
220
225
  if n_retries > 0:
221
- metadata.append(("x-retry-delay", str(time.time() - t0)))
226
+ attempt_metadata.append(("x-retry-delay", str(time.time() - t0)))
222
227
  timeouts = []
223
228
  if attempt_timeout is not None:
224
229
  timeouts.append(attempt_timeout)
@@ -229,7 +234,7 @@ async def retry_transient_errors(
229
234
  else:
230
235
  timeout = None
231
236
  try:
232
- return await fn(*args, metadata=metadata, timeout=timeout)
237
+ return await fn(*args, metadata=attempt_metadata, timeout=timeout)
233
238
  except (StreamTerminatedError, GRPCError, OSError, asyncio.TimeoutError, AttributeError) as exc:
234
239
  if isinstance(exc, GRPCError) and exc.status not in status_codes:
235
240
  if exc.status == Status.UNAUTHENTICATED:
modal/client.pyi CHANGED
@@ -31,7 +31,7 @@ class _Client:
31
31
  server_url: str,
32
32
  client_type: int,
33
33
  credentials: typing.Optional[tuple[str, str]],
34
- version: str = "1.0.5.dev11",
34
+ version: str = "1.0.5.dev13",
35
35
  ):
36
36
  """mdmd:hidden
37
37
  The Modal client object is not intended to be instantiated directly by users.
@@ -160,7 +160,7 @@ class Client:
160
160
  server_url: str,
161
161
  client_type: int,
162
162
  credentials: typing.Optional[tuple[str, str]],
163
- version: str = "1.0.5.dev11",
163
+ version: str = "1.0.5.dev13",
164
164
  ):
165
165
  """mdmd:hidden
166
166
  The Modal client object is not intended to be instantiated directly by users.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.0.5.dev11
3
+ Version: 1.0.5.dev13
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -3,7 +3,7 @@ modal/__main__.py,sha256=sTJcc9EbDuCKSwg3tL6ZckFw9WWdlkXW8mId1IvJCNc,2846
3
3
  modal/_clustered_functions.py,sha256=kTf-9YBXY88NutC1akI-gCbvf01RhMPCw-zoOI_YIUE,2700
4
4
  modal/_clustered_functions.pyi,sha256=_QKM87tdYwcALSGth8a0-9qXl02fZK6zMfEGEoYz7eA,1007
5
5
  modal/_container_entrypoint.py,sha256=2Zx9O_EMJg0H77EdnC2vGKs6uFMWwbP1NLFf-qYmWmU,28962
6
- modal/_functions.py,sha256=urJo-hqeLWrOMQLLaYQCi0O7Mz39Z4n-FQ3w5sKM5rQ,79803
6
+ modal/_functions.py,sha256=MOffek84MZ50Lj1Gh0GelkGtJuazz6lQKV4awMSioRg,80705
7
7
  modal/_ipython.py,sha256=TW1fkVOmZL3YYqdS2YlM1hqpf654Yf8ZyybHdBnlhSw,301
8
8
  modal/_location.py,sha256=joiX-0ZeutEUDTrrqLF1GHXCdVLF-rHzstocbMcd_-k,366
9
9
  modal/_object.py,sha256=KzzzZoM41UQUiY9TKOrft9BtZKgjWG_ukdlyLGjB4UY,10758
@@ -22,7 +22,7 @@ modal/app.py,sha256=pj-4mpvBR6phFG38rQZ8GM1FIgcaM8cje5d_Vo2_gJU,46602
22
22
  modal/app.pyi,sha256=Z6wi_dkXywiaM2rvAvguj2Wgu9ZgPjMSLl1nH1a7EYI,42243
23
23
  modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
24
24
  modal/client.py,sha256=OwISJvkgMb-rHm9Gc4i-7YcDgGiZgwJ7F_PzwZH7a6Q,16847
25
- modal/client.pyi,sha256=dMeFdidtBnwpM_KtLhwbgdYNH9vXAH_Iyme-p7FC8wg,15081
25
+ modal/client.pyi,sha256=897xKP1jggviSbYivsLlmNM8Et3mzzWV3uIJHehj39U,15081
26
26
  modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
27
27
  modal/cloud_bucket_mount.pyi,sha256=-qSfYAQvIoO_l2wsCCGTG5ZUwQieNKXdAO00yP1-LYU,7394
28
28
  modal/cls.py,sha256=6GMJFnqVm5BqfLbEGWcI7M_QBAuUzn-apB9P1sllI9s,39843
@@ -96,10 +96,10 @@ modal/_utils/blob_utils.py,sha256=IexC2Jbtqp_Tkmy62ayfgzTYte0UPCNufB_v-DO21g8,18
96
96
  modal/_utils/bytes_io_segment_payload.py,sha256=vaXPq8b52-x6G2hwE7SrjS58pg_aRm7gV3bn3yjmTzQ,4261
97
97
  modal/_utils/deprecation.py,sha256=EXP1beU4pmEqEzWMLw6E3kUfNfpmNA_VOp6i0EHi93g,4856
98
98
  modal/_utils/docker_utils.py,sha256=h1uETghR40mp_y3fSWuZAfbIASH1HMzuphJHghAL6DU,3722
99
- modal/_utils/function_utils.py,sha256=cc1QQ5s_Y-5mlLa2wzZ6NF6cH2k8asaDHerASUqI7FU,26878
99
+ modal/_utils/function_utils.py,sha256=QS8cRE0zGerlCW-r5457HXNj5uQM_4SGs7AbQLAtbwA,27319
100
100
  modal/_utils/git_utils.py,sha256=qtUU6JAttF55ZxYq51y55OR58B0tDPZsZWK5dJe6W5g,3182
101
101
  modal/_utils/grpc_testing.py,sha256=H1zHqthv19eGPJz2HKXDyWXWGSqO4BRsxah3L5Xaa8A,8619
102
- modal/_utils/grpc_utils.py,sha256=xSFosSJYQ4m6cH9WtChcSXqsnyk6DMeVvOHI4N3914g,10922
102
+ modal/_utils/grpc_utils.py,sha256=inJccK9MYCmkyF8SFp86RCw2pZzwvsGk_YaLQ2Bw_H4,11046
103
103
  modal/_utils/hash_utils.py,sha256=zg3J6OGxTFGSFri1qQ12giDz90lWk8bzaxCTUCRtiX4,3034
104
104
  modal/_utils/http_utils.py,sha256=yeTFsXYr0rYMEhB7vBP7audG9Uc7OLhzKBANFDZWVt0,2451
105
105
  modal/_utils/jwt_utils.py,sha256=fxH9plyrbAemTbjSsQtzIdDXE9QXxvMC4DiUZ16G0aA,1360
@@ -147,7 +147,7 @@ modal/requirements/2024.10.txt,sha256=qD-5cVIVM9wXesJ6JC89Ew-3m2KjEElUz3jaw_MddR
147
147
  modal/requirements/PREVIEW.txt,sha256=KxDaVTOwatHvboDo4lorlgJ7-n-MfAwbPwxJ0zcJqrs,312
148
148
  modal/requirements/README.md,sha256=9tK76KP0Uph7O0M5oUgsSwEZDj5y-dcUPsnpR0Sc-Ik,854
149
149
  modal/requirements/base-images.json,sha256=f1bwyp2UkM844eoO9Qk30gQw_xrMqKpMSeJ6MErXnEk,995
150
- modal-1.0.5.dev11.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
150
+ modal-1.0.5.dev13.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
151
151
  modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
152
152
  modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
153
153
  modal_docs/gen_reference_docs.py,sha256=d_CQUGQ0rfw28u75I2mov9AlS773z9rG40-yq5o7g2U,6359
@@ -155,10 +155,10 @@ modal_docs/mdmd/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,2
155
155
  modal_docs/mdmd/mdmd.py,sha256=Irx49MCCTlBOP4FBdLR--JrpA3-WhsVeriq0LGgsRic,6232
156
156
  modal_docs/mdmd/signatures.py,sha256=XJaZrK7Mdepk5fdX51A8uENiLFNil85Ud0d4MH8H5f0,3218
157
157
  modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
158
- modal_proto/api.proto,sha256=i-ETZCN-HofvuOxK-0TQ9V0lYpCOyREEUg3VxuUfjJY,97293
158
+ modal_proto/api.proto,sha256=HQSwSvH8kTumsLeNEEkyDQpFa7vMnvLPP-qRyKMEW-M,97424
159
159
  modal_proto/api_grpc.py,sha256=KR3X2FZiKjJuistRWzsBsDi8DKeIlKJJ2iPPbzltDJg,119140
160
- modal_proto/api_pb2.py,sha256=QruoJk16KzDhNut2aoANMPpnj2KCt_EBvQU5gsAIq88,342410
161
- modal_proto/api_pb2.pyi,sha256=zTjXqsw79xO2EkzVWaspD-skxW8JrK0PJUM5BlAmXZA,468320
160
+ modal_proto/api_pb2.py,sha256=gK6H1bncUrb_F1o1gSgSQFGZGaHWTfxscxuVZhf8a88,342599
161
+ modal_proto/api_pb2.pyi,sha256=NtXJpSEdait0BXnx6o4OpJa91gu3C2_pn1SaKDLcZns,469483
162
162
  modal_proto/api_pb2_grpc.py,sha256=xRO6E7F9wSeE75T2NW_EVSN0JHUkCz-qQDgPMTG1x0o,257566
163
163
  modal_proto/api_pb2_grpc.pyi,sha256=pCgIpIcJnEoWnh1Bu1LT62-oesNHN-XyQJaZzxRNeB4,60334
164
164
  modal_proto/modal_api_grpc.py,sha256=Vc2BoHcB6hV2GlkwvpB5yBfeJT72dxQ6-VMUhbPD-0U,18019
@@ -170,10 +170,10 @@ modal_proto/options_pb2.pyi,sha256=l7DBrbLO7q3Ir-XDkWsajm0d0TQqqrfuX54i4BMpdQg,1
170
170
  modal_proto/options_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
171
171
  modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0yJSI,247
172
172
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
173
- modal_version/__init__.py,sha256=z-HejmZfJ0tIrdq6OjrID0PXv1kygiUz14I8sxQs5Xk,121
173
+ modal_version/__init__.py,sha256=K85Q9uGTO0wtk9OeYnzx14-3vdoLGYw_-sMV2tplKgI,121
174
174
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
175
- modal-1.0.5.dev11.dist-info/METADATA,sha256=XCyDeZqZOkSXqPM_gvtTVF6ME0u9-EtdE9xPNdsOPU4,2455
176
- modal-1.0.5.dev11.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
177
- modal-1.0.5.dev11.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
178
- modal-1.0.5.dev11.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
179
- modal-1.0.5.dev11.dist-info/RECORD,,
175
+ modal-1.0.5.dev13.dist-info/METADATA,sha256=xfJNkrtgB6USyAzdSommGwIrjKwMnruD1XqPpkpvWOw,2455
176
+ modal-1.0.5.dev13.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
177
+ modal-1.0.5.dev13.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
178
+ modal-1.0.5.dev13.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
179
+ modal-1.0.5.dev13.dist-info/RECORD,,
modal_proto/api.proto CHANGED
@@ -1412,6 +1412,8 @@ message Function {
1412
1412
  // If set, client deps will be mounted into the container, and are
1413
1413
  // no longer expected to exist in the image itself.
1414
1414
  bool mount_client_dependencies = 82;
1415
+
1416
+ repeated string flash_service_urls = 83;
1415
1417
  }
1416
1418
 
1417
1419
  message FunctionAsyncInvokeRequest {
@@ -1564,6 +1566,8 @@ message FunctionData {
1564
1566
  FunctionSchema function_schema = 32;
1565
1567
 
1566
1568
  map<string, string> experimental_options = 33;
1569
+
1570
+ repeated string flash_service_urls = 34;
1567
1571
  }
1568
1572
 
1569
1573
  message FunctionExtended {
@@ -1699,6 +1703,7 @@ message FunctionHandleMetadata {
1699
1703
  map<string, FunctionHandleMetadata> method_handle_metadata = 44;
1700
1704
  FunctionSchema function_schema = 45;
1701
1705
  optional string input_plane_url = 46;
1706
+ optional string input_plane_region = 47;
1702
1707
  }
1703
1708
 
1704
1709
  message FunctionInput {