modal 0.72.11__py3-none-any.whl → 0.72.14__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.
@@ -38,7 +38,7 @@ from modal.partial_function import (
38
38
  _find_callables_for_obj,
39
39
  _PartialFunctionFlags,
40
40
  )
41
- from modal.running_app import RunningApp
41
+ from modal.running_app import RunningApp, running_app_from_layout
42
42
  from modal_proto import api_pb2
43
43
 
44
44
  from ._runtime.container_io_manager import (
@@ -468,7 +468,7 @@ def main(container_args: api_pb2.ContainerArguments, client: Client):
468
468
  batch_wait_ms = function_def.batch_linger_ms or 0
469
469
 
470
470
  # Get ids and metadata for objects (primarily functions and classes) on the app
471
- container_app: RunningApp = container_io_manager.get_app_objects(container_args.app_layout)
471
+ container_app: RunningApp = running_app_from_layout(container_args.app_id, container_args.app_layout)
472
472
 
473
473
  # Initialize objects on the app.
474
474
  # This is basically only functions and classes - anything else is deprecated and will be unsupported soon
@@ -591,15 +591,10 @@ if __name__ == "__main__":
591
591
  logger.debug("Container: starting")
592
592
 
593
593
  container_args = api_pb2.ContainerArguments()
594
-
595
594
  container_arguments_path: Optional[str] = os.environ.get("MODAL_CONTAINER_ARGUMENTS_PATH")
596
595
  if container_arguments_path is None:
597
- # TODO(erikbern): this fallback is for old workers and we can remove it very soon (days)
598
- import base64
599
-
600
- container_args.ParseFromString(base64.b64decode(sys.argv[1]))
601
- else:
602
- container_args.ParseFromString(open(container_arguments_path, "rb").read())
596
+ raise RuntimeError("No path to the container arguments file provided!")
597
+ container_args.ParseFromString(open(container_arguments_path, "rb").read())
603
598
 
604
599
  # Note that we're creating the client in a synchronous context, but it will be running in a separate thread.
605
600
  # This is good because if the function is long running then we the client can still send heartbeats
@@ -35,7 +35,6 @@ from modal._utils.package_utils import parse_major_minor_version
35
35
  from modal.client import HEARTBEAT_INTERVAL, HEARTBEAT_TIMEOUT, _Client
36
36
  from modal.config import config, logger
37
37
  from modal.exception import ClientClosed, InputCancellation, InvalidError, SerializationError
38
- from modal.running_app import RunningApp, running_app_from_layout
39
38
  from modal_proto import api_pb2
40
39
 
41
40
  if TYPE_CHECKING:
@@ -449,16 +448,6 @@ class _ContainerIOManager:
449
448
 
450
449
  await asyncio.sleep(DYNAMIC_CONCURRENCY_INTERVAL_SECS)
451
450
 
452
- async def get_app_objects(self, app_layout: api_pb2.AppLayout) -> RunningApp:
453
- if len(app_layout.objects) == 0:
454
- # TODO(erikbern): this should never happen! let's keep it in here for a short second
455
- # until we've sanity checked that this is, in fact, dead code.
456
- req = api_pb2.AppGetLayoutRequest(app_id=self.app_id)
457
- resp = await retry_transient_errors(self._client.stub.AppGetLayout, req)
458
- app_layout = resp.app_layout
459
-
460
- return running_app_from_layout(self.app_id, app_layout)
461
-
462
451
  async def get_serialized_function(self) -> tuple[Optional[Any], Optional[Callable[..., Any]]]:
463
452
  # Fetch the serialized function definition
464
453
  request = api_pb2.FunctionGetSerializedRequest(function_id=self.function_id)
modal/cli/app.py CHANGED
@@ -26,9 +26,10 @@ app_cli = typer.Typer(name="app", help="Manage deployed and running apps.", no_a
26
26
  APP_STATE_TO_MESSAGE = {
27
27
  api_pb2.APP_STATE_DEPLOYED: Text("deployed", style="green"),
28
28
  api_pb2.APP_STATE_DETACHED: Text("ephemeral (detached)", style="green"),
29
+ api_pb2.APP_STATE_DETACHED_DISCONNECTED: Text("ephemeral (detached)", style="green"),
29
30
  api_pb2.APP_STATE_DISABLED: Text("disabled", style="dim"),
30
31
  api_pb2.APP_STATE_EPHEMERAL: Text("ephemeral", style="green"),
31
- api_pb2.APP_STATE_INITIALIZING: Text("initializing...", style="green"),
32
+ api_pb2.APP_STATE_INITIALIZING: Text("initializing...", style="yellow"),
32
33
  api_pb2.APP_STATE_STOPPED: Text("stopped", style="blue"),
33
34
  api_pb2.APP_STATE_STOPPING: Text("stopping...", style="blue"),
34
35
  }
modal/client.pyi CHANGED
@@ -26,7 +26,7 @@ class _Client:
26
26
  _stub: typing.Optional[modal_proto.api_grpc.ModalClientStub]
27
27
 
28
28
  def __init__(
29
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.72.11"
29
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.72.14"
30
30
  ): ...
31
31
  def is_closed(self) -> bool: ...
32
32
  @property
@@ -81,7 +81,7 @@ class Client:
81
81
  _stub: typing.Optional[modal_proto.api_grpc.ModalClientStub]
82
82
 
83
83
  def __init__(
84
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.72.11"
84
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.72.14"
85
85
  ): ...
86
86
  def is_closed(self) -> bool: ...
87
87
  @property
@@ -112,7 +112,7 @@ class FilePatternMatcher(_AbstractPatternMatcher):
112
112
  self._set_patterns(pattern)
113
113
 
114
114
  @classmethod
115
- def from_file(cls, file_path: Path) -> "FilePatternMatcher":
115
+ def from_file(cls, file_path: Union[str, Path]) -> "FilePatternMatcher":
116
116
  """Initialize a new FilePatternMatcher instance from a file.
117
117
 
118
118
  The patterns in the file will be read lazily when the matcher is first used.
@@ -122,17 +122,16 @@ class FilePatternMatcher(_AbstractPatternMatcher):
122
122
 
123
123
  **Usage:**
124
124
  ```python
125
- from pathlib import Path
126
125
  from modal import FilePatternMatcher
127
126
 
128
- matcher = FilePatternMatcher.from_file(Path("/path/to/ignorefile"))
127
+ matcher = FilePatternMatcher.from_file("/path/to/ignorefile")
129
128
  ```
130
129
 
131
130
  """
132
131
  uninitialized = cls.__new__(cls)
133
132
 
134
133
  def _delayed_init():
135
- uninitialized._set_patterns(file_path.read_text("utf8").splitlines())
134
+ uninitialized._set_patterns(Path(file_path).read_text("utf8").splitlines())
136
135
  uninitialized._delayed_init = None
137
136
 
138
137
  uninitialized._delayed_init = _delayed_init
modal/image.py CHANGED
@@ -741,7 +741,6 @@ class _Image(_Object, type_prefix="im"):
741
741
  **Usage:**
742
742
 
743
743
  ```python
744
- from pathlib import Path
745
744
  from modal import FilePatternMatcher
746
745
 
747
746
  image = modal.Image.debian_slim().add_local_dir(
@@ -773,7 +772,7 @@ class _Image(_Object, type_prefix="im"):
773
772
  image = modal.Image.debian_slim().add_local_dir(
774
773
  "~/assets",
775
774
  remote_path="/assets",
776
- ignore=FilePatternMatcher.from_file(Path("/path/to/ignorefile")),
775
+ ignore=FilePatternMatcher.from_file("/path/to/ignorefile"),
777
776
  )
778
777
  ```
779
778
  """
@@ -892,7 +891,7 @@ class _Image(_Object, type_prefix="im"):
892
891
  image = modal.Image.debian_slim().copy_local_dir(
893
892
  "~/assets",
894
893
  remote_path="/assets",
895
- ignore=FilePatternMatcher.from_file(Path("/path/to/ignorefile")),
894
+ ignore=FilePatternMatcher.from_file("/path/to/ignorefile"),
896
895
  )
897
896
  ```
898
897
  """
@@ -1292,7 +1291,6 @@ class _Image(_Object, type_prefix="im"):
1292
1291
  **Usage:**
1293
1292
 
1294
1293
  ```python
1295
- from pathlib import Path
1296
1294
  from modal import FilePatternMatcher
1297
1295
 
1298
1296
  # By default a .dockerignore file is used if present in the current working directory
@@ -1324,7 +1322,7 @@ class _Image(_Object, type_prefix="im"):
1324
1322
  # You can also read ignore patterns from a file.
1325
1323
  image = modal.Image.debian_slim().dockerfile_commands(
1326
1324
  ["COPY data /data"],
1327
- ignore=FilePatternMatcher.from_file(Path("/path/to/dockerignore")),
1325
+ ignore=FilePatternMatcher.from_file("/path/to/dockerignore"),
1328
1326
  )
1329
1327
  ```
1330
1328
  """
@@ -1730,7 +1728,6 @@ class _Image(_Object, type_prefix="im"):
1730
1728
  **Usage:**
1731
1729
 
1732
1730
  ```python
1733
- from pathlib import Path
1734
1731
  from modal import FilePatternMatcher
1735
1732
 
1736
1733
  # By default a .dockerignore file is used if present in the current working directory
@@ -1768,7 +1765,7 @@ class _Image(_Object, type_prefix="im"):
1768
1765
  image = modal.Image.from_dockerfile(
1769
1766
  "./Dockerfile",
1770
1767
  add_python="3.12",
1771
- ignore=FilePatternMatcher.from_file(Path("/path/to/dockerignore")),
1768
+ ignore=FilePatternMatcher.from_file("/path/to/dockerignore"),
1772
1769
  )
1773
1770
  ```
1774
1771
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modal
3
- Version: 0.72.11
3
+ Version: 0.72.14
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=U1ZU-Sa0LC646YPh0AWSGVBHmzfTxYUiGu2viKzW-Zs,29643
5
+ modal/_container_entrypoint.py,sha256=xvz2kZAI0y02BZVSlpyrdgKHk2WCYEqI_iu1FBRDCOM,29553
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=1h8v96KuIg_SAdWDK9gNWVOYYFciBIerhldRPjvDgxs,45511
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=-v1O2T9BTfBTfxYRuIJbvAhIZ1mBB5Teo1SrqDFvBjw,7280
22
+ modal/client.pyi,sha256=GQWztWiyEIfPTabqLPkp7W-UD1k0TP2V3Fz18FzHYIw,7280
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=iKDSd8cDTH-txXygdV8q1m8XPnflDieDHemMEIqSSkg,31666
@@ -35,11 +35,11 @@ modal/exception.py,sha256=4JyO-SACaLNDe2QC48EjsK8GMkZ8AgEurZ8j1YdRu8E,5263
35
35
  modal/experimental.py,sha256=npfKbyMpI41uZZs9HW_QiB3E4ykWfDXZbACXXbw6qeA,2385
36
36
  modal/file_io.py,sha256=lcMs_E9Xfm0YX1t9U2wNIBPnqHRxmImqjLW1GHqVmyg,20945
37
37
  modal/file_io.pyi,sha256=NrIoB0YjIqZ8MDMe826xAnybT0ww_kxQM3iPLo82REU,8898
38
- modal/file_pattern_matcher.py,sha256=2ozXoalgCByA-aVk81Jv9W4_DWqLgBZAix_NADwPOrs,6527
38
+ modal/file_pattern_matcher.py,sha256=dSo7BMQGZBAuoBFOX-e_72HxmF3FLzjQlEtnGtJiaD4,6506
39
39
  modal/functions.py,sha256=3uJPbrEAWhpFfLfUnoRjGmvEUC-_wVh-8yNJBx8eVeM,68249
40
40
  modal/functions.pyi,sha256=3ESJ61f8oEDycDmrpnuNB2vjFKuLBG_aqyliXPTdY7M,25407
41
41
  modal/gpu.py,sha256=MTxj6ql8EpgfBg8YmZ5a1cLznyuZFssX1qXbEX4LKVM,7503
42
- modal/image.py,sha256=iqfN-SjjIFhl-qtUWiMrPvdwzvU7r4DP1xb64fI-HU4,90870
42
+ modal/image.py,sha256=0eGAw3bImUTS0KzsfnsKreixaZlbWfutgoluo7Hq7RQ,90747
43
43
  modal/image.pyi,sha256=NfZyLkl4rmxpc5fokaO4mmEeGFOwGn0AndV1vKwBdbs,26027
44
44
  modal/io_streams.py,sha256=QkQiizKRzd5bnbKQsap31LJgBYlAnj4-XkV_50xPYX0,15079
45
45
  modal/io_streams.pyi,sha256=bCCVSxkMcosYd8O3PQDDwJw7TQ8JEcnYonLJ5t27TQs,4804
@@ -78,7 +78,7 @@ modal/volume.py,sha256=NoqdOTrjSUEBkUj-Of_oi7I_yCuNmaLqr3TIsTWOddM,29674
78
78
  modal/volume.pyi,sha256=GfyVeLyM7DMiBlg0I5N6OtJl0Bzv0-rNQXkWVO0j5c0,11903
79
79
  modal/_runtime/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
80
80
  modal/_runtime/asgi.py,sha256=c4hmaMW1pLo-cm7ouriJjieuFm4ZF6D2LMy0638sfOs,22139
81
- modal/_runtime/container_io_manager.py,sha256=HgDLjE78yy1P7WZTmsEVDf89YnFFWG63Ddes8uYLVDY,43764
81
+ modal/_runtime/container_io_manager.py,sha256=drb-cY78h8P9Krzmmjex7uZlSSocniEF5cIXmUcvGnY,43145
82
82
  modal/_runtime/execution_context.py,sha256=E6ofm6j1POXGPxS841X3V7JU6NheVb8OkQc7JpLq4Kg,2712
83
83
  modal/_runtime/telemetry.py,sha256=T1RoAGyjBDr1swiM6pPsGRSITm7LI5FDK18oNXxY08U,5163
84
84
  modal/_runtime/user_code_imports.py,sha256=n4CQOojzSdf0jwSKSy6MEnVX3IWl3t3Dq54-x9VS2Ds,14663
@@ -108,7 +108,7 @@ modal/_vendor/tblib.py,sha256=g1O7QUDd3sDoLd8YPFltkXkih7r_fyZOjgmGuligv3s,9722
108
108
  modal/cli/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
109
109
  modal/cli/_download.py,sha256=t6BXZwjTd9MgznDvbsV8rp0FZWggdzC-lUAGZU4xx1g,3984
110
110
  modal/cli/_traceback.py,sha256=QlLa_iw3fAOA-mqCqjS8qAxvNT48J3YY3errtVVc2cw,7316
111
- modal/cli/app.py,sha256=HkwI38FZxx66jxiur4o_DRN3uwyO3L8hqgyo8oXKZxc,7726
111
+ modal/cli/app.py,sha256=UlLT1MI-b_6wHxpXNOBYBFeoL8yL3QxBSwc2fkTUQYI,7817
112
112
  modal/cli/config.py,sha256=pXPLmX0bIoV57rQNqIPK7V-yllj-GPRY4jiBO_EklGg,1667
113
113
  modal/cli/container.py,sha256=nCySVD10VJPzmX3ghTsGmpxdYeVYYMW6ofjsyt2gQcM,3667
114
114
  modal/cli/dict.py,sha256=HaEcjfll7i3Uj3Fg56aj4407if5UljsYfr6fIq-D2W8,4589
@@ -165,10 +165,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
165
165
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
166
166
  modal_version/__init__.py,sha256=kGya2ZlItX2zB7oHORs-wvP4PG8lg_mtbi1QIK3G6SQ,470
167
167
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
168
- modal_version/_version_generated.py,sha256=FPmkQVTa6nKAChte3cN9prcAec5i3YiqoaRn0MUcYPM,149
169
- modal-0.72.11.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
170
- modal-0.72.11.dist-info/METADATA,sha256=wj2_hujzH9hRZv4peAFdwX1wnUN9U1SRbdF_MwxmBxQ,2329
171
- modal-0.72.11.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
172
- modal-0.72.11.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
173
- modal-0.72.11.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
174
- modal-0.72.11.dist-info/RECORD,,
168
+ modal_version/_version_generated.py,sha256=akfNCe9ewTF8ZA9Rqpqg5WBGCylfEOseJrnKAd1MYKs,149
169
+ modal-0.72.14.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
170
+ modal-0.72.14.dist-info/METADATA,sha256=9QVZVvT7IvNfwSEaIq2WacjZI3QBQwGfnGXzMyJkUdU,2329
171
+ modal-0.72.14.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
172
+ modal-0.72.14.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
173
+ modal-0.72.14.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
174
+ modal-0.72.14.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2025
2
2
 
3
3
  # Note: Reset this value to -1 whenever you make a minor `0.X` release of the client.
4
- build_number = 11 # git: b7c5fbb
4
+ build_number = 14 # git: 6e1e498