modal 0.73.27__py3-none-any.whl → 0.73.29__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/_resolver.py CHANGED
@@ -142,8 +142,7 @@ class Resolver:
142
142
  and obj.object_id != existing_object_id
143
143
  ):
144
144
  raise Exception(
145
- f"Tried creating an object using existing id {existing_object_id}"
146
- f" but it has id {obj.object_id}"
145
+ f"Tried creating an object using existing id {existing_object_id} but it has id {obj.object_id}"
147
146
  )
148
147
 
149
148
  return obj
@@ -896,7 +896,7 @@ class _ContainerIOManager:
896
896
  gpu_process_state = gpu_memory_snapshot.get_state()
897
897
  if gpu_process_state != gpu_memory_snapshot.CudaCheckpointState.RUNNING:
898
898
  raise ValueError(
899
- "Cannot snapshot GPU state if it isn't running. " f"Current GPU state: {gpu_process_state}"
899
+ f"Cannot snapshot GPU state if it isn't running. Current GPU state: {gpu_process_state}"
900
900
  )
901
901
 
902
902
  gpu_memory_snapshot.toggle()
@@ -10,10 +10,10 @@ import modal._runtime.container_io_manager
10
10
  import modal.cls
11
11
  from modal import Function
12
12
  from modal._functions import _Function
13
+ from modal._partial_function import _find_partial_methods_for_user_cls, _PartialFunctionFlags
13
14
  from modal._utils.async_utils import synchronizer
14
15
  from modal._utils.function_utils import LocalFunctionError, is_async as get_is_async, is_global_object
15
16
  from modal.exception import ExecutionError, InvalidError
16
- from modal.partial_function import _find_partial_methods_for_user_cls, _PartialFunctionFlags
17
17
  from modal_proto import api_pb2
18
18
 
19
19
  if typing.TYPE_CHECKING:
@@ -46,8 +46,7 @@ class Service(metaclass=ABCMeta):
46
46
  @abstractmethod
47
47
  def get_finalized_functions(
48
48
  self, fun_def: api_pb2.Function, container_io_manager: "modal._runtime.container_io_manager.ContainerIOManager"
49
- ) -> dict[str, "FinalizedFunction"]:
50
- ...
49
+ ) -> dict[str, "FinalizedFunction"]: ...
51
50
 
52
51
 
