modal 0.68.50__py3-none-any.whl → 0.71.5__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 (44) hide show
  1. modal/_container_entrypoint.py +24 -16
  2. modal/_runtime/container_io_manager.py +11 -23
  3. modal/_utils/docker_utils.py +64 -0
  4. modal/_utils/function_utils.py +10 -1
  5. modal/app.py +25 -23
  6. modal/app.pyi +6 -2
  7. modal/cli/launch.py +2 -0
  8. modal/cli/programs/vscode.py +27 -2
  9. modal/cli/run.py +1 -1
  10. modal/client.pyi +2 -2
  11. modal/exception.py +6 -0
  12. modal/experimental.py +3 -0
  13. modal/file_io.py +102 -10
  14. modal/file_io.pyi +59 -0
  15. modal/file_pattern_matcher.py +11 -1
  16. modal/functions.py +20 -5
  17. modal/functions.pyi +2 -2
  18. modal/image.py +95 -39
  19. modal/image.pyi +11 -2
  20. modal/io_streams.py +15 -27
  21. modal/io_streams_helper.py +53 -0
  22. modal/mount.py +3 -5
  23. modal/mount.pyi +4 -4
  24. modal/partial_function.py +4 -4
  25. modal/runner.py +34 -37
  26. modal/runner.pyi +6 -3
  27. modal/running_app.py +23 -4
  28. modal/sandbox.py +19 -6
  29. modal/sandbox.pyi +25 -0
  30. {modal-0.68.50.dist-info → modal-0.71.5.dist-info}/METADATA +1 -1
  31. {modal-0.68.50.dist-info → modal-0.71.5.dist-info}/RECORD +44 -42
  32. modal_proto/api.proto +13 -0
  33. modal_proto/api_grpc.py +16 -0
  34. modal_proto/api_pb2.py +456 -436
  35. modal_proto/api_pb2.pyi +41 -1
  36. modal_proto/api_pb2_grpc.py +34 -1
  37. modal_proto/api_pb2_grpc.pyi +13 -3
  38. modal_proto/modal_api_grpc.py +1 -0
  39. modal_version/__init__.py +1 -1
  40. modal_version/_version_generated.py +2 -2
  41. {modal-0.68.50.dist-info → modal-0.71.5.dist-info}/LICENSE +0 -0
  42. {modal-0.68.50.dist-info → modal-0.71.5.dist-info}/WHEEL +0 -0
  43. {modal-0.68.50.dist-info → modal-0.71.5.dist-info}/entry_points.txt +0 -0
  44. {modal-0.68.50.dist-info → modal-0.71.5.dist-info}/top_level.txt +0 -0
modal/mount.py CHANGED
@@ -16,6 +16,7 @@ from typing import Callable, Optional, Sequence, Union
16
16
  from google.protobuf.message import Message
17
17
 
18
18
  import modal.exception
19
+ import modal.file_pattern_matcher
19
20
  from modal_proto import api_pb2
20
21
  from modal_version import __version__
21
22
 
@@ -325,12 +326,9 @@ class _Mount(_Object, type_prefix="mo"):
325
326
  @staticmethod
326
327
  def _add_local_dir(
327
328
  local_path: Path,
328
- remote_path: Path,
329
- ignore: Union[Sequence[str], Callable[[Path], bool]] = [],
329
+ remote_path: PurePosixPath,
330
+ ignore: Callable[[Path], bool] = modal.file_pattern_matcher._NOTHING,
330
331
  ):
