modal 1.0.0.dev16__py3-none-any.whl → 1.0.0.dev18__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/__init__.py CHANGED
@@ -20,7 +20,6 @@ try:
20
20
  from .file_pattern_matcher import FilePatternMatcher
21
21
  from .functions import Function, FunctionCall
22
22
  from .image import Image
23
- from .mount import Mount
24
23
  from .network_file_system import NetworkFileSystem
25
24
  from .output import enable_output
26
25
  from .partial_function import (
@@ -67,7 +66,6 @@ __all__ = [
67
66
  "Function",
68
67
  "FunctionCall",
69
68
  "Image",
70
- "Mount",
71
69
  "NetworkFileSystem",
72
70
  "Period",
73
71
  "Proxy",
modal/_functions.py CHANGED
@@ -6,7 +6,7 @@ import textwrap
6
6
  import time
7
7
  import typing
8
8
  import warnings
9
- from collections.abc import AsyncGenerator, Collection, Sequence, Sized
9
+ from collections.abc import AsyncGenerator, Sequence, Sized
10
10
  from dataclasses import dataclass
11
11
  from pathlib import PurePosixPath
12
12
  from typing import TYPE_CHECKING, Any, Callable, Optional, Union
@@ -99,6 +99,8 @@ if TYPE_CHECKING:
99
99
  import modal.cls
100
100
  import modal.partial_function
101
101
 
102
+ MAX_INTERNAL_FAILURE_COUNT = 100
103
+
102
104
 
103
105
  @dataclasses.dataclass
104
106
  class _RetryContext:
@@ -348,10 +350,14 @@ class _InputPlaneInvocation:
348
350
  stub: ModalClientModal,
349
351
  attempt_token: str,
350
352
  client: _Client,
353
+ input_item: api_pb2.FunctionPutInputsItem,
354
+ function_id: str,
351
355
  ):
352
356
  self.stub = stub
353
357
  self.client = client # Used by the deserializer.
354
358
  self.attempt_token = attempt_token
359
+ self.input_item = input_item
360
+ self.function_id = function_id
355
361
 
356
362
  @staticmethod
357
363
  async def create(
@@ -365,36 +371,53 @@ class _InputPlaneInvocation:
365
371
  stub = await client.get_stub(input_plane_url)
366
372
 
367
373
  function_id = function.object_id
368
- item = await _create_input(args, kwargs, stub, method_name=function._use_method_name)
374
+ input_item = await _create_input(args, kwargs, stub, method_name=function._use_method_name)
369
375
 
370
376
  request = api_pb2.AttemptStartRequest(
371
377
  function_id=function_id,
372
378
  parent_input_id=current_input_id() or "",
373
- input=item,
379
+ input=input_item,
374
380
  )
375
381
  response = await retry_transient_errors(stub.AttemptStart, request)
376
382
  attempt_token = response.attempt_token
377
383
 
378
- return _InputPlaneInvocation(stub, attempt_token, client)
384
+ return _InputPlaneInvocation(stub, attempt_token, client, input_item, function_id)
379
385
 
380
386
  async def run_function(self) -> Any:
381
- # TODO(nathan): add retry logic
387
+ # This will retry when the server returns GENERIC_STATUS_INTERNAL_FAILURE, i.e. lost inputs or worker preemption
388
+ # TODO(ryan): add logic to retry for user defined
389
+ internal_failure_count = 0
382
390
  while True:
383
- request = api_pb2.AttemptAwaitRequest(
391
+ await_request = api_pb2.AttemptAwaitRequest(
384
392
  attempt_token=self.attempt_token,
385
393
  timeout_secs=OUTPUTS_TIMEOUT,
386
394
  requested_at=time.time(),
387
395
  )
388
- response: api_pb2.AttemptAwaitResponse = await retry_transient_errors(
396
+ await_response: api_pb2.AttemptAwaitResponse = await retry_transient_errors(
389
397
  self.stub.AttemptAwait,
390
- request,
398
+ await_request,
391
399
  attempt_timeout=OUTPUTS_TIMEOUT + ATTEMPT_TIMEOUT_GRACE_PERIOD,
392
400
  )
393
401
 
394
- if response.HasField("output"):
402
+ try:
395
403
  return await _process_result(
396
- response.output.result, response.output.data_format, self.stub, self.client
404
+ await_response.output.result, await_response.output.data_format, self.stub, self.client
397
405
  )
406
+ except InternalFailure as e:
407
+ internal_failure_count += 1
408
+ # Limit the number of times we retry
409
+ if internal_failure_count >= MAX_INTERNAL_FAILURE_COUNT:
410
+ raise e
411
+ # For system failures on the server, we retry immediately,
412
+ # and the failure does not count towards the retry policy.
413
+ retry_request = api_pb2.AttemptRetryRequest(
414
+ function_id=self.function_id,
415
+ parent_input_id=current_input_id() or "",
416
+ input=self.input_item,
417
+ attempt_token=self.attempt_token,
418
+ )
419
+ retry_response = await retry_transient_errors(self.stub.AttemptRetry, retry_request)
420
+ self.attempt_token = retry_response.attempt_token
398
421
 
399
422
 
400
423
  # Wrapper type for api_pb2.FunctionStats
@@ -505,7 +528,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
505
528
  is_generator: bool = False,
506
529
  gpu: Union[GPU_T, list[GPU_T]] = None,
507
530
  # TODO: maybe break this out into a separate decorator for notebooks.
508
- mounts: Collection[_Mount] = (),
509
531
  network_file_systems: dict[Union[str, PurePosixPath], _NetworkFileSystem] = {},
510
532
  volumes: dict[Union[str, PurePosixPath], Union[_Volume, _CloudBucketMount]] = {},
511
533
  webhook_config: Optional[api_pb2.WebhookConfig] = None,
@@ -561,8 +583,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
561
583
  assert not webhook_config
562
584
  assert not schedule
563
585
 
564
- explicit_mounts = mounts
565
-
566
586
  include_source_mode = get_include_source_mode(include_source)
567
587
  if include_source_mode != IncludeSourceMode.INCLUDE_NOTHING:
568
588
  entrypoint_mounts = info.get_entrypoint_mount()
@@ -571,7 +591,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
571
591
 
572
592
  all_mounts = [
573
593
  _get_client_mount(),
574
- *explicit_mounts,
575
594
  *entrypoint_mounts.values(),
576
595
  ]
577
596
 
@@ -611,7 +630,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
611
630
  image=image,
612
631
  secrets=secrets,
613
632
  gpu=gpu,
614
- mounts=mounts,
615
633
  network_file_systems=network_file_systems,
616
634
  volumes=volumes,
617
635
  memory=memory,
@@ -719,16 +737,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
719
737
 
720
738
  def _deps(only_explicit_mounts=False) -> list[_Object]:
721
739
  deps: list[_Object] = list(secrets)
722
- if only_explicit_mounts:
723
- # TODO: this is a bit hacky, but all_mounts may differ in the container vs locally
724
- # We don't want the function dependencies to change, so we have this way to force it to
725
- # only include its declared dependencies.
726
- # Only objects that need interaction within a user's container actually need to be
727
- # included when only_explicit_mounts=True, so omitting auto mounts here
728
- # wouldn't be a problem as long as Mounts are "passive" and only loaded by the
729
- # worker runtime
730
- deps += list(explicit_mounts)
731
- else:
740
+ if not only_explicit_mounts:
732
741
  deps += list(all_mounts)
733
742
  if proxy:
734
743
  deps.append(proxy)
@@ -996,7 +1005,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
996
1005
  obj._build_args = dict( # See get_build_def
997
1006
  secrets=repr(secrets),
998
1007
  gpu_config=repr([parse_gpu_config(_gpu) for _gpu in gpus]),
999
- mounts=repr(mounts),
1000
1008
  network_file_systems=repr(network_file_systems),
1001
1009
  )
1002
1010
  # these key are excluded if empty to avoid rebuilds on client upgrade
@@ -466,7 +466,10 @@ async def _process_result(result: api_pb2.GenericResult, data_format: int, stub,
466
466
 
467
467
  if result.status == api_pb2.GenericResult.GENERIC_STATUS_TIMEOUT:
468
468
  raise FunctionTimeoutError(result.exception)
469
- elif result.status == api_pb2.GenericResult.GENERIC_STATUS_INTERNAL_FAILURE:
469
+ elif result.status in [
470
+ api_pb2.GenericResult.GENERIC_STATUS_INTERNAL_FAILURE,
471
+ api_pb2.GenericResult.GENERIC_STATUS_TERMINATED,
472
+ ]:
470
473
  raise InternalFailure(result.exception)
471
474
  elif result.status != api_pb2.GenericResult.GENERIC_STATUS_SUCCESS:
472
475
  if data:
modal/app.py CHANGED
@@ -44,7 +44,6 @@ from .exception import ExecutionError, InvalidError
44
44
  from .functions import Function
45
45
  from .gpu import GPU_T
46
46
  from .image import _Image
47
- from .mount import _Mount
48
47
  from .network_file_system import _NetworkFileSystem
49
48
  from .partial_function import PartialFunction
50
49
  from .proxy import _Proxy
@@ -156,7 +155,6 @@ class _App:
156
155
  _classes: dict[str, _Cls]
157
156
 
158
157
  _image: Optional[_Image]
159
- _mounts: Sequence[_Mount]
160
158
  _secrets: Sequence[_Secret]
161
159
  _volumes: dict[Union[str, PurePosixPath], _Volume]
162
160
  _web_endpoints: list[str] # Used by the CLI
@@ -174,7 +172,6 @@ class _App:
174
172
  name: Optional[str] = None,
175
173
  *,
176
174
  image: Optional[_Image] = None, # default image for all functions (default is `modal.Image.debian_slim()`)
177
- mounts: Sequence[_Mount] = [], # default mounts for all functions
178
175
  secrets: Sequence[_Secret] = [], # default secrets for all functions
179
176
  volumes: dict[Union[str, PurePosixPath], _Volume] = {}, # default volumes for all functions
180
177
  include_source: Optional[bool] = None,
@@ -195,7 +192,6 @@ class _App:
195
192
  self._description = name
196
193
  self._include_source_default = include_source
197
194
 
198
- check_sequence(mounts, _Mount, "`mounts=` has to be a list or tuple of `modal.Mount` objects")
199
195
  check_sequence(secrets, _Secret, "`secrets=` has to be a list or tuple of `modal.Secret` objects")
200
196
  validate_volumes(volumes)
201
197
 
@@ -205,7 +201,6 @@ class _App:
205
201
  self._functions = {}
206
202
  self._classes = {}
207
203
  self._image = image
208
- self._mounts = mounts
209
204
  self._secrets = secrets
210
205
  self._volumes = volumes
211
206
  self._local_entrypoints = {}
@@ -446,9 +441,7 @@ class _App:
446
441
  if not self._running_app:
447
442
  raise ExecutionError("`_get_watch_mounts` requires a running app.")
448
443
 
449
- all_mounts = [
450
- *self._mounts,
451
- ]
444
+ all_mounts = []
452
445
  for function in self.registered_functions.values():
453
446
  all_mounts.extend(function._serve_mounts)
454
447
 
@@ -612,7 +605,6 @@ class _App:
612
605
  GPU_T, list[GPU_T]
613
606
  ] = None, # GPU request as string ("any", "T4", ...), object (`modal.GPU.A100()`, ...), or a list of either
614
607
  serialized: bool = False, # Whether to send the function over using cloudpickle.
615
- mounts: Sequence[_Mount] = (), # Modal Mounts added to the container
616
608
  network_file_systems: dict[
617
609
  Union[str, PurePosixPath], _NetworkFileSystem
618
610
  ] = {}, # Mountpoints for Modal NetworkFileSystems
@@ -792,7 +784,6 @@ class _App:
792
784
  schedule=schedule,
793
785
  is_generator=is_generator,
794
786
  gpu=gpu,
795
- mounts=[*self._mounts, *mounts],
796
787
  network_file_systems=network_file_systems,
797
788
  volumes={**self._volumes, **volumes},
798
789
  cpu=cpu,
@@ -843,7 +834,6 @@ class _App:
843
834
  GPU_T, list[GPU_T]
844
835
  ] = None, # GPU request as string ("any", "T4", ...), object (`modal.GPU.A100()`, ...), or a list of either
845
836
  serialized: bool = False, # Whether to send the function over using cloudpickle.
846
- mounts: Sequence[_Mount] = (),
847
837
  network_file_systems: dict[
848
838
  Union[str, PurePosixPath], _NetworkFileSystem
849
839
  ] = {}, # Mountpoints for Modal NetworkFileSystems
@@ -965,7 +955,6 @@ class _App:
965
955
  image=image or self._get_default_image(),
966
956
  secrets=[*self._secrets, *secrets],
967
957
  gpu=gpu,
968
- mounts=[*self._mounts, *mounts],
969
958
  network_file_systems=network_file_systems,
970
959
  volumes={**self._volumes, **volumes},
971
960
  cpu=cpu,
modal/app.pyi CHANGED
@@ -8,7 +8,6 @@ import modal.cls
8
8
  import modal.functions
9
9
  import modal.gpu
10
10
  import modal.image
11
- import modal.mount
12
11
  import modal.network_file_system
13
12
  import modal.partial_function
14
13
  import modal.proxy
@@ -77,7 +76,6 @@ class _App:
77
76
  _functions: dict[str, modal._functions._Function]
78
77
  _classes: dict[str, modal.cls._Cls]
79
78
  _image: typing.Optional[modal.image._Image]
80
- _mounts: collections.abc.Sequence[modal.mount._Mount]
81
79
  _secrets: collections.abc.Sequence[modal.secret._Secret]
82
80
  _volumes: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume._Volume]
83
81
  _web_endpoints: list[str]
@@ -92,7 +90,6 @@ class _App:
92
90
  name: typing.Optional[str] = None,
93
91
  *,
94
92
  image: typing.Optional[modal.image._Image] = None,
95
- mounts: collections.abc.Sequence[modal.mount._Mount] = [],
96
93
  secrets: collections.abc.Sequence[modal.secret._Secret] = [],
97
94
  volumes: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume._Volume] = {},
98
95
  include_source: typing.Optional[bool] = None,
@@ -164,7 +161,6 @@ class _App:
164
161
  secrets: collections.abc.Sequence[modal.secret._Secret] = (),
165
162
  gpu: typing.Union[None, str, modal.gpu._GPUConfig, list[typing.Union[None, str, modal.gpu._GPUConfig]]] = None,
166
163
  serialized: bool = False,
167
- mounts: collections.abc.Sequence[modal.mount._Mount] = (),
168
164
  network_file_systems: dict[
169
165
  typing.Union[str, pathlib.PurePosixPath], modal.network_file_system._NetworkFileSystem
170
166
  ] = {},
@@ -216,7 +212,6 @@ class _App:
216
212
  secrets: collections.abc.Sequence[modal.secret._Secret] = (),
217
213
  gpu: typing.Union[None, str, modal.gpu._GPUConfig, list[typing.Union[None, str, modal.gpu._GPUConfig]]] = None,
218
214
  serialized: bool = False,
219
- mounts: collections.abc.Sequence[modal.mount._Mount] = (),
220
215
  network_file_systems: dict[
221
216
  typing.Union[str, pathlib.PurePosixPath], modal.network_file_system._NetworkFileSystem
222
217
  ] = {},
@@ -272,7 +267,6 @@ class App:
272
267
  _functions: dict[str, modal.functions.Function]
273
268
  _classes: dict[str, modal.cls.Cls]
274
269
  _image: typing.Optional[modal.image.Image]
275
- _mounts: collections.abc.Sequence[modal.mount.Mount]
276
270
  _secrets: collections.abc.Sequence[modal.secret.Secret]
277
271
  _volumes: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume.Volume]