53
52
  def construct_webhook_callable(
@@ -139,7 +138,7 @@ class ImportedClass(Service):
139
138
  app: Optional["modal.app._App"]
140
139
  code_deps: Optional[Sequence["modal._object._Object"]]
141
140
 
142
- _partial_functions: dict[str, "modal.partial_function._PartialFunction"]
141
+ _partial_functions: dict[str, "modal._partial_function._PartialFunction"]
143
142
 
144
143
  def get_finalized_functions(
145
144
  self, fun_def: api_pb2.Function, container_io_manager: "modal._runtime.container_io_manager.ContainerIOManager"
@@ -505,13 +505,11 @@ async def sync_or_async_iter(iter: Union[Iterable[T], AsyncIterable[T]]) -> Asyn
505
505
 
506
506
 
507
507
  @typing.overload
508
- def async_zip(g1: AsyncGenerator[T, None], g2: AsyncGenerator[V, None], /) -> AsyncGenerator[tuple[T, V], None]:
509
- ...
508
+ def async_zip(g1: AsyncGenerator[T, None], g2: AsyncGenerator[V, None], /) -> AsyncGenerator[tuple[T, V], None]: ...
510
509
 
511
510
 
512
511
  @typing.overload
513
- def async_zip(*generators: AsyncGenerator[T, None]) -> AsyncGenerator[tuple[T, ...], None]:
514
- ...
512
+ def async_zip(*generators: AsyncGenerator[T, None]) -> AsyncGenerator[tuple[T, ...], None]: ...
515
513
 
516
514
 
517
515
  async def async_zip(*generators):
@@ -561,8 +559,7 @@ class ExceptionWrapper:
561
559
  value: Exception
562
560
 
563
561
 
564
- class StopSentinelType:
565
- ...
562
+ class StopSentinelType: ...
566
563
 
567
564
 
568
565
  STOP_SENTINEL = StopSentinelType()
@@ -227,7 +227,7 @@ async def blob_upload(payload: bytes, stub: ModalClientModal) -> str:
227
227
  blob_id = await _blob_upload(upload_hashes, payload, stub)
228
228
  dur_s = max(time.time() - t0, 0.001) # avoid division by zero
229
229
  throughput_mib_s = (size_mib) / dur_s
230
- logger.debug(f"Uploaded large blob of size {size_mib:.2f} MiB ({throughput_mib_s:.2f} MiB/s)." f" {blob_id}")
230
+ logger.debug(f"Uploaded large blob of size {size_mib:.2f} MiB ({throughput_mib_s:.2f} MiB/s). {blob_id}")
231
231
  return blob_id
232
232
 
233
233
 
@@ -246,7 +246,6 @@ class FunctionInfo:
246
246
 
247
247
  def get_cls_var_attrs(self) -> dict[str, Any]:
248
248
  import dis
249
-
250
249
  import opcode
251
250
 
252
251
  LOAD_ATTR = opcode.opmap["LOAD_ATTR"]
@@ -603,7 +602,7 @@ class FunctionCreationStatus:
603
602
  for custom_domain in self.response.function.custom_domain_info:
604
603
  custom_domain_status_row = self.resolver.add_status_row()
605
604
  custom_domain_status_row.finish(
606
- f"Custom domain for {self.tag} => [magenta underline]" f"{custom_domain.url}[/magenta underline]"
605
+ f"Custom domain for {self.tag} => [magenta underline]{custom_domain.url}[/magenta underline]"
607
606
  )
608
607
  else:
609
608
  self.status_row.finish(f"Created function {self.tag}.")
modal/app.py CHANGED
@@ -23,6 +23,11 @@ from modal_proto import api_pb2
23
23
  from ._functions import _Function
24
24
  from ._ipython import is_notebook
25
25
  from ._object import _get_environment_name, _Object
26
+ from ._partial_function import (
27
+ _find_partial_methods_for_user_cls,
28
+ _PartialFunction,
29
+ _PartialFunctionFlags,
30
+ )
26
31
  from ._utils.async_utils import synchronize_api
27
32
  from ._utils.deprecation import deprecation_error, deprecation_warning, renamed_parameter
28
33
  from ._utils.function_utils import FunctionInfo, is_global_object, is_method_fn
@@ -38,12 +43,7 @@ from .gpu import GPU_T
38
43
  from .image import _Image
39
44
  from .mount import _Mount
40
45
  from .network_file_system import _NetworkFileSystem
41
- from .partial_function import (
42
- PartialFunction,
43
- _find_partial_methods_for_user_cls,
44
- _PartialFunction,
45
- _PartialFunctionFlags,
46
- )
46
+ from .partial_function import PartialFunction
47
47
  from .proxy import _Proxy
48
48
  from .retries import Retries
49
49
  from .running_app import RunningApp
@@ -102,21 +102,19 @@ class _FunctionDecoratorType:
102
102
  @overload
103
103
  def __call__(
104
104
  self, func: PartialFunction[P, ReturnType, OriginalReturnType]
105
- ) -> Function[P, ReturnType, OriginalReturnType]:
106
- ... # already wrapped by a modal decorator, e.g. web_endpoint
105
+ ) -> Function[P, ReturnType, OriginalReturnType]: ... # already wrapped by a modal decorator, e.g. web_endpoint
107
106
 
108
107
  @overload
109
108
  def __call__(
110
109
  self, func: Callable[P, Coroutine[Any, Any, ReturnType]]
111
- ) -> Function[P, ReturnType, Coroutine[Any, Any, ReturnType]]:
112
- ... # decorated async function
110
+ ) -> Function[P, ReturnType, Coroutine[Any, Any, ReturnType]]: ... # decorated async function
113
111
 
114
112
  @overload
115
- def __call__(self, func: Callable[P, ReturnType]) -> Function[P, ReturnType, ReturnType]:
116
- ... # decorated non-async function
113
+ def __call__(
114
+ self, func: Callable[P, ReturnType]
115
+ ) -> Function[P, ReturnType, ReturnType]: ... # decorated non-async function
117
116
 
118
- def __call__(self, func):
119
- ...
117
+ def __call__(self, func): ...
120
118
 
121
119
 
122
120
  class _App:
modal/cli/entry_point.py CHANGED
@@ -69,7 +69,7 @@ def check_path():
69
69
  "[red]The `[white]modal[/white]` command is not executable!\n"
70
70
  "You may need to give it permissions or use `[white]python -m modal[/white]` as a workaround.[/red]\n"
71
71
  )
