modal 1.2.2.dev21__py3-none-any.whl → 1.2.2.dev30__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/_grpc_client.py CHANGED
@@ -1,5 +1,5 @@
1
1
  # Copyright Modal Labs 2025
2
- from typing import TYPE_CHECKING, Any, Collection, Generic, Literal, Mapping, Optional, TypeVar, Union
2
+ from typing import TYPE_CHECKING, Any, Collection, Generic, Literal, Mapping, Optional, TypeVar, Union, overload
3
3
 
4
4
  import grpclib.client
5
5
  from google.protobuf.message import Message
@@ -47,6 +47,9 @@ class grpc_error_converter:
47
47
  return False
48
48
 
49
49
 
50
+ _DEFAULT_RETRY = Retry()
51
+
52
+
50
53
  class UnaryUnaryWrapper(Generic[RequestType, ResponseType]):
51
54
  # Calls a grpclib.UnaryUnaryMethod using a specific Client instance, respecting
52
55
  # if that client is closed etc. and possibly introducing Modal-specific retry logic
@@ -67,11 +70,31 @@ class UnaryUnaryWrapper(Generic[RequestType, ResponseType]):
67
70
  def name(self) -> str:
68
71
  return self.wrapped_method.name
69
72
 
73
+ @overload
74
+ async def __call__(
75
+ self,
76
+ req: RequestType,
77
+ *,
78
+ retry: Retry = _DEFAULT_RETRY,
79
+ timeout: None = None,
80
+ metadata: Optional[list[tuple[str, str]]] = None,
81
+ ) -> ResponseType: ...
82
+
83
+ @overload
84
+ async def __call__(
85
+ self,
86
+ req: RequestType,
87
+ *,
88
+ retry: None,
89
+ timeout: Optional[float] = None,
90
+ metadata: Optional[list[tuple[str, str]]] = None,
91
+ ) -> ResponseType: ...
92
+
70
93
  async def __call__(
71
94
  self,
72
95
  req: RequestType,
73
96
  *,
74
- retry: Optional[Retry] = Retry(),
97
+ retry: Optional[Retry] = _DEFAULT_RETRY,
75
98
  timeout: Optional[float] = None,
76
99
  metadata: Optional[list[tuple[str, str]]] = None,
77
100
  ) -> ResponseType:
@@ -645,14 +645,13 @@ class FunctionCreationStatus:
645
645
  if not self.response:
646
646
  self.status_row.finish(f"Unknown error when creating function {self.tag}")
647
647
 
648
- elif self.response.function.web_url:
648
+ elif web_url := self.response.handle_metadata.web_url:
649
649
  url_info = self.response.function.web_url_info
650
650
  requires_proxy_auth = self.response.function.webhook_config.requires_proxy_auth
651
651
  proxy_auth_suffix = " 🔑" if requires_proxy_auth else ""
652
652
  # Ensure terms used here match terms used in modal.com/docs/guide/webhook-urls doc.
653
653
  suffix = _get_suffix_from_web_url_info(url_info)
654
654
  # TODO: this is only printed when we're showing progress. Maybe move this somewhere else.
655
- web_url = self.response.handle_metadata.web_url
656
655
  for warning in self.response.server_warnings:
657
656
  self.status_row.warning(warning)
658
657
  self.status_row.finish(
modal/client.pyi CHANGED
@@ -33,7 +33,7 @@ class _Client:
33
33
  server_url: str,
34
34
  client_type: int,
35
35
  credentials: typing.Optional[tuple[str, str]],
36
- version: str = "1.2.2.dev21",
36
+ version: str = "1.2.2.dev30",
37
37
  ):
38
38
  """mdmd:hidden
39
39
  The Modal client object is not intended to be instantiated directly by users.
@@ -164,7 +164,7 @@ class Client:
164
164
  server_url: str,
165
165
  client_type: int,
166
166
  credentials: typing.Optional[tuple[str, str]],
167
- version: str = "1.2.2.dev21",
167
+ version: str = "1.2.2.dev30",
168
168
  ):
169
169
  """mdmd:hidden
170
170
  The Modal client object is not intended to be instantiated directly by users.
@@ -117,6 +117,7 @@ class _CloudBucketMount:
117
117
 
118
118
  read_only: bool = False
119
119
  requester_pays: bool = False
120
+ force_path_style: bool = False
120
121
 
121
122
 
