modal 0.71.5__py3-none-any.whl → 0.71.9__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/image.pyi CHANGED
@@ -126,6 +126,8 @@ class _Image(modal.object._Object):
126
126
  remote_path: typing.Union[str, pathlib.Path] = ".",
127
127
  ignore: typing.Union[collections.abc.Sequence[str], typing.Callable[[pathlib.Path], bool]] = [],
128
128
  ) -> _Image: ...
129
+ @staticmethod
130
+ async def from_id(image_id: str, client: typing.Optional[modal.client._Client] = None) -> _Image: ...
129
131
  def pip_install(
130
132
  self,
131
133
  *packages: typing.Union[str, list[str]],
@@ -387,6 +389,13 @@ class Image(modal.object.Object):
387
389
  remote_path: typing.Union[str, pathlib.Path] = ".",
388
390
  ignore: typing.Union[collections.abc.Sequence[str], typing.Callable[[pathlib.Path], bool]] = [],
389
391
  ) -> Image: ...
392
+
393
+ class __from_id_spec(typing_extensions.Protocol):
394
+ def __call__(self, image_id: str, client: typing.Optional[modal.client.Client] = None) -> Image: ...
395
+ async def aio(self, image_id: str, client: typing.Optional[modal.client.Client] = None) -> Image: ...
396
+
397
+ from_id: __from_id_spec
398
+
390
399
  def pip_install(
391
400
  self,
392
401
  *packages: typing.Union[str, list[str]],
modal/io_streams.py CHANGED
@@ -14,8 +14,7 @@ from typing import (
14
14
  from grpclib import Status
15
15
  from grpclib.exceptions import GRPCError, StreamTerminatedError
16
16
 
17
- from modal.exception import InvalidError
18
- from modal.io_streams_helper import consume_stream_with_retries
17
+ from modal.exception import ClientClosed, InvalidError
19
18
  from modal_proto import api_pb2
20
19
 
21
20
  from ._utils.async_utils import synchronize_api
@@ -177,21 +176,34 @@ class _StreamReader(Generic[T]):
177
176
  if self._stream_type == StreamType.DEVNULL:
178
177
  return
179
178
 
180
- def item_handler(item: Optional[bytes]):
181
- if self._stream_type == StreamType.STDOUT and item is not None:
182
- print(item.decode("utf-8"), end="")
183
- elif self._stream_type == StreamType.PIPE:
184
- self._container_process_buffer.append(item)
179
+ completed = False
180
+ retries_remaining = 10
181
+ while not completed:
182
+ try:
183
+ iterator = _container_process_logs_iterator(self._object_id, self._file_descriptor, self._client)
185
184
 
186
- def completion_check(item: Optional[bytes]):
187
- return item is None
185
+ async for message in iterator:
186
+ if self._stream_type == StreamType.STDOUT and message:
187
+ print(message.decode("utf-8"), end="")
188
+ elif self._stream_type == StreamType.PIPE:
189
+ self._container_process_buffer.append(message)
190
+ if message is None:
191
+ completed = True
192
+ break
188
193
 
189
- iterator = _container_process_logs_iterator(self._object_id, self._file_descriptor, self._client)
190
- await consume_stream_with_retries(
191
- iterator,
192
- item_handler,
193
- completion_check,
194
- )
194
+ except (GRPCError, StreamTerminatedError, ClientClosed) as exc:
195
+ if retries_remaining > 0:
196
+ retries_remaining -= 1
197
+ if isinstance(exc, GRPCError):
198
+ if exc.status in RETRYABLE_GRPC_STATUS_CODES:
199
+ await asyncio.sleep(1.0)
200
+ continue
201
+ elif isinstance(exc, StreamTerminatedError):
202
+ continue
203
+ elif isinstance(exc, ClientClosed):
204
+ # If the client was closed, the user has triggered a cleanup.
205
+ break
206
+ raise exc
195
207
 
196
208
  async def _stream_container_process(self) -> AsyncGenerator[tuple[Optional[bytes], str], None]:
197
209
  """Streams the container process buffer to the reader."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modal
3
- Version: 0.71.5
3
+ Version: 0.71.9
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=-zUa567FgOKmF0TtFWQ6DgehUD2CMfABDBQ8oLSpjyc,29171
5
+ modal/_container_entrypoint.py,sha256=U1ZU-Sa0LC646YPh0AWSGVBHmzfTxYUiGu2viKzW-Zs,29643
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
@@ -19,7 +19,7 @@ modal/app.py,sha256=vEE0cK5QPF6_cdW5AJvcuWxz5KmeprHwBEtlDkVRHgE,45582
19
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=pjZG1Z_8vLGkYtlrkEBAkl9tV9wqACVl0a3qWxHPacQ,7278
22
+ modal/client.pyi,sha256=048oyStc76Dp_i9xUsae5Z7xDlIJBDpaDymVwl9eCj4,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
@@ -33,17 +33,16 @@ modal/environments.py,sha256=wbv9ttFCbzATGfwcmvYiG608PfHovx0AQmawsg-jmic,6660
33
33
  modal/environments.pyi,sha256=rF7oaaELoSNuoD6qImGnIbuGPtgWwR5SlcExyYJ61hQ,3515
34
34
  modal/exception.py,sha256=4JyO-SACaLNDe2QC48EjsK8GMkZ8AgEurZ8j1YdRu8E,5263
35
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
36
+ modal/file_io.py,sha256=lcMs_E9Xfm0YX1t9U2wNIBPnqHRxmImqjLW1GHqVmyg,20945
37
+ modal/file_io.pyi,sha256=NrIoB0YjIqZ8MDMe826xAnybT0ww_kxQM3iPLo82REU,8898
38
38
  modal/file_pattern_matcher.py,sha256=LaI7Paxg0xR9D-D7Tgc60xR0w1KZee22LjGbFie1Vms,5571
39
39
  modal/functions.py,sha256=3uJPbrEAWhpFfLfUnoRjGmvEUC-_wVh-8yNJBx8eVeM,68249
40
- modal/functions.pyi,sha256=LiSDgH-X7jcZ56pAoLMwo3x9Dzdp_3Sd7W5MVAJPoCg,25407
40
+ modal/functions.pyi,sha256=3ESJ61f8oEDycDmrpnuNB2vjFKuLBG_aqyliXPTdY7M,25407
41
41
  modal/gpu.py,sha256=MTxj6ql8EpgfBg8YmZ5a1cLznyuZFssX1qXbEX4LKVM,7503
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
42
+ modal/image.py,sha256=oKqqLhc3Ap2XMG5MKVlERKkMTwJPkNMNcSzxoZh4zuw,85259
43
+ modal/image.pyi,sha256=Pa1_LVr3FyNsnu_MhBO08fBgCeLazTEe25phYdu0bzE,25365
44
+ modal/io_streams.py,sha256=QkQiizKRzd5bnbKQsap31LJgBYlAnj4-XkV_50xPYX0,15079
45
45
  modal/io_streams.pyi,sha256=bCCVSxkMcosYd8O3PQDDwJw7TQ8JEcnYonLJ5t27TQs,4804
46
- modal/io_streams_helper.py,sha256=B5Ui56ph7LkRpZX0tAF80Q-gOMsvPPLx5bpIPX0kgDc,1772
47
46
  modal/mount.py,sha256=wOr-2vmKImsE3lHBII8hL2gYy5ng46R58QwId4JultQ,29313
48
47
  modal/mount.pyi,sha256=FiNV1wIKFvd0ZMZ0tm1mz6ZSA5Hjsge-kFSA5tPWfcI,10503
49
48
  modal/network_file_system.py,sha256=INj1TfN_Fsmabmlte7anvey1epodjbMmjBW_TIJSST4,14406
@@ -78,7 +77,7 @@ modal/token_flow.pyi,sha256=gOYtYujrWt_JFZeiI8EmfahXPx5GCR5Na-VaPQcWgEY,1937
78
77
  modal/volume.py,sha256=T-pLxCYqmqRO6OolpAXlPxomMu0RWjti2e4kUpaj2cQ,29229
79
78
  modal/volume.pyi,sha256=eekb2dnAAwFK_NO9ciAOOTthl8NP1iAmMFrCGgjDA2k,11100
80
79
  modal/_runtime/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
81
- modal/_runtime/asgi.py,sha256=Mjs859pSgOmtZL-YmEsSKN557v1A2Ax_5-ERgPfj55E,21920
80
+ modal/_runtime/asgi.py,sha256=c4hmaMW1pLo-cm7ouriJjieuFm4ZF6D2LMy0638sfOs,22139
82
81
  modal/_runtime/container_io_manager.py,sha256=HgDLjE78yy1P7WZTmsEVDf89YnFFWG63Ddes8uYLVDY,43764
83
82
  modal/_runtime/execution_context.py,sha256=E6ofm6j1POXGPxS841X3V7JU6NheVb8OkQc7JpLq4Kg,2712
84
83
  modal/_runtime/telemetry.py,sha256=T1RoAGyjBDr1swiM6pPsGRSITm7LI5FDK18oNXxY08U,5163
@@ -149,10 +148,10 @@ modal_global_objects/mounts/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0
149
148
  modal_global_objects/mounts/modal_client_package.py,sha256=W0E_yShsRojPzWm6LtIQqNVolapdnrZkm2hVEQuZK_4,767
150
149
  modal_global_objects/mounts/python_standalone.py,sha256=SL_riIxpd8mP4i4CLDCWiFFNj0Ltknm9c_UIGfX5d60,1836
151
150
  modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
152
- modal_proto/api.proto,sha256=yxqa3djtNDAD6_AolYTUR_BM5w2apPN6UIXcvjRAFvY,80137
151
+ modal_proto/api.proto,sha256=ERfCFygQvpd09LyVtpZ-eInPfJ4p6UIDh_z3za_rbsw,80174
153
152
  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
153
+ modal_proto/api_pb2.py,sha256=dJJ88RIIPlwyTBQk9rKfSfbAxeZXDZn7FpszS6mF0Qs,294984
154
+ modal_proto/api_pb2.pyi,sha256=I1cHME11tDMerj_8DzHF2SEwN1QorEfdjziW3_v-omA,393699
156
155
  modal_proto/api_pb2_grpc.py,sha256=4d5SwJPLldCqqHz_BGqmJLlX-BMG592WFKUQ6IBg5rg,222415
157
156
  modal_proto/api_pb2_grpc.pyi,sha256=C4c3jndI6TKEgVnx3vAmT86In4T9JKmB1CImiye_aQk,51822
158
157
  modal_proto/modal_api_grpc.py,sha256=eeH1vHXgwO768tM7DXqvj-P37u15SI00gZtm8_EK15I,13732
@@ -166,10 +165,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
166
165
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
167
166
  modal_version/__init__.py,sha256=BEBWj9tcbFUwzEjUrqly601rauw5cYsHdcmJHs3iu0s,470
168
167
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
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,,
168
+ modal_version/_version_generated.py,sha256=C2VvMSG13U4S4K9L9Nthr_lxGR7HiZeFshAyyUIHqC0,148
169
+ modal-0.71.9.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
170
+ modal-0.71.9.dist-info/METADATA,sha256=v1Vj6l8YKv41yUx7_9scp6tX0Sy0aR4e6qpp5ueMBIY,2328
171
+ modal-0.71.9.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
172
+ modal-0.71.9.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
173
+ modal-0.71.9.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
174
+ modal-0.71.9.dist-info/RECORD,,
modal_proto/api.proto CHANGED
@@ -298,6 +298,7 @@ message AppDeploymentHistory {
298
298
  string client_version = 3;
299
299
  double deployed_at = 4;
300
300
  string deployed_by = 5;
301
+ string deployed_by_avatar_url = 9;
301
302
  string tag = 6;
302
303
  uint32 rollback_version = 7;
303
304
  bool rollback_allowed = 8;