modal 0.67.42__py3-none-any.whl → 0.68.11__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. modal/_container_entrypoint.py +4 -1
  2. modal/_runtime/container_io_manager.py +3 -0
  3. modal/_runtime/user_code_imports.py +4 -2
  4. modal/_traceback.py +16 -2
  5. modal/_utils/function_utils.py +5 -1
  6. modal/_utils/grpc_testing.py +6 -2
  7. modal/_utils/hash_utils.py +14 -2
  8. modal/cli/_traceback.py +11 -4
  9. modal/cli/container.py +16 -5
  10. modal/cli/run.py +23 -21
  11. modal/cli/utils.py +4 -0
  12. modal/client.py +6 -37
  13. modal/client.pyi +2 -6
  14. modal/cls.py +132 -62
  15. modal/cls.pyi +13 -7
  16. modal/container_process.py +10 -3
  17. modal/container_process.pyi +3 -3
  18. modal/exception.py +20 -0
  19. modal/file_io.py +380 -0
  20. modal/file_io.pyi +185 -0
  21. modal/functions.py +33 -11
  22. modal/functions.pyi +11 -9
  23. modal/object.py +4 -2
  24. modal/partial_function.py +14 -10
  25. modal/partial_function.pyi +2 -2
  26. modal/runner.py +19 -7
  27. modal/runner.pyi +11 -4
  28. modal/sandbox.py +50 -3
  29. modal/sandbox.pyi +18 -0
  30. {modal-0.67.42.dist-info → modal-0.68.11.dist-info}/METADATA +2 -2
  31. {modal-0.67.42.dist-info → modal-0.68.11.dist-info}/RECORD +41 -39
  32. modal_docs/gen_reference_docs.py +1 -0
  33. modal_proto/api.proto +25 -1
  34. modal_proto/api_pb2.py +758 -718
  35. modal_proto/api_pb2.pyi +95 -10
  36. modal_version/__init__.py +1 -1
  37. modal_version/_version_generated.py +1 -1
  38. {modal-0.67.42.dist-info → modal-0.68.11.dist-info}/LICENSE +0 -0
  39. {modal-0.67.42.dist-info → modal-0.68.11.dist-info}/WHEEL +0 -0
  40. {modal-0.67.42.dist-info → modal-0.68.11.dist-info}/entry_points.txt +0 -0
  41. {modal-0.67.42.dist-info → modal-0.68.11.dist-info}/top_level.txt +0 -0
modal/functions.pyi CHANGED
@@ -157,7 +157,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.
157
157
  image: modal.image._Image,
158
158
  secrets: collections.abc.Sequence[modal.secret._Secret] = (),
159
159
  schedule: typing.Optional[modal.schedule.Schedule] = None,
160
- is_generator=False,
160
+ is_generator: bool = False,
161
161
  gpu: typing.Union[
162
162
  None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]
163
163
  ] = None,
@@ -234,7 +234,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.
234
234
  @property
235
235
  async def web_url(self) -> str: ...
236
236
  @property
237
- def is_generator(self) -> bool: ...
237
+ async def is_generator(self) -> bool: ...
238
238
  @property
239
239
  def cluster_size(self) -> int: ...
240
240
  def _map(
@@ -246,6 +246,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.
246
246
  async def _call_generator_nowait(self, args, kwargs): ...
247
247
  async def remote(self, *args: P.args, **kwargs: P.kwargs) -> ReturnType: ...
248
248
  def remote_gen(self, *args, **kwargs) -> collections.abc.AsyncGenerator[typing.Any, None]: ...
249
+ def _is_local(self): ...
249
250
  def _get_info(self) -> modal._utils.function_utils.FunctionInfo: ...
250
251
  def _get_obj(self) -> typing.Optional[modal.cls._Obj]: ...
251
252
  def local(self, *args: P.args, **kwargs: P.kwargs) -> OriginalReturnType: ...
@@ -325,7 +326,7 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
325
326
  image: modal.image.Image,
326
327
  secrets: collections.abc.Sequence[modal.secret.Secret] = (),
327
328
  schedule: typing.Optional[modal.schedule.Schedule] = None,
328
- is_generator=False,
329
+ is_generator: bool = False,
329
330
  gpu: typing.Union[
330
331
  None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]
331
332
  ] = None,
@@ -455,11 +456,11 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
455
456
 
456
457
  _call_generator_nowait: ___call_generator_nowait_spec
457
458
 
458
- class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
459
+ class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
459
460
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
460
461
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
461
462
 
462
- remote: __remote_spec[ReturnType, P]
463
+ remote: __remote_spec[P, ReturnType]
463
464
 
464
465
  class __remote_gen_spec(typing_extensions.Protocol):