122
123
  def cloud_bucket_mounts_to_proto(mounts: Sequence[tuple[str, _CloudBucketMount]]) -> list[api_pb2.CloudBucketMount]:
@@ -159,6 +160,7 @@ def cloud_bucket_mounts_to_proto(mounts: Sequence[tuple[str, _CloudBucketMount]]
159
160
  requester_pays=mount.requester_pays,
160
161
  key_prefix=key_prefix,
161
162
  oidc_auth_role_arn=mount.oidc_auth_role_arn,
163
+ force_path_style=mount.force_path_style,
162
164
  )
163
165
  cloud_bucket_mounts.append(cloud_bucket_mount)
164
166
 
@@ -99,6 +99,7 @@ class _CloudBucketMount:
99
99
  oidc_auth_role_arn: typing.Optional[str]
100
100
  read_only: bool
101
101
  requester_pays: bool
102
+ force_path_style: bool
102
103
 
103
104
  def __init__(
104
105
  self,
@@ -109,6 +110,7 @@ class _CloudBucketMount:
109
110
  oidc_auth_role_arn: typing.Optional[str] = None,
110
111
  read_only: bool = False,
111
112
  requester_pays: bool = False,
113
+ force_path_style: bool = False,
112
114
  ) -> None:
113
115
  """Initialize self. See help(type(self)) for accurate signature."""
114
116
  ...
@@ -224,6 +226,7 @@ class CloudBucketMount:
224
226
  oidc_auth_role_arn: typing.Optional[str]
225
227
  read_only: bool
226
228
  requester_pays: bool
229
+ force_path_style: bool
227
230
 
228
231
  def __init__(
229
232
  self,
@@ -234,6 +237,7 @@ class CloudBucketMount:
234
237
  oidc_auth_role_arn: typing.Optional[str] = None,
235
238
  read_only: bool = False,
236
239
  requester_pays: bool = False,
240
+ force_path_style: bool = False,
237
241
  ) -> None: ...
238
242
  def __repr__(self): ...
239
243
  def __eq__(self, other): ...
@@ -112,6 +112,7 @@ class _FlashManager:
112
112
  port=port,
113
113
  ),
114
114
  timeout=10,
115
+ retry=None,
115
116
  )
116
117
  self.num_failures = 0
117
118
  if first_registration:
@@ -145,9 +146,7 @@ class _FlashManager:
145
146
 
146
147
  async def stop(self):
147
148
  self.heartbeat_task.cancel()
148
- await self.client.stub.FlashContainerDeregister(
149
- api_pb2.FlashContainerDeregisterRequest(),
150
- )
149
+ await self.client.stub.FlashContainerDeregister(api_pb2.FlashContainerDeregisterRequest())
151
150
 
152
151
  self.stopped = True
153
152
  logger.warning(f"[Modal Flash] No longer accepting new requests on {self.tunnel.url}.")
modal/image.py CHANGED
@@ -886,8 +886,8 @@ class _Image(_Object, type_prefix="im"):
886
886
  ```python
887
887
  image = modal.Image.debian_slim().uv_pip_install("scipy", "numpy")
888
888
 
889
- app = modal.App("build-image")
890
- with modal.enable_output(), app.run():
889
+ app = modal.App.lookup("build-image", create_if_missing=True)
890
+ with modal.enable_output(): # To see logs in your local terminal
891
891
  image.build(app)
892
892
 
893
893
  # Save the image id
@@ -900,7 +900,7 @@ class _Image(_Object, type_prefix="im"):
900
900
  Alternatively, you can pre-build a image and use it in a sandbox.
901
901
 
902
902
  ```python notest
903
- app = modal.App.lookup("sandbox-example")
903
+ app = modal.App.lookup("sandbox-example", create_if_missing=True)
904
904
 
905
905
  with modal.enable_output():
906
906
  image = modal.Image.debian_slim().uv_pip_install("scipy")
modal/image.pyi CHANGED
@@ -330,8 +330,8 @@ class _Image(modal._object._Object):
330
330
  ```python
331
331
  image = modal.Image.debian_slim().uv_pip_install("scipy", "numpy")
332
332
 
333
- app = modal.App("build-image")
334
- with modal.enable_output(), app.run():
333
+ app = modal.App.lookup("build-image", create_if_missing=True)
334
+ with modal.enable_output(): # To see logs in your local terminal
335
335
  image.build(app)
336
336
 
337
337
  # Save the image id
@@ -344,7 +344,7 @@ class _Image(modal._object._Object):
344
344
  Alternatively, you can pre-build a image and use it in a sandbox.
345
345
 
346
346
  ```python notest