278
272
  _web_endpoints: list[str]
@@ -287,7 +281,6 @@ class App:
287
281
  name: typing.Optional[str] = None,
288
282
  *,
289
283
  image: typing.Optional[modal.image.Image] = None,
290
- mounts: collections.abc.Sequence[modal.mount.Mount] = [],
291
284
  secrets: collections.abc.Sequence[modal.secret.Secret] = [],
292
285
  volumes: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume.Volume] = {},
293
286
  include_source: typing.Optional[bool] = None,
@@ -410,7 +403,6 @@ class App:
410
403
  secrets: collections.abc.Sequence[modal.secret.Secret] = (),
411
404
  gpu: typing.Union[None, str, modal.gpu._GPUConfig, list[typing.Union[None, str, modal.gpu._GPUConfig]]] = None,
412
405
  serialized: bool = False,
413
- mounts: collections.abc.Sequence[modal.mount.Mount] = (),
414
406
  network_file_systems: dict[
415
407
  typing.Union[str, pathlib.PurePosixPath], modal.network_file_system.NetworkFileSystem
416
408
  ] = {},
@@ -462,7 +454,6 @@ class App:
462
454
  secrets: collections.abc.Sequence[modal.secret.Secret] = (),
463
455
  gpu: typing.Union[None, str, modal.gpu._GPUConfig, list[typing.Union[None, str, modal.gpu._GPUConfig]]] = None,
