modal 0.67.34__py3-none-any.whl → 0.67.40__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.
@@ -908,7 +908,7 @@ class _ContainerIOManager:
908
908
  if self.checkpoint_id:
909
909
  logger.debug(f"Checkpoint ID: {self.checkpoint_id} (Memory Snapshot ID)")
910
910
  else:
911
- logger.debug("No checkpoint ID provided (Memory Snapshot ID)")
911
+ raise ValueError("No checkpoint ID provided for memory snapshot")
912
912
 
913
913
  # Pause heartbeats since they keep the client connection open which causes the snapshotter to crash
914
914
  async with self.heartbeat_condition:
@@ -918,7 +918,7 @@ class _ContainerIOManager:
918
918
  self.heartbeat_condition.notify_all()
919
919
 
920
920
  await self._client.stub.ContainerCheckpoint(
921
- api_pb2.ContainerCheckpointRequest(checkpoint_id=self.checkpoint_id or "")
921
+ api_pb2.ContainerCheckpointRequest(checkpoint_id=self.checkpoint_id)
922
922
  )
923
923
 
924
924
  await self._client._close(prep_for_restore=True)
modal/cli/_traceback.py CHANGED
@@ -1,6 +1,7 @@
1
1
  # Copyright Modal Labs 2024
2
2
  """Helper functions related to displaying tracebacks in the CLI."""
3
3
  import functools
4
+ import re
4
5
  import warnings
5
6
  from typing import Optional
6
7
 
@@ -166,8 +167,12 @@ def highlight_modal_deprecation_warnings() -> None:
166
167
  def showwarning(warning, category, filename, lineno, file=None, line=None):
167
168
  if issubclass(category, (DeprecationError, PendingDeprecationError)):
168
169
  content = str(warning)
169
- date = content[:10]
170
- message = content[11:].strip()
170
+ if re.match(r"^\d{4}-\d{2}-\d{2}", content):
171
+ date = content[:10]
172
+ message = content[11:].strip()
173
+ else:
174
+ date = ""
175
+ message = content
171
176
  try:
172
177
  with open(filename, encoding="utf-8", errors="replace") as code_file:
173
178
  source = code_file.readlines()[lineno - 1].strip()
@@ -178,7 +183,7 @@ def highlight_modal_deprecation_warnings() -> None:
178
183
  panel = Panel(
179
184
  message,
180
185
  style="yellow",
181
- title=f"Modal Deprecation Warning ({date})",
186
+ title=f"Modal Deprecation Warning ({date})" if date else "Modal Deprecation Warning",
182
187
  title_align="left",
183
188
  )
184
189
  Console().print(panel)