347
- app = modal.App.lookup("sandbox-example")
347
+ app = modal.App.lookup("sandbox-example", create_if_missing=True)
348
348
 
349
349
  with modal.enable_output():
350
350
  image = modal.Image.debian_slim().uv_pip_install("scipy")
@@ -1257,8 +1257,8 @@ class Image(modal.object.Object):
1257
1257
  ```python
1258
1258
  image = modal.Image.debian_slim().uv_pip_install("scipy", "numpy")
1259
1259
 
1260
- app = modal.App("build-image")
1261
- with modal.enable_output(), app.run():
1260
+ app = modal.App.lookup("build-image", create_if_missing=True)
1261
+ with modal.enable_output(): # To see logs in your local terminal
1262
1262
  image.build(app)
1263
1263
 
1264
1264
  # Save the image id
@@ -1271,7 +1271,7 @@ class Image(modal.object.Object):
1271
1271
  Alternatively, you can pre-build a image and use it in a sandbox.
1272
1272
 
1273
1273
  ```python notest
1274
- app = modal.App.lookup("sandbox-example")
1274
+ app = modal.App.lookup("sandbox-example", create_if_missing=True)
1275
1275
 
1276
1276
  with modal.enable_output():
1277
1277
  image = modal.Image.debian_slim().uv_pip_install("scipy")
@@ -1310,8 +1310,8 @@ class Image(modal.object.Object):
1310
1310
  ```python
1311
1311
  image = modal.Image.debian_slim().uv_pip_install("scipy", "numpy")
1312
1312
 
1313
- app = modal.App("build-image")
1314
- with modal.enable_output(), app.run():
1313
+ app = modal.App.lookup("build-image", create_if_missing=True)
1314
+ with modal.enable_output(): # To see logs in your local terminal
1315
1315
  image.build(app)
1316
1316
 
1317
1317
  # Save the image id
@@ -1324,7 +1324,7 @@ class Image(modal.object.Object):
1324
1324
  Alternatively, you can pre-build a image and use it in a sandbox.
1325
1325
 
1326
1326
  ```python notest
1327
- app = modal.App.lookup("sandbox-example")
1327
+ app = modal.App.lookup("sandbox-example", create_if_missing=True)
1328
1328
 
1329
1329
  with modal.enable_output():
1330
1330
  image = modal.Image.debian_slim().uv_pip_install("scipy")