464
456
  serialized: bool = False,
465
- mounts: collections.abc.Sequence[modal.mount.Mount] = (),
466
457
  network_file_systems: dict[
467
458
  typing.Union[str, pathlib.PurePosixPath], modal.network_file_system.NetworkFileSystem
468
459
  ] = {},
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.0.dev16",
34
+ version: str = "1.0.0.dev18",
35
35
  ): ...
36
36
  def is_closed(self) -> bool: ...
37
37
  @property
@@ -94,7 +94,7 @@ class Client:
94
94
  server_url: str,
95
95
  client_type: int,
96
96
  credentials: typing.Optional[tuple[str, str]],
97
- version: str = "1.0.0.dev16",
97
+ version: str = "1.0.0.dev18",
98
98
  ): ...
99
99
  def is_closed(self) -> bool: ...
100
100
  @property
modal/functions.pyi CHANGED
@@ -63,7 +63,6 @@ class Function(
63
63
  schedule: typing.Optional[modal.schedule.Schedule] = None,
64
64
  is_generator: bool = False,
65
65
  gpu: typing.Union[None, str, modal.gpu._GPUConfig, list[typing.Union[None, str, modal.gpu._GPUConfig]]] = None,
66
- mounts: collections.abc.Collection[modal.mount.Mount] = (),
67
66
  network_file_systems: dict[
68
67
  typing.Union[str, pathlib.PurePosixPath], modal.network_file_system.NetworkFileSystem
69
68
  ] = {},
modal/image.py CHANGED
@@ -437,7 +437,7 @@ class _Image(_Object, type_prefix="im"):
437
437
 
438
438
  def _add_mount_layer_or_copy(self, mount: _Mount, copy: bool = False):
439
439
  if copy:
440
- return self.copy_mount(mount, remote_path="/")
440
+ return self._copy_mount(mount, remote_path="/")
441
441
 
442
442
  base_image = self
443
443
 
@@ -672,23 +672,9 @@ class _Image(_Object, type_prefix="im"):
672
672
  )
673
673
  return obj
674
674
 
