modal 0.67.5__py3-none-any.whl → 0.67.6__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/app.py CHANGED
@@ -313,23 +313,6 @@ class _App:
313
313
  if not isinstance(value, _Object):
314
314
  raise InvalidError(f"App attribute `{key}` with value {value!r} is not a valid Modal object")
315
315
 
316
- def _add_object(self, tag, obj):
317
- # TODO(erikbern): replace this with _add_function and _add_class
318
- if self._running_app:
319
- # If this is inside a container, then objects can be defined after app initialization.
320
- # So we may have to initialize objects once they get bound to the app.
321
- if tag in self._running_app.tag_to_object_id:
322
- object_id: str = self._running_app.tag_to_object_id[tag]
323
- metadata: Message = self._running_app.object_handle_metadata[object_id]
324
- obj._hydrate(object_id, self._client, metadata)
325
-
326
- if isinstance(obj, _Function):
327
- self._functions[tag] = obj
328
- elif isinstance(obj, _Cls):
329
- self._classes[tag] = obj
330
- else:
331
- raise RuntimeError(f"Expected `obj` to be a _Function or _Cls (got {type(obj)}")
332
-
333
316
  def __getitem__(self, tag: str):
334
317
  deprecation_error((2024, 3, 25), _app_attr_error)
335
318
 
@@ -481,10 +464,29 @@ class _App:
481
464
  if function.tag in self._classes:
482
465
  logger.warning(f"Warning: tag {function.tag} exists but is overridden by function")
483
466
 
484
- self._add_object(function.tag, function)
467
+ if self._running_app:
468
+ # If this is inside a container, then objects can be defined after app initialization.
469
+ # So we may have to initialize objects once they get bound to the app.
470
+ if function.tag in self._running_app.tag_to_object_id:
471
+ object_id: str = self._running_app.tag_to_object_id[function.tag]
472
+ metadata: Message = self._running_app.object_handle_metadata[object_id]
473
+ function._hydrate(object_id, self._client, metadata)
474
+
475
+ self._functions[function.tag] = function
485
476
  if is_web_endpoint:
486
477
  self._web_endpoints.append(function.tag)
487
478
 
479
+ def _add_class(self, tag: str, cls: _Cls):
480
+ if self._running_app:
481
+ # If this is inside a container, then objects can be defined after app initialization.
482
+ # So we may have to initialize objects once they get bound to the app.
483
+ if tag in self._running_app.tag_to_object_id:
484
+ object_id: str = self._running_app.tag_to_object_id[tag]
485
+ metadata: Message = self._running_app.object_handle_metadata[object_id]
486
+ cls._hydrate(object_id, self._client, metadata)
487
+
488
+ self._classes[tag] = cls
489
+
488
490
  def _init_container(self, client: _Client, running_app: RunningApp):
489
491
  self._app_id = running_app.app_id
490
492
  self._running_app = running_app
@@ -935,7 +937,7 @@ class _App:
935
937
  cls: _Cls = _Cls.from_local(user_cls, self, cls_func)
936
938
 
937
939
  tag: str = user_cls.__name__
938
- self._add_object(tag, cls)
940
+ self._add_class(tag, cls)
939
941
  return cls # type: ignore # a _Cls instance "simulates" being the user provided class
940
942
 
941
943
  return wrapper
@@ -1022,16 +1024,25 @@ class _App:
1022
1024
  bar.remote()