modal/runner.py CHANGED
@@ -76,6 +76,7 @@ async def _init_local_app_existing(client: _Client, existing_app_id: str, enviro
76
76
  async def _init_local_app_new(
77
77
  client: _Client,
78
78
  description: str,
79
+ tags: dict[str, str],
79
80
  app_state: int, # ValueType
80
81
  environment_name: str = "",
81
82
  interactive: bool = False,
@@ -84,6 +85,7 @@ async def _init_local_app_new(
84
85
  description=description,
85
86
  environment_name=environment_name,
86
87
  app_state=app_state, # type: ignore
88
+ tags=tags,
87
89
  )
88
90
  app_resp, _ = await gather_cancel_on_exc( # TODO: use TaskGroup?
89
91
  client.stub.AppCreate(app_req),
@@ -102,6 +104,7 @@ async def _init_local_app_new(
102
104
  async def _init_local_app_from_name(
103
105
  client: _Client,
104
106
  name: str,
107
+ tags: dict[str, str],
105
108
  environment_name: str = "",
106
109
  ) -> RunningApp:
107
110
  # Look up any existing deployment
@@ -117,7 +120,7 @@ async def _init_local_app_from_name(
117
120
  return await _init_local_app_existing(client, existing_app_id, environment_name)
118
121
  else:
119
122
  return await _init_local_app_new(
120
- client, name, api_pb2.APP_STATE_INITIALIZING, environment_name=environment_name
123
+ client, name, tags, api_pb2.APP_STATE_INITIALIZING, environment_name=environment_name
121
124
  )
122
125
 
123
126
 
@@ -295,9 +298,12 @@ async def _run_app(
295
298
  msg = "Interactive mode requires output to be enabled. (Use the the `modal.enable_output()` context manager.)"
296
299
  raise InvalidError(msg)
297
300
 
301
+ local_app_state = app._local_state
302
+
298
303
  running_app: RunningApp = await _init_local_app_new(
299
304
  client,
300
305
  app.description or "",
306
+ local_app_state.tags,
301
307
  environment_name=environment_name or "",
302
308
  app_state=app_state,
303
309
  interactive=interactive,
@@ -333,7 +339,6 @@ async def _run_app(
333
339
  get_app_logs_loop(client, output_mgr, app_id=running_app.app_id, app_logs_url=running_app.app_logs_url)
334
340
  )
335
341
 
336
- local_app_state = app._local_state
337
342
  try:
338
343
  # Create all members
339
344
  await _create_all_objects(client, running_app, local_app_state, environment_name)
@@ -521,12 +526,15 @@ async def _deploy_app(
521
526
  if client is None:
522
527
  client = await _Client.from_env()
523
528
 
529
+ local_app_state = app._local_state
524
530
  t0 = time.time()
525
531
 
526
532
  # Get git information to track deployment history
527
533
  commit_info_task = asyncio.create_task(get_git_commit_info())
528
534
 
529
- running_app: RunningApp = await _init_local_app_from_name(client, name, environment_name=environment_name)
535
+ running_app: RunningApp = await _init_local_app_from_name(
536
+ client, name, local_app_state.tags, environment_name=environment_name
537
+ )
530
538
 
531
539
  async with TaskContext(0) as tc:
532
540
  # Start heartbeats loop to keep the client alive
@@ -540,7 +548,7 @@ async def _deploy_app(
540
548
  await _create_all_objects(
541
549
  client,
542
550
  running_app,
543
- app._local_state,
551
+ local_app_state,
544
552
  environment_name=environment_name,
545
553
  )
546
554
 
@@ -554,7 +562,7 @@ async def _deploy_app(
554
562
  client,
555
563
  running_app,
556
564
  api_pb2.APP_STATE_DEPLOYED,
557
- app._local_state,
565
+ local_app_state,
558
566
  name=name,
559
567
  deployment_tag=tag,
560
568
  commit_info=commit_info,
modal/runner.pyi CHANGED
@@ -16,12 +16,13 @@ async def _init_local_app_existing(
16
16
  async def _init_local_app_new(
17
17
  client: modal.client._Client,
18
18
  description: str,
19
+ tags: dict[str, str],
19
20
  app_state: int,
20
21
  environment_name: str = "",
21
22
  interactive: bool = False,
22
23
  ) -> modal.running_app.RunningApp: ...
23
24
  async def _init_local_app_from_name(
24
- client: modal.client._Client, name: str, environment_name: str = ""
25
+ client: modal.client._Client, name: str, tags: dict[str, str], environment_name: str = ""
25
26
  ) -> modal.running_app.RunningApp: ...
26
27
  async def _create_all_objects(
27
28
  client: modal.client._Client,
modal/sandbox.py CHANGED
@@ -29,7 +29,7 @@ from ._resources import convert_fn_config_to_resources_config
29
29
  from ._utils.async_utils import TaskContext, synchronize_api
30
30
  from ._utils.deprecation import deprecation_warning
31
31
  from ._utils.mount_utils import validate_network_file_systems, validate_volumes
32
- from ._utils.name_utils import is_valid_object_name
32
+ from ._utils.name_utils import check_object_name
33
33
  from ._utils.task_command_router_client import TaskCommandRouterClient
34
34
  from .client import _Client
35
35
  from .container_process import _ContainerProcess
@@ -79,16 +79,6 @@ def _validate_exec_args(args: Sequence[str]) -> None:
79
79
  )
80
80
 
81
81
 
82
- def _warn_if_invalid_name(name: str) -> None:
83
- if not is_valid_object_name(name):
84
- deprecation_warning(
85
- (2025, 9, 3),
86
- f"Sandbox name '{name}' will be considered invalid in a future release."
87
- "\n\nNames may contain only alphanumeric characters, dashes, periods, and underscores,"
88
- " must be shorter than 64 characters, and cannot conflict with App ID strings.",
89
- )
90
-
91
-
92
82
  class DefaultSandboxNameOverride(str):
93
83
  """A singleton class that represents the default sandbox name override.
94
84
 
@@ -440,7 +430,7 @@ class _Sandbox(_Object, type_prefix="sb"):
440
430
 
441
431
  _validate_exec_args(args)
442
432
  if name is not None:
443
- _warn_if_invalid_name(name)
433
+ check_object_name(name, "Sandbox")
444
434
 
445
435
  if block_network and (encrypted_ports or h2_ports or unencrypted_ports):
446
436
  raise InvalidError("Cannot specify open ports when `block_network` is enabled")
@@ -1020,7 +1010,7 @@ class _Sandbox(_Object, type_prefix="sb"):
1020
1010
  client = client or await _Client.from_env()
1021
1011
 
1022
1012
  if name is not None and name != _DEFAULT_SANDBOX_NAME_OVERRIDE:
1023
- _warn_if_invalid_name(name)
1013
+ check_object_name(name, "Sandbox")
1024
1014
 
1025
1015
  if name is _DEFAULT_SANDBOX_NAME_OVERRIDE:
1026
1016
  restore_req = api_pb2.SandboxRestoreRequest(
modal/sandbox.pyi CHANGED
@@ -27,7 +27,6 @@ import typing
27
27
  import typing_extensions
28
28
 
29
29
  def _validate_exec_args(args: collections.abc.Sequence[str]) -> None: ...
30
- def _warn_if_invalid_name(name: str) -> None: ...
31
30
 
32
31
  class DefaultSandboxNameOverride(str):
33
32
  """A singleton class that represents the default sandbox name override.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.2.dev21
3
+ Version: 1.2.2.dev30
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -13,7 +13,7 @@ Classifier: Topic :: System :: Distributed Computing
13
13
  Classifier: Operating System :: OS Independent
14
14
  Classifier: License :: OSI Approved :: Apache Software License
15
15
  Classifier: Programming Language :: Python :: 3
16
- Requires-Python: >=3.9
16
+ Requires-Python: <3.14,>=3.9
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
19
  Requires-Dist: aiohttp
@@ -5,7 +5,7 @@ modal/_clustered_functions.py,sha256=7amiOxErtlciWeBJBL2KvaxerUomJpTAJ3qElflFHQA
5
5
  modal/_clustered_functions.pyi,sha256=JmYwAGOLEnD5AF-gYF9O5tu-SgGjeoJz-X1j48b1Ijg,1157
6
6
  modal/_container_entrypoint.py,sha256=zYk5mC8_IMx4kWnyFMRHKOrFRLBWchy6x-py3M8FYEw,28084
7
7
  modal/_functions.py,sha256=QCEm1_6l0WSGlF4ICyH580wd8VyFinQRybQVxUXESuM,90416
8
- modal/_grpc_client.py,sha256=xnrubCsqK8JlbVMLI3_iHuDLmV2rNZjEAQeCDAZl-eE,5558
8
+ modal/_grpc_client.py,sha256=KZcggVNvFL5jRQkFumshMppeFHMbaZI9Dzf13run6As,6083
9
9
  modal/_ipython.py,sha256=TW1fkVOmZL3YYqdS2YlM1hqpf654Yf8ZyybHdBnlhSw,301
10
10
  modal/_location.py,sha256=joiX-0ZeutEUDTrrqLF1GHXCdVLF-rHzstocbMcd_-k,366
11
11
  modal/_object.py,sha256=gwsLdXb-Ecd8nH8LVCo8oVZPzzdyo9BrN1DjgQmsSuM,11967
@@ -25,9 +25,9 @@ modal/app.pyi,sha256=AUV5Rp8qQrZJTP2waoKHFY7rYgsXNMYibMcCAQKuSeo,50544
25
25
  modal/billing.py,sha256=zmQ3bcCJlwa4KD1IA_QgdWpm1pn13c-7qfy79iEauYI,195
26
26
  modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
27
27
  modal/client.py,sha256=tPzihC7R9WtP56k6dyPKi5GLGdLEHdMA6YUj9Ry5G8o,14409
28
- modal/client.pyi,sha256=s_IT8XcG1tfW2xcmkbV6VVPi34dHBWKY9mqizveqhqk,13094
29
- modal/cloud_bucket_mount.py,sha256=I2GRXYhOWLIz2kJZjXu75jAm9EJkBNcutGc6jR2ReUw,5928
30
- modal/cloud_bucket_mount.pyi,sha256=VuUOipMIHqFXMkD-3g2bsoqpSxV5qswlFHDOqPQzYAo,7405
28
+ modal/client.pyi,sha256=wqhlqlBI75mdVJFrcfKk0gQ1qbKmFeXwiIvRC7hTEJo,13094
29
+ modal/cloud_bucket_mount.py,sha256=Ff8UFG_Z0HUzcRAAfo1jvDwzaNgiX_btTFOHL7CGyI8,6016
30
+ modal/cloud_bucket_mount.pyi,sha256=vXusGMOUk9HjCs4lhxteuCK4xLQclPfugGWKo7LECEA,7539
31
31
  modal/cls.py,sha256=1kxGkqXgAJS6anuWKdbqWx_n0rbXqyFuYJIROeBxNyw,40306
32
32
  modal/cls.pyi,sha256=jJsDPFoqzM4ht-V-e-xEJKJ5TINLF0fYtoBm_UeAW5Y,27281
33
33
  modal/config.py,sha256=xUbw_ETdR7S3guj4dyzqdd9EYwRRht3aGYQRogZbi1o,13050
@@ -44,8 +44,8 @@ modal/file_pattern_matcher.py,sha256=A_Kdkej6q7YQyhM_2-BvpFmPqJ0oHb54B6yf9VqvPVE
44
44
  modal/functions.py,sha256=kcNHvqeGBxPI7Cgd57NIBBghkfbeFJzXO44WW0jSmao,325
45
45
  modal/functions.pyi,sha256=Z6VuukLrjASAgf0kV9I6c09WvP_b2gCujX6f9j2bBaw,37988
46
46
  modal/gpu.py,sha256=Fe5ORvVPDIstSq1xjmM6OoNgLYFWvogP9r5BgmD3hYg,6769
47
- modal/image.py,sha256=SW2QJNZCXpPwLwK5UAjRJexWr1-pUJR6AJJ5OCF7rQI,108048
48
- modal/image.pyi,sha256=NQ82YbSF_kadH0r4UqBDgHPDHZo5_yD8qNEFJgUzJZM,77956
47
+ modal/image.py,sha256=Pm2nONagz9HfeZyyK4KWvTzDTKx9QRlumpFhzhuHW90,108130
48
+ modal/image.pyi,sha256=grkqK9BfyKDXmJYNme-lGa0O3u7pOU5GifyLOAhG3sc,78202
49
49
  modal/io_streams.py,sha256=Lc-id7HvW-ffJKSoN1xQxf37pHARNkr4re2HKyGpKy4,29316
50
50
  modal/io_streams.pyi,sha256=P9kvQhXmh9fxQNGI2DtuFnnZ_9MJQ4ZiqOpDP2-QWUU,16746
51
51
  modal/mount.py,sha256=UPel5L2JfeOgI96718SSrjJ0dhMOQgnFDJrzpzsZ4A8,33111
@@ -65,11 +65,11 @@ modal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
65
  modal/queue.py,sha256=3IyfLRp_G_sg4-Wr7cplnt3KSjJkL-H3U0asfTacd7I,25536
66
66
  modal/queue.pyi,sha256=mFu7GFFVFNLU9VZshnfekEsb-ABgpjdhJ07KXHvdv3A,37256
67
67
  modal/retries.py,sha256=IvNLDM0f_GLUDD5VgEDoN09C88yoxSrCquinAuxT1Sc,5205
68
- modal/runner.py,sha256=GP-8dU5J8ZSAVk1U8UtZ0KCxfq3i8Y49hX6BzVJwyaU,25053
69
- modal/runner.pyi,sha256=DV3Z7h0owgRyOu9W5KU5O3UbRftX99KGrZQId91fpsU,8671
68
+ modal/runner.py,sha256=PvAdsJ0YVg3Bz9JOvVy_3tGQGSUwc1EuLq8oJ4UKVXc,25230
69
+ modal/runner.pyi,sha256=NwhiJmchsiASJWELmrrLMqHplCkq4r3j9Ft9fpOAurg,8719
70
70
  modal/running_app.py,sha256=v61mapYNV1-O-Uaho5EfJlryMLvIT9We0amUOSvSGx8,1188
71
- modal/sandbox.py,sha256=NbMS4iLQvz0moFZEcndXJ1OwpwVzXJDnoyMVugNrb3U,50295
72
- modal/sandbox.pyi,sha256=VqGO59NZX5fSU1tnA_g0pAd7eq6GvV6lNtC8TH9Xlo8,57478
71
+ modal/sandbox.py,sha256=TwmME5-BHRLcT3PQwc2yzSm3MBKvG0ifBWMOtyzl0TQ,49876
72
+ modal/sandbox.pyi,sha256=XWH57XZIouFGeE-CidVYXdI_l5w-kjCzIhqN4kd2y8Q,57428
73
73
  modal/schedule.py,sha256=ng0g0AqNY5GQI9KhkXZQ5Wam5G42glbkqVQsNpBtbDE,3078
74
74
  modal/scheduler_placement.py,sha256=BAREdOY5HzHpzSBqt6jDVR6YC_jYfHMVqOzkyqQfngU,1235
75
75
  modal/secret.py,sha256=ZSI7OAT8YXWQn4gmidH1bwjh8h7z68jxv0of46xiam8,18173
@@ -100,7 +100,7 @@ modal/_utils/blob_utils.py,sha256=NoAWDqYQsqAjievWmH5mCFSXA6XxQStDt9otT-Nh7_g,22
100
100
  modal/_utils/bytes_io_segment_payload.py,sha256=vaXPq8b52-x6G2hwE7SrjS58pg_aRm7gV3bn3yjmTzQ,4261
101
101
  modal/_utils/deprecation.py,sha256=-Bgg7jZdcJU8lROy18YyVnQYbM8hue-hVmwJqlWAGH0,5504
102
102
  modal/_utils/docker_utils.py,sha256=h1uETghR40mp_y3fSWuZAfbIASH1HMzuphJHghAL6DU,3722
103
- modal/_utils/function_utils.py,sha256=B5dAhcOM6SK3H-iwbrJjZ7XbjpweFd3YfmuFS26R8fQ,28671
103
+ modal/_utils/function_utils.py,sha256=wL2AA8aEftxCBATPStHgKDRPxrFjPAv-rHt0Wb7y9Ts,28629
104
104
  modal/_utils/git_utils.py,sha256=qtUU6JAttF55ZxYq51y55OR58B0tDPZsZWK5dJe6W5g,3182
105
105
  modal/_utils/grpc_testing.py,sha256=H1zHqthv19eGPJz2HKXDyWXWGSqO4BRsxah3L5Xaa8A,8619
106
106
  modal/_utils/grpc_utils.py,sha256=9KOQ3JW6DEmsi0lqve0YkTMU23u9AmWIyvLWJVA3TKc,11515
@@ -154,10 +154,10 @@ modal/cli/programs/run_jupyter.py,sha256=IJw8nds8Cjl9j4dxBqMGxhz-bIyVX0kle7jbt8H
154
154
  modal/cli/programs/run_marimo.py,sha256=QlCGPkwQ0XLajt2LtujR_BGsRV1AZ3OCUgZxkkM1lug,2893
155
155
  modal/cli/programs/vscode.py,sha256=E1aJPU7b8RWWj-JX71DifsCoLYsCAnre7lATiBJjUms,3386
156
156
  modal/experimental/__init__.py,sha256=sCwNbBLcR2t-jhrpwtMAPGKt2WNqXBg0xkNZdyB-6CE,13940
157
- modal/experimental/flash.py,sha256=9Xk3W2tMobiP6QknnPUDeOnWf7aE89a1VZ2EByQYmEM,26662
157
+ modal/experimental/flash.py,sha256=RKS3X3h4tY_mOLcMzbRs5tNCLPFL01dBAhCZSqCeBgA,26675
158
158
  modal/experimental/flash.pyi,sha256=uwinKAYxpunNNfBj58FP88DXb535Qik4F6tnJKPAIwQ,14696
159
159
  modal/experimental/ipython.py,sha256=TrCfmol9LGsRZMeDoeMPx3Hv3BFqQhYnmD_iH0pqdhk,2904
160
- modal-1.2.2.dev21.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
160
+ modal-1.2.2.dev30.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
161
161
  modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
162
162
  modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
163
163
  modal_docs/gen_reference_docs.py,sha256=d_CQUGQ0rfw28u75I2mov9AlS773z9rG40-yq5o7g2U,6359
@@ -165,10 +165,10 @@ modal_docs/mdmd/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,2
165
165
  modal_docs/mdmd/mdmd.py,sha256=tUTImNd4UMFk1opkaw8J672gX8AkBO5gbY2S_NMxsxs,7140
166
166
  modal_docs/mdmd/signatures.py,sha256=XJaZrK7Mdepk5fdX51A8uENiLFNil85Ud0d4MH8H5f0,3218
167
167
  modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
168
- modal_proto/api.proto,sha256=EkJaFgWBGchVeHz8q_kICaWfPNhyHyvp7EvsorTpjAo,108773
168
+ modal_proto/api.proto,sha256=_S8S_Ci838KDw8dqf4fmhVOE5_apAuctufrX56ze7bk,109030
169
169
  modal_proto/api_grpc.py,sha256=vwC-GjejDKWbG5jRN3rkU8WBSqQ8Pdj-T2E2xAECAUw,134411
170
- modal_proto/api_pb2.py,sha256=7VoMfkKpoImk7cwhVflvTLoj9Sc5MmMPcciIKpW0Md4,380509
171
- modal_proto/api_pb2.pyi,sha256=1aBhUNXnllNF7tNj_BBbJkqBfaxS22N8uVmQJiBc5_Y,532288
170
+ modal_proto/api_pb2.py,sha256=9D9DrafONt1rKOa8o-Qa-4Et7AGk8_XwV9kYXuja4g8,381073
171
+ modal_proto/api_pb2.pyi,sha256=vAuI2gGBbKY2APIcWitUCSjdw7uM92zU9FL32i6R75s,534109
172
172
  modal_proto/api_pb2_grpc.py,sha256=Hqw9jcbhpr-W6jsfog_tGU55ouZjITxGvA-DGNBqOLA,289714
173
173
  modal_proto/api_pb2_grpc.pyi,sha256=QLJ58ANCx147HeGJva58h0MTCLIDs9JmVjrx8bDdwlg,67776
174
174
  modal_proto/modal_api_grpc.py,sha256=MqaBZB2ZqYj6XTIgI_p5dOPjt9gKT4pAJNd_WXR3W84,21295
@@ -185,10 +185,10 @@ modal_proto/task_command_router_pb2.py,sha256=_pD2ZpU0bNzhwBdzmLoLyLtAtftI_Agxwn
185
185
  modal_proto/task_command_router_pb2.pyi,sha256=EyDgXPLr7alqjXYERV8w_MPuO404x0uCppmSkrfE9IE,14589
186
186
  modal_proto/task_command_router_pb2_grpc.py,sha256=uEQ0HdrCp8v-9bB5yIic9muA8spCShLHY6Bz9cCgOUE,10114
187
187
  modal_proto/task_command_router_pb2_grpc.pyi,sha256=s3Yxsrawdj4nr8vqQqsAxyX6ilWaGbdECy425KKbLIA,3301
188
- modal_version/__init__.py,sha256=0xqMZmBrC75YQupzkYZGu0f5eFCPWbDIn-I0EQwqHGk,121
188
+ modal_version/__init__.py,sha256=zvuna815ilJagWL3Xg8huaAv_l72NGA63ECILONhr5I,121
189
189
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
190
- modal-1.2.2.dev21.dist-info/METADATA,sha256=eivPEsX6sFzI5srzC8tA17IzIzSdEhzTq5aEI8jkoG4,2484
191
- modal-1.2.2.dev21.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
192
- modal-1.2.2.dev21.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
193
- modal-1.2.2.dev21.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
194
- modal-1.2.2.dev21.dist-info/RECORD,,
190
+ modal-1.2.2.dev30.dist-info/METADATA,sha256=omF9tdS7xacsGah8jgkumnAt2loWlqZ_2eoT9eYFajo,2490
191
+ modal-1.2.2.dev30.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
192
+ modal-1.2.2.dev30.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
193
+ modal-1.2.2.dev30.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
194
+ modal-1.2.2.dev30.dist-info/RECORD,,
modal_proto/api.proto CHANGED
@@ -849,6 +849,12 @@ message CloudBucketMount {
849
849
  GCP = 3;
850
850
  }
851
851
 
852
+ enum MetadataTTLType {
853
+ METADATA_TTL_TYPE_UNSPECIFIED = 0;
854
+ METADATA_TTL_TYPE_MINIMAL = 1;
855
+ METADATA_TTL_TYPE_INDEFINITE = 2;
856
+ }
857
+
852
858
  string bucket_name = 1;
853
859
  string mount_path = 2;
854
860
  string credentials_secret_id = 3;
@@ -859,6 +865,10 @@ message CloudBucketMount {
859
865
  optional string key_prefix = 8;
860
866
  optional string oidc_auth_role_arn = 9;
861
867
  bool force_path_style = 10;
868
+ oneof metadata_ttl_oneof {
869
+ MetadataTTLType metadata_ttl_type = 11;
870
+ uint64 metadata_ttl_seconds = 12;
871
+ }
862
872
  }
863
873
 
864
874
  message ClusterGetRequest {