675
- def copy_mount(self, mount: _Mount, remote_path: Union[str, Path] = ".") -> "_Image":
675
+ def _copy_mount(self, mount: _Mount, remote_path: Union[str, Path] = ".") -> "_Image":
676
676
  """mdmd:hidden
677
- **Deprecated**: Use image.add_local_dir(..., copy=True) or similar instead.
678
-
679
- Copy the entire contents of a `modal.Mount` into an image.
680
- Useful when files only available locally are required during the image
681
- build process.
682
-
683
- **Example**
684
-
685
- ```python notest
686
- static_images_dir = "./static"
687
- # place all static images in root of mount
688
- mount = modal.Mount.from_local_dir(static_images_dir, remote_path="/")
689
- # place mount's contents into /static directory of image.
690
- image = modal.Image.debian_slim().copy_mount(mount, remote_path="/static")
691
- ```
677
+ Internal
692
678
  """
693
679
  if not isinstance(mount, _Mount):
694
680
  raise InvalidError("The mount argument to copy has to be a Modal Mount object")
@@ -1892,7 +1878,6 @@ class _Image(_Object, type_prefix="im"):
1892
1878
  *,
1893
1879
  secrets: Sequence[_Secret] = (), # Optional Modal Secret objects with environment variables for the container
1894
1880
  gpu: Union[GPU_T, list[GPU_T]] = None, # Requested GPU or or list of acceptable GPUs( e.g. ["A10", "A100"])
1895
- mounts: Sequence[_Mount] = (), # Mounts attached to the function
1896
1881
  volumes: dict[Union[str, PurePosixPath], Union[_Volume, _CloudBucketMount]] = {}, # Volume mount paths
1897
1882
  network_file_systems: dict[Union[str, PurePosixPath], _NetworkFileSystem] = {}, # NFS mount paths
1898
1883
  cpu: Optional[float] = None, # How many CPU cores to request. This is a soft limit.
@@ -1950,7 +1935,6 @@ class _Image(_Object, type_prefix="im"):
1950
1935
  image=self, # type: ignore[reportArgumentType] # TODO: probably conflict with type stub?
1951
1936
  secrets=secrets,
1952
1937
  gpu=gpu,
1953
- mounts=mounts,
1954
1938
  volumes=volumes,
1955
1939
  network_file_systems=network_file_systems,
1956
1940
  cloud=cloud,
modal/image.pyi CHANGED
@@ -120,7 +120,7 @@ class _Image(modal._object._Object):
120
120
  _namespace: int = 1,
121
121
  _do_assert_no_mount_layers: bool = True,
122
122
  ): ...
123
- def copy_mount(self, mount: modal.mount._Mount, remote_path: typing.Union[str, pathlib.Path] = ".") -> _Image: ...
123
+ def _copy_mount(self, mount: modal.mount._Mount, remote_path: typing.Union[str, pathlib.Path] = ".") -> _Image: ...
124
124
  def add_local_file(
125
125
  self, local_path: typing.Union[str, pathlib.Path], remote_path: str, *, copy: bool = False
126
126
  ) -> _Image: ...
@@ -316,7 +316,6 @@ class _Image(modal._object._Object):
316
316
  *,
317
317
  secrets: collections.abc.Sequence[modal.secret._Secret] = (),
318
318
  gpu: typing.Union[None, str, modal.gpu._GPUConfig, list[typing.Union[None, str, modal.gpu._GPUConfig]]] = None,
319
- mounts: collections.abc.Sequence[modal.mount._Mount] = (),
320
319
  volumes: dict[
321
320
  typing.Union[str, pathlib.PurePosixPath],
322
321
  typing.Union[modal.volume._Volume, modal.cloud_bucket_mount._CloudBucketMount],
@@ -377,7 +376,7 @@ class Image(modal.object.Object):
377
376
  _namespace: int = 1,
378
377
  _do_assert_no_mount_layers: bool = True,
379
378
  ): ...
380
- def copy_mount(self, mount: modal.mount.Mount, remote_path: typing.Union[str, pathlib.Path] = ".") -> Image: ...
379
+ def _copy_mount(self, mount: modal.mount.Mount, remote_path: typing.Union[str, pathlib.Path] = ".") -> Image: ...
381
380
  def add_local_file(
382
381
  self, local_path: typing.Union[str, pathlib.Path], remote_path: str, *, copy: bool = False
383
382
  ) -> Image: ...
@@ -578,7 +577,6 @@ class Image(modal.object.Object):
578
577
  *,
579
578
  secrets: collections.abc.Sequence[modal.secret.Secret] = (),
580
579
  gpu: typing.Union[None, str, modal.gpu._GPUConfig, list[typing.Union[None, str, modal.gpu._GPUConfig]]] = None,