465
466
  def __call__(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
@@ -467,21 +468,22 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
467
468
 
468
469
  remote_gen: __remote_gen_spec
469
470
 
471
+ def _is_local(self): ...
470
472
  def _get_info(self) -> modal._utils.function_utils.FunctionInfo: ...
471
473
  def _get_obj(self) -> typing.Optional[modal.cls.Obj]: ...
472
474
  def local(self, *args: P.args, **kwargs: P.kwargs) -> OriginalReturnType: ...
473
475
 
474
- class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
476
+ class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
475
477
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
476
478
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
477
479
 
478
- _experimental_spawn: ___experimental_spawn_spec[ReturnType, P]
480
+ _experimental_spawn: ___experimental_spawn_spec[P, ReturnType]
479
481
 
480
- class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
482
+ class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
481
483
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
482
484
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
483
485
 
484
- spawn: __spawn_spec[ReturnType, P]
486
+ spawn: __spawn_spec[P, ReturnType]
485
487
 
486
488
  def get_raw_f(self) -> typing.Callable[..., typing.Any]: ...
487
489
 
modal/object.py CHANGED
@@ -96,7 +96,9 @@ class _Object:
96
96
 
97
97
  def _initialize_from_other(self, other):
98
98
  # default implementation, can be overriden in subclasses
99
- pass
99
+ self._object_id = other._object_id
100
+ self._is_hydrated = other._is_hydrated
101
+ self._client = other._client
100
102
 
101
103
  def _hydrate(self, object_id: str, client: _Client, metadata: Optional[Message]):
102
104
  assert isinstance(object_id, str)
@@ -139,7 +141,7 @@ class _Object:
139
141
 
140
142
  # Object to clone must already be hydrated, otherwise from_loader is more suitable.
141
143
  self._validate_is_hydrated()
142
- obj = _Object.__new__(type(self))
144
+ obj = type(self).__new__(type(self))
143
145
  obj._initialize_from_other(self)
144
146
  return obj
145
147
 
modal/partial_function.py CHANGED
@@ -49,7 +49,7 @@ class _PartialFunction(typing.Generic[P, ReturnType, OriginalReturnType]):
49
49
  raw_f: Callable[P, ReturnType]
50
50
  flags: _PartialFunctionFlags
51
51
  webhook_config: Optional[api_pb2.WebhookConfig]
52
- is_generator: Optional[bool]
52
+ is_generator: bool
53
53
  keep_warm: Optional[int]
54
54
  batch_max_size: Optional[int]
55
55
  batch_wait_ms: Optional[int]
@@ -73,7 +73,13 @@ class _PartialFunction(typing.Generic[P, ReturnType, OriginalReturnType]):
73
73
  self.raw_f = raw_f
74
74
  self.flags = flags
75
75
  self.webhook_config = webhook_config
76
- self.is_generator = is_generator
76
+ if is_generator is None:
77
+ # auto detect - doesn't work if the function *returns* a generator
78
+ final_is_generator = inspect.isgeneratorfunction(raw_f) or inspect.isasyncgenfunction(raw_f)
79
+ else:
80
+ final_is_generator = is_generator
81
+
82
+ self.is_generator = final_is_generator
77
83
  self.keep_warm = keep_warm
78
84
  self.wrapped = False # Make sure that this was converted into a FunctionHandle
79
85
  self.batch_max_size = batch_max_size
@@ -101,7 +107,7 @@ class _PartialFunction(typing.Generic[P, ReturnType, OriginalReturnType]):
101
107
  # This happens mainly during serialization of the wrapped underlying class of a Cls
102
108
  # since we don't have the instance info here we just return the PartialFunction itself
103
109
  # to let it be bound to a variable and become a Function later on
104
- return self
110
+ return self # type: ignore # this returns a PartialFunction in a special internal case
105
111
 
106
112
  def __del__(self):
107
113
  if (self.flags & _PartialFunctionFlags.FUNCTION) and self.wrapped is False:
@@ -154,14 +160,14 @@ def _find_partial_methods_for_user_cls(user_cls: type[Any], flags: int) -> dict[
154
160
  )
155
161
  deprecation_error((2024, 2, 21), message)
156
162
 
157
- partial_functions: dict[str, PartialFunction] = {}
163
+ partial_functions: dict[str, _PartialFunction] = {}
158
164
  for parent_cls in reversed(user_cls.mro()):
159
165
  if parent_cls is not object:
160
166
  for k, v in parent_cls.__dict__.items():
161
- if isinstance(v, PartialFunction):
162
- partial_function = synchronizer._translate_in(v) # TODO: remove need for?
163
- if partial_function.flags & flags:
164
- partial_functions[k] = partial_function
167
+ if isinstance(v, PartialFunction): # type: ignore[reportArgumentType] # synchronicity wrapper types
168
+ _partial_function: _PartialFunction = typing.cast(_PartialFunction, synchronizer._translate_in(v))
169
+ if _partial_function.flags & flags:
170
+ partial_functions[k] = _partial_function
165
171
 
166
172
  return partial_functions
167
173
 
@@ -245,8 +251,6 @@ def _method(
245
251
  "Batched function on classes should not be wrapped by `@method`. "
246
252
  "Suggestion: remove the `@method` decorator."
247
253
  )
248
- if is_generator is None:
249
- is_generator = inspect.isgeneratorfunction(raw_f) or inspect.isasyncgenfunction(raw_f)
250
254
  return _PartialFunction(raw_f, _PartialFunctionFlags.FUNCTION, is_generator=is_generator, keep_warm=keep_warm)
251
255
 
252
256
  return wrapper
@@ -28,7 +28,7 @@ class _PartialFunction(typing.Generic[P, ReturnType, OriginalReturnType]):
28
28
  raw_f: typing.Callable[P, ReturnType]
29
29
  flags: _PartialFunctionFlags
30
30
  webhook_config: typing.Optional[modal_proto.api_pb2.WebhookConfig]
31
- is_generator: typing.Optional[bool]
31
+ is_generator: bool
32
32
  keep_warm: typing.Optional[int]
33
33
  batch_max_size: typing.Optional[int]
34
34
  batch_wait_ms: typing.Optional[int]
@@ -57,7 +57,7 @@ class PartialFunction(typing.Generic[P, ReturnType, OriginalReturnType]):
57
57
  raw_f: typing.Callable[P, ReturnType]
58
58
  flags: _PartialFunctionFlags
59
59
  webhook_config: typing.Optional[modal_proto.api_pb2.WebhookConfig]
60
- is_generator: typing.Optional[bool]
60
+ is_generator: bool
61
61
  keep_warm: typing.Optional[int]
62
62
  batch_max_size: typing.Optional[int]
63
63
  batch_wait_ms: typing.Optional[int]
modal/runner.py CHANGED
@@ -17,7 +17,7 @@ from modal_proto import api_pb2
17
17
  from ._pty import get_pty_info
18
18
  from ._resolver import Resolver
19
19
  from ._runtime.execution_context import is_local
20
- from ._traceback import traceback_contains_remote_call
20
+ from ._traceback import print_server_warnings, traceback_contains_remote_call
21
21
  from ._utils.async_utils import TaskContext, gather_cancel_on_exc, synchronize_api
22
22
  from ._utils.grpc_utils import retry_transient_errors
23
23
  from ._utils.name_utils import check_object_name, is_valid_tag
@@ -38,6 +38,7 @@ from .output import _get_output_manager, enable_output
38
38
  from .running_app import RunningApp
39
39
  from .sandbox import _Sandbox
40
40
  from .secret import _Secret
41
+ from .stream_type import StreamType
41
42
 
42
43
  if TYPE_CHECKING:
43
44
  from .app import _App
@@ -175,7 +176,7 @@ async def _publish_app(
175
176
  indexed_objects: dict[str, _Object],
176
177
  name: str = "", # Only relevant for deployments
177
178
  tag: str = "", # Only relevant for deployments
178
- ) -> tuple[str, list[str]]:
179
+ ) -> tuple[str, list[api_pb2.Warning]]:
179
180
  """Wrapper for AppPublish RPC."""
