modal 0.66.50__py3-none-any.whl → 0.66.51__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/client.pyi CHANGED
@@ -31,7 +31,7 @@ class _Client:
31
31
  server_url: str,
32
32
  client_type: int,
33
33
  credentials: typing.Optional[typing.Tuple[str, str]],
34
- version: str = "0.66.50",
34
+ version: str = "0.66.51",
35
35
  ): ...
36
36
  def is_closed(self) -> bool: ...
37
37
  @property
@@ -90,7 +90,7 @@ class Client:
90
90
  server_url: str,
91
91
  client_type: int,
92
92
  credentials: typing.Optional[typing.Tuple[str, str]],
93
- version: str = "0.66.50",
93
+ version: str = "0.66.51",
94
94
  ): ...
95
95
  def is_closed(self) -> bool: ...
96
96
  @property
modal/image.py CHANGED
@@ -19,7 +19,6 @@ from typing import (
19
19
  Optional,
20
20
  Sequence,
21
21
  Set,
22
- Tuple,
23
22
  Union,
24
23
  cast,
25
24
  get_args,
@@ -36,6 +35,7 @@ from ._utils.async_utils import synchronize_api
36
35
  from ._utils.blob_utils import MAX_OBJECT_SIZE_BYTES
37
36
  from ._utils.function_utils import FunctionInfo
38
37
  from ._utils.grpc_utils import RETRYABLE_GRPC_STATUS_CODES, retry_transient_errors
38
+ from .client import _Client
39
39
  from .cloud_bucket_mount import _CloudBucketMount
40
40
  from .config import config, logger, user_config_path
41
41
  from .environments import _get_environment_cached
@@ -52,7 +52,6 @@ from .volume import _Volume
52
52
  if typing.TYPE_CHECKING:
53
53
  import modal.functions
54
54
 
55
-
56
55
  # This is used for both type checking and runtime validation
57
56
  ImageBuilderVersion = Literal["2023.12", "2024.04", "2024.10"]
58
57
 
@@ -147,8 +146,8 @@ def _get_modal_requirements_command(version: ImageBuilderVersion) -> str:
147
146
  return f"{prefix} -r {CONTAINER_REQUIREMENTS_PATH}"
148
147
 
149
148
 
150
- def _flatten_str_args(function_name: str, arg_name: str, args: Tuple[Union[str, List[str]], ...]) -> List[str]:
151
- """Takes a tuple of strings, or string lists, and flattens it.
149
+ def _flatten_str_args(function_name: str, arg_name: str, args: Sequence[Union[str, List[str]]]) -> List[str]:
150
+ """Takes a sequence of strings, or string lists, and flattens it.
152
151
 
153
152
  Raises an error if any of the elements are not strings or string lists.
154
153
  """
@@ -244,7 +243,7 @@ class _ImageRegistryConfig:
244
243
  def __init__(
245
244
  self,
246
245
  # TODO: change to _PUBLIC after worker starts handling it.
247
- registry_auth_type: int = api_pb2.REGISTRY_AUTH_TYPE_UNSPECIFIED,
246
+ registry_auth_type: "api_pb2.RegistryAuthType.ValueType" = api_pb2.REGISTRY_AUTH_TYPE_UNSPECIFIED,
248
247
  secret: Optional[_Secret] = None,
249
248
  ):
250
249
  self.registry_auth_type = registry_auth_type
@@ -253,7 +252,7 @@ class _ImageRegistryConfig:
253
252
  def get_proto(self) -> api_pb2.ImageRegistryConfig:
254
253
  return api_pb2.ImageRegistryConfig(
255
254
  registry_auth_type=self.registry_auth_type,
256
- secret_id=(self.secret.object_id if self.secret else None),
255
+ secret_id=(self.secret.object_id if self.secret else ""),
257
256
  )
258
257
 
259
258
 
@@ -264,6 +263,45 @@ class DockerfileSpec:
264
263
  context_files: Dict[str, str]
265
264
 
266
265
 
266
+ async def _image_await_build_result(image_id: str, client: _Client) -> api_pb2.ImageJoinStreamingResponse:
267
+ last_entry_id: str = ""
268
+ result_response: Optional[api_pb2.ImageJoinStreamingResponse] = None
269
+
270
+ async def join():
271
+ nonlocal last_entry_id, result_response
272
+
273
+ request = api_pb2.ImageJoinStreamingRequest(image_id=image_id, timeout=55, last_entry_id=last_entry_id)
274
+ async for response in client.stub.ImageJoinStreaming.unary_stream(request):
275
+ if response.entry_id:
276
+ last_entry_id = response.entry_id
277
+ if response.result.status:
278
+ result_response = response
279
+ # can't return yet, since there may still be logs streaming back in subsequent responses
280
+ for task_log in response.task_logs:
281
+ if task_log.task_progress.pos or task_log.task_progress.len:
282
+ assert task_log.task_progress.progress_type == api_pb2.IMAGE_SNAPSHOT_UPLOAD
283
+ if output_mgr := _get_output_manager():
284
+ output_mgr.update_snapshot_progress(image_id, task_log.task_progress)
285
+ elif task_log.data:
286
+ if output_mgr := _get_output_manager():
287
+ await output_mgr.put_log_content(task_log)
288
+ if output_mgr := _get_output_manager():
289
+ output_mgr.flush_lines()
290
+
291
+ # Handle up to n exceptions while fetching logs
292
+ retry_count = 0
293
+ while result_response is None:
294
+ try:
295
+ await join()
296
+ except (StreamTerminatedError, GRPCError) as exc:
297
+ if isinstance(exc, GRPCError) and exc.status not in RETRYABLE_GRPC_STATUS_CODES:
298
+ raise exc
299
+ retry_count += 1
300
+ if retry_count >= 3:
301
+ raise exc
302
+ return result_response
303
+
304
+
267
305
  class _Image(_Object, type_prefix="im"):
268
306
  """Base class for container images to run functions in.
269
307
 
@@ -292,7 +330,7 @@ class _Image(_Object, type_prefix="im"):
292
330
  self._serve_mounts = other._serve_mounts
293
331
  self._deferred_mounts = other._deferred_mounts
294
332
 
295
- def _hydrate_metadata(self, message: Optional[Message]):
333
+ def _hydrate_metadata(self, metadata: Optional[Message]):
296
334
  env_image_id = config.get("image_id") # set as an env var in containers
297
335
  if env_image_id == self.object_id:
298
336
  for exc in self.inside_exceptions:
@@ -300,9 +338,9 @@ class _Image(_Object, type_prefix="im"):
300
338
  # if the hydrated image is the one used by the container
301
339
  raise exc
302
340
 
303
- if message:
304
- assert isinstance(message, api_pb2.ImageMetadata)
305
- self._metadata = message
341
+ if metadata:
342
+ assert isinstance(metadata, api_pb2.ImageMetadata)
343
+ self._metadata = metadata
306
344
 
307
345
  def _add_mount_layer_or_copy(self, mount: _Mount, copy: bool = False):
308
346
  if copy:
@@ -318,7 +356,7 @@ class _Image(_Object, type_prefix="im"):
318
356
  return _Image._from_loader(_load, "Image(local files)", deps=lambda: [base_image, mount])
319
357
 
320
358
  @property
321
- def _mount_layers(self) -> typing.Tuple[_Mount]:
359
+ def _mount_layers(self) -> typing.Sequence[_Mount]:
322
360
  """Non-evaluated mount layers on the image
323
361
 
324
362
  When the image is used by a Modal container, these mounts need to be attached as well to
@@ -362,7 +400,7 @@ class _Image(_Object, type_prefix="im"):
362
400
  context_mount: Optional[_Mount] = None,
363
401
  force_build: bool = False,
364
402
  # For internal use only.
365
- _namespace: int = api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
403
+ _namespace: "api_pb2.DeploymentNamespace.ValueType" = api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
366
404
  _do_assert_no_mount_layers: bool = True,
367
405
  ):
368
406
  if base_images is None:
@@ -382,14 +420,14 @@ class _Image(_Object, type_prefix="im"):
382
420
  if build_function and len(base_images) != 1:
383
421
  raise InvalidError("Cannot run a build function with multiple base images!")
384
422
 
385
- def _deps() -> List[_Object]:
386
- deps: List[_Object] = list(base_images.values()) + list(secrets)
423
+ def _deps() -> Sequence[_Object]:
424
+ deps = tuple(base_images.values()) + tuple(secrets)
387
425
  if build_function:
388
- deps.append(build_function)
426
+ deps += (build_function,)
389
427
  if context_mount:
390
- deps.append(context_mount)
391
- if image_registry_config.secret:
392
- deps.append(image_registry_config.secret)
428
+ deps += (context_mount,)
429
+ if image_registry_config and image_registry_config.secret:
430
+ deps += (image_registry_config.secret,)
393
431
  return deps
394
432
 
395
433
  async def _load(self: _Image, resolver: Resolver, existing_object_id: Optional[str]):
@@ -398,6 +436,7 @@ class _Image(_Object, type_prefix="im"):
398
436
  # base images can't have
399
437
  image._assert_no_mount_layers()
400
438
 
439
+ assert resolver.app_id # type narrowing
401
440
  environment = await _get_environment_cached(resolver.environment_name or "", resolver.client)
402
441
  # A bit hacky,but assume that the environment provides a valid builder version
403
442
  image_builder_version = cast(ImageBuilderVersion, environment._settings.image_builder_version)
@@ -432,7 +471,6 @@ class _Image(_Object, type_prefix="im"):
432
471
 
433
472
  if build_function:
434
473
  build_function_id = build_function.object_id
435
-
436
474
  globals = build_function._get_info().get_globals()
437
475
  attrs = build_function._get_info().get_cls_var_attrs()
438
476
  globals = {**globals, **attrs}
@@ -454,14 +492,14 @@ class _Image(_Object, type_prefix="im"):
454
492
 
455
493
  # Cloudpickle function serialization produces unstable values.
456
494
  # TODO: better way to filter out types that don't have a stable hash?
457
- build_function_globals = serialize(filtered_globals) if filtered_globals else None
495
+ build_function_globals = serialize(filtered_globals) if filtered_globals else b""
458
496
  _build_function = api_pb2.BuildFunction(
459
497
  definition=build_function.get_build_def(),
460
498
  globals=build_function_globals,
461
499
  input=build_function_input,
462
500
  )
463
501
  else:
464
- build_function_id = None
502
+ build_function_id = ""
465
503
  _build_function = None
466
504
 
467
505
  image_definition = api_pb2.Image(
@@ -470,7 +508,7 @@ class _Image(_Object, type_prefix="im"):
470
508
  context_files=context_file_pb2s,
471
509
  secret_ids=[secret.object_id for secret in secrets],
472
510
  gpu=bool(gpu_config.type), # Note: as of 2023-01-27, server still uses this
473
- context_mount_id=(context_mount.object_id if context_mount else None),
511
+ context_mount_id=(context_mount.object_id if context_mount else ""),
474
512
  gpu_config=gpu_config, # Note: as of 2023-01-27, server ignores this
475
513
  image_registry_config=image_registry_config.get_proto(),
476
514
  runtime=config.get("function_runtime"),
@@ -481,7 +519,7 @@ class _Image(_Object, type_prefix="im"):
481
519
  req = api_pb2.ImageGetOrCreateRequest(
482
520
  app_id=resolver.app_id,
483
521
  image=image_definition,
484
- existing_image_id=existing_object_id, # TODO: ignored
522
+ existing_image_id=existing_object_id or "", # TODO: ignored
485
523
  build_function_id=build_function_id,
486
524
  force_build=config.get("force_build") or force_build,
487
525
  namespace=_namespace,
@@ -492,46 +530,22 @@ class _Image(_Object, type_prefix="im"):
492
530
  )
493
531
  resp = await retry_transient_errors(resolver.client.stub.ImageGetOrCreate, req)
494
532
  image_id = resp.image_id
533
+ result: api_pb2.GenericResult
534
+ metadata: Optional[api_pb2.ImageMetadata] = None
535
+
536
+ if resp.result.status:
537
+ # image already built
538
+ result = resp.result
539
+ if resp.HasField("metadata"):
540
+ metadata = resp.metadata
541
+ else:
542
+ # not built or in the process of building - wait for build
543
+ logger.debug("Waiting for image %s" % image_id)
544
+ resp = await _image_await_build_result(image_id, resolver.client)
545
+ result = resp.result
546
+ if resp.HasField("metadata"):
547
+ metadata = resp.metadata
495
548
 
496
- logger.debug("Waiting for image %s" % image_id)
497
- last_entry_id: Optional[str] = None
498
- result_response: Optional[api_pb2.ImageJoinStreamingResponse] = None
499
-
500
- async def join():
501
- nonlocal last_entry_id, result_response
502
-
503
- request = api_pb2.ImageJoinStreamingRequest(image_id=image_id, timeout=55, last_entry_id=last_entry_id)
504
-
505
- async for response in resolver.client.stub.ImageJoinStreaming.unary_stream(request):
506
- if response.entry_id:
507
- last_entry_id = response.entry_id
508
- if response.result.status:
509
- result_response = response
510
- # can't return yet, since there may still be logs streaming back in subsequent responses
511
- for task_log in response.task_logs:
512
- if task_log.task_progress.pos or task_log.task_progress.len:
513
- assert task_log.task_progress.progress_type == api_pb2.IMAGE_SNAPSHOT_UPLOAD
514
- if output_mgr := _get_output_manager():
515
- output_mgr.update_snapshot_progress(image_id, task_log.task_progress)
516
- elif task_log.data:
517
- if output_mgr := _get_output_manager():
518
- await output_mgr.put_log_content(task_log)
519
- if output_mgr := _get_output_manager():
520
- output_mgr.flush_lines()
521
-
522
- # Handle up to n exceptions while fetching logs
523
- retry_count = 0
524
- while result_response is None:
525
- try:
526
- await join()
527
- except (StreamTerminatedError, GRPCError) as exc:
528
- if isinstance(exc, GRPCError) and exc.status not in RETRYABLE_GRPC_STATUS_CODES:
529
- raise exc
530
- retry_count += 1
531
- if retry_count >= 3:
532
- raise exc
533
-
534
- result = result_response.result
535
549
  if result.status == api_pb2.GenericResult.GENERIC_STATUS_FAILURE:
536
550
  raise RemoteError(f"Image build for {image_id} failed with the exception:\n{result.exception}")
537
551
  elif result.status == api_pb2.GenericResult.GENERIC_STATUS_TERMINATED:
@@ -545,7 +559,7 @@ class _Image(_Object, type_prefix="im"):
545
559
  else:
546
560
  raise RemoteError("Unknown status %s!" % result.status)
547
561
 
548
- self._hydrate(image_id, resolver.client, result_response.metadata)
562
+ self._hydrate(image_id, resolver.client, metadata)
549
563
  local_mounts = set()
550
564
  for base in base_images.values():
551
565
  local_mounts |= base._serve_mounts
@@ -666,7 +680,7 @@ class _Image(_Object, type_prefix="im"):
666
680
  context_mount=mount,
667
681
  )
668
682
 
669
- def _add_local_python_packages(self, *packages: Union[str, Path], copy: bool = False) -> "_Image":
683
+ def _add_local_python_packages(self, *packages: str, copy: bool = False) -> "_Image":
670
684
  """Adds Python package files to containers
671
685
 
672
686
  Adds all files from the specified Python packages to containers running the Image.
@@ -1632,7 +1646,7 @@ class _Image(_Object, type_prefix="im"):
1632
1646
  function = _Function.from_args(
1633
1647
  info,
1634
1648
  app=None,
1635
- image=self,
1649
+ image=self, # type: ignore[reportArgumentType] # TODO: probably conflict with type stub?
1636
1650
  secrets=secrets,
1637
1651
  gpu=gpu,
1638
1652
  mounts=mounts,
@@ -1744,7 +1758,7 @@ class _Image(_Object, type_prefix="im"):
1744
1758
 
1745
1759
  This method is considered private since its interface may change - use it at your own risk!
1746
1760
  """
1747
- last_entry_id: Optional[str] = None
1761
+ last_entry_id: str = ""
1748
1762
 
1749
1763
  request = api_pb2.ImageJoinStreamingRequest(
1750
1764
  image_id=self._object_id, timeout=55, last_entry_id=last_entry_id, include_logs_for_finished=True
modal/image.pyi CHANGED
@@ -1,4 +1,5 @@
1
1
  import google.protobuf.message
2
+ import modal.client
2
3
  import modal.cloud_bucket_mount
3
4
  import modal.functions
4
5
  import modal.gpu
@@ -28,7 +29,7 @@ def _get_modal_requirements_path(
28
29
  ) -> str: ...
29
30
  def _get_modal_requirements_command(version: typing.Literal["2023.12", "2024.04", "2024.10"]) -> str: ...
30
31
  def _flatten_str_args(
31
- function_name: str, arg_name: str, args: typing.Tuple[typing.Union[str, typing.List[str]], ...]
32
+ function_name: str, arg_name: str, args: typing.Sequence[typing.Union[str, typing.List[str]]]
32
33
  ) -> typing.List[str]: ...
33
34
  def _validate_packages(packages: typing.List[str]) -> bool: ...
34
35
  def _warn_invalid_packages(old_command: str) -> None: ...
@@ -55,6 +56,10 @@ class DockerfileSpec:
55
56
  def __repr__(self): ...
56
57
  def __eq__(self, other): ...
57
58
 
59
+ async def _image_await_build_result(
60
+ image_id: str, client: modal.client._Client
61
+ ) -> modal_proto.api_pb2.ImageJoinStreamingResponse: ...
62
+
58
63
  class _Image(modal.object._Object):
59
64
  force_build: bool
60
65
  inside_exceptions: typing.List[Exception]
@@ -64,10 +69,10 @@ class _Image(modal.object._Object):
64
69
 
65
70
  def _initialize_from_empty(self): ...
66
71
  def _initialize_from_other(self, other: _Image): ...
67
- def _hydrate_metadata(self, message: typing.Optional[google.protobuf.message.Message]): ...
72
+ def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
68
73
  def _add_mount_layer_or_copy(self, mount: modal.mount._Mount, copy: bool = False): ...
69
74
  @property
70
- def _mount_layers(self) -> typing.Tuple[modal.mount._Mount]: ...
75
+ def _mount_layers(self) -> typing.Sequence[modal.mount._Mount]: ...
71
76
  def _assert_no_mount_layers(self): ...
72
77
  @staticmethod
73
78
  def _from_args(
@@ -109,7 +114,7 @@ class _Image(modal.object._Object):
109
114
  def copy_local_file(
110
115
  self, local_path: typing.Union[str, pathlib.Path], remote_path: typing.Union[str, pathlib.Path] = "./"
111
116
  ) -> _Image: ...
112
- def _add_local_python_packages(self, *module_names, copy: bool = False) -> _Image: ...
117
+ def _add_local_python_packages(self, *module_names: str, copy: bool = False) -> _Image: ...
113
118
  def copy_local_dir(
114
119
  self, local_path: typing.Union[str, pathlib.Path], remote_path: typing.Union[str, pathlib.Path] = "."
115
120
  ) -> _Image: ...
@@ -321,10 +326,10 @@ class Image(modal.object.Object):
321
326
  def __init__(self, *args, **kwargs): ...
322
327
  def _initialize_from_empty(self): ...
323
328
  def _initialize_from_other(self, other: Image): ...
324
- def _hydrate_metadata(self, message: typing.Optional[google.protobuf.message.Message]): ...
329
+ def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
325
330
  def _add_mount_layer_or_copy(self, mount: modal.mount.Mount, copy: bool = False): ...
326
331
  @property
327
- def _mount_layers(self) -> typing.Tuple[modal.mount.Mount]: ...
332
+ def _mount_layers(self) -> typing.Sequence[modal.mount.Mount]: ...
328
333
  def _assert_no_mount_layers(self): ...
329
334
  @staticmethod
330
335
  def _from_args(
@@ -366,7 +371,7 @@ class Image(modal.object.Object):
366
371
  def copy_local_file(
367
372
  self, local_path: typing.Union[str, pathlib.Path], remote_path: typing.Union[str, pathlib.Path] = "./"
368
373
  ) -> Image: ...
369
- def _add_local_python_packages(self, *module_names, copy: bool = False) -> Image: ...
374
+ def _add_local_python_packages(self, *module_names: str, copy: bool = False) -> Image: ...
370
375
  def copy_local_dir(
371
376
  self, local_path: typing.Union[str, pathlib.Path], remote_path: typing.Union[str, pathlib.Path] = "."
372
377
  ) -> Image: ...
modal/object.py CHANGED
@@ -205,7 +205,7 @@ class _Object:
205
205
  return self._local_uuid
206
206
 
207
207
  @property
208
- def object_id(self):
208
+ def object_id(self) -> str:
209
209
  """mdmd:hidden"""
210
210
  return self._object_id
211
211
 
modal/object.pyi CHANGED
@@ -86,7 +86,7 @@ class _Object:
86
86
  @property
87
87
  def local_uuid(self): ...
88
88
  @property
89
- def object_id(self): ...
89
+ def object_id(self) -> str: ...
90
90
  @property
91
91
  def is_hydrated(self) -> bool: ...
92
92
  @property
@@ -188,7 +188,7 @@ class Object:
188
188
  @property
189
189
  def local_uuid(self): ...
190
190
  @property
191
- def object_id(self): ...
191
+ def object_id(self) -> str: ...
192
192
  @property
193
193
  def is_hydrated(self) -> bool: ...
194
194
  @property
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modal
3
- Version: 0.66.50
3
+ Version: 0.66.51
4
4
  Summary: Python client library for Modal
5
5
  Author: Modal Labs
6
6
  Author-email: support@modal.com
@@ -19,7 +19,7 @@ modal/app.py,sha256=ZQux8ZGLblIWbKHn7s15mucx97EwbjJso9WKRTYYOf0,45208
19
19
  modal/app.pyi,sha256=sX2BXX_178lp8O_GvwZqsxDdxQi1j3DjNfthMvlMlJU,25273
20
20
  modal/call_graph.py,sha256=l-Wi6vM8aosCdHTWegcCyGeVJGFdZ_fzlCmbRVPBXFI,2593
21
21
  modal/client.py,sha256=4SpWb4n0nolITR36kADZl1tYLOg6avukmzZU56UQjCo,16385
22
- modal/client.pyi,sha256=WsQ9bDrSHJSCa_xKRMoYw6PEOP_ECRJoi3bI8fdUgdQ,7372
22
+ modal/client.pyi,sha256=--KnbBKK2zE8YAHDTeNIOJywSWrtrL-IPjR3oCBGwyc,7372
23
23
  modal/cloud_bucket_mount.py,sha256=eWQhCtMIczpokjfTZEgNBCGO_s5ft46PqTSLfKBykq4,5748
24
24
  modal/cloud_bucket_mount.pyi,sha256=tTF7M4FR9bTA30cFkz8qq3ZTlFL19NHU_36e_5GgAGA,1424
25
25
  modal/cls.py,sha256=apKnBOHKYEpBiMC8mRvHtCDJl1g0vP0tG1r8mUZ1yH0,24684
@@ -36,16 +36,16 @@ modal/experimental.py,sha256=jFuNbwrNHos47viMB9q-cHJSvf2RDxDdoEcss9plaZE,2302
36
36
  modal/functions.py,sha256=BxccB-3a1migZQ6JA6iiHZJQ7WQ-jYpmg9DEZoTxzcc,71639
37
37
  modal/functions.pyi,sha256=0JsvWf9vvj2fMSNIHoXmL9FS7sWoRU4hU6911PyqEls,24800
38
38
  modal/gpu.py,sha256=r4rL6uH3UJIQthzYvfWauXNyh01WqCPtKZCmmSX1fd4,6881
39
- modal/image.py,sha256=j-NH8pLWk4jd5UOGD4y6W7DHWoeb3rG_VR7zPLSqj-Q,78927
40
- modal/image.pyi,sha256=QEjjnl4ZSmqt7toHww5ZbhL2Re5qaFGgH7qADcJS_vA,24493
39
+ modal/image.py,sha256=GVCZaiF-kJHUuUMgP_7bjzZbne4tTgfnrZZuLoVhbd0,79545
40
+ modal/image.pyi,sha256=3rfae_E0KuNHqdi5j33nHXp_7P3tTkt7QKH5cXYczUc,24672
41
41
  modal/io_streams.py,sha256=XUsNsxRzDrhkjyb2Hx0hugCoOEz266SHQF8wP-VgsfY,14582
42
42
  modal/io_streams.pyi,sha256=WJmSI1WvZITUNBO7mnIuJgYdSKdbLaHk10V4GbttAVw,4452
43
43
  modal/mount.py,sha256=QZ4nabpbNU9tjLIPCq86rlHor9CXzADMkhJWBYfKKgg,27750
44
44
  modal/mount.pyi,sha256=nywUmeUELLY2OEnAc1NNBHmSxuEylTWBzkh6nuXkkuc,9965
45
45
  modal/network_file_system.py,sha256=P_LsILecyda1SRHU76Hk4Lq3M1HSx9shFJbaLThzw0U,14071
46
46
  modal/network_file_system.pyi,sha256=XLyUnDx55ExbJcF_xlKxRax_r06XTvSsQh-a-_EyCOU,7239
47
- modal/object.py,sha256=zbRFZIt-Z3NQtgZPzlcEdy7u36ug4tKAuntYQBR3sDM,9625
48
- modal/object.pyi,sha256=cwWg93H4rBk9evt1itLZAZXH5wUMyTJBZ_ADazgfjGg,8465
47
+ modal/object.py,sha256=V5_-x8-jQpJ4N0IkIJo0E1rE0RMVyQmcKgi0qEujXKk,9632
48
+ modal/object.pyi,sha256=GGbBOuBAW160EyZ6B0qquRBIzKwAD7pKQmx17StE-1g,8479
49
49
  modal/output.py,sha256=FtPR7yvjZMgdSKD_KYkIcwYgCOiV9EKYjaj7K55Hjvg,1940
50
50
  modal/parallel_map.py,sha256=lf8Wer6FAf8-dYqPqoL45cz7FYDU66-TF-h5CO2Kf5Q,16052
51
51
  modal/parallel_map.pyi,sha256=pOhT0P3DDYlwLx0fR3PTsecA7DI8uOdXC1N8i-ZkyOY,2328
@@ -159,10 +159,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
159
159
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
160
160
  modal_version/__init__.py,sha256=UnAuHBPuPSstqgdCOx0SBVdfhpeJnMlY_oxEbu44Izg,470
161
161
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
162
- modal_version/_version_generated.py,sha256=ebE9iJTKZYTHQ3sX0Co4kO9qZg6vc814hd9KvMgaFvk,149
163
- modal-0.66.50.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
164
- modal-0.66.50.dist-info/METADATA,sha256=VEm-0bnVheLxgWXX5oiYnLb2HXzro3kK9gvF_cnU3JA,2329
165
- modal-0.66.50.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
166
- modal-0.66.50.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
167
- modal-0.66.50.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
168
- modal-0.66.50.dist-info/RECORD,,
162
+ modal_version/_version_generated.py,sha256=d0s2aJxmegPa4z6NFL6-taTAcvWSkjfj--1VYzWQqNI,149
163
+ modal-0.66.51.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
164
+ modal-0.66.51.dist-info/METADATA,sha256=U1iJKZzf60IFCvEEZs6TQiDtV1pemOxwasscLry_CQ0,2329
165
+ modal-0.66.51.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
166
+ modal-0.66.51.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
167
+ modal-0.66.51.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
168
+ modal-0.66.51.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2024
2
2
 
3
3
  # Note: Reset this value to -1 whenever you make a minor `0.X` release of the client.
4
- build_number = 50 # git: 2903bbe
4
+ build_number = 51 # git: 442103d