581
- mounts: collections.abc.Sequence[modal.mount.Mount] = (),
582
580
  volumes: dict[
583
581
  typing.Union[str, pathlib.PurePosixPath],
584
582
  typing.Union[modal.volume.Volume, modal.cloud_bucket_mount.CloudBucketMount],
modal/runner.py CHANGED
@@ -601,8 +601,9 @@ async def _interactive_shell(
601
601
  "MODAL_ENVIRONMENT": _get_environment_name(),
602
602
  }
603
603
  secrets = kwargs.pop("secrets", []) + [_Secret.from_dict(sandbox_env)]
604
+
604
605
  with enable_output(): # show any image build logs
605
- sandbox = await _Sandbox.create(
606
+ sandbox = await _Sandbox._create(
606
607
  "sleep",
607
608
  "100000",
608
609
  app=_app,
modal/sandbox.py CHANGED
@@ -12,6 +12,7 @@ from grpclib import GRPCError, Status
12
12
 
13
13
  from modal._tunnel import Tunnel
14
14
  from modal.cloud_bucket_mount import _CloudBucketMount, cloud_bucket_mounts_to_proto
15
+ from modal.mount import _Mount
15
16
  from modal.volume import _Volume
16
17
  from modal_proto import api_pb2
17
18
 
@@ -29,7 +30,6 @@ from .file_io import FileWatchEvent, FileWatchEventType, _FileIO
29
30
  from .gpu import GPU_T
30
31
  from .image import _Image
31
32
  from .io_streams import StreamReader, StreamWriter, _StreamReader, _StreamWriter
32
- from .mount import _Mount
33
33
  from .network_file_system import _NetworkFileSystem, network_file_system_mount_protos
34
34
  from .proxy import _Proxy
35
35
  from .scheduler_placement import SchedulerPlacement
@@ -85,7 +85,6 @@ class _Sandbox(_Object, type_prefix="sb"):
85
85
  def _new(
86
86
  entrypoint_args: Sequence[str],
87
87
  image: _Image,
88
- mounts: Sequence[_Mount],
89
88
  secrets: Sequence[_Secret],
90
89
  timeout: Optional[int] = None,
91
90
  workdir: Optional[str] = None,
@@ -94,6 +93,7 @@ class _Sandbox(_Object, type_prefix="sb"):
94
93
  region: Optional[Union[str, Sequence[str]]] = None,
95
94
  cpu: Optional[float] = None,
96
95
  memory: Optional[Union[int, tuple[int, int]]] = None,
96
+ mounts: Sequence[_Mount] = (),
97
97
  network_file_systems: dict[Union[str, os.PathLike], _NetworkFileSystem] = {},
98
98
  block_network: bool = False,
99
99
  cidr_allowlist: Optional[Sequence[str]] = None,
@@ -217,7 +217,6 @@ class _Sandbox(_Object, type_prefix="sb"):
217
217
  app: Optional["modal.app._App"] = None, # Optionally associate the sandbox with an app
218
218
  environment_name: Optional[str] = None, # Optionally override the default environment
219
219
  image: Optional[_Image] = None, # The image to run as the container for the sandbox.
220
- mounts: Sequence[_Mount] = (), # Mounts to attach to the sandbox.
221
220
  secrets: Sequence[_Secret] = (), # Environment variables to inject into the sandbox.
222
221
  network_file_systems: dict[Union[str, os.PathLike], _NetworkFileSystem] = {},
223
222
  timeout: Optional[int] = None, # Maximum execution time of the sandbox in seconds.
@@ -264,6 +263,76 @@ class _Sandbox(_Object, type_prefix="sb"):
264
263
  sandbox.wait()
265
264
  ```
266
265
  """
266
+ return await _Sandbox._create(
267
+ *entrypoint_args,
268
+ app=app,
269
+ environment_name=environment_name,
270
+ image=image,
271
+ secrets=secrets,
272
+ network_file_systems=network_file_systems,
273
+ timeout=timeout,
274
+ workdir=workdir,
275
+ gpu=gpu,
276
+ cloud=cloud,
277
+ region=region,
278
+ cpu=cpu,
279
+ memory=memory,
280
+ block_network=block_network,
281
+ cidr_allowlist=cidr_allowlist,
282
+ volumes=volumes,
283
+ pty_info=pty_info,
284
+ encrypted_ports=encrypted_ports,
285
+ unencrypted_ports=unencrypted_ports,
286
+ proxy=proxy,
287
+ _experimental_enable_snapshot=_experimental_enable_snapshot,
288
+ _experimental_scheduler_placement=_experimental_scheduler_placement,
289
+ client=client,
290
+ )
291
+
292
+ @staticmethod
293
+ async def _create(
294
+ *entrypoint_args: str,
295
+ app: Optional["modal.app._App"] = None, # Optionally associate the sandbox with an app
296
+ environment_name: Optional[str] = None, # Optionally override the default environment
297
+ image: Optional[_Image] = None, # The image to run as the container for the sandbox.
298
+ secrets: Sequence[_Secret] = (), # Environment variables to inject into the sandbox.
299
+ mounts: Sequence[_Mount] = (),
300
+ network_file_systems: dict[Union[str, os.PathLike], _NetworkFileSystem] = {},
301
+ timeout: Optional[int] = None, # Maximum execution time of the sandbox in seconds.
302
+ workdir: Optional[str] = None, # Working directory of the sandbox.
303
+ gpu: GPU_T = None,
304
+ cloud: Optional[str] = None,
305
+ region: Optional[Union[str, Sequence[str]]] = None, # Region or regions to run the sandbox on.
306
+ # Specify, in fractional CPU cores, how many CPU cores to request.
307
+ # Or, pass (request, limit) to additionally specify a hard limit in fractional CPU cores.
308
+ # CPU throttling will prevent a container from exceeding its specified limit.
309
+ cpu: Optional[Union[float, tuple[float, float]]] = None,
310
+ # Specify, in MiB, a memory request which is the minimum memory required.
311
+ # Or, pass (request, limit) to additionally specify a hard limit in MiB.
312
+ memory: Optional[Union[int, tuple[int, int]]] = None,
313
+ block_network: bool = False, # Whether to block network access
314
+ # List of CIDRs the sandbox is allowed to access. If None, all CIDRs are allowed.
315
+ cidr_allowlist: Optional[Sequence[str]] = None,
316
+ volumes: dict[
317
+ Union[str, os.PathLike], Union[_Volume, _CloudBucketMount]
318
+ ] = {}, # Mount points for Modal Volumes and CloudBucketMounts
319
+ pty_info: Optional[api_pb2.PTYInfo] = None,
320
+ # List of ports to tunnel into the sandbox. Encrypted ports are tunneled with TLS.
321
+ encrypted_ports: Sequence[int] = [],
322
+ # List of ports to tunnel into the sandbox without encryption.
323
+ unencrypted_ports: Sequence[int] = [],
324
+ # Reference to a Modal Proxy to use in front of this Sandbox.
325
+ proxy: Optional[_Proxy] = None,
326
+ # Enable memory snapshots.
327
+ _experimental_enable_snapshot: bool = False,
328
+ _experimental_scheduler_placement: Optional[
329
+ SchedulerPlacement
330
+ ] = None, # Experimental controls over fine-grained scheduling (alpha).
331
+ client: Optional[_Client] = None,
332
+ ):
333
+ # This method exposes some internal arguments (currently `mounts`) which are not in the public API
334
+ # `mounts` is currently only used by modal shell (cli) to provide a function's mounts to the
335
+ # sandbox that runs the shell session
267
336
  from .app import _App
268
337
 
269
338
  environment_name = _get_environment_name(environment_name)
@@ -274,7 +343,6 @@ class _Sandbox(_Object, type_prefix="sb"):
274
343
  obj = _Sandbox._new(
275
344
  entrypoint_args,
276
345
  image=image or _default_image,
277
- mounts=mounts,
278
346
  secrets=secrets,
279
347
  timeout=timeout,
280
348
  workdir=workdir,
@@ -283,6 +351,7 @@ class _Sandbox(_Object, type_prefix="sb"):
283
351
  region=region,
284
352
  cpu=cpu,
285
353
  memory=memory,
354
+ mounts=mounts,
286
355
  network_file_systems=network_file_systems,
287
356
  block_network=block_network,
288
357
  cidr_allowlist=cidr_allowlist,
modal/sandbox.pyi CHANGED
@@ -40,7 +40,6 @@ class _Sandbox(modal._object._Object):
40
40
  def _new(
41
41
  entrypoint_args: collections.abc.Sequence[str],
42
42
  image: modal.image._Image,
43
- mounts: collections.abc.Sequence[modal.mount._Mount],
44
43
  secrets: collections.abc.Sequence[modal.secret._Secret],
45
44
  timeout: typing.Optional[int] = None,
46
45
  workdir: typing.Optional[str] = None,
@@ -49,6 +48,7 @@ class _Sandbox(modal._object._Object):
49
48
  region: typing.Union[str, collections.abc.Sequence[str], None] = None,
50
49
  cpu: typing.Optional[float] = None,
51
50
  memory: typing.Union[int, tuple[int, int], None] = None,
51
+ mounts: collections.abc.Sequence[modal.mount._Mount] = (),
52
52
  network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem] = {},
53
53
  block_network: bool = False,
54
54
  cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
@@ -69,7 +69,6 @@ class _Sandbox(modal._object._Object):
69
69
  app: typing.Optional[modal.app._App] = None,
70
70
  environment_name: typing.Optional[str] = None,
71
71
  image: typing.Optional[modal.image._Image] = None,
72
- mounts: collections.abc.Sequence[modal.mount._Mount] = (),
73
72
  secrets: collections.abc.Sequence[modal.secret._Secret] = (),
74
73
  network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem] = {},
75
74
  timeout: typing.Optional[int] = None,
@@ -93,6 +92,36 @@ class _Sandbox(modal._object._Object):
93
92
  _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
94
93
  client: typing.Optional[modal.client._Client] = None,
95
94
  ) -> _Sandbox: ...
95
+ @staticmethod
96
+ async def _create(
97
+ *entrypoint_args: str,
98
+ app: typing.Optional[modal.app._App] = None,
99
+ environment_name: typing.Optional[str] = None,
100
+ image: typing.Optional[modal.image._Image] = None,
101
+ secrets: collections.abc.Sequence[modal.secret._Secret] = (),
102
+ mounts: collections.abc.Sequence[modal.mount._Mount] = (),
103
+ network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem] = {},
104
+ timeout: typing.Optional[int] = None,
105
+ workdir: typing.Optional[str] = None,
106
+ gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
107
+ cloud: typing.Optional[str] = None,
108
+ region: typing.Union[str, collections.abc.Sequence[str], None] = None,
109
+ cpu: typing.Union[float, tuple[float, float], None] = None,
110
+ memory: typing.Union[int, tuple[int, int], None] = None,
111
+ block_network: bool = False,
112
+ cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
113
+ volumes: dict[
114
+ typing.Union[str, os.PathLike],
115
+ typing.Union[modal.volume._Volume, modal.cloud_bucket_mount._CloudBucketMount],
116
+ ] = {},
117
+ pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
118
+ encrypted_ports: collections.abc.Sequence[int] = [],
119
+ unencrypted_ports: collections.abc.Sequence[int] = [],
120
+ proxy: typing.Optional[modal.proxy._Proxy] = None,
121
+ _experimental_enable_snapshot: bool = False,
122
+ _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
123
+ client: typing.Optional[modal.client._Client] = None,
124
+ ): ...
96
125
  def _hydrate_metadata(self, handle_metadata: typing.Optional[google.protobuf.message.Message]): ...
97
126
  @staticmethod
98
127
  async def from_id(sandbox_id: str, client: typing.Optional[modal.client._Client] = None) -> _Sandbox: ...
@@ -182,7 +211,6 @@ class Sandbox(modal.object.Object):
182
211
  def _new(
183
212
  entrypoint_args: collections.abc.Sequence[str],
184
213
  image: modal.image.Image,
185
- mounts: collections.abc.Sequence[modal.mount.Mount],
186
214
  secrets: collections.abc.Sequence[modal.secret.Secret],
187
215
  timeout: typing.Optional[int] = None,
188
216
  workdir: typing.Optional[str] = None,
@@ -191,6 +219,7 @@ class Sandbox(modal.object.Object):
191
219
  region: typing.Union[str, collections.abc.Sequence[str], None] = None,
192
220
  cpu: typing.Optional[float] = None,
193
221
  memory: typing.Union[int, tuple[int, int], None] = None,
222
+ mounts: collections.abc.Sequence[modal.mount.Mount] = (),
194
223
  network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem] = {},
195
224
  block_network: bool = False,
196
225
  cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
@@ -213,7 +242,6 @@ class Sandbox(modal.object.Object):
213
242
  app: typing.Optional[modal.app.App] = None,
214
243
  environment_name: typing.Optional[str] = None,
215
244
  image: typing.Optional[modal.image.Image] = None,
216
- mounts: collections.abc.Sequence[modal.mount.Mount] = (),
217
245
  secrets: collections.abc.Sequence[modal.secret.Secret] = (),
218
246
  network_file_systems: dict[
219
247
  typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
@@ -246,7 +274,6 @@ class Sandbox(modal.object.Object):
246
274
  app: typing.Optional[modal.app.App] = None,
247
275
  environment_name: typing.Optional[str] = None,
248
276
  image: typing.Optional[modal.image.Image] = None,
249
- mounts: collections.abc.Sequence[modal.mount.Mount] = (),
250
277
  secrets: collections.abc.Sequence[modal.secret.Secret] = (),
251
278
  network_file_systems: dict[
252
279
  typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
@@ -275,6 +302,76 @@ class Sandbox(modal.object.Object):
275
302
 
276
303
  create: __create_spec
277
304
 
305
+ class ___create_spec(typing_extensions.Protocol):
306
+ def __call__(
307
+ self,
308
+ /,
309
+ *entrypoint_args: str,
310
+ app: typing.Optional[modal.app.App] = None,
311
+ environment_name: typing.Optional[str] = None,
312
+ image: typing.Optional[modal.image.Image] = None,
313
+ secrets: collections.abc.Sequence[modal.secret.Secret] = (),
314
+ mounts: collections.abc.Sequence[modal.mount.Mount] = (),
315
+ network_file_systems: dict[
316
+ typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
317
+ ] = {},
318
+ timeout: typing.Optional[int] = None,
319
+ workdir: typing.Optional[str] = None,
320
+ gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
321
+ cloud: typing.Optional[str] = None,
322
+ region: typing.Union[str, collections.abc.Sequence[str], None] = None,
323
+ cpu: typing.Union[float, tuple[float, float], None] = None,
324
+ memory: typing.Union[int, tuple[int, int], None] = None,
325
+ block_network: bool = False,
326
+ cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
327
+ volumes: dict[
328
+ typing.Union[str, os.PathLike],
329
+ typing.Union[modal.volume.Volume, modal.cloud_bucket_mount.CloudBucketMount],
330
+ ] = {},
331
+ pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
332
+ encrypted_ports: collections.abc.Sequence[int] = [],
333
+ unencrypted_ports: collections.abc.Sequence[int] = [],
334
+ proxy: typing.Optional[modal.proxy.Proxy] = None,
335
+ _experimental_enable_snapshot: bool = False,
336
+ _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
337
+ client: typing.Optional[modal.client.Client] = None,
338
+ ): ...
339
+ async def aio(
340
+ self,
341
+ /,
342
+ *entrypoint_args: str,
343
+ app: typing.Optional[modal.app.App] = None,
344
+ environment_name: typing.Optional[str] = None,
345
+ image: typing.Optional[modal.image.Image] = None,
346
+ secrets: collections.abc.Sequence[modal.secret.Secret] = (),
347
+ mounts: collections.abc.Sequence[modal.mount.Mount] = (),
348
+ network_file_systems: dict[
349
+ typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
350
+ ] = {},
351
+ timeout: typing.Optional[int] = None,
352
+ workdir: typing.Optional[str] = None,
353
+ gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
354
+ cloud: typing.Optional[str] = None,
355
+ region: typing.Union[str, collections.abc.Sequence[str], None] = None,
356
+ cpu: typing.Union[float, tuple[float, float], None] = None,
357
+ memory: typing.Union[int, tuple[int, int], None] = None,
358
+ block_network: bool = False,
359
+ cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
360
+ volumes: dict[
361
+ typing.Union[str, os.PathLike],
362
+ typing.Union[modal.volume.Volume, modal.cloud_bucket_mount.CloudBucketMount],
363
+ ] = {},
364
+ pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
365
+ encrypted_ports: collections.abc.Sequence[int] = [],
366
+ unencrypted_ports: collections.abc.Sequence[int] = [],
367
+ proxy: typing.Optional[modal.proxy.Proxy] = None,
368
+ _experimental_enable_snapshot: bool = False,
369
+ _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
370
+ client: typing.Optional[modal.client.Client] = None,
371
+ ): ...
372
+
373
+ _create: ___create_spec
374
+
278
375
  def _hydrate_metadata(self, handle_metadata: typing.Optional[google.protobuf.message.Message]): ...
279
376
 
280
377
  class __from_id_spec(typing_extensions.Protocol):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.0.0.dev16
3
+ Version: 1.0.0.dev18
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -1,9 +1,9 @@
1
- modal/__init__.py,sha256=AaO8fXHO6BYltmFoYOwCB2pSjEECXVvGK5p2Vfo_SpU,2752
1
+ modal/__init__.py,sha256=1131svUxi876UMFC6Z68qe5Z031ZfZ9NrduvGwHphj8,2710
2
2
  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=2aWxN2v5WUnj-R-sk6BzJ-3AvggkQGQjwhtvbDH3pds,777
5
5
  modal/_container_entrypoint.py,sha256=2Zx9O_EMJg0H77EdnC2vGKs6uFMWwbP1NLFf-qYmWmU,28962
6
- modal/_functions.py,sha256=8ZHWZu2su2bbWb_QXjr9S2KfZemKxuMSxCansbVd0VY,77970
6
+ modal/_functions.py,sha256=QRV4xgsgCB6yOE5rkudCsvOvwZXkZE66FRwqEmmnei4,78394
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
@@ -18,11 +18,11 @@ modal/_tunnel.py,sha256=zTBxBiuH1O22tS1OliAJdIsSmaZS8PlnifS_6S5z-mk,6320
18
18
  modal/_tunnel.pyi,sha256=a4Ea0RQ5jaJB0A4LH9FANGB44ObqkHHGVDV4RwtokzU,1251
19
19
  modal/_type_manager.py,sha256=DWjgmjYJuOagw2erin506UUbG2H5UzZCFEekS-7hmfA,9087
20
20
  modal/_watcher.py,sha256=K6LYnlmSGQB4tWWI9JADv-tvSvQ1j522FwT71B51CX8,3584
21
- modal/app.py,sha256=Wz9DIFzO2ByObuqoh3zk9B76WTWcPqYoQDuPU-yrLTU,47100
22
- modal/app.pyi,sha256=1dHHI6RgvJ1y5Ouzb1_S-wpjfjCL7QHz0gqE4BxMw10,23192
21
+ modal/app.py,sha256=NZ_rJ9TuMfiNiLg8-gOFgufD5flGtXWPHOZI0gdD3hE,46585
22
+ modal/app.pyi,sha256=4-b_vbe3lNAqQPcMRpQCEDsE1zsVkQRJGUql9B7HvbM,22659
23
23
  modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
24
24
  modal/client.py,sha256=o-aQThHpvDHUzg_kUafyhWzACViUBhY2WLZ2EitnSHA,16787
25
- modal/client.pyi,sha256=e6ghxi754Z0WfJ_zMQ8mrthEitSVfS-QZ_AgzWWVUlc,8459
25
+ modal/client.pyi,sha256=DMt_aLOzxYEbhj0qc3wHcOnmbLzrRk3GViVFLmVVP5w,8459
26
26
  modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
27
27
  modal/cloud_bucket_mount.pyi,sha256=30T3K1a89l6wzmEJ_J9iWv9SknoGqaZDx59Xs-ZQcmk,1607
28
28
  modal/cls.py,sha256=dBbeARwOWftlKd1cwtM0cHFtQWSWkwVXwVmOV4w0SyI,37907
@@ -39,10 +39,10 @@ modal/file_io.py,sha256=lcMs_E9Xfm0YX1t9U2wNIBPnqHRxmImqjLW1GHqVmyg,20945
39
39
  modal/file_io.pyi,sha256=oB7x-rKq7bmm8cA7Z7W9C9yeko7KK9m9i5GidFnkGK4,9569
40
40
  modal/file_pattern_matcher.py,sha256=wov-otB5M1oTdrYDtR2_VgacYin2srdtAP4McA1Cqzw,6516
41
41
  modal/functions.py,sha256=kcNHvqeGBxPI7Cgd57NIBBghkfbeFJzXO44WW0jSmao,325
42
- modal/functions.pyi,sha256=cllJF89sCKlX82On69XG8XlETgI364xF7Hsj3kxJaeU,16304
42
+ modal/functions.pyi,sha256=iqdp5ixtOOlm8bF-QYbD_G8VKqSRt_AVLT7AWjpn6pQ,16236
43
43
  modal/gpu.py,sha256=Kbhs_u49FaC2Zi0TjCdrpstpRtT5eZgecynmQi5IZVE,6752
44
- modal/image.py,sha256=glnu6LDf3iFq71CGVstHx40CKVN4rw8tukPLAy5JgTQ,92464
45
- modal/image.pyi,sha256=NbegOjy6QX_SL-eTxtJm1_4gOJHW04Ja449QHZIdKgU,25586
44
+ modal/image.py,sha256=yfOaKHS0YQtaAB1lb9Dv22fV5jqp_7qeIYLtz5vVc6w,91751
45
+ modal/image.pyi,sha256=V0IKbs_fAvkxzFrceJm5W_Dl4s5ATy4LEy8L2tMuemQ,25455
46
46
  modal/io_streams.py,sha256=YDZVQSDv05DeXg5TwcucC9Rj5hQBx2GXdluan9rIUpw,15467
47
47
  modal/io_streams.pyi,sha256=1UK6kWLREASQfq-wL9wSp5iqjLU0egRZPDn4LXs1PZY,5136
48
48
  modal/mount.py,sha256=HbpGQbqqT5pTP4dh8j6USWXb2Fr1ro3V1uHIardkya4,30726
@@ -62,11 +62,11 @@ modal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
62
  modal/queue.py,sha256=lu-QYW8GTqhZgX0TPTndmltT9uIWgLFV5mKZ_yTfmd4,18829
63
63
  modal/queue.pyi,sha256=O0f0S5kM1P0GVgzUzgsN0XsI46B9cJem4kkWluFndjM,10632
64
64
  modal/retries.py,sha256=IvNLDM0f_GLUDD5VgEDoN09C88yoxSrCquinAuxT1Sc,5205
65
- modal/runner.py,sha256=BqqN9rWfr-Bwuv9fVNZqAwZnM8OSC9H-HTJC1KQPRMg,24150
65
+ modal/runner.py,sha256=nvpnU7U2O5d2WqME1QUTTwu-NkSLLwblytlGk7HXPAw,24152
66
66
  modal/runner.pyi,sha256=1AnEu48SUPnLWp3raQ2zJCV5lc85EGLkX2nL0bHWaB0,5162
67
67
  modal/running_app.py,sha256=v61mapYNV1-O-Uaho5EfJlryMLvIT9We0amUOSvSGx8,1188
68
- modal/sandbox.py,sha256=RuTA3VjnOTNDRAxIzW9ffxHhUG4PDK5SUyNVWYeqSBw,31941
69
- modal/sandbox.pyi,sha256=BD1VfQGFY6X6sismOWGd8_UMTPE7-gs3eSfNFw44u2M,22931
68
+ modal/sandbox.py,sha256=VwbbQPK6e03kp11M8SQWbe6SLWSOwMaFwoQLYdP5EV0,35573
69
+ modal/sandbox.pyi,sha256=stxwoLcyQNToPISj6umlU8sDUgqzeooLdMs3BwIr740,28195
70
70
  modal/schedule.py,sha256=ewa7hb9NKYnoeSCW2PujZAbGGJL8btX6X3KalCFpc_M,2626
71
71
  modal/scheduler_placement.py,sha256=BAREdOY5HzHpzSBqt6jDVR6YC_jYfHMVqOzkyqQfngU,1235
72
72
  modal/secret.py,sha256=I2z-rgKWl_Ix107d2_Y2OWGXdFOuJ7zMOyDfIOdFI1A,10374
@@ -96,7 +96,7 @@ modal/_utils/blob_utils.py,sha256=IexC2Jbtqp_Tkmy62ayfgzTYte0UPCNufB_v-DO21g8,18
96
96
  modal/_utils/bytes_io_segment_payload.py,sha256=uunxVJS4PE1LojF_UpURMzVK9GuvmYWRqQo_bxEj5TU,3385
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=bhrjyOHPPXm6fAyJx3bzI1Yh56j6xh8eeMSFKdAWrHQ,26978
99
+ modal/_utils/function_utils.py,sha256=qi_ubD5jvOpksKvaxitJDXxfVl1R2Kph6eX8k3y5Hz4,27052
100
100
  modal/_utils/git_utils.py,sha256=qtUU6JAttF55ZxYq51y55OR58B0tDPZsZWK5dJe6W5g,3182
101
101
  modal/_utils/grpc_testing.py,sha256=H1zHqthv19eGPJz2HKXDyWXWGSqO4BRsxah3L5Xaa8A,8619
102
102
  modal/_utils/grpc_utils.py,sha256=xSFosSJYQ4m6cH9WtChcSXqsnyk6DMeVvOHI4N3914g,10922
@@ -146,7 +146,7 @@ modal/requirements/2024.10.txt,sha256=qD-5cVIVM9wXesJ6JC89Ew-3m2KjEElUz3jaw_MddR
146
146
  modal/requirements/PREVIEW.txt,sha256=qD-5cVIVM9wXesJ6JC89Ew-3m2KjEElUz3jaw_MddRo,296
147
147
  modal/requirements/README.md,sha256=9tK76KP0Uph7O0M5oUgsSwEZDj5y-dcUPsnpR0Sc-Ik,854
148
148
  modal/requirements/base-images.json,sha256=57vMSqzMbLBxw5tFWSaMiIkkVEps4JfX5PAtXGnkS4U,740
149
- modal-1.0.0.dev16.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
149
+ modal-1.0.0.dev18.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
150
150
  modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
151
151
  modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
152
152
  modal_docs/gen_reference_docs.py,sha256=d_CQUGQ0rfw28u75I2mov9AlS773z9rG40-yq5o7g2U,6359
@@ -169,10 +169,10 @@ modal_proto/options_pb2.pyi,sha256=l7DBrbLO7q3Ir-XDkWsajm0d0TQqqrfuX54i4BMpdQg,1
169
169
  modal_proto/options_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
170
170
  modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0yJSI,247
171
171
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
172
- modal_version/__init__.py,sha256=-BSzjamBYi1bfz_PGPNWb6JtCWPr4i-Q5Txuq0wPwPs,121
172
+ modal_version/__init__.py,sha256=-UXwTg3_9gxntpP1Yjua5PzS27KZsRvtX2gAnefdTvQ,121
173
173
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
174
- modal-1.0.0.dev16.dist-info/METADATA,sha256=0sLq92t_upACBNZHkXXnirRuo-15pDljGA8vKq21a8g,2455
175
- modal-1.0.0.dev16.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
176
- modal-1.0.0.dev16.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
177
- modal-1.0.0.dev16.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
178
- modal-1.0.0.dev16.dist-info/RECORD,,
174
+ modal-1.0.0.dev18.dist-info/METADATA,sha256=5eXIJqSaN4TWDyvfXlmD9yVOZcXg21goNyCOJPlEm3M,2455
175
+ modal-1.0.0.dev18.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
176
+ modal-1.0.0.dev18.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
177
+ modal-1.0.0.dev18.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
178
+ modal-1.0.0.dev18.dist-info/RECORD,,
modal_version/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2025
2
2
  """Supplies the current version of the modal client library."""
3
3
 
4
- __version__ = "1.0.0.dev16"
4
+ __version__ = "1.0.0.dev18"