modal/cli/app.py CHANGED
@@ -115,7 +115,7 @@ def logs(
115
115
  ```
116
116
 
117
117
  """
118
- app_identifier = warn_on_name_option("stop", app_identifier, name)
118
+ app_identifier = warn_on_name_option("logs", app_identifier, name)
119
119
  app_id = get_app_id(app_identifier, env)
120
120
  stream_app_logs(app_id)
121
121
 
@@ -10,7 +10,7 @@ from grpclib import GRPCError, Status
10
10
  from rich.console import Console
11
11
  from rich.syntax import Syntax
12
12
  from rich.table import Table
13
- from typer import Typer
13
+ from typer import Argument, Typer
14
14
 
15
15
  import modal
16
16
  from modal._location import display_location
@@ -18,7 +18,7 @@ from modal._output import OutputManager, ProgressHandler
18
18
  from modal._utils.async_utils import synchronizer
19
19
  from modal._utils.grpc_utils import retry_transient_errors
20
20
  from modal.cli._download import _volume_download
21
- from modal.cli.utils import ENV_OPTION, display_table, timestamp_to_local
21
+ from modal.cli.utils import ENV_OPTION, YES_OPTION, display_table, timestamp_to_local
22
22
  from modal.client import _Client
23
23
  from modal.environments import ensure_env
24
24
  from modal.network_file_system import _NetworkFileSystem
@@ -217,3 +217,24 @@ async def rm(
217
217
  if exc.status in (Status.NOT_FOUND, Status.INVALID_ARGUMENT):
218
218
  raise UsageError(exc.message)
219
219
  raise
220
+
221
+
222
+ @nfs_cli.command(
223
+ name="delete",
224
+ help="Delete a named, persistent modal.NetworkFileSystem.",
225
+ rich_help_panel="Management",
226
+ )
227
+ @synchronizer.create_blocking
228
+ async def delete(
229
+ nfs_name: str = Argument(help="Name of the modal.NetworkFileSystem to be deleted. Case sensitive"),
230
+ yes: bool = YES_OPTION,
231
+ env: Optional[str] = ENV_OPTION,
232
+ ):
233
+ if not yes:
234
+ typer.confirm(
235
+ f"Are you sure you want to irrevocably delete the modal.NetworkFileSystem '{nfs_name}'?",
236
+ default=False,
237
+ abort=True,
238
+ )
239
+
240
+ await _NetworkFileSystem.delete(label=nfs_name, environment_name=env)
modal/client.py CHANGED
@@ -147,7 +147,7 @@ class _Client:
147
147
  )
148
148
  if resp.warning:
149
149
  ALARM_EMOJI = chr(0x1F6A8)
150
- warnings.warn(f"{ALARM_EMOJI} {resp.warning} {ALARM_EMOJI}", DeprecationError)
150
+ warnings.warn_explicit(f"{ALARM_EMOJI} {resp.warning} {ALARM_EMOJI}", DeprecationError, "<unknown>", 0)
151
151
  except GRPCError as exc:
152
152
  if exc.status == Status.FAILED_PRECONDITION:
153
153
  raise VersionError(
modal/client.pyi CHANGED
@@ -26,7 +26,7 @@ class _Client:
26
26
  _stub: typing.Optional[modal_proto.api_grpc.ModalClientStub]
27
27
 
28
28
  def __init__(
29
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.67.34"
29
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.67.40"
30
30
  ): ...
31
31
  def is_closed(self) -> bool: ...
32
32
  @property
@@ -81,7 +81,7 @@ class Client:
81
81
  _stub: typing.Optional[modal_proto.api_grpc.ModalClientStub]
82
82
 
83
83
  def __init__(
84
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.67.34"
84
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.67.40"
85
85
  ): ...
86
86
  def is_closed(self) -> bool: ...
87
87
  @property
modal/functions.py CHANGED
@@ -347,7 +347,7 @@ class _FunctionSpec:
347
347
  volumes: dict[Union[str, PurePosixPath], Union[_Volume, _CloudBucketMount]]
348
348
  gpus: Union[GPU_T, list[GPU_T]] # TODO(irfansharif): Somehow assert that it's the first kind, in sandboxes
349
349
  cloud: Optional[str]
350
- cpu: Optional[float]
350
+ cpu: Optional[Union[float, tuple[float, float]]]
351
351
  memory: Optional[Union[int, tuple[int, int]]]
352
352
  ephemeral_disk: Optional[int]
353
353
  scheduler_placement: Optional[SchedulerPlacement]
@@ -448,7 +448,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
448
448
  batch_max_size: Optional[int] = None,
449
449
  batch_wait_ms: Optional[int] = None,
450
450
  container_idle_timeout: Optional[int] = None,
451
- cpu: Optional[float] = None,
451
+ cpu: Optional[Union[float, tuple[float, float]]] = None,
452
452
  keep_warm: Optional[int] = None, # keep_warm=True is equivalent to keep_warm=1
453
453
  cloud: Optional[str] = None,
454
454
  scheduler_placement: Optional[SchedulerPlacement] = None,
modal/functions.pyi CHANGED
@@ -96,7 +96,7 @@ class _FunctionSpec:
96
96
  ]
97
97
  gpus: typing.Union[None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]]
98
98
  cloud: typing.Optional[str]
99
- cpu: typing.Optional[float]
99
+ cpu: typing.Union[float, tuple[float, float], None]
100
100
  memory: typing.Union[int, tuple[int, int], None]
101
101
  ephemeral_disk: typing.Optional[int]
102
102
  scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement]
@@ -117,7 +117,7 @@ class _FunctionSpec:
117
117
  None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]
118
118
  ],
119
119
  cloud: typing.Optional[str],
120
- cpu: typing.Optional[float],
120
+ cpu: typing.Union[float, tuple[float, float], None],
121
121
  memory: typing.Union[int, tuple[int, int], None],
122
122
  ephemeral_disk: typing.Optional[int],
123
123
  scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement],
@@ -180,7 +180,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.
180
180
  batch_max_size: typing.Optional[int] = None,
181
181
  batch_wait_ms: typing.Optional[int] = None,
182
182
  container_idle_timeout: typing.Optional[int] = None,
183
- cpu: typing.Optional[float] = None,
183
+ cpu: typing.Union[float, tuple[float, float], None] = None,
184
184
  keep_warm: typing.Optional[int] = None,
185
185
  cloud: typing.Optional[str] = None,
186
186
  scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
@@ -348,7 +348,7 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
348
348
  batch_max_size: typing.Optional[int] = None,
349
349
  batch_wait_ms: typing.Optional[int] = None,
350
350
  container_idle_timeout: typing.Optional[int] = None,
351
- cpu: typing.Optional[float] = None,
351
+ cpu: typing.Union[float, tuple[float, float], None] = None,
352
352
  keep_warm: typing.Optional[int] = None,
353
353
  cloud: typing.Optional[str] = None,
354
354
  scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
@@ -455,11 +455,11 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
455
455
 
456
456
  _call_generator_nowait: ___call_generator_nowait_spec
457
457
 
458
- class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
458
+ class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
459
459
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
460
460
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
461
461
 
462
- remote: __remote_spec[ReturnType, P]
462
+ remote: __remote_spec[P, ReturnType]
463
463
 
464
464
  class __remote_gen_spec(typing_extensions.Protocol):
465
465
  def __call__(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
@@ -471,17 +471,17 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
471
471
  def _get_obj(self) -> typing.Optional[modal.cls.Obj]: ...
472
472
  def local(self, *args: P.args, **kwargs: P.kwargs) -> OriginalReturnType: ...
473
473
 
474
- class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
474
+ class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
475
475
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
476
476
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
477
477
 
478
- _experimental_spawn: ___experimental_spawn_spec[ReturnType, P]
478
+ _experimental_spawn: ___experimental_spawn_spec[P, ReturnType]
479
479
 
480
- class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
480
+ class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
481
481
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
482
482
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
483
483
 
484
- spawn: __spawn_spec[ReturnType, P]
484
+ spawn: __spawn_spec[P, ReturnType]
485
485
 
486
486
  def get_raw_f(self) -> typing.Callable[..., typing.Any]: ...
487
487
 
modal/io_streams.py CHANGED
@@ -184,7 +184,7 @@ class _StreamReader(Generic[T]):
184
184
 
185
185
  async for message in iterator:
186
186
  if self._stream_type == StreamType.STDOUT and message:
187
- print(message, end="")
187
+ print(message.decode("utf-8"), end="")
188
188
  elif self._stream_type == StreamType.PIPE:
189
189
  self._container_process_buffer.append(message)
190
190
  if message is None:
@@ -221,6 +221,12 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
221
221
  resp = await retry_transient_errors(client.stub.SharedVolumeGetOrCreate, request)
222
222
  return resp.shared_volume_id
223
223
 
224
+ @staticmethod
225
+ async def delete(label: str, client: Optional[_Client] = None, environment_name: Optional[str] = None):
226
+ obj = await _NetworkFileSystem.lookup(label, client=client, environment_name=environment_name)
227
+ req = api_pb2.SharedVolumeDeleteRequest(shared_volume_id=obj.object_id)
228
+ await retry_transient_errors(obj._client.stub.SharedVolumeDelete, req)
229
+
224
230
  @live_method
225
231
  async def write_file(self, remote_path: str, fp: BinaryIO, progress_cb: Optional[Callable[..., Any]] = None) -> int:
226
232
  """Write from a file object to a path on the network file system, atomically.
@@ -41,6 +41,10 @@ class _NetworkFileSystem(modal.object._Object):
41
41
  client: typing.Optional[modal.client._Client] = None,
42
42
  environment_name: typing.Optional[str] = None,
43
43
  ) -> str: ...
44
+ @staticmethod
45
+ async def delete(
46
+ label: str, client: typing.Optional[modal.client._Client] = None, environment_name: typing.Optional[str] = None
47
+ ): ...
44
48
  async def write_file(
45
49
  self,
46
50
  remote_path: str,
@@ -118,6 +122,22 @@ class NetworkFileSystem(modal.object.Object):
118
122
 
119
123
  create_deployed: __create_deployed_spec
120
124
 
125
+ class __delete_spec(typing_extensions.Protocol):
126
+ def __call__(
127
+ self,
128
+ label: str,
129
+ client: typing.Optional[modal.client.Client] = None,
130
+ environment_name: typing.Optional[str] = None,
131
+ ): ...
132
+ async def aio(
133
+ self,
134
+ label: str,
135
+ client: typing.Optional[modal.client.Client] = None,
136
+ environment_name: typing.Optional[str] = None,
137
+ ): ...
138
+
139
+ delete: __delete_spec
140
+
121
141
  class __write_file_spec(typing_extensions.Protocol):
122
142
  def __call__(
123
143
  self,
modal/sandbox.py CHANGED
@@ -21,7 +21,7 @@ from ._utils.mount_utils import validate_network_file_systems, validate_volumes
21
21
  from .client import _Client
22
22
  from .config import config
23
23
  from .container_process import _ContainerProcess
24
- from .exception import InvalidError, SandboxTerminatedError, SandboxTimeoutError, deprecation_warning
24
+ from .exception import ExecutionError, InvalidError, SandboxTerminatedError, SandboxTimeoutError, deprecation_warning
25
25
  from .gpu import GPU_T
26
26
  from .image import _Image
27
27
  from .io_streams import StreamReader, StreamWriter, _StreamReader, _StreamWriter
@@ -196,7 +196,10 @@ class _Sandbox(_Object, type_prefix="sb"):
196
196
  gpu: GPU_T = None,
197
197
  cloud: Optional[str] = None,
198
198
  region: Optional[Union[str, Sequence[str]]] = None, # Region or regions to run the sandbox on.
199
- cpu: Optional[float] = None, # How many CPU cores to request. This is a soft limit.
199
+ # Specify, in fractional CPU cores, how many CPU cores to request.
200
+ # Or, pass (request, limit) to additionally specify a hard limit in fractional CPU cores.
201
+ # CPU throttling will prevent a container from exceeding its specified limit.
202
+ cpu: Optional[Union[float, tuple[float, float]]] = None,
200
203
  # Specify, in MiB, a memory request which is the minimum memory required.
201
204
  # Or, pass (request, limit) to additionally specify a hard limit in MiB.
202
205
  memory: Optional[Union[int, tuple[int, int]]] = None,
@@ -331,6 +334,29 @@ class _Sandbox(_Object, type_prefix="sb"):
331
334
  except GRPCError as exc:
332
335
  raise InvalidError(exc.message) if exc.status == Status.INVALID_ARGUMENT else exc
333
336
 
337
+ async def snapshot_filesystem(self, timeout: int = 55) -> _Image:
338
+ """Snapshot the filesystem of the Sandbox.
339
+
340
+ Returns an [`Image`](https://modal.com/docs/reference/modal.Image) object which
341
+ can be used to spawn a new Sandbox with the same filesystem.
342
+ """
343
+ req = api_pb2.SandboxSnapshotFsRequest(sandbox_id=self.object_id, timeout=timeout)
344
+ resp = await retry_transient_errors(self._client.stub.SandboxSnapshotFs, req)
345
+
346
+ if resp.result.status != api_pb2.GenericResult.GENERIC_STATUS_SUCCESS:
347
+ raise ExecutionError(resp.result.exception)
348
+
349
+ image_id = resp.image_id
350
+ metadata = resp.image_metadata
351
+
352
+ async def _load(self: _Image, resolver: Resolver, existing_object_id: Optional[str]):
353
+ self._hydrate(image_id, resolver.client, metadata)
354
+
355
+ rep = "Image()"
356
+ image = _Image._from_loader(_load, rep)
357
+
358
+ return image
359
+
334
360
  # Live handle methods
335
361
 
336
362
  async def wait(self, raise_on_termination: bool = True):
@@ -481,17 +507,16 @@ class _Sandbox(_Object, type_prefix="sb"):
481
507
  await secret.resolve(client=self._client)
482
508
 
483
509
  task_id = await self._get_task_id()
484
- resp = await self._client.stub.ContainerExec(
485
- api_pb2.ContainerExecRequest(
486
- task_id=task_id,
487
- command=cmds,
488
- pty_info=_pty_info or pty_info,
489
- runtime_debug=config.get("function_runtime_debug"),
490
- timeout_secs=timeout or 0,
491
- workdir=workdir,
492
- secret_ids=[secret.object_id for secret in secrets],
493
- )
510
+ req = api_pb2.ContainerExecRequest(
511
+ task_id=task_id,
512
+ command=cmds,
513
+ pty_info=_pty_info or pty_info,
514
+ runtime_debug=config.get("function_runtime_debug"),
515
+ timeout_secs=timeout or 0,
516
+ workdir=workdir,
517
+ secret_ids=[secret.object_id for secret in secrets],
494
518
  )
519
+ resp = await retry_transient_errors(self._client.stub.ContainerExec, req)
495
520
  by_line = bufsize == 1
496
521
  return _ContainerProcess(resp.exec_id, self._client, stdout=stdout, stderr=stderr, text=text, by_line=by_line)
497
522
 
modal/sandbox.pyi CHANGED
@@ -69,7 +69,7 @@ class _Sandbox(modal.object._Object):
69
69
  gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
70
70
  cloud: typing.Optional[str] = None,
71
71
  region: typing.Union[str, collections.abc.Sequence[str], None] = None,
72
- cpu: typing.Optional[float] = None,
72
+ cpu: typing.Union[float, tuple[float, float], None] = None,
73
73
  memory: typing.Union[int, tuple[int, int], None] = None,
74
74
  block_network: bool = False,
75
75
  cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
@@ -88,6 +88,7 @@ class _Sandbox(modal.object._Object):
88
88
  @staticmethod
89
89
  async def from_id(sandbox_id: str, client: typing.Optional[modal.client._Client] = None) -> _Sandbox: ...
90
90
  async def set_tags(self, tags: dict[str, str], *, client: typing.Optional[modal.client._Client] = None): ...
91
+ async def snapshot_filesystem(self, timeout: int = 55) -> modal.image._Image: ...
91
92
  async def wait(self, raise_on_termination: bool = True): ...
92
93
  async def tunnels(self, timeout: int = 50) -> dict[int, modal._tunnel.Tunnel]: ...
93
94
  async def terminate(self): ...
@@ -189,7 +190,7 @@ class Sandbox(modal.object.Object):
189
190
  gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
190
191
  cloud: typing.Optional[str] = None,
191
192
  region: typing.Union[str, collections.abc.Sequence[str], None] = None,
192
- cpu: typing.Optional[float] = None,
193
+ cpu: typing.Union[float, tuple[float, float], None] = None,
193
194
  memory: typing.Union[int, tuple[int, int], None] = None,
194
195
  block_network: bool = False,
195
196
  cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
@@ -220,7 +221,7 @@ class Sandbox(modal.object.Object):
220
221
  gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
221
222
  cloud: typing.Optional[str] = None,
222
223
  region: typing.Union[str, collections.abc.Sequence[str], None] = None,
223
- cpu: typing.Optional[float] = None,
224
+ cpu: typing.Union[float, tuple[float, float], None] = None,
224
225
  memory: typing.Union[int, tuple[int, int], None] = None,
225
226
  block_network: bool = False,
226
227
  cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
@@ -252,6 +253,12 @@ class Sandbox(modal.object.Object):
252
253
 
253
254
  set_tags: __set_tags_spec
254
255
 
256
+ class __snapshot_filesystem_spec(typing_extensions.Protocol):
257
+ def __call__(self, timeout: int = 55) -> modal.image.Image: ...
258
+ async def aio(self, timeout: int = 55) -> modal.image.Image: ...
259
+
260
+ snapshot_filesystem: __snapshot_filesystem_spec
261
+
255
262
  class __wait_spec(typing_extensions.Protocol):
256
263
  def __call__(self, raise_on_termination: bool = True): ...
257
264
  async def aio(self, raise_on_termination: bool = True): ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modal
3
- Version: 0.67.34
3
+ Version: 0.67.40
4
4
  Summary: Python client library for Modal
5
5
  Author: Modal Labs
6
6
  Author-email: support@modal.com
@@ -18,8 +18,8 @@ modal/_watcher.py,sha256=K6LYnlmSGQB4tWWI9JADv-tvSvQ1j522FwT71B51CX8,3584
18
18
  modal/app.py,sha256=EJ7FUN6rWnSwLJoYJh8nmKg_t-8hdN8_rt0OrkP7JvQ,46084
19
19
  modal/app.pyi,sha256=BE5SlR5tRECuc6-e2lUuOknDdov3zxgZ4N0AsLb5ZVQ,25270
20
20
  modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
21
- modal/client.py,sha256=VMg_aIuo_LOEe2ttxBHEND3PLhTp5lo-onH4wELhIyY,16375
22
- modal/client.pyi,sha256=MIQCWtk0sw8R_KRsF36u4-L5yZzTghMH8BCmRjWlvxM,7354
21
+ modal/client.py,sha256=cmylZhU35txmrx4nltNYuuqXRgeoMtm0ow1J9wJkEYQ,16400
22
+ modal/client.pyi,sha256=4S85O-xfVK3PbxZndQ8LworEUAZWNQrse4vbwA9UU3E,7354
23
23
  modal/cloud_bucket_mount.py,sha256=G7T7jWLD0QkmrfKR75mSTwdUZ2xNfj7pkVqb4ipmxmI,5735
24
24
  modal/cloud_bucket_mount.pyi,sha256=CEi7vrH3kDUF4LAy4qP6tfImy2UJuFRcRbsgRNM1wo8,1403
25
25
  modal/cls.py,sha256=OJqzj_V-n1g48BY_4Jg_BOTQdftEEl4kTWN0X4FOOdg,27378
@@ -33,17 +33,17 @@ modal/environments.py,sha256=5cgA-zbm6ngKLsRA19zSOgtgo9-BarJK3FJK0BiF2Lo,6505
33
33
  modal/environments.pyi,sha256=XalNpiPkAtHWAvOU2Cotq0ozmtl-Jv0FDsR8h9mr27Q,3521
34
34
  modal/exception.py,sha256=EBkdWVved2XEPsXaoPRu56xfxFFHL9iuqvUsdj42WDA,6392
35
35
  modal/experimental.py,sha256=jFuNbwrNHos47viMB9q-cHJSvf2RDxDdoEcss9plaZE,2302
36
- modal/functions.py,sha256=Lteg8dMa8ly72-RM1ozxeGQ500pdeFyJgtflVwp3U7Q,66629
37
- modal/functions.pyi,sha256=DXodybnhZ4kD0CAFmQXRTv6FhcsHIgZ5TT_rInG3xDo,24892
36
+ modal/functions.py,sha256=3GjjFbf40XciWAa4rTmh0erkZjPzRjKHqWxUu91mHOU,66685
37
+ modal/functions.pyi,sha256=IyuM9TV79JfrtfTaJ4yq3EcWp3yHuxLavpxTOwSWEDw,24988
38
38
  modal/gpu.py,sha256=r4rL6uH3UJIQthzYvfWauXNyh01WqCPtKZCmmSX1fd4,6881
39
39
  modal/image.py,sha256=cQ6WP1xHXZT_nY8z3aEFiGwKzrTV0yxi3Ab8JzF91eo,79653
40
40
  modal/image.pyi,sha256=PIKH6JBA4L5TfdJrQu3pm2ykyIITmiP920TpP8cdyQA,24585
41
- modal/io_streams.py,sha256=YfKAlWQAxzPCHE0-wVlAlX5vldrpfKMdr9ggL0c5VJo,15063
41
+ modal/io_streams.py,sha256=QkQiizKRzd5bnbKQsap31LJgBYlAnj4-XkV_50xPYX0,15079
42
42
  modal/io_streams.pyi,sha256=bCCVSxkMcosYd8O3PQDDwJw7TQ8JEcnYonLJ5t27TQs,4804
43
43
  modal/mount.py,sha256=liaid5p42o0OKnzoocJJ_oCovDVderk3-JuCTa5pqtA,27656
44
44
  modal/mount.pyi,sha256=3e4nkXUeeVmUmOyK8Tiyk_EQlHeWruN3yGJVnmDUVrI,9761
45
- modal/network_file_system.py,sha256=mwtYp25XtFaiGpSG7U0KSkiTzJWrxgGTcoxfPZ9yGR0,14141
46
- modal/network_file_system.pyi,sha256=kRqK-n8FxZfyboV3MQuaH40RqAeBU2VA2WfZrhj4hwk,7242
45
+ modal/network_file_system.py,sha256=NKZgh_p8MyJyyJgP92lhRgTmwA3kOPw7m8AbYlchhCE,14530
46
+ modal/network_file_system.pyi,sha256=8mHKXuRkxHPazF6ljIW7g4M5aVqLSl6eKUPLgDCug5c,7901
47
47
  modal/object.py,sha256=KmtWRDd5ntHGSO9ASHe9MJcIgjNRqaDXGc3rWOXwrmA,9646
48
48
  modal/object.pyi,sha256=MO78H9yFSE5i1gExPEwyyQzLdlshkcGHN1aQ0ylyvq0,8802
49
49
  modal/output.py,sha256=N0xf4qeudEaYrslzdAl35VKV8rapstgIM2e9wO8_iy0,1967
@@ -60,8 +60,8 @@ modal/retries.py,sha256=HKR2Q9aNPWkMjQ5nwobqYTuZaSuw0a8lI2zrtY5IW98,5230
60
60
  modal/runner.py,sha256=7obU-Gq1ocpBGCuR6pvn1T-D6ggg1T48qFo2TNUGWkU,24089
61
61
  modal/runner.pyi,sha256=RAtCvx_lXWjyFjIaZ3t9-X1c7rqpgAQlhl4Hww53OY8,5038
62
62
  modal/running_app.py,sha256=CshNvGDJtagOdKW54uYjY8HY73j2TpnsL9jkPFZAsfA,560
63
- modal/sandbox.py,sha256=25DvTWSgClANvk67HM3FHukRVLig_Fw_aQC1BLMCRhs,25150
64
- modal/sandbox.pyi,sha256=JRh6Q-WdY6GgVSOGm0L_pgo5bfsi2UacsZezpT0-cDU,17685
63
+ modal/sandbox.py,sha256=ua2z6aV_fBE_7hSCv9vcRp4U9j6lRE9uOrcen4LEJks,26316
64
+ modal/sandbox.pyi,sha256=fRl32Pt5F6TbK7aYewjlcL4WQxxmp7m6Ybktmkd2VOk,18108
65
65
  modal/schedule.py,sha256=0ZFpKs1bOxeo5n3HZjoL7OE2ktsb-_oGtq-WJEPO4tY,2615
66
66
  modal/scheduler_placement.py,sha256=BAREdOY5HzHpzSBqt6jDVR6YC_jYfHMVqOzkyqQfngU,1235
67
67
  modal/secret.py,sha256=Y1WgybQIkfkxdzH9CQ1h-Wd1DJJpzipigMhyyvSxTww,10007
@@ -75,7 +75,7 @@ modal/volume.py,sha256=IISuMeXq9MoSkhXg8Q6JG0F-2n9NTkWk0xGuJB8l3d8,29159
75
75
  modal/volume.pyi,sha256=St0mDiaojfep6Bs4sBbkRJmeacYHF6lh6FKOWGmheHA,11182
76
76
  modal/_runtime/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
77
77
  modal/_runtime/asgi.py,sha256=GvuxZqWnIHMIR-Bx5f7toCQlkERaJO8CHjTPNM9IFIw,21537
78
- modal/_runtime/container_io_manager.py,sha256=yVKSBBybfciDaady7NxOPVU5cm9qL690OgdZ4dZN1bs,44134
78
+ modal/_runtime/container_io_manager.py,sha256=8NyX5uuwmHEJgxMwdoY9PpEO-IHA8LGdYdbdHLIafK8,44131
79
79
  modal/_runtime/execution_context.py,sha256=E6ofm6j1POXGPxS841X3V7JU6NheVb8OkQc7JpLq4Kg,2712
80
80
  modal/_runtime/telemetry.py,sha256=T1RoAGyjBDr1swiM6pPsGRSITm7LI5FDK18oNXxY08U,5163
81
81
  modal/_runtime/user_code_imports.py,sha256=q_3JOYqCPDcVFZWCHEjyEqj8yzdFsQ49HzeqYmFDLbk,14521
@@ -101,8 +101,8 @@ modal/_vendor/cloudpickle.py,sha256=Loq12qo7PBNbE4LFVEW6BdMMwY10MG94EOW1SCpcnQ0,
101
101
  modal/_vendor/tblib.py,sha256=g1O7QUDd3sDoLd8YPFltkXkih7r_fyZOjgmGuligv3s,9722
102
102
  modal/cli/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
103
103
  modal/cli/_download.py,sha256=t6BXZwjTd9MgznDvbsV8rp0FZWggdzC-lUAGZU4xx1g,3984
104
- modal/cli/_traceback.py,sha256=WRs24CaEY1VW2tx8d4JZLipeTXe9YprQiPX8OmCAAP8,6936
105
- modal/cli/app.py,sha256=RtiZhHjg-9lAQV2goKqALnK44xuBbUkapnBBaoQdZ04,7717
104
+ modal/cli/_traceback.py,sha256=Tm0g4V_fr4XAlmuh_4MNgZKtjJly9wsWtnKKvOJFM7Q,7130
105
+ modal/cli/app.py,sha256=KOU3tKdcw50612rmN2LmO-N8cT1M1-UgLs7tw68Kgds,7717
106
106
  modal/cli/config.py,sha256=pXPLmX0bIoV57rQNqIPK7V-yllj-GPRY4jiBO_EklGg,1667
107
107
  modal/cli/container.py,sha256=lRSrxnl7bTLLW9T6hzkqOxqFzzV9qHyXPOuOHY8zkc4,3194
108
108
  modal/cli/dict.py,sha256=gwX4ZBsrr0dpWf_B5_5GN_ealcVzpcGyvY24dEY4y3Y,4455
@@ -110,7 +110,7 @@ modal/cli/entry_point.py,sha256=aaNxFAqZcmtSjwzkYIA_Ba9CkL4cL4_i2gy5VjoXxkM,4228
110
110
  modal/cli/environment.py,sha256=Ayddkiq9jdj3XYDJ8ZmUqFpPPH8xajYlbexRkzGtUcg,4334
111
111
  modal/cli/import_refs.py,sha256=wnqE5AMeyAN3IZmQvJCp54KRnJh8Nq_5fMqB6u6GEL8,9147
112
112
  modal/cli/launch.py,sha256=uyI-ouGvYRjHLGxGQ2lYBZq32BiRT1i0L8ksz5iy7K8,2935
113
- modal/cli/network_file_system.py,sha256=tDwTJ3LP2H5TP-SkHlRFnsP3Zsk7XEeRF_Hxej5jViM,7528
113
+ modal/cli/network_file_system.py,sha256=3QbAxKEoRc6RCMsYE3OS-GcuiI4GMkz_wAKsIBbN1qg,8186
114
114
  modal/cli/profile.py,sha256=rLXfjJObfPNjaZvNfHGIKqs7y9bGYyGe-K7V0w-Ni0M,3110
115
115
  modal/cli/queues.py,sha256=MIh2OsliNE2QeL1erubfsRsNuG4fxqcqWA2vgIfQ4Mg,4494
116
116
  modal/cli/run.py,sha256=IPA5Hx7HqCE01NilPZDh1fFaslO4QZa-RKEpMPqjLqA,17066
@@ -159,10 +159,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
159
159
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
160
160
  modal_version/__init__.py,sha256=3IY-AWLH55r35_mQXIaut0jrJvoPuf1NZJBQQfSbPuo,470
161
161
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
162
- modal_version/_version_generated.py,sha256=X3LELCBR6W9zyy2SL-uYl9U3bdvXGKCVczJW3X8d0dk,149
163
- modal-0.67.34.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
164
- modal-0.67.34.dist-info/METADATA,sha256=Vz-3Hlgpk05yFgUgdlOUUIMauxzV04BpPaZTXy5Acqc,2329
165
- modal-0.67.34.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
166
- modal-0.67.34.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
167
- modal-0.67.34.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
168
- modal-0.67.34.dist-info/RECORD,,
162
+ modal_version/_version_generated.py,sha256=5gLMLY-cYu0FT5xTjYMlRGB5AwCo0WwwtxIwDntd8t0,149
163
+ modal-0.67.40.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
164
+ modal-0.67.40.dist-info/METADATA,sha256=uIBq5XeGQA9EgjAJY_75cg1J-jpSZb34icpK7S96g_8,2329
165
+ modal-0.67.40.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
166
+ modal-0.67.40.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
167
+ modal-0.67.40.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
168
+ modal-0.67.40.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2024
2
2
 
3
3
  # Note: Reset this value to -1 whenever you make a minor `0.X` release of the client.
4
- build_number = 34 # git: e9b06f1
4
+ build_number = 40 # git: c83a119