1023
1025
  ```
1024
1026
  """
1025
- indexed_objects = dict(**other_app._functions, **other_app._classes)
1026
- for tag, object in indexed_objects.items():
1027
- existing_object = indexed_objects.get(tag)
1028
- if existing_object and existing_object != object:
1027
+ for tag, function in other_app._functions.items():
1028
+ existing_function = self._functions.get(tag)
1029
+ if existing_function and existing_function != function:
1030
+ logger.warning(
1031
+ f"Named app function {tag} with existing value {existing_function} is being "
1032
+ f"overwritten by a different function {function}"
1033
+ )
1034
+
1035
+ self._add_function(function, False) # TODO(erikbern): webhook config?
1036
+
1037
+ for tag, cls in other_app._classes.items():
1038
+ existing_cls = self._classes.get(tag)
1039
+ if existing_cls and existing_cls != cls:
1029
1040
  logger.warning(
1030
- f"Named app object {tag} with existing value {existing_object} is being "
1031
- f"overwritten by a different object {object}"
1041
+ f"Named app class {tag} with existing value {existing_cls} is being "
1042
+ f"overwritten by a different class {cls}"
1032
1043
  )
1033
1044
 
1034
- self._add_object(tag, object)
1045
+ self._add_class(tag, cls)
1035
1046
 
1036
1047
  async def _logs(self, client: Optional[_Client] = None) -> AsyncGenerator[str, None]:
1037
1048
  """Stream logs from the app.
modal/app.pyi CHANGED
@@ -114,7 +114,6 @@ class _App:
114
114
  ) -> _App: ...
115
115
  def set_description(self, description: str): ...
116
116
  def _validate_blueprint_value(self, key: str, value: typing.Any): ...
117
- def _add_object(self, tag, obj): ...
118
117
  def __getitem__(self, tag: str): ...
119
118
  def __setitem__(self, tag: str, obj: modal.object._Object): ...
120
119
  def __getattr__(self, tag: str): ...
@@ -137,6 +136,7 @@ class _App:
137
136
  def _get_default_image(self): ...
138
137
  def _get_watch_mounts(self): ...
139
138
  def _add_function(self, function: modal.functions._Function, is_web_endpoint: bool): ...
139
+ def _add_class(self, tag: str, cls: modal.cls._Cls): ...
140
140
  def _init_container(self, client: modal.client._Client, running_app: modal.running_app.RunningApp): ...
141
141
  @property
142
142
  def registered_functions(self) -> typing.Dict[str, modal.functions._Function]: ...
@@ -321,7 +321,6 @@ class App:
321
321
 
322
322
  def set_description(self, description: str): ...
323
323
  def _validate_blueprint_value(self, key: str, value: typing.Any): ...
324
- def _add_object(self, tag, obj): ...
325
324
  def __getitem__(self, tag: str): ...
326
325
  def __setitem__(self, tag: str, obj: modal.object.Object): ...
327
326
  def __getattr__(self, tag: str): ...
@@ -363,6 +362,7 @@ class App:
363
362
  def _get_default_image(self): ...
364
363
  def _get_watch_mounts(self): ...
365
364
  def _add_function(self, function: modal.functions.Function, is_web_endpoint: bool): ...
365
+ def _add_class(self, tag: str, cls: modal.cls.Cls): ...
366
366
  def _init_container(self, client: modal.client.Client, running_app: modal.running_app.RunningApp): ...
367
367
  @property
368
368
  def registered_functions(self) -> typing.Dict[str, modal.functions.Function]: ...
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.67.5",
34
+ version: str = "0.67.6",
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.67.5",
93
+ version: str = "0.67.6",
94
94
  ): ...
95
95
  def is_closed(self) -> bool: ...
96
96
  @property
modal/functions.pyi CHANGED
@@ -436,11 +436,11 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
436
436
 
437
437
  _call_generator_nowait: ___call_generator_nowait_spec
438
438
 
439
- class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
439
+ class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
440
440
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
441
441
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
442
442
 
443
- remote: __remote_spec[ReturnType, P]
443
+ remote: __remote_spec[P, ReturnType]
444
444
 
445
445
  class __remote_gen_spec(typing_extensions.Protocol):
446
446
  def __call__(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
@@ -452,17 +452,17 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
452
452
  def _get_obj(self) -> typing.Optional[modal.cls.Obj]: ...
453
453
  def local(self, *args: P.args, **kwargs: P.kwargs) -> OriginalReturnType: ...
454
454
 
455
- class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
455
+ class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
456
456
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
457
457
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
458
458
 
459
- _experimental_spawn: ___experimental_spawn_spec[ReturnType, P]
459
+ _experimental_spawn: ___experimental_spawn_spec[P, ReturnType]
460
460
 
461
- class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
461
+ class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
462
462
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
463
463
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
464
464
 
465
- spawn: __spawn_spec[ReturnType, P]
465
+ spawn: __spawn_spec[P, ReturnType]
466
466
 
467
467
  def get_raw_f(self) -> typing.Callable[..., typing.Any]: ...
468
468
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modal
3
- Version: 0.67.5
3
+ Version: 0.67.6
4
4
  Summary: Python client library for Modal
5
5
  Author: Modal Labs
6
6
  Author-email: support@modal.com
@@ -15,11 +15,11 @@ modal/_traceback.py,sha256=1yNp1Dqq4qRIQp8idDp5PEqjwH4eA8MNI0FhFkCOFgo,4408
15
15
  modal/_tunnel.py,sha256=BC9Fbvr9xvE3UMp5t8rn4ek-jXu2uwU778cKPMJfTtM,6290
16
16
  modal/_tunnel.pyi,sha256=SA_Q0UGB-D9skFjv6CqlTnCEWU67a2xJxfwVdXtar3Y,1259
17
17
  modal/_watcher.py,sha256=STlDe73R7IS33a_GMW2HnDc3hCDKLdsBfMxRpVh-flA,3581
18
- modal/app.py,sha256=Nm__k-xIebchBkVM4qBdz4XbAfF4GTWmi00IEx_0_n4,45500
19
- modal/app.pyi,sha256=sX2BXX_178lp8O_GvwZqsxDdxQi1j3DjNfthMvlMlJU,25273
18
+ modal/app.py,sha256=J2vcc3MDUnawxgEe-WXvfISPGLLcdCPlCqnYk9TeP2I,46114
19
+ modal/app.pyi,sha256=AWJVT92FaRN7DvSA5tD5w3_E-_PJeEPXTAf8rcwxR60,25312
20
20
  modal/call_graph.py,sha256=l-Wi6vM8aosCdHTWegcCyGeVJGFdZ_fzlCmbRVPBXFI,2593
21
21
  modal/client.py,sha256=4SpWb4n0nolITR36kADZl1tYLOg6avukmzZU56UQjCo,16385
22
- modal/client.pyi,sha256=DwioUlUaUhBrb50Q3q3ZZrEPaIzry87laj5l2opfpXI,7370
22
+ modal/client.pyi,sha256=hJ4icHlSyz3LcVDSF0myB0Zi5G2mVoMS4Vr4uqiQKJY,7370
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=v3Uad6nTpHNwkAZ04KlQY3jZGgntKt5Onz6DusFRtg8,24706
@@ -34,7 +34,7 @@ modal/environments.pyi,sha256=oScvFAclF55-tL9UioLIL_SPBwgy_9O-BBvJ-PLbRgY,3542
34
34
  modal/exception.py,sha256=K-czk1oK8wFvK8snWrytXSByo2WNb9SJAlgBVPGWZBs,6417
35
35
  modal/experimental.py,sha256=jFuNbwrNHos47viMB9q-cHJSvf2RDxDdoEcss9plaZE,2302
36
36
  modal/functions.py,sha256=Gfr-IsAeH0uIHCSfVYNWSzjnnrN33LPY3Ui4S6c6Pvo,66953
37
- modal/functions.pyi,sha256=5i5CTK6Eic-80o8NAPXHPujg_qpLj9d95eN71lpYSxE,24375
37
+ modal/functions.pyi,sha256=1pFjUQBZx__UGaqJadYoMycQdlVb4jTex307VREzpQA,24375
38
38
  modal/gpu.py,sha256=r4rL6uH3UJIQthzYvfWauXNyh01WqCPtKZCmmSX1fd4,6881
39
39
  modal/image.py,sha256=DoubwAD9ebYNIEO3GJWbtAaJl_ZRW4K0tpIJdS9CZAg,79551
40
40
  modal/image.pyi,sha256=3rfae_E0KuNHqdi5j33nHXp_7P3tTkt7QKH5cXYczUc,24672
@@ -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=3IY-AWLH55r35_mQXIaut0jrJvoPuf1NZJBQQfSbPuo,470
161
161
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
162
- modal_version/_version_generated.py,sha256=oSCusXuRJhNxjKI1nhoJGUM9jZoGrCEMXuKzaocBL8s,148
163
- modal-0.67.5.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
164
- modal-0.67.5.dist-info/METADATA,sha256=oqZ1Di5flX86xT97UGavXlInaXyj17h83iEOOsUn3v0,2328
165
- modal-0.67.5.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
166
- modal-0.67.5.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
167
- modal-0.67.5.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
168
- modal-0.67.5.dist-info/RECORD,,
162
+ modal_version/_version_generated.py,sha256=w1TBMXGTDLGjMZ9q-CYFNmAgzYtrFjHKc0nUcuwOGEg,148
163
+ modal-0.67.6.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
164
+ modal-0.67.6.dist-info/METADATA,sha256=gEvosk6PchWUcuXAFRrWJcWX8J3vWX6bd9G_55uJ88o,2328
165
+ modal-0.67.6.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
166
+ modal-0.67.6.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
167
+ modal-0.67.6.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
168
+ modal-0.67.6.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 = 5 # git: 99a7dd7
4
+ build_number = 6 # git: d4f8c25
File without changes