331
- if isinstance(ignore, list):
332
- ignore = FilePatternMatcher(*ignore)
333
-
334
332
  return _Mount._new()._extend(
335
333
  _MountDir(
336
334
  local_dir=local_path,
modal/mount.pyi CHANGED
@@ -94,8 +94,8 @@ class _Mount(modal.object._Object):
94
94
  @staticmethod
95
95
  def _add_local_dir(
96
96
  local_path: pathlib.Path,
97
- remote_path: pathlib.Path,
98
- ignore: typing.Union[typing.Sequence[str], typing.Callable[[pathlib.Path], bool]] = [],
97
+ remote_path: pathlib.PurePosixPath,
98
+ ignore: typing.Callable[[pathlib.Path], bool] = modal.file_pattern_matcher._NOTHING,
99
99
  ): ...
100
100
  def add_local_dir(
101
101
  self,
@@ -176,8 +176,8 @@ class Mount(modal.object.Object):
176
176
  @staticmethod
177
177
  def _add_local_dir(
178
178
  local_path: pathlib.Path,
179
- remote_path: pathlib.Path,
180
- ignore: typing.Union[typing.Sequence[str], typing.Callable[[pathlib.Path], bool]] = [],
179
+ remote_path: pathlib.PurePosixPath,
180
+ ignore: typing.Callable[[pathlib.Path], bool] = modal.file_pattern_matcher._NOTHING,
181
181
  ): ...
182
182
  def add_local_dir(
183
183
  self,
modal/partial_function.py CHANGED
@@ -253,7 +253,7 @@ def _web_endpoint(
253
253
  custom_domains: Optional[
254
254
  Iterable[str]
255
255
  ] = None, # Create an endpoint using a custom domain fully-qualified domain name (FQDN).
256
- requires_proxy_auth: bool = False, # Require Proxy-Authorization HTTP Headers on requests to the endpoint
256
+ requires_proxy_auth: bool = False, # Require Proxy-Authorization HTTP Headers on requests
257
257
  wait_for_response: bool = True, # DEPRECATED: this must always be True now
258
258
  ) -> Callable[[Callable[P, ReturnType]], _PartialFunction[P, ReturnType, ReturnType]]:
259
259
  """Register a basic web endpoint with this application.
@@ -316,7 +316,7 @@ def _asgi_app(
316
316
  *,
317
317
  label: Optional[str] = None, # Label for created endpoint. Final subdomain will be <workspace>--<label>.modal.run.
318
318
  custom_domains: Optional[Iterable[str]] = None, # Deploy this endpoint on a custom domain.
319
- requires_proxy_auth: bool = False, # Require Proxy-Authorization HTTP Headers on requests to the endpoint
319
+ requires_proxy_auth: bool = False, # Require Proxy-Authorization HTTP Headers on requests
320
320
  wait_for_response: bool = True, # DEPRECATED: this must always be True now
321
321
  ) -> Callable[[Callable[..., Any]], _PartialFunction]:
322
322
  """Decorator for registering an ASGI app with a Modal function.
@@ -392,7 +392,7 @@ def _wsgi_app(
392
392
  *,
393
393
  label: Optional[str] = None, # Label for created endpoint. Final subdomain will be <workspace>--<label>.modal.run.
394
394
  custom_domains: Optional[Iterable[str]] = None, # Deploy this endpoint on a custom domain.
395
- requires_proxy_auth: bool = False, # Require Proxy-Authorization HTTP Headers on requests to the endpoint
395
+ requires_proxy_auth: bool = False, # Require Proxy-Authorization HTTP Headers on requests
396
396
  wait_for_response: bool = True, # DEPRECATED: this must always be True now
397
397
  ) -> Callable[[Callable[..., Any]], _PartialFunction]:
398
398
  """Decorator for registering a WSGI app with a Modal function.
@@ -469,7 +469,7 @@ def _web_server(
469
469
  startup_timeout: float = 5.0, # Maximum number of seconds to wait for the web server to start.
470
470
  label: Optional[str] = None, # Label for created endpoint. Final subdomain will be <workspace>--<label>.modal.run.
471
471
  custom_domains: Optional[Iterable[str]] = None, # Deploy this endpoint on a custom domain.
472
- requires_proxy_auth: bool = False, # Require Proxy-Authorization HTTP Headers on requests to the endpoint
472
+ requires_proxy_auth: bool = False, # Require Proxy-Authorization HTTP Headers on requests
473
473
  ) -> Callable[[Callable[..., Any]], _PartialFunction]:
474
474
  """Decorator that registers an HTTP web server inside the container.
475
475
 
modal/runner.py CHANGED
@@ -6,7 +6,7 @@ import time
6
6
  import typing
7
7
  from collections.abc import AsyncGenerator
8
8
  from multiprocessing.synchronize import Event
9
- from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar
9
+ from typing import TYPE_CHECKING, Any, Optional, TypeVar
10
10
 
11
11
  from grpclib import GRPCError, Status
12
12
  from synchronicity.async_wrap import asynccontextmanager
@@ -30,7 +30,7 @@ from .exception import InteractiveTimeoutError, InvalidError, RemoteError, _CliU
30
30
  from .functions import _Function
31
31
  from .object import _get_environment_name, _Object
32
32
  from .output import _get_output_manager, enable_output
33
- from .running_app import RunningApp
33
+ from .running_app import RunningApp, running_app_from_layout
34
34
  from .sandbox import _Sandbox
35
35
  from .secret import _Secret
36
36
  from .stream_type import StreamType
@@ -54,15 +54,18 @@ async def _heartbeat(client: _Client, app_id: str) -> None:
54
54
 
55
55
  async def _init_local_app_existing(client: _Client, existing_app_id: str, environment_name: str) -> RunningApp:
56
56
  # Get all the objects first
57
- obj_req = api_pb2.AppGetObjectsRequest(app_id=existing_app_id, only_class_function=True)
57
+ obj_req = api_pb2.AppGetLayoutRequest(app_id=existing_app_id)
58
58
  obj_resp, _ = await gather_cancel_on_exc(
59
- retry_transient_errors(client.stub.AppGetObjects, obj_req),
59
+ retry_transient_errors(client.stub.AppGetLayout, obj_req),
60
60
  # Cache the environment associated with the app now as we will use it later
61
61
  _get_environment_cached(environment_name, client),
62
62
  )
63
63
  app_page_url = f"https://modal.com/apps/{existing_app_id}" # TODO (elias): this should come from the backend
64
- object_ids = {item.tag: item.object.object_id for item in obj_resp.items}
65
- return RunningApp(existing_app_id, app_page_url=app_page_url, tag_to_object_id=object_ids, client=client)
64
+ return running_app_from_layout(
65
+ existing_app_id,
66
+ obj_resp.app_layout,
67
+ app_page_url=app_page_url,
68
+ )
66
69
 
67
70
 
68
71
  async def _init_local_app_new(
@@ -85,10 +88,8 @@ async def _init_local_app_new(
85
88
  logger.debug(f"Created new app with id {app_resp.app_id}")
86
89
  return RunningApp(
87
90
  app_resp.app_id,
88
- client=client,
89
91
  app_page_url=app_resp.app_page_url,
90
92
  app_logs_url=app_resp.app_logs_url,
91
- environment_name=environment_name,
92
93
  interactive=interactive,
93
94
  )
94
95
 
@@ -120,10 +121,12 @@ async def _init_local_app_from_name(
120
121
  async def _create_all_objects(
121
122
  client: _Client,
122
123
  running_app: RunningApp,
123
- indexed_objects: dict[str, _Object],
124
+ functions: dict[str, _Function],
125
+ classes: dict[str, _Cls],
124
126
  environment_name: str,
125
127
  ) -> None:
126
128
  """Create objects that have been defined but not created on the server."""
129
+ indexed_objects: dict[str, _Object] = {**functions, **classes}
127
130
  resolver = Resolver(
128
131
  client,
129
132
  environment_name=environment_name,
@@ -131,8 +134,9 @@ async def _create_all_objects(
131
134
  )
132
135
  with resolver.display():
133
136
  # Get current objects, and reset all objects
134
- tag_to_object_id = running_app.tag_to_object_id
135
- running_app.tag_to_object_id = {}
137
+ tag_to_object_id = {**running_app.function_ids, **running_app.class_ids}
138
+ running_app.function_ids = {}
139
+ running_app.class_ids = {}
136
140
 
137
141
  # Assign all objects
138
142
  for tag, obj in indexed_objects.items():
@@ -159,7 +163,12 @@ async def _create_all_objects(
159
163
  async def _load(tag, obj):
160
164
  existing_object_id = tag_to_object_id.get(tag)
161
165
  await resolver.load(obj, existing_object_id)
162
- running_app.tag_to_object_id[tag] = obj.object_id
166
+ if _Function._is_id_type(obj.object_id):
167
+ running_app.function_ids[tag] = obj.object_id
168
+ elif _Cls._is_id_type(obj.object_id):
169
+ running_app.class_ids[tag] = obj.object_id
170
+ else:
171
+ raise RuntimeError(f"Unexpected object {obj.object_id}")
163
172
 
164
173
  await TaskContext.gather(*(_load(tag, obj) for tag, obj in indexed_objects.items()))
165
174
 
@@ -168,30 +177,22 @@ async def _publish_app(
168
177
  client: _Client,
169
178
  running_app: RunningApp,
170
179
  app_state: int, # api_pb2.AppState.value
171
- indexed_objects: dict[str, _Object],
180
+ functions: dict[str, _Function],
181
+ classes: dict[str, _Cls],
172
182
  name: str = "", # Only relevant for deployments
173
183
  tag: str = "", # Only relevant for deployments
174
184
  ) -> tuple[str, list[api_pb2.Warning]]:
175
185
  """Wrapper for AppPublish RPC."""
176
186
 
177
- # Could simplify this function some changing the internal representation to use
178
- # function_ids / class_ids rather than the current tag_to_object_id (i.e. "indexed_objects")
179
- def filter_values(full_dict: dict[str, V], condition: Callable[[V], bool]) -> dict[str, V]:
180
- return {k: v for k, v in full_dict.items() if condition(v)}
181
-
182
- function_ids = filter_values(running_app.tag_to_object_id, _Function._is_id_type)
183
- class_ids = filter_values(running_app.tag_to_object_id, _Cls._is_id_type)
184
-
185
- function_objs = filter_values(indexed_objects, lambda v: v.object_id in function_ids.values())
186
- definition_ids = {obj.object_id: obj._get_metadata().definition_id for obj in function_objs.values()} # type: ignore
187
+ definition_ids = {obj.object_id: obj._get_metadata().definition_id for obj in functions.values()} # type: ignore
187
188
 
188
189
  request = api_pb2.AppPublishRequest(
189
190
  app_id=running_app.app_id,
190
191
  name=name,
191
192
  deployment_tag=tag,
192
193
  app_state=app_state, # type: ignore : should be a api_pb2.AppState.value
193
- function_ids=function_ids,
194
- class_ids=class_ids,
194
+ function_ids=running_app.function_ids,
195
+ class_ids=running_app.class_ids,
195
196
  definition_ids=definition_ids,
196
197
  )
197
198
  try:
@@ -325,13 +326,11 @@ async def _run_app(
325
326
  )
326
327
 
327
328
  try:
328
- indexed_objects = dict(**app._functions, **app._classes) # TODO(erikbern): remove
329
-
330
329
  # Create all members
331
- await _create_all_objects(client, running_app, indexed_objects, environment_name)
330
+ await _create_all_objects(client, running_app, app._functions, app._classes, environment_name)
332
331
 
333
332
  # Publish the app
334
- await _publish_app(client, running_app, app_state, indexed_objects)
333
+ await _publish_app(client, running_app, app_state, app._functions, app._classes)
335
334
  except asyncio.CancelledError as e:
336
335
  # this typically happens on sigint/ctrl-C during setup (the KeyboardInterrupt happens in the main thread)
337
336
  if output_mgr := _get_output_manager():
@@ -424,18 +423,17 @@ async def _serve_update(
424
423
  try:
425
424
  running_app: RunningApp = await _init_local_app_existing(client, existing_app_id, environment_name)
426
425
 
427
- indexed_objects = dict(**app._functions, **app._classes) # TODO(erikbern): remove
428
-
429
426
  # Create objects
430
427
  await _create_all_objects(
431
428
  client,
432
429
  running_app,
433
- indexed_objects,
430
+ app._functions,
431
+ app._classes,
434
432
  environment_name,
435
433
  )
436
434
 
437
435
  # Publish the updated app
438
- await _publish_app(client, running_app, api_pb2.APP_STATE_UNSPECIFIED, indexed_objects)
436
+ await _publish_app(client, running_app, api_pb2.APP_STATE_UNSPECIFIED, app._functions, app._classes)
439
437
 
440
438
  # Communicate to the parent process
441
439
  is_ready.set()
@@ -523,19 +521,18 @@ async def _deploy_app(
523
521
 
524
522
  tc.infinite_loop(heartbeat, sleep=HEARTBEAT_INTERVAL)
525
523
 
526
- indexed_objects = dict(**app._functions, **app._classes) # TODO(erikbern): remove
527
-
528
524
  try:
529
525
  # Create all members
530
526
  await _create_all_objects(
531
527
  client,
532
528
  running_app,
533
- indexed_objects,
529
+ app._functions,
530
+ app._classes,
534
531
  environment_name=environment_name,
535
532
  )
536
533
 
537
534
  app_url, warnings = await _publish_app(
538
- client, running_app, api_pb2.APP_STATE_DEPLOYED, indexed_objects, name, tag
535
+ client, running_app, api_pb2.APP_STATE_DEPLOYED, app._functions, app._classes, name, tag
539
536
  )
540
537
  except Exception as e:
541
538
  # Note that AppClientDisconnect only stops the app if it's still initializing, and is a no-op otherwise.
modal/runner.pyi CHANGED
@@ -1,5 +1,6 @@
1
1
  import modal.client
2
- import modal.object
2
+ import modal.cls
3
+ import modal.functions
3
4
  import modal.running_app
4
5
  import modal_proto.api_pb2
5
6
  import multiprocessing.synchronize
@@ -28,14 +29,16 @@ async def _init_local_app_from_name(
28
29
  async def _create_all_objects(
29
30
  client: modal.client._Client,
30
31
  running_app: modal.running_app.RunningApp,
31
- indexed_objects: dict[str, modal.object._Object],
32
+ functions: dict[str, modal.functions._Function],
33
+ classes: dict[str, modal.cls._Cls],
32
34
  environment_name: str,
33
35
  ) -> None: ...
34
36
  async def _publish_app(
35
37
  client: modal.client._Client,
36
38
  running_app: modal.running_app.RunningApp,
37
39
  app_state: int,
38
- indexed_objects: dict[str, modal.object._Object],
40
+ functions: dict[str, modal.functions._Function],
41
+ classes: dict[str, modal.cls._Cls],
39
42
  name: str = "",
40
43
  tag: str = "",
41
44
  ) -> tuple[str, list[modal_proto.api_pb2.Warning]]: ...
modal/running_app.py CHANGED
@@ -4,16 +4,35 @@ from typing import Optional
4
4
 
5
5
  from google.protobuf.message import Message
6
6
 
7
- from .client import _Client
7
+ from modal._utils.grpc_utils import get_proto_oneof
8
+ from modal_proto import api_pb2
8
9
 
9
10
 
10
11
  @dataclass
11
12
  class RunningApp:
12
13
  app_id: str
13
- environment_name: Optional[str] = None
14
14
  app_page_url: Optional[str] = None
15
15
  app_logs_url: Optional[str] = None
16
- tag_to_object_id: dict[str, str] = field(default_factory=dict)
16
+ function_ids: dict[str, str] = field(default_factory=dict)
17
+ class_ids: dict[str, str] = field(default_factory=dict)
17
18
  object_handle_metadata: dict[str, Optional[Message]] = field(default_factory=dict)
18
19
  interactive: bool = False
19
- client: Optional[_Client] = None
20
+
21
+
22
+ def running_app_from_layout(
23
+ app_id: str,
24
+ app_layout: api_pb2.AppLayout,
25
+ app_page_url: Optional[str] = None,
26
+ ) -> RunningApp:
27
+ object_handle_metadata = {}
28
+ for obj in app_layout.objects:
29
+ handle_metadata: Optional[Message] = get_proto_oneof(obj, "handle_metadata_oneof")
30
+ object_handle_metadata[obj.object_id] = handle_metadata
31
+
32
+ return RunningApp(
33
+ app_id,
34
+ function_ids=dict(app_layout.function_ids),
35
+ class_ids=dict(app_layout.class_ids),
36
+ object_handle_metadata=object_handle_metadata,
37
+ app_page_url=app_page_url,
38
+ )
modal/sandbox.py CHANGED
@@ -2,7 +2,7 @@
2
2
  import asyncio
3
3
  import os
4
4
  from collections.abc import AsyncGenerator, Sequence
5
- from typing import TYPE_CHECKING, Literal, Optional, Union, overload
5
+ from typing import TYPE_CHECKING, AsyncIterator, Literal, Optional, Union, overload
6
6
 
7
7
  if TYPE_CHECKING:
8
8
  import _typeshed
@@ -26,7 +26,7 @@ from .client import _Client
26
26
  from .config import config
27
27
  from .container_process import _ContainerProcess
28
28
  from .exception import ExecutionError, InvalidError, SandboxTerminatedError, SandboxTimeoutError
29
- from .file_io import _FileIO
29
+ from .file_io import FileWatchEvent, FileWatchEventType, _FileIO
30
30
  from .gpu import GPU_T
31
31
  from .image import _Image
32
32
  from .io_streams import StreamReader, StreamWriter, _StreamReader, _StreamWriter
@@ -276,9 +276,9 @@ class _Sandbox(_Object, type_prefix="sb"):
276
276
 
277
277
  app_id = app.app_id
278
278
  app_client = app._client
279
- elif _App._container_app is not None:
280
- app_id = _App._container_app.app_id
281
- app_client = _App._container_app.client
279
+ elif (container_app := _App._get_container_app()) is not None:
280
+ app_id = container_app.app_id
281
+ app_client = container_app._client
282
282
  else:
283
283
  arglist = ", ".join(repr(s) for s in entrypoint_args)
284
284
  deprecation_error(
@@ -320,7 +320,9 @@ class _Sandbox(_Object, type_prefix="sb"):
320
320
  resp = await retry_transient_errors(client.stub.SandboxWait, req)
321
321
 
322
322
  obj = _Sandbox._new_hydrated(sandbox_id, client, None)
323
- obj._result = resp.result
323
+
324
+ if resp.result.status:
325
+ obj._result = resp.result
324
326
 
325
327
  return obj
326
328
 
@@ -579,6 +581,17 @@ class _Sandbox(_Object, type_prefix="sb"):
579
581
  task_id = await self._get_task_id()
580
582
  return await _FileIO.rm(path, self._client, task_id, recursive)
581
583
 
584
+ async def watch(
585
+ self,
586
+ path: str,
587
+ filter: Optional[list[FileWatchEventType]] = None,
588
+ recursive: Optional[bool] = None,
589
+ timeout: Optional[int] = None,
590
+ ) -> AsyncIterator[FileWatchEvent]:
591
+ task_id = await self._get_task_id()
592
+ async for event in _FileIO.watch(path, self._client, task_id, filter, recursive, timeout):
593
+ yield event
594
+
582
595
  @property
583
596
  def stdout(self) -> _StreamReader[str]:
584
597
  """
modal/sandbox.pyi CHANGED
@@ -131,6 +131,13 @@ class _Sandbox(modal.object._Object):
131
131
  async def ls(self, path: str) -> list[str]: ...
132
132
  async def mkdir(self, path: str, parents: bool = False) -> None: ...
133
133
  async def rm(self, path: str, recursive: bool = False) -> None: ...
134
+ def watch(
135
+ self,
136
+ path: str,
137
+ filter: typing.Optional[list[modal.file_io.FileWatchEventType]] = None,
138
+ recursive: typing.Optional[bool] = None,
139
+ timeout: typing.Optional[int] = None,
140
+ ) -> typing.AsyncIterator[modal.file_io.FileWatchEvent]: ...
134
141
  @property
135
142
  def stdout(self) -> modal.io_streams._StreamReader[str]: ...
136
143
  @property
@@ -388,6 +395,24 @@ class Sandbox(modal.object.Object):
388
395
 
389
396
  rm: __rm_spec
390
397
 
398
+ class __watch_spec(typing_extensions.Protocol):
399
+ def __call__(
400
+ self,
401
+ path: str,
402
+ filter: typing.Optional[list[modal.file_io.FileWatchEventType]] = None,
403
+ recursive: typing.Optional[bool] = None,
404
+ timeout: typing.Optional[int] = None,
405
+ ) -> typing.Iterator[modal.file_io.FileWatchEvent]: ...
406
+ def aio(
407
+ self,
408
+ path: str,
409
+ filter: typing.Optional[list[modal.file_io.FileWatchEventType]] = None,
410
+ recursive: typing.Optional[bool] = None,
411
+ timeout: typing.Optional[int] = None,
412
+ ) -> typing.AsyncIterator[modal.file_io.FileWatchEvent]: ...
413
+
414
+ watch: __watch_spec
415
+
391
416
  @property
392
417
  def stdout(self) -> modal.io_streams.StreamReader[str]: ...
393
418
  @property
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modal
3
- Version: 0.68.50
3
+ Version: 0.71.5
4
4
  Summary: Python client library for Modal
5
5
  Author: Modal Labs
6
6
  Author-email: support@modal.com
@@ -2,7 +2,7 @@ modal/__init__.py,sha256=3NJLLHb0TRc2tc68kf8NHzORx38GbtbZvPEWDWrQ6N4,2234
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=wk10vA5vRZZsVwQ0yINOLd0i-NwH7x6XbhTslumvGjo,28910
5
+ modal/_container_entrypoint.py,sha256=-zUa567FgOKmF0TtFWQ6DgehUD2CMfABDBQ8oLSpjyc,29171
6
6
  modal/_ipython.py,sha256=TW1fkVOmZL3YYqdS2YlM1hqpf654Yf8ZyybHdBnlhSw,301
7
7
  modal/_location.py,sha256=S3lSxIU3h9HkWpkJ3Pwo0pqjIOSB1fjeSgUsY3x7eec,1202
8
8
  modal/_output.py,sha256=0fWX_KQwhER--U81ys16CL-pA5A-LN20C0EZjElKGJQ,25410
@@ -15,11 +15,11 @@ modal/_traceback.py,sha256=IZQzB3fVlUfMHOSyKUgw0H6qv4yHnpyq-XVCNZKfUdA,5023
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
- modal/app.py,sha256=JWefPs4yB70BKQwSZejB_4_muhxn63cC9UmnNvpQ9XY,45526
19
- modal/app.pyi,sha256=FYPCEJNhof4YF6HIuNP_2yG6s2PgZnKW9tO1hFE6sfA,25194
18
+ modal/app.py,sha256=vEE0cK5QPF6_cdW5AJvcuWxz5KmeprHwBEtlDkVRHgE,45582
19
+ modal/app.pyi,sha256=Gx7gxjfQ70sxhbwfpx1VjvzEON-ZEMTJ_Vy8qt0oQvo,25302
20
20
  modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
21
21
  modal/client.py,sha256=JAnd4-GCN093BwkvOFAK5a6iy5ycxofjpUncMxlrIMw,15253
22
- modal/client.pyi,sha256=F97Ao08XxQn1RMnJx2ZYX_R2bP9k-d_rekRUjHvVzEE,7280
22
+ modal/client.pyi,sha256=pjZG1Z_8vLGkYtlrkEBAkl9tV9wqACVl0a3qWxHPacQ,7278
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=3hjb0JcoPjxKZNeK22f5rR43bZRBjoRI7_EMZXY7YrE,31172
@@ -31,20 +31,21 @@ modal/dict.py,sha256=ei9jsA5iTj4UFGPJxTAed6vjd49W47ezDtj0koUmVts,12497
31
31
  modal/dict.pyi,sha256=VmbzxltA2vFlIHZCxpNGtd-ieXwcUwdw3iyy3WCweqU,7115
32
32
  modal/environments.py,sha256=wbv9ttFCbzATGfwcmvYiG608PfHovx0AQmawsg-jmic,6660
33
33
  modal/environments.pyi,sha256=rF7oaaELoSNuoD6qImGnIbuGPtgWwR5SlcExyYJ61hQ,3515
34
- modal/exception.py,sha256=GEV6xMnVnkle0gsFZVLB4B7cUMyw8HzVDvAvPr34ZV4,5185
35
- modal/experimental.py,sha256=jFuNbwrNHos47viMB9q-cHJSvf2RDxDdoEcss9plaZE,2302
36
- modal/file_io.py,sha256=pDOFNQU5m-x-k3oJauck4fOp3bZ55Vc-_LvSaN5_Bow,16465
37
- modal/file_io.pyi,sha256=GMhCCRyMftXYI3HqI9EdGPOx70CbCNi-VC5Sfy5TYnc,7631
38
- modal/file_pattern_matcher.py,sha256=V6P74Vc7LAuBFe_uepIaZmoDJiuAvqjFibe0GcMJwxo,5119
39
- modal/functions.py,sha256=aXXXr3rk7BCeh5OWMvxGksGm8FQoYCyrBDGV74FPoPE,67827
40
- modal/functions.pyi,sha256=snttn47K81lKhmrCLWNVZelZTDhNsbxtw4l1DlLDR74,25317
34
+ modal/exception.py,sha256=4JyO-SACaLNDe2QC48EjsK8GMkZ8AgEurZ8j1YdRu8E,5263
35
+ modal/experimental.py,sha256=npfKbyMpI41uZZs9HW_QiB3E4ykWfDXZbACXXbw6qeA,2385
36
+ modal/file_io.py,sha256=ZR8VBCDsDt5uB9TNN9XbEh7sniJzM_5YL47m8WP0m5c,19617
37
+ modal/file_io.pyi,sha256=79Fg75BjmMEeCX0Lx-Z8C4XSNPCotwNdK6ZLIDFm2f4,9770
38
+ modal/file_pattern_matcher.py,sha256=LaI7Paxg0xR9D-D7Tgc60xR0w1KZee22LjGbFie1Vms,5571
39
+ modal/functions.py,sha256=3uJPbrEAWhpFfLfUnoRjGmvEUC-_wVh-8yNJBx8eVeM,68249
40
+ modal/functions.pyi,sha256=LiSDgH-X7jcZ56pAoLMwo3x9Dzdp_3Sd7W5MVAJPoCg,25407
41
41
  modal/gpu.py,sha256=MTxj6ql8EpgfBg8YmZ5a1cLznyuZFssX1qXbEX4LKVM,7503
42
- modal/image.py,sha256=sv45bYaF5Jlmk8mQE3EDADYyXLi14hOe2CUM0Zb8Xao,82243
43
- modal/image.pyi,sha256=VY_4HnDBhW8u_Zd3n-YBZ1H9idbTorWGwzsAzY7-B70,24213
44
- modal/io_streams.py,sha256=QkQiizKRzd5bnbKQsap31LJgBYlAnj4-XkV_50xPYX0,15079
42
+ modal/image.py,sha256=Krvcsclomp9YsqSNwFj2FoAyg10OvU47RDnsNCwjGbQ,84550
43
+ modal/image.pyi,sha256=1fgGvsL5Rb0Sa-_2OCgIyJ_QgHcL0_9MWD_oY7cyFFM,24937
44
+ modal/io_streams.py,sha256=Xxc5grJiO94nBA48FFWH3S3g6SPR0xFVgZ_DZ1oFmvI,14428
45
45
  modal/io_streams.pyi,sha256=bCCVSxkMcosYd8O3PQDDwJw7TQ8JEcnYonLJ5t27TQs,4804
46
- modal/mount.py,sha256=Miu9V5LB80uoMasSXxxf0aYTC7H1G08PjnjmmjQdyRc,29346
47
- modal/mount.pyi,sha256=7dKl_JeVka3g4oKw7D-FFRU-Zpadt9LJEcfNUnhj540,10491
46
+ modal/io_streams_helper.py,sha256=B5Ui56ph7LkRpZX0tAF80Q-gOMsvPPLx5bpIPX0kgDc,1772
47
+ modal/mount.py,sha256=wOr-2vmKImsE3lHBII8hL2gYy5ng46R58QwId4JultQ,29313
48
+ modal/mount.pyi,sha256=FiNV1wIKFvd0ZMZ0tm1mz6ZSA5Hjsge-kFSA5tPWfcI,10503
48
49
  modal/network_file_system.py,sha256=INj1TfN_Fsmabmlte7anvey1epodjbMmjBW_TIJSST4,14406
49
50
  modal/network_file_system.pyi,sha256=61M-sdWrtaRjmuNVsvusI6kf1Qw-jUOVXvEAeOkM8Aw,7751
50
51
  modal/object.py,sha256=HZs3N59C6JxlMuPQWJYvrWV1FEEkH9txUovVDorVUbs,9763
@@ -52,7 +53,7 @@ modal/object.pyi,sha256=MO78H9yFSE5i1gExPEwyyQzLdlshkcGHN1aQ0ylyvq0,8802
52
53
  modal/output.py,sha256=N0xf4qeudEaYrslzdAl35VKV8rapstgIM2e9wO8_iy0,1967
53
54
  modal/parallel_map.py,sha256=4aoMXIrlG3wl5Ifk2YDNOQkXsGRsm6Xbfm6WtJ2t3WY,16002
54
55
  modal/parallel_map.pyi,sha256=pOhT0P3DDYlwLx0fR3PTsecA7DI8uOdXC1N8i-ZkyOY,2328
55
- modal/partial_function.py,sha256=pDDNR6KTaIIPpuKQaoO1vgP83_LTwxMhtOn6sVRrmC8,27862
56
+ modal/partial_function.py,sha256=KSpHhu7Gsbe4h-5mcJjxnE4328biKOB7yVouHZbObA8,27798
56
57
  modal/partial_function.pyi,sha256=pO6kf8i5HVsZ7CF0z_KkzLk4Aeq7NJhFJ_VNIycRXaU,9260
57
58
  modal/proxy.py,sha256=ZrOsuQP7dSZFq1OrIxalNnt0Zvsnp1h86Th679sSL40,1417
58
59
  modal/proxy.pyi,sha256=UvygdOYneLTuoDY6hVaMNCyZ947Tmx93IdLjErUqkvM,368
@@ -60,11 +61,11 @@ modal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
61
  modal/queue.py,sha256=zMUQtdAyqZzBg-2iAo3c3G54HLP7TEWfVhiQXLjewb4,18556
61
62
  modal/queue.pyi,sha256=gGV97pWelSSYqMV9Bl4ys3mSP7q82fS71oqSWeAwyDE,9818
62
63
  modal/retries.py,sha256=HKR2Q9aNPWkMjQ5nwobqYTuZaSuw0a8lI2zrtY5IW98,5230
63
- modal/runner.py,sha256=qfkB0OM97kb_-oP-D5KPj_jUwfd8ePUA3R_zLkjSTBQ,24586
64
- modal/runner.pyi,sha256=BvMS1ZVzWSn8B8q0KnIZOJKPkN5L-i5b-USbV6SWWHQ,5177
65
- modal/running_app.py,sha256=CshNvGDJtagOdKW54uYjY8HY73j2TpnsL9jkPFZAsfA,560
66
- modal/sandbox.py,sha256=c-Qli3QJPN7bBQzsTk4iS51zurNlq--InZ2eRR-B6No,28106
67
- modal/sandbox.pyi,sha256=k8_vHjN3oigxSCF13Cm2HfcSHuliGuSb8ryd3CGqwoA,19815
64
+ modal/runner.py,sha256=mhqgRdjD5cUDpBQIokiX7OCfVblpGV6aWmZ-WvWJgGg,24114
65
+ modal/runner.pyi,sha256=YmP4EOCNjjkwSIPi2Gl6hF_ji_ytkxz9dw3iB9KXaOI,5275
66
+ modal/running_app.py,sha256=v61mapYNV1-O-Uaho5EfJlryMLvIT9We0amUOSvSGx8,1188
67
+ modal/sandbox.py,sha256=H63K3MTcgdb9KkKc79sMKe6UzFMGBNI7HB2TUwBbE_U,28609
68
+ modal/sandbox.pyi,sha256=lceWDeXqzdeRc1iIuM5YmpoZlBJcVBpQO1Jc3AT1AQI,20809
68
69
  modal/schedule.py,sha256=0ZFpKs1bOxeo5n3HZjoL7OE2ktsb-_oGtq-WJEPO4tY,2615
69
70
  modal/scheduler_placement.py,sha256=BAREdOY5HzHpzSBqt6jDVR6YC_jYfHMVqOzkyqQfngU,1235
70
71
  modal/secret.py,sha256=lebVTZi4fC9PXQpLVmsvgQLzy-2Kzxv1WBD0Jr2wsxQ,10117
@@ -78,7 +79,7 @@ modal/volume.py,sha256=T-pLxCYqmqRO6OolpAXlPxomMu0RWjti2e4kUpaj2cQ,29229
78
79
  modal/volume.pyi,sha256=eekb2dnAAwFK_NO9ciAOOTthl8NP1iAmMFrCGgjDA2k,11100
79
80
  modal/_runtime/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
80
81
  modal/_runtime/asgi.py,sha256=Mjs859pSgOmtZL-YmEsSKN557v1A2Ax_5-ERgPfj55E,21920
81
- modal/_runtime/container_io_manager.py,sha256=ctgyNFiHjq1brCrabXmlurkAXjnrCeWPRvTVa735vRw,44215
82
+ modal/_runtime/container_io_manager.py,sha256=HgDLjE78yy1P7WZTmsEVDf89YnFFWG63Ddes8uYLVDY,43764
82
83
  modal/_runtime/execution_context.py,sha256=E6ofm6j1POXGPxS841X3V7JU6NheVb8OkQc7JpLq4Kg,2712
83
84
  modal/_runtime/telemetry.py,sha256=T1RoAGyjBDr1swiM6pPsGRSITm7LI5FDK18oNXxY08U,5163
84
85
  modal/_runtime/user_code_imports.py,sha256=n4CQOojzSdf0jwSKSy6MEnVX3IWl3t3Dq54-x9VS2Ds,14663
@@ -88,7 +89,8 @@ modal/_utils/async_utils.py,sha256=9ubwMkwiDB4gzOYG2jL9j7Fs-5dxHjcifZe3r7JRg-k,2
88
89
  modal/_utils/blob_utils.py,sha256=N66LtZI8PpCkZ7maA7GLW5CAmYUoNJdG-GjaAUR4_NQ,14509
89
90
  modal/_utils/bytes_io_segment_payload.py,sha256=uunxVJS4PE1LojF_UpURMzVK9GuvmYWRqQo_bxEj5TU,3385
90
91
  modal/_utils/deprecation.py,sha256=dycySRBxyZf3ITzEqPNM6MxXTk9-0VVLA8oCPQ5j_Os,3426
91
- modal/_utils/function_utils.py,sha256=4LYFbNY5aHc96QitwP4Ty-dBl45SD1HjfZrvBFUF-ko,25343
92
+ modal/_utils/docker_utils.py,sha256=FLz1q0YicL6i_Iq-4inkgDVFfEINVG6YPT2s_P6ly0o,2264
93
+ modal/_utils/function_utils.py,sha256=q68HhFH16MwhHRnGD8jvIgqDjduRQVp3a_qMWXPyrgU,25518
92
94
  modal/_utils/grpc_testing.py,sha256=H1zHqthv19eGPJz2HKXDyWXWGSqO4BRsxah3L5Xaa8A,8619
93
95
  modal/_utils/grpc_utils.py,sha256=PPB5ay-vXencXNIWPVw5modr3EH7gfq2QPcO5YJ1lMU,7737
94
96
  modal/_utils/hash_utils.py,sha256=zg3J6OGxTFGSFri1qQ12giDz90lWk8bzaxCTUCRtiX4,3034
@@ -114,18 +116,18 @@ modal/cli/dict.py,sha256=HaEcjfll7i3Uj3Fg56aj4407if5UljsYfr6fIq-D2W8,4589
114
116
  modal/cli/entry_point.py,sha256=aaNxFAqZcmtSjwzkYIA_Ba9CkL4cL4_i2gy5VjoXxkM,4228
115
117
  modal/cli/environment.py,sha256=Ayddkiq9jdj3XYDJ8ZmUqFpPPH8xajYlbexRkzGtUcg,4334
116
118
  modal/cli/import_refs.py,sha256=wnqE5AMeyAN3IZmQvJCp54KRnJh8Nq_5fMqB6u6GEL8,9147
117
- modal/cli/launch.py,sha256=uyI-ouGvYRjHLGxGQ2lYBZq32BiRT1i0L8ksz5iy7K8,2935
119
+ modal/cli/launch.py,sha256=44oOlGB0KYDBMfuIlkhW2uzjkWbHhDRR64UOEnGwsJ4,2989
118
120
  modal/cli/network_file_system.py,sha256=o6VLTgN4xn5XUiNPBfxYec-5uWCgYrDmfFFLM1ZW_eE,8180
119
121
  modal/cli/profile.py,sha256=rLXfjJObfPNjaZvNfHGIKqs7y9bGYyGe-K7V0w-Ni0M,3110
120
122
  modal/cli/queues.py,sha256=MIh2OsliNE2QeL1erubfsRsNuG4fxqcqWA2vgIfQ4Mg,4494
121
- modal/cli/run.py,sha256=9SvPmBzB8ZZRaqUJc9LmL2tfT5OMiR4Ow0dLANVwuB8,17870
123
+ modal/cli/run.py,sha256=QMs3BVSkq8jve76BqgstGt4C6jilbDD9gpCCRPuHUy0,17879
122
124
  modal/cli/secret.py,sha256=uQpwYrMY98iMCWeZOQTcktOYhPTZ8IHnyealDc2CZqo,4206
123
125
  modal/cli/token.py,sha256=mxSgOWakXG6N71hQb1ko61XAR9ZGkTMZD-Txn7gmTac,1924
124
126
  modal/cli/utils.py,sha256=hZmjyzcPjDnQSkLvycZD2LhGdcsfdZshs_rOU78EpvI,3717
125
127
  modal/cli/volume.py,sha256=Oxc8WGP8wm2a_S87bp-P4OnPwoT1wIYQhbgkCvvFIdI,9998
126
128
  modal/cli/programs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
127
129
  modal/cli/programs/run_jupyter.py,sha256=RRr07CqZrStMbLdBM3PpzU6KM8t9FtLbdIPthg2-Mpw,2755
128
- modal/cli/programs/vscode.py,sha256=acKvTUNA2uIGITKWYS9mkb_W8WUuNmvOSOvf1KBtUco,2479
130
+ modal/cli/programs/vscode.py,sha256=m80wuQyTALTc7y-kAVqmMjtrcb6muCtpuhxsJm4Va2Y,3453
129
131
  modal/extensions/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
130
132
  modal/extensions/ipython.py,sha256=Xvzy-A7cvwMSDa9p4c4CEMLOX2_Xsg9DkM1J9uyu7jc,983
131
133
  modal/requirements/2023.12.312.txt,sha256=zWWUVgVQ92GXBKNYYr2-5vn9rlnXcmkqlwlX5u1eTYw,400
@@ -147,13 +149,13 @@ modal_global_objects/mounts/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0
147
149
  modal_global_objects/mounts/modal_client_package.py,sha256=W0E_yShsRojPzWm6LtIQqNVolapdnrZkm2hVEQuZK_4,767
148
150
  modal_global_objects/mounts/python_standalone.py,sha256=SL_riIxpd8mP4i4CLDCWiFFNj0Ltknm9c_UIGfX5d60,1836
149
151
  modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
150
- modal_proto/api.proto,sha256=LdD5XC5IhLP4rL_7nLeO0FL3emTs7jpEZGON2JIJDs4,79741
151
- modal_proto/api_grpc.py,sha256=AiUCWTHQQFC9RFB_XuavB_OnVMr7GJMRLEwcf4FSTio,102088
152
- modal_proto/api_pb2.py,sha256=rvBtjxpHVIXZmecc0OZS5PgZm4n1DcI4q1EHE675iW0,293583
153
- modal_proto/api_pb2.pyi,sha256=LNvol6MFzFuG1J_wKA4AKPiSKSLkYfNW1kF7c5XXABk,391781
154
- modal_proto/api_pb2_grpc.py,sha256=dFxVTgosyp_o8NCI1JIySlR0qTzG4ILm9mq8MNo4jYc,220795
155
- modal_proto/api_pb2_grpc.pyi,sha256=yJgwEl-1YU42m7MU_Sm5SK3rB9xdkisPk3nZB-mlqkg,51463
156
- modal_proto/modal_api_grpc.py,sha256=MyNzvY_WqB7QTMOQjoH6lsqCY5-6_s1HP-knsOSjANs,13640
152
+ modal_proto/api.proto,sha256=yxqa3djtNDAD6_AolYTUR_BM5w2apPN6UIXcvjRAFvY,80137
153
+ modal_proto/api_grpc.py,sha256=MLsxlZXikcv36aSs0iVZywIOANMWstVZMWJGQTDjdM0,102823
154
+ modal_proto/api_pb2.py,sha256=Mt0QjSEeSNi9vbpK8LoEAfrCF2obuDyJdFWAob2zYFw,294928
155
+ modal_proto/api_pb2.pyi,sha256=uSsIePIeIK06rkW3rPHSOnpKoagr5bhDWuXjk73W_l8,393499
156
+ modal_proto/api_pb2_grpc.py,sha256=4d5SwJPLldCqqHz_BGqmJLlX-BMG592WFKUQ6IBg5rg,222415
157
+ modal_proto/api_pb2_grpc.pyi,sha256=C4c3jndI6TKEgVnx3vAmT86In4T9JKmB1CImiye_aQk,51822
158
+ modal_proto/modal_api_grpc.py,sha256=eeH1vHXgwO768tM7DXqvj-P37u15SI00gZtm8_EK15I,13732
157
159
  modal_proto/modal_options_grpc.py,sha256=qJ1cuwA54oRqrdTyPTbvfhFZYd9HhJKK5UCwt523r3Y,120
158
160
  modal_proto/options.proto,sha256=a-siq4swVbZPfaFRXAipRZzGP2bq8OsdUvjlyzAeodQ,488
159
161
  modal_proto/options_grpc.py,sha256=M18X3d-8F_cNYSVM3I25dUTO5rZ0rd-vCCfynfh13Nc,125
@@ -162,12 +164,12 @@ modal_proto/options_pb2.pyi,sha256=l7DBrbLO7q3Ir-XDkWsajm0d0TQqqrfuX54i4BMpdQg,1
162
164
  modal_proto/options_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
163
165
  modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0yJSI,247
164
166
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
165
- modal_version/__init__.py,sha256=RT6zPoOdFO99u5Wcxxaoir4ZCuPTbQ22cvzFAXl3vUY,470
167
+ modal_version/__init__.py,sha256=BEBWj9tcbFUwzEjUrqly601rauw5cYsHdcmJHs3iu0s,470
166
168
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
167
- modal_version/_version_generated.py,sha256=ut0wAyoP-7s5gVURkLb4fKBrb9HgRbFc7l23f9RyI24,149
168
- modal-0.68.50.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
169
- modal-0.68.50.dist-info/METADATA,sha256=bfjb4nM-LUkYVatsQ2-SdK_EOyiNICQFyKfYV5mRQjw,2329
170
- modal-0.68.50.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
171
- modal-0.68.50.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
172
- modal-0.68.50.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
173
- modal-0.68.50.dist-info/RECORD,,
169
+ modal_version/_version_generated.py,sha256=Ryi8NC5BNPKr4cGNqMzFAc_4pmvMQHAGNycNZBu1EBI,148
170
+ modal-0.71.5.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
171
+ modal-0.71.5.dist-info/METADATA,sha256=-r6kJm_xHIGyfR0rcCVEpqeh7hJcMF9WlwUEaGzcm8k,2328
172
+ modal-0.71.5.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
173
+ modal-0.71.5.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
174
+ modal-0.71.5.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
175
+ modal-0.71.5.dist-info/RECORD,,
modal_proto/api.proto CHANGED
@@ -1479,6 +1479,8 @@ message FunctionGetOutputsRequest {
1479
1479
  string last_entry_id = 6;
1480
1480
  bool clear_on_success = 7; // expires *any* remaining outputs soon after this call, not just the returned ones
1481
1481
  double requested_at = 8; // Used for waypoints.
1482
+ // The jwts the client expects the server to be processing. This is optional and used for sync inputs only.
1483
+ repeated string input_jwts = 9;
1482
1484
  }
1483
1485
 
1484
1486
  message FunctionGetOutputsResponse {
@@ -1678,6 +1680,7 @@ message GenericResult { // Used for both tasks and function outputs
1678
1680
  // Used when the user's function fails to initialize (ex. S3 mount failed due to invalid credentials).
1679
1681
  // Terminates the function and all remaining inputs.
1680
1682
  GENERIC_STATUS_INIT_FAILURE = 5;
1683
+ GENERIC_STATUS_INTERNAL_FAILURE = 6;
1681
1684
  }
1682
1685
 
1683
1686
  GenericStatus status = 1; // Status of the task or function output.
@@ -1727,6 +1730,15 @@ message ImageContextFile {
1727
1730
  bytes data = 2;
1728
1731
  }
1729
1732
 
1733
+ message ImageFromIdRequest {
1734
+ string image_id = 1;
1735
+ }
1736
+
1737
+ message ImageFromIdResponse {
1738
+ string image_id = 1;
1739
+ ImageMetadata metadata = 2;
1740
+ }
1741
+
1730
1742
  message ImageGetOrCreateRequest {
1731
1743
  Image image = 2;
1732
1744
  string app_id = 4 [ (modal.options.audit_target_attr) = true ];
@@ -2794,6 +2806,7 @@ service ModalClient {
2794
2806
  rpc FunctionUpdateSchedulingParams(FunctionUpdateSchedulingParamsRequest) returns (FunctionUpdateSchedulingParamsResponse);
2795
2807
 
2796
2808
  // Images
2809
+ rpc ImageFromId(ImageFromIdRequest) returns (ImageFromIdResponse);
2797
2810
  rpc ImageGetOrCreate(ImageGetOrCreateRequest) returns (ImageGetOrCreateResponse);
2798
2811
  rpc ImageJoinStreaming(ImageJoinStreamingRequest) returns (stream ImageJoinStreamingResponse);
2799
2812