72
- text += "See more information here:\n\n" f"[link={url}]{url}[/link]\n"
72
+ text += f"See more information here:\n\n[link={url}]{url}[/link]\n"
73
73
  console = Console()
74
74
  console.print(text)
75
75
  console.print(Rule(style="white"))
modal/cli/run.py CHANGED
@@ -230,8 +230,7 @@ def _get_click_command_for_cls(app: App, method_ref: MethodReference):
230
230
  method_name = method_names[0]
231
231
  else:
232
232
  raise click.UsageError(
233
- f"Please specify a specific method of {cls._get_name()} to run, "
234
- f"e.g. `modal run foo.py::MyClass.bar`" # noqa: E501
233
+ f"Please specify a specific method of {cls._get_name()} to run, e.g. `modal run foo.py::MyClass.bar`" # noqa: E501
235
234
  )
236
235
 
237
236
  partial_function = partial_functions[method_name]
@@ -493,7 +492,7 @@ def shell(
493
492
  cloud: Optional[str] = typer.Option(
494
493
  default=None,
495
494
  help=(
496
- "Cloud provider to run the shell on. " "Possible values are `aws`, `gcp`, `oci`, `auto` (if not using REF)."
495
+ "Cloud provider to run the shell on. Possible values are `aws`, `gcp`, `oci`, `auto` (if not using REF)."
497
496
  ),
498
497
  ),
499
498
  region: Optional[str] = typer.Option(
modal/cli/secret.py CHANGED
@@ -85,7 +85,7 @@ def some_function():
85
85
  """
86
86
  plural_s = "s" if len(env_dict) > 1 else ""
87
87
  console.print(
88
- f"""Created a new secret '{secret_name}' with the key{plural_s} {', '.join(repr(k) for k in env_dict.keys())}"""
88
+ f"""Created a new secret '{secret_name}' with the key{plural_s} {", ".join(repr(k) for k in env_dict.keys())}"""
89
89
  )
90
90
  console.print("\nUse it in to your Modal app using:\n")
91
91
  console.print(Syntax(example_code, "python"))
modal/cli/volume.py CHANGED
@@ -297,8 +297,7 @@ async def rename(
297
297
  ):
298
298
  if not yes:
299
299
  typer.confirm(
300
- f"Are you sure you want rename the modal.Volume '{old_name}'?"
301
- " This may break any Apps currently using it.",
300
+ f"Are you sure you want rename the modal.Volume '{old_name}'? This may break any Apps currently using it.",
302
301
  default=False,
303
302
  abort=True,
304
303
  )
modal/client.pyi CHANGED
@@ -27,7 +27,7 @@ class _Client:
27
27
  _snapshotted: bool
28
28
 
29
29
  def __init__(
30
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.27"
30
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.29"
31
31
  ): ...
32
32
  def is_closed(self) -> bool: ...
33
33
  @property
@@ -85,7 +85,7 @@ class Client:
85
85
  _snapshotted: bool
86
86
 
87
87
  def __init__(
88
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.27"
88
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.29"
89
89
  ): ...
90
90
  def is_closed(self) -> bool: ...
91
91
  @property
modal/cls.py CHANGED
@@ -13,6 +13,12 @@ from modal_proto import api_pb2
13
13
 
14
14
  from ._functions import _Function, _parse_retries
15
15
  from ._object import _Object
16
+ from ._partial_function import (
17
+ _find_callables_for_obj,
18
+ _find_partial_methods_for_user_cls,
19
+ _PartialFunction,
20
+ _PartialFunctionFlags,
21
+ )
16
22
  from ._resolver import Resolver
17
23
  from ._resources import convert_fn_config_to_resources_config
18
24
  from ._serialization import check_valid_cls_constructor_arg
@@ -25,12 +31,6 @@ from .client import _Client
25
31
  from .config import config
26
32
  from .exception import ExecutionError, InvalidError, NotFoundError
27
33
  from .gpu import GPU_T
28
- from .partial_function import (
29
- _find_callables_for_obj,
30
- _find_partial_methods_for_user_cls,
31
- _PartialFunction,
32
- _PartialFunctionFlags,
33
- )
34
34
  from .retries import Retries
35
35
  from .secret import _Secret
36
36
  from .volume import _Volume
@@ -674,8 +674,7 @@ class _Cls(_Object, type_prefix="cs"):
674
674
  )
675
675
 
676
676
  def __getattr__(self, k):
677
- # Used by CLI and container entrypoint
678
- # TODO: remove this method - access to attributes on classes should be discouraged
677
+ # TODO: remove this method - access to attributes on classes (not instances) should be discouraged
679
678
  if k in self._method_functions:
680
679
  deprecation_warning(
681
680
  (2025, 1, 13),
modal/cls.pyi CHANGED
@@ -3,6 +3,7 @@ import google.protobuf.message
3
3
  import inspect
4
4
  import modal._functions
5
5
  import modal._object
6
+ import modal._partial_function
6
7
  import modal.app
7
8
  import modal.client
8
9
  import modal.functions
@@ -104,7 +105,7 @@ class _Cls(modal._object._Object):
104
105
 
105
106
  def _initialize_from_empty(self): ...
106
107
  def _initialize_from_other(self, other: _Cls): ...
107
- def _get_partial_functions(self) -> dict[str, modal.partial_function._PartialFunction]: ...
108
+ def _get_partial_functions(self) -> dict[str, modal._partial_function._PartialFunction]: ...
108
109
  def _get_app(self) -> modal.app._App: ...
109
110
  def _get_user_cls(self) -> type: ...
110
111
  def _get_name(self) -> str: ...
modal/environments.py CHANGED
@@ -29,9 +29,7 @@ class _Environment(_Object, type_prefix="en"):
29
29
 
30
30
  def __init__(self):
31
31
  """mdmd:hidden"""
32
- raise RuntimeError(
33
- "`Environment(...)` constructor is not allowed." " Please use `Environment.from_name` instead."
34
- )
32
+ raise RuntimeError("`Environment(...)` constructor is not allowed. Please use `Environment.from_name` instead.")
35
33
 
36
34
  # TODO(michael) Keeping this private for now until we decide what else should be in it
37
35
  # And what the rules should be about updates / mutability
modal/experimental.py CHANGED
@@ -7,11 +7,11 @@ from modal_proto import api_pb2
7
7
  from ._clustered_functions import ClusterInfo, get_cluster_info as _get_cluster_info
8
8
  from ._functions import _Function
9
9
  from ._object import _get_environment_name
10
+ from ._partial_function import _PartialFunction, _PartialFunctionFlags
10
11
  from ._runtime.container_io_manager import _ContainerIOManager
11
12
  from ._utils.async_utils import synchronizer
12
13
  from .client import _Client
13
14
  from .exception import InvalidError
14
- from .partial_function import _PartialFunction, _PartialFunctionFlags
15
15
 
16
16
 
17
17
  def stop_fetching_inputs():
@@ -47,8 +47,7 @@ class _AbstractPatternMatcher:
47
47
  return super().__repr__()
48
48
 
49
49
  @abstractmethod
50
- def __call__(self, path: Path) -> bool:
51
- ...
50
+ def __call__(self, path: Path) -> bool: ...
52
51
 
53
52
 
54
53
  class _CustomPatternMatcher(_AbstractPatternMatcher):
modal/mount.py CHANGED
@@ -78,20 +78,16 @@ def python_standalone_mount_name(version: str) -> str:
78
78
 
79
79
  class _MountEntry(metaclass=abc.ABCMeta):
80
80
  @abc.abstractmethod
81
- def description(self) -> str:
82
- ...
81
+ def description(self) -> str: ...
83
82
 
84
83
  @abc.abstractmethod
85
- def get_files_to_upload(self) -> typing.Iterator[tuple[Path, str]]:
86
- ...
84
+ def get_files_to_upload(self) -> typing.Iterator[tuple[Path, str]]: ...
87
85
 
88
86
  @abc.abstractmethod
89
- def watch_entry(self) -> tuple[Path, Path]:
90
- ...
87
+ def watch_entry(self) -> tuple[Path, Path]: ...
91
88
 
92
89
  @abc.abstractmethod
93
- def top_level_paths(self) -> list[tuple[Path, PurePosixPath]]:
94
- ...
90
+ def top_level_paths(self) -> list[tuple[Path, PurePosixPath]]: ...
95
91
 
96
92
 
97
93
  def _select_files(entries: list[_MountEntry]) -> list[tuple[Path, PurePosixPath]]:
modal/output.py CHANGED
@@ -6,6 +6,7 @@ transitively importing Rich, as we do in global scope in _output.py. This allows
6
6
  us to avoid importing Rich for client code that runs in the container environment.
7
7
 
8
8
  """
9
+
9
10
  import contextlib
10
11
  from collections.abc import Generator
11
12
  from typing import TYPE_CHECKING, Optional