180
181
 
181
182
  # Could simplify this function some changing the internal representation to use
@@ -205,7 +206,8 @@ async def _publish_app(
205
206
  raise InvalidError(exc.message)
206
207
  raise
207
208
 
208
- return response.url, response.warnings
209
+ print_server_warnings(response.server_warnings)
210
+ return response.url, response.server_warnings
209
211
 
210
212
 
211
213
  async def _disconnect(
@@ -553,11 +555,13 @@ async def _deploy_app(
553
555
  app_id=running_app.app_id,
554
556
  app_page_url=running_app.app_page_url,
555
557
  app_logs_url=running_app.app_logs_url, # type: ignore
556
- warnings=warnings,
558
+ warnings=[warning.message for warning in warnings],
557
559
  )
558
560
 
559
561
 
560
- async def _interactive_shell(_app: _App, cmds: list[str], environment_name: str = "", **kwargs: Any) -> None:
562
+ async def _interactive_shell(
563
+ _app: _App, cmds: list[str], environment_name: str = "", pty: bool = True, **kwargs: Any
564
+ ) -> None:
561
565
  """Run an interactive shell (like `bash`) within the image for this app.
562
566
 
563
567
  This is useful for online debugging and interactive exploration of the
@@ -599,9 +603,17 @@ async def _interactive_shell(_app: _App, cmds: list[str], environment_name: str
599
603
  **kwargs,
600
604
  )
601
605
 
602
- container_process = await sandbox.exec(*sandbox_cmds, pty_info=get_pty_info(shell=True))
603
606
  try:
604
- await container_process.attach(pty=True)
607
+ if pty:
608
+ container_process = await sandbox.exec(
609
+ *sandbox_cmds, pty_info=get_pty_info(shell=True) if pty else None
610
+ )
611
+ await container_process.attach()
612
+ else:
613
+ container_process = await sandbox.exec(
614
+ *sandbox_cmds, stdout=StreamType.STDOUT, stderr=StreamType.STDOUT
615
+ )
616
+ await container_process.wait()
605
617
  except InteractiveTimeoutError:
606
618
  # Check on status of Sandbox. It may have crashed, causing connection failure.
607
619
  req = api_pb2.SandboxWaitRequest(sandbox_id=sandbox._object_id, timeout=0)
modal/runner.pyi CHANGED
@@ -1,6 +1,7 @@
1
1
  import modal.client
2
2
  import modal.object
3
3
  import modal.running_app
4
+ import modal_proto.api_pb2
4
5
  import multiprocessing.synchronize
5
6
  import synchronicity.combined_types
6
7
  import typing
@@ -37,7 +38,7 @@ async def _publish_app(
37
38
  indexed_objects: dict[str, modal.object._Object],
38
39
  name: str = "",
39
40
  tag: str = "",
40
- ) -> tuple[str, list[str]]: ...
41
+ ) -> tuple[str, list[modal_proto.api_pb2.Warning]]: ...
41
42
  async def _disconnect(client: modal.client._Client, app_id: str, reason: int, exc_str: str = "") -> None: ...
42
43
  async def _status_based_disconnect(
43
44
  client: modal.client._Client, app_id: str, exc_info: typing.Optional[BaseException] = None
@@ -75,7 +76,9 @@ async def _deploy_app(
75
76
  environment_name: typing.Optional[str] = None,
76
77
  tag: str = "",
77
78
  ) -> DeployResult: ...
78
- async def _interactive_shell(_app: _App, cmds: list[str], environment_name: str = "", **kwargs: typing.Any) -> None: ...
79
+ async def _interactive_shell(
80
+ _app: _App, cmds: list[str], environment_name: str = "", pty: bool = True, **kwargs: typing.Any
81
+ ) -> None: ...
79
82
  def _run_stub(*args: typing.Any, **kwargs: typing.Any): ...
80
83
  def _deploy_stub(*args: typing.Any, **kwargs: typing.Any): ...
81
84
 
@@ -134,8 +137,12 @@ class __deploy_app_spec(typing_extensions.Protocol):
134
137
  deploy_app: __deploy_app_spec
135
138
 
136
139
  class __interactive_shell_spec(typing_extensions.Protocol):
137
- def __call__(self, _app: _App, cmds: list[str], environment_name: str = "", **kwargs: typing.Any) -> None: ...
138
- async def aio(self, _app: _App, cmds: list[str], environment_name: str = "", **kwargs: typing.Any) -> None: ...
140
+ def __call__(
141
+ self, _app: _App, cmds: list[str], environment_name: str = "", pty: bool = True, **kwargs: typing.Any
142
+ ) -> None: ...
143
+ async def aio(
144
+ self, _app: _App, cmds: list[str], environment_name: str = "", pty: bool = True, **kwargs: typing.Any
145
+ ) -> None: ...
139
146
 
140
147
  interactive_shell: __interactive_shell_spec
141
148
 
modal/sandbox.py CHANGED
@@ -4,6 +4,9 @@ import os
4
4
  from collections.abc import AsyncGenerator, Sequence
5
5
  from typing import TYPE_CHECKING, Literal, Optional, Union, overload
6
6
 
7
+ if TYPE_CHECKING:
8
+ import _typeshed
9
+
7
10
  from google.protobuf.message import Message
8
11
  from grpclib import GRPCError, Status
9
12
 
@@ -21,7 +24,15 @@ from ._utils.mount_utils import validate_network_file_systems, validate_volumes
21
24
  from .client import _Client
22
25
  from .config import config
23
26
  from .container_process import _ContainerProcess
24
- from .exception import ExecutionError, InvalidError, SandboxTerminatedError, SandboxTimeoutError, deprecation_warning
27
+ from .exception import (
28
+ ExecutionError,
29
+ InvalidError,
30
+ SandboxTerminatedError,
31
+ SandboxTimeoutError,
32
+ deprecation_error,
33
+ deprecation_warning,
34
+ )
35
+ from .file_io import _FileIO
25
36
  from .gpu import GPU_T
26
37
  from .image import _Image
27
38
  from .io_streams import StreamReader, StreamWriter, _StreamReader, _StreamWriter
@@ -520,6 +531,42 @@ class _Sandbox(_Object, type_prefix="sb"):
520
531
  by_line = bufsize == 1
521
532
  return _ContainerProcess(resp.exec_id, self._client, stdout=stdout, stderr=stderr, text=text, by_line=by_line)
522
533
 
534
+ @overload
535
+ async def open(
536
+ self,
537
+ path: str,
538
+ mode: "_typeshed.OpenTextMode",
539
+ ) -> _FileIO[str]:
540
+ ...
541
+
542
+ @overload
543
+ async def open(
544
+ self,
545
+ path: str,
546
+ mode: "_typeshed.OpenBinaryMode",
547
+ ) -> _FileIO[bytes]:
548
+ ...
549
+
550
+ async def open(
551
+ self,
552
+ path: str,
553
+ mode: Union["_typeshed.OpenTextMode", "_typeshed.OpenBinaryMode"] = "r",
554
+ ):
555
+ """Open a file in the Sandbox and return
556
+ a [`FileIO`](/docs/reference/modal.FileIO#modalfile_io) handle.
557
+
558
+ **Usage**
559
+
560
+ ```python notest
561
+ sb = modal.Sandbox.create(app=sb_app)
562
+ f = sb.open("/test.txt", "w")
563
+ f.write("hello")
564
+ f.close()
565
+ ```
566
+ """
567
+ task_id = await self._get_task_id()
568
+ return await _FileIO.create(path, mode, self._client, task_id)
569
+
523
570
  @property
524
571
  def stdout(self) -> _StreamReader[str]:
525
572
  """
@@ -606,7 +653,7 @@ Sandbox = synchronize_api(_Sandbox)
606
653
 
607
654
  def __getattr__(name):
608
655
  if name == "LogsReader":
609
- deprecation_warning(
656
+ deprecation_error(
610
657
  (2024, 8, 12),
611
658
  "`modal.sandbox.LogsReader` is deprecated. Please import `modal.io_streams.StreamReader` instead.",
612
659
  )
@@ -614,7 +661,7 @@ def __getattr__(name):
614
661
 
615
662
  return StreamReader
616
663
  elif name == "StreamWriter":
617
- deprecation_warning(
664
+ deprecation_error(
618
665
  (2024, 8, 12),
619
666
  "`modal.sandbox.StreamWriter` is deprecated. Please import `modal.io_streams.StreamWriter` instead.",
620
667
  )
modal/sandbox.pyi CHANGED
@@ -1,3 +1,4 @@
1
+ import _typeshed
1
2
  import collections.abc
2
3
  import google.protobuf.message
3
4
  import modal._tunnel
@@ -5,6 +6,7 @@ import modal.app
5
6
  import modal.client
6
7
  import modal.cloud_bucket_mount
7
8
  import modal.container_process
9
+ import modal.file_io
8
10
  import modal.gpu
9
11
  import modal.image
10
12
  import modal.io_streams
@@ -122,6 +124,10 @@ class _Sandbox(modal.object._Object):
122
124
  bufsize: typing.Literal[-1, 1] = -1,
123
125
  _pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
124
126
  ) -> modal.container_process._ContainerProcess[bytes]: ...
127
+ @typing.overload
128
+ async def open(self, path: str, mode: _typeshed.OpenTextMode) -> modal.file_io._FileIO[str]: ...
129
+ @typing.overload
130
+ async def open(self, path: str, mode: _typeshed.OpenBinaryMode) -> modal.file_io._FileIO[bytes]: ...
125
131
  @property
126
132
  def stdout(self) -> modal.io_streams._StreamReader[str]: ...
127
133
  @property
@@ -349,6 +355,18 @@ class Sandbox(modal.object.Object):
349
355
 
350
356
  exec: __exec_spec
351
357
 
358
+ class __open_spec(typing_extensions.Protocol):
359
+ @typing.overload
360
+ def __call__(self, path: str, mode: _typeshed.OpenTextMode) -> modal.file_io.FileIO[str]: ...
361
+ @typing.overload
362
+ def __call__(self, path: str, mode: _typeshed.OpenBinaryMode) -> modal.file_io.FileIO[bytes]: ...
363
+ @typing.overload
364
+ async def aio(self, path: str, mode: _typeshed.OpenTextMode) -> modal.file_io.FileIO[str]: ...
365
+ @typing.overload
366
+ async def aio(self, path: str, mode: _typeshed.OpenBinaryMode) -> modal.file_io.FileIO[bytes]: ...
367
+
368
+ open: __open_spec
369
+
352
370
  @property
353
371
  def stdout(self) -> modal.io_streams.StreamReader[str]: ...
354
372
  @property
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modal
3
- Version: 0.67.42
3
+ Version: 0.68.11
4
4
  Summary: Python client library for Modal
5
5
  Author: Modal Labs
6
6
  Author-email: support@modal.com
@@ -21,7 +21,7 @@ Requires-Dist: fastapi
21
21
  Requires-Dist: grpclib (==0.4.7)
22
22
  Requires-Dist: protobuf (!=4.24.0,<6.0,>=3.19)
23
23
  Requires-Dist: rich (>=12.0.0)
24
- Requires-Dist: synchronicity (~=0.9.4)
24
+ Requires-Dist: synchronicity (~=0.9.6)
25
25
  Requires-Dist: toml
26
26
  Requires-Dist: typer (>=0.9)
27
27
  Requires-Dist: types-certifi
@@ -2,7 +2,7 @@ modal/__init__.py,sha256=Yn8zS7Jxl5uZjPM331Pc4FdSmp9Rt6VdE7TiE4ZKRc8,2151
2
2
  modal/__main__.py,sha256=scYhGFqh8OJcVDo-VOxIT6CCwxOgzgflYWMnIZiMRqE,2871
3
3
  modal/_clustered_functions.py,sha256=kTf-9YBXY88NutC1akI-gCbvf01RhMPCw-zoOI_YIUE,2700
4
4
  modal/_clustered_functions.pyi,sha256=vllkegc99A0jrUOWa8mdlSbdp6uz36TsHhGxysAOpaQ,771
5
- modal/_container_entrypoint.py,sha256=Tae8hAbgN62HM9Q_UFuCyyswfdh1rOey2zzXkbG4Cns,28795
5
+ modal/_container_entrypoint.py,sha256=wk10vA5vRZZsVwQ0yINOLd0i-NwH7x6XbhTslumvGjo,28910
6
6
  modal/_ipython.py,sha256=HF_DYy0e0qM9WnGDmTY30s1RxzGya9GeORCauCEpRaE,450
7
7
  modal/_location.py,sha256=S3lSxIU3h9HkWpkJ3Pwo0pqjIOSB1fjeSgUsY3x7eec,1202
8
8
  modal/_output.py,sha256=0fWX_KQwhER--U81ys16CL-pA5A-LN20C0EZjElKGJQ,25410
@@ -11,30 +11,32 @@ modal/_pty.py,sha256=JZfPDDpzqICZqtyPI_oMJf_9w-p_lLNuzHhwhodUXio,1329
11
11
  modal/_resolver.py,sha256=TtowKu2LdZ7NpiYkSXs058BZ4ivY8KVYdchqLfREkiA,6775
12
12
  modal/_resources.py,sha256=5qmcirXUI8dSH926nwkUaeX9H25mqYu9mXD_KuT79-o,1733
13
13
  modal/_serialization.py,sha256=qPLH6OUEBas1CT-a6i5pOP1hPGt5AfKr9q7RMUTFOMc,18722
14
- modal/_traceback.py,sha256=tueIGN5DbPaQlo23F-GrFMjl-HpDxBxfSAkqjU39zwg,4389
14
+ modal/_traceback.py,sha256=orZ7rsCk9ekV7ZoFjZTH_H00azCypwRKaLh0MZb1dR8,4898
15
15
  modal/_tunnel.py,sha256=o-jJhS4vQ6-XswDhHcJWGMZZmD03SC0e9i8fEu1JTjo,6310
16
16
  modal/_tunnel.pyi,sha256=JmmDYAy9F1FpgJ_hWx0xkom2nTOFQjn4mTPYlU3PFo4,1245
17
17
  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=cmylZhU35txmrx4nltNYuuqXRgeoMtm0ow1J9wJkEYQ,16400
22
- modal/client.pyi,sha256=-fnThLyTYwsvmI5wZIayIBBHAkeTQPwnbRT-GNGQe8g,7354
21
+ modal/client.py,sha256=nyPjfromWBeOyurexpFP2QLQNk822RPggMCLyX9j1jA,15247
22
+ modal/client.pyi,sha256=wnmsE-wrmK3qkFH1a5PoT45B11cFC5T3gLLO9KceJNU,7280
23
23
  modal/cloud_bucket_mount.py,sha256=G7T7jWLD0QkmrfKR75mSTwdUZ2xNfj7pkVqb4ipmxmI,5735
24
24
  modal/cloud_bucket_mount.pyi,sha256=CEi7vrH3kDUF4LAy4qP6tfImy2UJuFRcRbsgRNM1wo8,1403
25
- modal/cls.py,sha256=OJqzj_V-n1g48BY_4Jg_BOTQdftEEl4kTWN0X4FOOdg,27378
26
- modal/cls.pyi,sha256=47jaIT06fz8PSUrs-MaNn6r03PHsAyUGsKuK5e9RMhQ,8140
25
+ modal/cls.py,sha256=ONnrfZ2vPcaY2JuKypPiBA9eTiyg8Qfg-Ull40nn9zs,30956
26
+ modal/cls.pyi,sha256=uoOEANXgCFT9Au3e-_bU98M6ZfAgQWF5ngj8f4c6qpY,8225
27
27
  modal/config.py,sha256=1KhNJkjYsJkX1V8RPPdRYPlM2HE-ZZs0JVSxbiXjmrw,11010
28
- modal/container_process.py,sha256=YRCKjn56oqTtGjtLxpl_KSkOhYrcRitgF3LOI6o14Q4,5759
29
- modal/container_process.pyi,sha256=k2kClwaSzz11eci1pzFZgCm-ptXapHAyHTOENorlazA,2594
28
+ modal/container_process.py,sha256=zDxCLk6KfJT1G9FfNtjom6gekBQ46op3TWepT7-Hkbg,6077
29
+ modal/container_process.pyi,sha256=dqtqBmyRpXXpRrDooESL6WBVU_1Rh6OG-66P2Hk9E5U,2666
30
30
  modal/dict.py,sha256=RmJlEwFJOdSfAYcVa50hbbFccV8e7BvC5tc5g1HXF-c,12622
31
31
  modal/dict.pyi,sha256=2cYgOqBxYZih4BYgMV0c3rNPuxYR6-cB1GBXzFkHA5c,7265
32
32
  modal/environments.py,sha256=5cgA-zbm6ngKLsRA19zSOgtgo9-BarJK3FJK0BiF2Lo,6505
33
33
  modal/environments.pyi,sha256=XalNpiPkAtHWAvOU2Cotq0ozmtl-Jv0FDsR8h9mr27Q,3521
34
- modal/exception.py,sha256=EBkdWVved2XEPsXaoPRu56xfxFFHL9iuqvUsdj42WDA,6392
34
+ modal/exception.py,sha256=dRK789TD1HaB63kHhu1yZuvS2vP_Vua3iLMBtA6dgqk,7128
35
35
  modal/experimental.py,sha256=jFuNbwrNHos47viMB9q-cHJSvf2RDxDdoEcss9plaZE,2302
36
- modal/functions.py,sha256=3GjjFbf40XciWAa4rTmh0erkZjPzRjKHqWxUu91mHOU,66685
37
- modal/functions.pyi,sha256=4k5CaJ9iTuEyHQ2rC5OysNHBLv1CZrD7zBMU1zXIU4w,24988
36
+ modal/file_io.py,sha256=q8s872qf6Ntdw7dPogDlpYbixxGkwCA0BlQn2UUoVhY,14637
37
+ modal/file_io.pyi,sha256=pfkmJiaBpMCZReE6-KCjYOzB1dVtyYDYokJoYX8ARK4,6932
38
+ modal/functions.py,sha256=IIdHw0FNOdoMksG1b2zvkn8f-xskhJu07ZvHMey9iq4,67667
39
+ modal/functions.pyi,sha256=EYH4w4VgQtdbEWLGarnU5QtYVfuM2_tnovKFEbYyg2c,25068
38
40
  modal/gpu.py,sha256=r4rL6uH3UJIQthzYvfWauXNyh01WqCPtKZCmmSX1fd4,6881
39
41
  modal/image.py,sha256=cQ6WP1xHXZT_nY8z3aEFiGwKzrTV0yxi3Ab8JzF91eo,79653
40
42
  modal/image.pyi,sha256=PIKH6JBA4L5TfdJrQu3pm2ykyIITmiP920TpP8cdyQA,24585
@@ -44,24 +46,24 @@ modal/mount.py,sha256=liaid5p42o0OKnzoocJJ_oCovDVderk3-JuCTa5pqtA,27656
44
46
  modal/mount.pyi,sha256=3e4nkXUeeVmUmOyK8Tiyk_EQlHeWruN3yGJVnmDUVrI,9761
45
47
  modal/network_file_system.py,sha256=NKZgh_p8MyJyyJgP92lhRgTmwA3kOPw7m8AbYlchhCE,14530
46
48
  modal/network_file_system.pyi,sha256=8mHKXuRkxHPazF6ljIW7g4M5aVqLSl6eKUPLgDCug5c,7901
47
- modal/object.py,sha256=KmtWRDd5ntHGSO9ASHe9MJcIgjNRqaDXGc3rWOXwrmA,9646
49
+ modal/object.py,sha256=HZs3N59C6JxlMuPQWJYvrWV1FEEkH9txUovVDorVUbs,9763
48
50
  modal/object.pyi,sha256=MO78H9yFSE5i1gExPEwyyQzLdlshkcGHN1aQ0ylyvq0,8802
49
51
  modal/output.py,sha256=N0xf4qeudEaYrslzdAl35VKV8rapstgIM2e9wO8_iy0,1967
50
52
  modal/parallel_map.py,sha256=4aoMXIrlG3wl5Ifk2YDNOQkXsGRsm6Xbfm6WtJ2t3WY,16002
51
53
  modal/parallel_map.pyi,sha256=pOhT0P3DDYlwLx0fR3PTsecA7DI8uOdXC1N8i-ZkyOY,2328
52
- modal/partial_function.py,sha256=938kcVJHcdGXKWsO7NE_FBxPldZ304a_GyhjxD79wHE,28215
53
- modal/partial_function.pyi,sha256=EafGOzZdEq-yE5bYRoMfnMqw-o8Hk_So8MRPDSB99_0,8982
54
+ modal/partial_function.py,sha256=rirVfihV6kp1SMTacrsfE5rNXV5JnTLpU_Zd4xukNg0,28529
55
+ modal/partial_function.pyi,sha256=mt9kUeeMSVTo5qJ6JF6qeQzr41zykYBi2Yt6R8dxtWk,8948
54
56
  modal/proxy.py,sha256=ZrOsuQP7dSZFq1OrIxalNnt0Zvsnp1h86Th679sSL40,1417
55
57
  modal/proxy.pyi,sha256=UvygdOYneLTuoDY6hVaMNCyZ947Tmx93IdLjErUqkvM,368
56
58
  modal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
59
  modal/queue.py,sha256=fJYFfpdrlVj_doc3QxgvJvv7c8BGHjjja5q_9HCtSqs,18658
58
60
  modal/queue.pyi,sha256=di3ownBw4jc6d4X7ygXtbpjlUMOK69qyaD3lVsJbpoM,9900
59
61
  modal/retries.py,sha256=HKR2Q9aNPWkMjQ5nwobqYTuZaSuw0a8lI2zrtY5IW98,5230
60
- modal/runner.py,sha256=7obU-Gq1ocpBGCuR6pvn1T-D6ggg1T48qFo2TNUGWkU,24089
61
- modal/runner.pyi,sha256=RAtCvx_lXWjyFjIaZ3t9-X1c7rqpgAQlhl4Hww53OY8,5038
62
+ modal/runner.py,sha256=Q02VdfLCO7YKpnOSqqh58XL3hR2XHaDeiJVYW3MKz_8,24580
63
+ modal/runner.pyi,sha256=BvMS1ZVzWSn8B8q0KnIZOJKPkN5L-i5b-USbV6SWWHQ,5177
62
64
  modal/running_app.py,sha256=CshNvGDJtagOdKW54uYjY8HY73j2TpnsL9jkPFZAsfA,560
63
- modal/sandbox.py,sha256=ua2z6aV_fBE_7hSCv9vcRp4U9j6lRE9uOrcen4LEJks,26316
64
- modal/sandbox.pyi,sha256=fRl32Pt5F6TbK7aYewjlcL4WQxxmp7m6Ybktmkd2VOk,18108
65
+ modal/sandbox.py,sha256=abmprnPtA-WVsHKu4J1deoltpAUvXtIHQHX-ZpYjYPE,27293
66
+ modal/sandbox.pyi,sha256=QPNuiTLNoKwYf8JK_fmfUBXpdGYlukyaksFV1DpCd2g,18987
65
67
  modal/schedule.py,sha256=0ZFpKs1bOxeo5n3HZjoL7OE2ktsb-_oGtq-WJEPO4tY,2615
66
68
  modal/scheduler_placement.py,sha256=BAREdOY5HzHpzSBqt6jDVR6YC_jYfHMVqOzkyqQfngU,1235
67
69
  modal/secret.py,sha256=Y1WgybQIkfkxdzH9CQ1h-Wd1DJJpzipigMhyyvSxTww,10007
@@ -75,18 +77,18 @@ modal/volume.py,sha256=IISuMeXq9MoSkhXg8Q6JG0F-2n9NTkWk0xGuJB8l3d8,29159
75
77
  modal/volume.pyi,sha256=St0mDiaojfep6Bs4sBbkRJmeacYHF6lh6FKOWGmheHA,11182
76
78
  modal/_runtime/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
77
79
  modal/_runtime/asgi.py,sha256=GvuxZqWnIHMIR-Bx5f7toCQlkERaJO8CHjTPNM9IFIw,21537
78
- modal/_runtime/container_io_manager.py,sha256=8NyX5uuwmHEJgxMwdoY9PpEO-IHA8LGdYdbdHLIafK8,44131
80
+ modal/_runtime/container_io_manager.py,sha256=ctgyNFiHjq1brCrabXmlurkAXjnrCeWPRvTVa735vRw,44215
79
81
  modal/_runtime/execution_context.py,sha256=E6ofm6j1POXGPxS841X3V7JU6NheVb8OkQc7JpLq4Kg,2712
80
82
  modal/_runtime/telemetry.py,sha256=T1RoAGyjBDr1swiM6pPsGRSITm7LI5FDK18oNXxY08U,5163
81
- modal/_runtime/user_code_imports.py,sha256=q_3JOYqCPDcVFZWCHEjyEqj8yzdFsQ49HzeqYmFDLbk,14521
83
+ modal/_runtime/user_code_imports.py,sha256=4fI0F9OIaNOcO_S4Tx2JcnYwZwZq6JdhMAkUzYN6je4,14629
82
84
  modal/_utils/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
83
85
  modal/_utils/app_utils.py,sha256=88BT4TPLWfYAQwKTHcyzNQRHg8n9B-QE2UyJs96iV-0,108
84
86
  modal/_utils/async_utils.py,sha256=9ubwMkwiDB4gzOYG2jL9j7Fs-5dxHjcifZe3r7JRg-k,25091
85
87
  modal/_utils/blob_utils.py,sha256=0k_qUpO5GHnz538wjRhyRw4NdJ5O322N7QSilIu32jw,16601
86
- modal/_utils/function_utils.py,sha256=GV-mq6sSGXQIX5PcExYWJMaWY9YLjChjsiQjg-oPvm8,24902
87
- modal/_utils/grpc_testing.py,sha256=iqM9n5M0cWUUIIWNaEDer_pIfPnzXdZBO4L8FVbNepQ,8309
88
+ modal/_utils/function_utils.py,sha256=LgcveUUb4XU_dWxtqgK_3ujZBvS3cGVzcDOkljyFZ2w,25066
89
+ modal/_utils/grpc_testing.py,sha256=H1zHqthv19eGPJz2HKXDyWXWGSqO4BRsxah3L5Xaa8A,8619
88
90
  modal/_utils/grpc_utils.py,sha256=PPB5ay-vXencXNIWPVw5modr3EH7gfq2QPcO5YJ1lMU,7737
89
- modal/_utils/hash_utils.py,sha256=xKwSI1eQobyWNdJwyLO59eB241LOXmQ6QvtzJsyIMcw,1784
91
+ modal/_utils/hash_utils.py,sha256=LOWJ9U5Eaye2ZIGQOdEk8RN8ExPFovGQisyuGv1PXU0,2236
90
92
  modal/_utils/http_utils.py,sha256=VKXYNPJtrSwZ1ttcXVGQUWmn8cLAXiOTv05g2ac3GbU,2179
91
93
  modal/_utils/logger.py,sha256=ePzdudrtx9jJCjuO6-bcL_kwUJfi4AwloUmIiNtqkY0,1330
92
94
  modal/_utils/mount_utils.py,sha256=J-FRZbPQv1i__Tob-FIpbB1oXWpFLAwZiB4OCiJpFG0,3206
@@ -101,10 +103,10 @@ modal/_vendor/cloudpickle.py,sha256=Loq12qo7PBNbE4LFVEW6BdMMwY10MG94EOW1SCpcnQ0,
101
103
  modal/_vendor/tblib.py,sha256=g1O7QUDd3sDoLd8YPFltkXkih7r_fyZOjgmGuligv3s,9722
102
104
  modal/cli/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
103
105
  modal/cli/_download.py,sha256=t6BXZwjTd9MgznDvbsV8rp0FZWggdzC-lUAGZU4xx1g,3984
104
- modal/cli/_traceback.py,sha256=Tm0g4V_fr4XAlmuh_4MNgZKtjJly9wsWtnKKvOJFM7Q,7130
106
+ modal/cli/_traceback.py,sha256=QlLa_iw3fAOA-mqCqjS8qAxvNT48J3YY3errtVVc2cw,7316
105
107
  modal/cli/app.py,sha256=KOU3tKdcw50612rmN2LmO-N8cT1M1-UgLs7tw68Kgds,7717
106
108
  modal/cli/config.py,sha256=pXPLmX0bIoV57rQNqIPK7V-yllj-GPRY4jiBO_EklGg,1667
107
- modal/cli/container.py,sha256=lRSrxnl7bTLLW9T6hzkqOxqFzzV9qHyXPOuOHY8zkc4,3194
109
+ modal/cli/container.py,sha256=nCySVD10VJPzmX3ghTsGmpxdYeVYYMW6ofjsyt2gQcM,3667
108
110
  modal/cli/dict.py,sha256=gwX4ZBsrr0dpWf_B5_5GN_ealcVzpcGyvY24dEY4y3Y,4455
109
111
  modal/cli/entry_point.py,sha256=aaNxFAqZcmtSjwzkYIA_Ba9CkL4cL4_i2gy5VjoXxkM,4228
110
112
  modal/cli/environment.py,sha256=Ayddkiq9jdj3XYDJ8ZmUqFpPPH8xajYlbexRkzGtUcg,4334
@@ -113,10 +115,10 @@ modal/cli/launch.py,sha256=uyI-ouGvYRjHLGxGQ2lYBZq32BiRT1i0L8ksz5iy7K8,2935
113
115
  modal/cli/network_file_system.py,sha256=3QbAxKEoRc6RCMsYE3OS-GcuiI4GMkz_wAKsIBbN1qg,8186
114
116
  modal/cli/profile.py,sha256=rLXfjJObfPNjaZvNfHGIKqs7y9bGYyGe-K7V0w-Ni0M,3110
115
117
  modal/cli/queues.py,sha256=MIh2OsliNE2QeL1erubfsRsNuG4fxqcqWA2vgIfQ4Mg,4494
116
- modal/cli/run.py,sha256=IPA5Hx7HqCE01NilPZDh1fFaslO4QZa-RKEpMPqjLqA,17066
118
+ modal/cli/run.py,sha256=rv2t7WURME6fCUYo4aA48azVIXLZqo4NjYjTg2I8vzk,17040
117
119
  modal/cli/secret.py,sha256=uQpwYrMY98iMCWeZOQTcktOYhPTZ8IHnyealDc2CZqo,4206
118
120
  modal/cli/token.py,sha256=mxSgOWakXG6N71hQb1ko61XAR9ZGkTMZD-Txn7gmTac,1924
119
- modal/cli/utils.py,sha256=EK_6BIJ7gorQevp9sD_o5iW12foytpg8icBGO32hdeM,3660
121
+ modal/cli/utils.py,sha256=hZmjyzcPjDnQSkLvycZD2LhGdcsfdZshs_rOU78EpvI,3717
120
122
  modal/cli/volume.py,sha256=ngbnX4nhURMaCOqDGO4HmTvAbRBZBjRnPvk5TumnbVw,10004
121
123
  modal/cli/programs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
122
124
  modal/cli/programs/run_jupyter.py,sha256=RRr07CqZrStMbLdBM3PpzU6KM8t9FtLbdIPthg2-Mpw,2755
@@ -131,7 +133,7 @@ modal/requirements/README.md,sha256=9tK76KP0Uph7O0M5oUgsSwEZDj5y-dcUPsnpR0Sc-Ik,
131
133
  modal/requirements/base-images.json,sha256=kLNo5Sqmnhp9H6Hr9IcaGJFrRaRg1yfuepUWkm-y8iQ,571
132
134
  modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
133
135
  modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
134
- modal_docs/gen_reference_docs.py,sha256=AI8h-JKfwn7Tohm3P3D5G0SivSpdGgN6gnw-fED-S0s,6613
136
+ modal_docs/gen_reference_docs.py,sha256=aDcUSSDtAAZ4eeFWyroeIg2TOzyRoYcic-d9Zh9TdLY,6656
135
137
  modal_docs/mdmd/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
136
138
  modal_docs/mdmd/mdmd.py,sha256=F6EXKkjwrTbOiG6I7wKtNGVVmmeWLAJ5pnE7DUkDpvM,6231
137
139
  modal_docs/mdmd/signatures.py,sha256=XJaZrK7Mdepk5fdX51A8uENiLFNil85Ud0d4MH8H5f0,3218
@@ -142,10 +144,10 @@ modal_global_objects/mounts/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0
142
144
  modal_global_objects/mounts/modal_client_package.py,sha256=W0E_yShsRojPzWm6LtIQqNVolapdnrZkm2hVEQuZK_4,767
143
145
  modal_global_objects/mounts/python_standalone.py,sha256=SL_riIxpd8mP4i4CLDCWiFFNj0Ltknm9c_UIGfX5d60,1836
144
146
  modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
145
- modal_proto/api.proto,sha256=zd8V-GFVMtUP8YwxnlVvaJIuocpWKchRCeUZSlMMk74,78818
147
+ modal_proto/api.proto,sha256=41iACETQzxnecGOJgoeyKPQOJVZcw8iHJNtiB6SMuWg,79317
146
148
  modal_proto/api_grpc.py,sha256=DveC4ejFYEhCLiWbQShnmY31_FWGYU675Bmr7nHhsgs,101342
147
- modal_proto/api_pb2.py,sha256=l88JT2IcEuSqCnk7WRTQrBoHtJyAQD4hHAoWmiCQr0A,287100
148
- modal_proto/api_pb2.pyi,sha256=a303c1L3sRnSk9wZXa7DuQWwBZm8u6EShoJImMYxt98,384236
149
+ modal_proto/api_pb2.py,sha256=316-2KJCwcoJm-oFQ7tG42LZjlA3lNhEUYsbbzoikUs,290107
150
+ modal_proto/api_pb2.pyi,sha256=kuvlkVay68o4OQTW8UGwH10Xvxejr-uQjcb2tT_Neso,388133
149
151
  modal_proto/api_pb2_grpc.py,sha256=2PEP6JPOoTw2rDC5qYjLNuumP68ZwAouRhCoayisAhY,219162
150
152
  modal_proto/api_pb2_grpc.pyi,sha256=uWtCxVEd0cFpOZ1oOGfZNO7Dv45OP4kp09jMnNyx9D4,51098
151
153
  modal_proto/modal_api_grpc.py,sha256=-8mLby_om5MYo6yu1zA_hqhz0yLsQW7k2YWBVZW1iVs,13546
@@ -157,12 +159,12 @@ modal_proto/options_pb2.pyi,sha256=l7DBrbLO7q3Ir-XDkWsajm0d0TQqqrfuX54i4BMpdQg,1
157
159
  modal_proto/options_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
158
160
  modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0yJSI,247
159
161
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
160
- modal_version/__init__.py,sha256=3IY-AWLH55r35_mQXIaut0jrJvoPuf1NZJBQQfSbPuo,470
162
+ modal_version/__init__.py,sha256=RT6zPoOdFO99u5Wcxxaoir4ZCuPTbQ22cvzFAXl3vUY,470
161
163
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
162
- modal_version/_version_generated.py,sha256=CPqvHkRI4G0suiPfCuDEKCeUgw_O5yILvh3KaNl3Np0,149
163
- modal-0.67.42.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
164
- modal-0.67.42.dist-info/METADATA,sha256=5HkkANTv2LGFzF5o8GlWJIgaUob1Vyk98nVmZienRxM,2329
165
- modal-0.67.42.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
166
- modal-0.67.42.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
167
- modal-0.67.42.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
168
- modal-0.67.42.dist-info/RECORD,,
164
+ modal_version/_version_generated.py,sha256=iMmZstd6JhPFScB-dfN5XinMS8GWtT-kQD4yTA3FQr4,149
165
+ modal-0.68.11.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
166
+ modal-0.68.11.dist-info/METADATA,sha256=xrxk7D7aRQurLJimfndYZrKyYvfhEFqBVT_o7q7Mxgk,2329
167
+ modal-0.68.11.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
168
+ modal-0.68.11.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
169
+ modal-0.68.11.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
170
+ modal-0.68.11.dist-info/RECORD,,
@@ -86,6 +86,7 @@ def run(output_dir: str = None):
86
86
  ("modal.Sandbox", "modal.sandbox"),
87
87
  ("modal.ContainerProcess", "modal.container_process"),
88
88
  ("modal.io_streams", "modal.io_streams"),
89
+ ("modal.FileIO", "modal.file_io"),
89
90
  ]
90
91
  # These aren't defined in `modal`, but should still be documented as top-level entries.
91
92
  forced_members = {"web_endpoint", "asgi_app", "method", "wsgi_app", "forward"}