modal 0.67.6__py3-none-any.whl → 0.67.11__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.
Files changed (103) hide show
  1. modal/_clustered_functions.py +2 -2
  2. modal/_clustered_functions.pyi +2 -2
  3. modal/_container_entrypoint.py +5 -4
  4. modal/_output.py +29 -28
  5. modal/_pty.py +2 -2
  6. modal/_resolver.py +6 -5
  7. modal/_resources.py +3 -3
  8. modal/_runtime/asgi.py +7 -6
  9. modal/_runtime/container_io_manager.py +22 -26
  10. modal/_runtime/execution_context.py +2 -2
  11. modal/_runtime/telemetry.py +1 -2
  12. modal/_runtime/user_code_imports.py +12 -14
  13. modal/_serialization.py +3 -7
  14. modal/_traceback.py +5 -5
  15. modal/_tunnel.py +4 -3
  16. modal/_tunnel.pyi +2 -2
  17. modal/_utils/async_utils.py +8 -15
  18. modal/_utils/blob_utils.py +4 -3
  19. modal/_utils/function_utils.py +14 -10
  20. modal/_utils/grpc_testing.py +7 -6
  21. modal/_utils/grpc_utils.py +2 -3
  22. modal/_utils/hash_utils.py +2 -2
  23. modal/_utils/mount_utils.py +5 -4
  24. modal/_utils/package_utils.py +2 -3
  25. modal/_utils/pattern_matcher.py +6 -6
  26. modal/_utils/rand_pb_testing.py +3 -3
  27. modal/_utils/shell_utils.py +2 -1
  28. modal/_vendor/a2wsgi_wsgi.py +62 -72
  29. modal/_vendor/cloudpickle.py +1 -1
  30. modal/_watcher.py +8 -7
  31. modal/app.py +29 -34
  32. modal/app.pyi +102 -97
  33. modal/call_graph.py +6 -6
  34. modal/cli/_download.py +3 -2
  35. modal/cli/_traceback.py +4 -4
  36. modal/cli/app.py +4 -4
  37. modal/cli/container.py +4 -4
  38. modal/cli/dict.py +1 -1
  39. modal/cli/environment.py +2 -3
  40. modal/cli/launch.py +2 -2
  41. modal/cli/network_file_system.py +1 -1
  42. modal/cli/profile.py +1 -1
  43. modal/cli/programs/run_jupyter.py +2 -2
  44. modal/cli/programs/vscode.py +3 -3
  45. modal/cli/queues.py +1 -1
  46. modal/cli/run.py +6 -6
  47. modal/cli/secret.py +3 -3
  48. modal/cli/utils.py +2 -1
  49. modal/cli/volume.py +3 -3
  50. modal/client.py +6 -11
  51. modal/client.pyi +18 -27
  52. modal/cloud_bucket_mount.py +3 -3
  53. modal/cloud_bucket_mount.pyi +2 -2
  54. modal/cls.py +30 -30
  55. modal/cls.pyi +35 -34
  56. modal/config.py +3 -2
  57. modal/dict.py +4 -3
  58. modal/dict.pyi +10 -9
  59. modal/environments.py +3 -3
  60. modal/environments.pyi +3 -3
  61. modal/exception.py +2 -3
  62. modal/functions.py +105 -35
  63. modal/functions.pyi +71 -48
  64. modal/image.py +45 -48
  65. modal/image.pyi +102 -101
  66. modal/io_streams.py +4 -7
  67. modal/io_streams.pyi +14 -13
  68. modal/mount.py +23 -22
  69. modal/mount.pyi +28 -29
  70. modal/network_file_system.py +7 -6
  71. modal/network_file_system.pyi +12 -11
  72. modal/object.py +9 -8
  73. modal/object.pyi +47 -34
  74. modal/output.py +2 -1
  75. modal/parallel_map.py +4 -4
  76. modal/partial_function.py +9 -13
  77. modal/partial_function.pyi +17 -18
  78. modal/queue.py +9 -8
  79. modal/queue.pyi +23 -22
  80. modal/retries.py +38 -0
  81. modal/runner.py +8 -7
  82. modal/runner.pyi +8 -14
  83. modal/running_app.py +3 -3
  84. modal/sandbox.py +14 -13
  85. modal/sandbox.pyi +67 -72
  86. modal/scheduler_placement.py +2 -1
  87. modal/secret.py +7 -7
  88. modal/secret.pyi +12 -12
  89. modal/serving.py +4 -3
  90. modal/serving.pyi +5 -4
  91. modal/token_flow.py +3 -2
  92. modal/token_flow.pyi +3 -3
  93. modal/volume.py +7 -12
  94. modal/volume.pyi +17 -16
  95. {modal-0.67.6.dist-info → modal-0.67.11.dist-info}/METADATA +1 -1
  96. modal-0.67.11.dist-info/RECORD +168 -0
  97. modal_docs/mdmd/signatures.py +1 -2
  98. modal_version/_version_generated.py +1 -1
  99. modal-0.67.6.dist-info/RECORD +0 -168
  100. {modal-0.67.6.dist-info → modal-0.67.11.dist-info}/LICENSE +0 -0
  101. {modal-0.67.6.dist-info → modal-0.67.11.dist-info}/WHEEL +0 -0
  102. {modal-0.67.6.dist-info → modal-0.67.11.dist-info}/entry_points.txt +0 -0
  103. {modal-0.67.6.dist-info → modal-0.67.11.dist-info}/top_level.txt +0 -0
modal/object.pyi CHANGED
@@ -1,3 +1,4 @@
1
+ import collections.abc
1
2
  import google.protobuf.message
2
3
  import modal._resolver
3
4
  import modal.client
@@ -14,16 +15,18 @@ def _get_environment_name(
14
15
 
15
16
  class _Object:
16
17
  _type_prefix: typing.ClassVar[typing.Optional[str]]
17
- _prefix_to_type: typing.ClassVar[typing.Dict[str, type]]
18
- _load: typing.Optional[typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], typing.Awaitable[None]]]
18
+ _prefix_to_type: typing.ClassVar[dict[str, type]]
19
+ _load: typing.Optional[
20
+ typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
21
+ ]
19
22
  _preload: typing.Optional[
20
- typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], typing.Awaitable[None]]
23
+ typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
21
24
  ]
22
25
  _rep: str
23
26
  _is_another_app: bool
24
27
  _hydrate_lazily: bool
25
- _deps: typing.Optional[typing.Callable[..., typing.List[_Object]]]
26
- _deduplication_key: typing.Optional[typing.Callable[[], typing.Awaitable[typing.Hashable]]]
28
+ _deps: typing.Optional[typing.Callable[..., list[_Object]]]
29
+ _deduplication_key: typing.Optional[typing.Callable[[], collections.abc.Awaitable[collections.abc.Hashable]]]
27
30
  _object_id: str
28
31
  _client: modal.client._Client
29
32
  _is_hydrated: bool
@@ -36,15 +39,17 @@ class _Object:
36
39
  self,
37
40
  rep: str,
38
41
  load: typing.Optional[
39
- typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], typing.Awaitable[None]]
42
+ typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
40
43
  ] = None,
41
44
  is_another_app: bool = False,
42
45
  preload: typing.Optional[
43
- typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], typing.Awaitable[None]]
46
+ typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
44
47
  ] = None,
45
48
  hydrate_lazily: bool = False,
46
- deps: typing.Optional[typing.Callable[..., typing.List[_Object]]] = None,
47
- deduplication_key: typing.Optional[typing.Callable[[], typing.Awaitable[typing.Hashable]]] = None,
49
+ deps: typing.Optional[typing.Callable[..., list[_Object]]] = None,
50
+ deduplication_key: typing.Optional[
51
+ typing.Callable[[], collections.abc.Awaitable[collections.abc.Hashable]]
52
+ ] = None,
48
53
  ): ...
49
54
  def _unhydrate(self): ...
50
55
  def _initialize_from_empty(self): ...
@@ -59,23 +64,25 @@ class _Object:
59
64
  @classmethod
60
65
  def _from_loader(
61
66
  cls,
62
- load: typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], typing.Awaitable[None]],
67
+ load: typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]],
63
68
  rep: str,
64
69
  is_another_app: bool = False,
65
70
  preload: typing.Optional[
66
- typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], typing.Awaitable[None]]
71
+ typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
67
72
  ] = None,
68
73
  hydrate_lazily: bool = False,
69
- deps: typing.Optional[typing.Callable[..., typing.Sequence[_Object]]] = None,
70
- deduplication_key: typing.Optional[typing.Callable[[], typing.Awaitable[typing.Hashable]]] = None,
74
+ deps: typing.Optional[typing.Callable[..., collections.abc.Sequence[_Object]]] = None,
75
+ deduplication_key: typing.Optional[
76
+ typing.Callable[[], collections.abc.Awaitable[collections.abc.Hashable]]
77
+ ] = None,
71
78
  ): ...
72
79
  @classmethod
73
- def _get_type_from_id(cls: typing.Type[O], object_id: str) -> typing.Type[O]: ...
80
+ def _get_type_from_id(cls: type[O], object_id: str) -> type[O]: ...
74
81
  @classmethod
75
- def _is_id_type(cls: typing.Type[O], object_id) -> bool: ...
82
+ def _is_id_type(cls: type[O], object_id) -> bool: ...
76
83
  @classmethod
77
84
  def _new_hydrated(
78
- cls: typing.Type[O],
85
+ cls: type[O],
79
86
  object_id: str,
80
87
  client: modal.client._Client,
81
88
  handle_metadata: typing.Optional[google.protobuf.message.Message],
@@ -90,23 +97,23 @@ class _Object:
90
97
  @property
91
98
  def is_hydrated(self) -> bool: ...
92
99
  @property
93
- def deps(self) -> typing.Callable[..., typing.List[_Object]]: ...
100
+ def deps(self) -> typing.Callable[..., list[_Object]]: ...
94
101
  async def resolve(self, client: typing.Optional[modal.client._Client] = None): ...
95
102
 
96
103
  class Object:
97
104
  _type_prefix: typing.ClassVar[typing.Optional[str]]
98
- _prefix_to_type: typing.ClassVar[typing.Dict[str, type]]
105
+ _prefix_to_type: typing.ClassVar[dict[str, type]]
99
106
  _load: typing.Optional[
100
- typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], typing.Awaitable[None]]
107
+ typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
101
108
  ]
102
109
  _preload: typing.Optional[
103
- typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], typing.Awaitable[None]]
110
+ typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
104
111
  ]
105
112
  _rep: str
106
113
  _is_another_app: bool
107
114
  _hydrate_lazily: bool
108
- _deps: typing.Optional[typing.Callable[..., typing.List[Object]]]
109
- _deduplication_key: typing.Optional[typing.Callable[[], typing.Awaitable[typing.Hashable]]]
115
+ _deps: typing.Optional[typing.Callable[..., list[Object]]]
116
+ _deduplication_key: typing.Optional[typing.Callable[[], collections.abc.Awaitable[collections.abc.Hashable]]]
110
117
  _object_id: str
111
118
  _client: modal.client.Client
112
119
  _is_hydrated: bool
@@ -128,22 +135,28 @@ class Object:
128
135
  typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], None]
129
136
  ] = None,
130
137
  hydrate_lazily: bool = False,
131
- deps: typing.Optional[typing.Callable[..., typing.List[Object]]] = None,
132
- deduplication_key: typing.Optional[typing.Callable[[], typing.Hashable]] = None,
138
+ deps: typing.Optional[typing.Callable[..., list[Object]]] = None,
139
+ deduplication_key: typing.Optional[typing.Callable[[], collections.abc.Hashable]] = None,
133
140
  ): ...
134
141
  def aio(
135
142
  self,
136
143
  rep: str,
137
144
  load: typing.Optional[
138
- typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], typing.Awaitable[None]]
145
+ typing.Callable[
146
+ [_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]
147
+ ]
139
148
  ] = None,
140
149
  is_another_app: bool = False,
141
150
  preload: typing.Optional[
142
- typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], typing.Awaitable[None]]
151
+ typing.Callable[
152
+ [_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]
153
+ ]
143
154
  ] = None,
144
155
  hydrate_lazily: bool = False,
145
- deps: typing.Optional[typing.Callable[..., typing.List[Object]]] = None,
146
- deduplication_key: typing.Optional[typing.Callable[[], typing.Awaitable[typing.Hashable]]] = None,
156
+ deps: typing.Optional[typing.Callable[..., list[Object]]] = None,
157
+ deduplication_key: typing.Optional[
158
+ typing.Callable[[], collections.abc.Awaitable[collections.abc.Hashable]]
159
+ ] = None,
147
160
  ): ...
148
161
 
149
162
  _init: ___init_spec
@@ -168,16 +181,16 @@ class Object:
168
181
  typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], None]
169
182
  ] = None,
170
183
  hydrate_lazily: bool = False,
171
- deps: typing.Optional[typing.Callable[..., typing.Sequence[Object]]] = None,
172
- deduplication_key: typing.Optional[typing.Callable[[], typing.Hashable]] = None,
184
+ deps: typing.Optional[typing.Callable[..., collections.abc.Sequence[Object]]] = None,
185
+ deduplication_key: typing.Optional[typing.Callable[[], collections.abc.Hashable]] = None,
173
186
  ): ...
174
187
  @classmethod
175
- def _get_type_from_id(cls: typing.Type[_BLOCKING_O], object_id: str) -> typing.Type[_BLOCKING_O]: ...
188
+ def _get_type_from_id(cls: type[_BLOCKING_O], object_id: str) -> type[_BLOCKING_O]: ...
176
189
  @classmethod
177
- def _is_id_type(cls: typing.Type[_BLOCKING_O], object_id) -> bool: ...
190
+ def _is_id_type(cls: type[_BLOCKING_O], object_id) -> bool: ...
178
191
  @classmethod
179
192
  def _new_hydrated(
180
- cls: typing.Type[_BLOCKING_O],
193
+ cls: type[_BLOCKING_O],
181
194
  object_id: str,
182
195
  client: modal.client.Client,
183
196
  handle_metadata: typing.Optional[google.protobuf.message.Message],
@@ -192,7 +205,7 @@ class Object:
192
205
  @property
193
206
  def is_hydrated(self) -> bool: ...
194
207
  @property
195
- def deps(self) -> typing.Callable[..., typing.List[Object]]: ...
208
+ def deps(self) -> typing.Callable[..., list[Object]]: ...
196
209
 
197
210
  class __resolve_spec(typing_extensions.Protocol):
198
211
  def __call__(self, client: typing.Optional[modal.client.Client] = None): ...
modal/output.py CHANGED
@@ -7,7 +7,8 @@ us to avoid importing Rich for client code that runs in the container environmen
7
7
 
8
8
  """
9
9
  import contextlib
10
- from typing import TYPE_CHECKING, Generator, Optional
10
+ from collections.abc import Generator
11
+ from typing import TYPE_CHECKING, Optional
11
12
 
12
13
  if TYPE_CHECKING:
13
14
  from ._output import OutputManager
modal/parallel_map.py CHANGED
@@ -3,7 +3,7 @@ import asyncio
3
3
  import time
4
4
  import typing
5
5
  from dataclasses import dataclass
6
- from typing import Any, Callable, Dict, Optional, Set, Tuple
6
+ from typing import Any, Callable, Optional
7
7
 
8
8
  from grpclib import GRPCError, Status
9
9
 
@@ -95,8 +95,8 @@ async def _map_invocation(
95
95
  if count_update_callback is not None:
96
96
  count_update_callback(num_outputs, num_inputs)
97
97
 
98
- pending_outputs: Dict[str, int] = {} # Map input_id -> next expected gen_index value
99
- completed_outputs: Set[str] = set() # Set of input_ids whose outputs are complete (expecting no more values)
98
+ pending_outputs: dict[str, int] = {} # Map input_id -> next expected gen_index value
99
+ completed_outputs: set[str] = set() # Set of input_ids whose outputs are complete (expecting no more values)
100
100
 
101
101
  input_queue: asyncio.Queue = asyncio.Queue()
102
102
 
@@ -216,7 +216,7 @@ async def _map_invocation(
216
216
  )
217
217
  await retry_transient_errors(client.stub.FunctionGetOutputs, request)
218
218
 
219
- async def fetch_output(item: api_pb2.FunctionGetOutputsItem) -> Tuple[int, Any]:
219
+ async def fetch_output(item: api_pb2.FunctionGetOutputsItem) -> tuple[int, Any]:
220
220
  try:
221
221
  output = await _process_result(item.result, item.data_format, client.stub, client)
222
222
  except Exception as e:
modal/partial_function.py CHANGED
@@ -2,15 +2,11 @@
2
2
  import enum
3
3
  import inspect
4
4
  import typing
5
+ from collections.abc import Coroutine, Iterable
5
6
  from typing import (
6
7
  Any,
7
8
  Callable,
8
- Coroutine,
9
- Dict,
10
- Iterable,
11
- List,
12
9
  Optional,
13
- Type,
14
10
  Union,
15
11
  )
16
12
 
@@ -132,11 +128,11 @@ class _PartialFunction(typing.Generic[P, ReturnType, OriginalReturnType]):
132
128
  PartialFunction = synchronize_api(_PartialFunction)
133
129
 
134
130
 
135
- def _find_partial_methods_for_user_cls(user_cls: Type[Any], flags: int) -> Dict[str, _PartialFunction]:
131
+ def _find_partial_methods_for_user_cls(user_cls: type[Any], flags: int) -> dict[str, _PartialFunction]:
136
132
  """Grabs all method on a user class, and returns partials. Includes legacy methods."""
137
133
 
138
134
  # Build up a list of legacy attributes to check
139
- check_attrs: List[str] = []
135
+ check_attrs: list[str] = []
140
136
  if flags & _PartialFunctionFlags.BUILD:
141
137
  check_attrs += ["__build__", "__abuild__"]
142
138
  if flags & _PartialFunctionFlags.ENTER_POST_SNAPSHOT:
@@ -158,7 +154,7 @@ def _find_partial_methods_for_user_cls(user_cls: Type[Any], flags: int) -> Dict[
158
154
  )
159
155
  deprecation_error((2024, 2, 21), message)
160
156
 
161
- partial_functions: Dict[str, PartialFunction] = {}
157
+ partial_functions: dict[str, PartialFunction] = {}
162
158
  for parent_cls in user_cls.mro():
163
159
  if parent_cls is not object:
164
160
  for k, v in parent_cls.__dict__.items():
@@ -170,9 +166,9 @@ def _find_partial_methods_for_user_cls(user_cls: Type[Any], flags: int) -> Dict[
170
166
  return partial_functions
171
167
 
172
168
 
173
- def _find_callables_for_obj(user_obj: Any, flags: int) -> Dict[str, Callable[..., Any]]:
169
+ def _find_callables_for_obj(user_obj: Any, flags: int) -> dict[str, Callable[..., Any]]:
174
170
  """Grabs all methods for an object, and binds them to the class"""
175
- user_cls: Type = type(user_obj)
171
+ user_cls: type = type(user_obj)
176
172
  return {k: pf.raw_f.__get__(user_obj) for k, pf in _find_partial_methods_for_user_cls(user_cls, flags).items()}
177
173
 
178
174
 
@@ -256,9 +252,9 @@ def _method(
256
252
  return wrapper
257
253
 
258
254
 
259
- def _parse_custom_domains(custom_domains: Optional[Iterable[str]] = None) -> List[api_pb2.CustomDomainConfig]:
255
+ def _parse_custom_domains(custom_domains: Optional[Iterable[str]] = None) -> list[api_pb2.CustomDomainConfig]:
260
256
  assert not isinstance(custom_domains, str), "custom_domains must be `Iterable[str]` but is `str` instead."
261
- _custom_domains: List[api_pb2.CustomDomainConfig] = []
257
+ _custom_domains: list[api_pb2.CustomDomainConfig] = []
262
258
  if custom_domains is not None:
263
259
  for custom_domain in custom_domains:
264
260
  _custom_domains.append(api_pb2.CustomDomainConfig(name=custom_domain))
@@ -608,7 +604,7 @@ ExitHandlerType = Union[
608
604
  # NOTE: return types of these callables should be `Union[None, Awaitable[None]]` but
609
605
  # synchronicity type stubs would strip Awaitable so we use Any for now
610
606
  # Original, __exit__ style method signature (now deprecated)
611
- Callable[[Any, Optional[Type[BaseException]], Optional[BaseException], Any], Any],
607
+ Callable[[Any, Optional[type[BaseException]], Optional[BaseException], Any], Any],
612
608
  # Forward-looking unparameterized method
613
609
  Callable[[Any], Any],
614
610
  ]
@@ -1,3 +1,4 @@
1
+ import collections.abc
1
2
  import enum
2
3
  import modal.functions
3
4
  import modal_proto.api_pb2
@@ -81,10 +82,8 @@ class PartialFunction(typing.Generic[P, ReturnType, OriginalReturnType]):
81
82
  def __del__(self): ...
82
83
  def add_flags(self, flags) -> PartialFunction: ...
83
84
 
84
- def _find_partial_methods_for_user_cls(
85
- user_cls: typing.Type[typing.Any], flags: int
86
- ) -> typing.Dict[str, _PartialFunction]: ...
87
- def _find_callables_for_obj(user_obj: typing.Any, flags: int) -> typing.Dict[str, typing.Callable[..., typing.Any]]: ...
85
+ def _find_partial_methods_for_user_cls(user_cls: type[typing.Any], flags: int) -> dict[str, _PartialFunction]: ...
86
+ def _find_callables_for_obj(user_obj: typing.Any, flags: int) -> dict[str, typing.Callable[..., typing.Any]]: ...
88
87
 
89
88
  class _MethodDecoratorType:
90
89
  @typing.overload
@@ -95,9 +94,9 @@ class _MethodDecoratorType:
95
94
  def __call__(
96
95
  self,
97
96
  func: typing.Callable[
98
- typing_extensions.Concatenate[typing.Any, P], typing.Coroutine[typing.Any, typing.Any, ReturnType]
97
+ typing_extensions.Concatenate[typing.Any, P], collections.abc.Coroutine[typing.Any, typing.Any, ReturnType]
99
98
  ],
100
- ) -> PartialFunction[P, ReturnType, typing.Coroutine[typing.Any, typing.Any, ReturnType]]: ...
99
+ ) -> PartialFunction[P, ReturnType, collections.abc.Coroutine[typing.Any, typing.Any, ReturnType]]: ...
101
100
  @typing.overload
102
101
  def __call__(
103
102
  self, func: typing.Callable[typing_extensions.Concatenate[typing.Any, P], ReturnType]
@@ -110,29 +109,29 @@ def _method(
110
109
  keep_warm: typing.Optional[int] = None,
111
110
  ) -> _MethodDecoratorType: ...
112
111
  def _parse_custom_domains(
113
- custom_domains: typing.Optional[typing.Iterable[str]] = None,
114
- ) -> typing.List[modal_proto.api_pb2.CustomDomainConfig]: ...
112
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
113
+ ) -> list[modal_proto.api_pb2.CustomDomainConfig]: ...
115
114
  def _web_endpoint(
116
115
  _warn_parentheses_missing=None,
117
116
  *,
118
117
  method: str = "GET",
119
118
  label: typing.Optional[str] = None,
120
119
  docs: bool = False,
121
- custom_domains: typing.Optional[typing.Iterable[str]] = None,
120
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
122
121
  wait_for_response: bool = True,
123
122
  ) -> typing.Callable[[typing.Callable[P, ReturnType]], _PartialFunction[P, ReturnType, ReturnType]]: ...
124
123
  def _asgi_app(
125
124
  _warn_parentheses_missing=None,
126
125
  *,
127
126
  label: typing.Optional[str] = None,
128
- custom_domains: typing.Optional[typing.Iterable[str]] = None,
127
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
129
128
  wait_for_response: bool = True,
130
129
  ) -> typing.Callable[[typing.Callable[..., typing.Any]], _PartialFunction]: ...
131
130
  def _wsgi_app(
132
131
  _warn_parentheses_missing=None,
133
132
  *,
134
133
  label: typing.Optional[str] = None,
135
- custom_domains: typing.Optional[typing.Iterable[str]] = None,
134
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
136
135
  wait_for_response: bool = True,
137
136
  ) -> typing.Callable[[typing.Callable[..., typing.Any]], _PartialFunction]: ...
138
137
  def _web_server(
@@ -140,7 +139,7 @@ def _web_server(
140
139
  *,
141
140
  startup_timeout: float = 5.0,
142
141
  label: typing.Optional[str] = None,
143
- custom_domains: typing.Optional[typing.Iterable[str]] = None,
142
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
144
143
  ) -> typing.Callable[[typing.Callable[..., typing.Any]], _PartialFunction]: ...
145
144
  def _disallow_wrapping_method(f: _PartialFunction, wrapper: str) -> None: ...
146
145
  def _build(
@@ -155,7 +154,7 @@ def _exit(
155
154
  [
156
155
  typing.Union[
157
156
  typing.Callable[
158
- [typing.Any, typing.Optional[typing.Type[BaseException]], typing.Optional[BaseException], typing.Any],
157
+ [typing.Any, typing.Optional[type[BaseException]], typing.Optional[BaseException], typing.Any],
159
158
  typing.Any,
160
159
  ],
161
160
  typing.Callable[[typing.Any], typing.Any],
@@ -178,21 +177,21 @@ def web_endpoint(
178
177
  method: str = "GET",
179
178
  label: typing.Optional[str] = None,
180
179
  docs: bool = False,
181
- custom_domains: typing.Optional[typing.Iterable[str]] = None,
180
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
182
181
  wait_for_response: bool = True,
183
182
  ) -> typing.Callable[[typing.Callable[P, ReturnType]], PartialFunction[P, ReturnType, ReturnType]]: ...
184
183
  def asgi_app(
185
184
  _warn_parentheses_missing=None,
186
185
  *,
187
186
  label: typing.Optional[str] = None,
188
- custom_domains: typing.Optional[typing.Iterable[str]] = None,
187
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
189
188
  wait_for_response: bool = True,
190
189
  ) -> typing.Callable[[typing.Callable[..., typing.Any]], PartialFunction]: ...
191
190
  def wsgi_app(
192
191
  _warn_parentheses_missing=None,
193
192
  *,
194
193
  label: typing.Optional[str] = None,
195
- custom_domains: typing.Optional[typing.Iterable[str]] = None,
194
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
196
195
  wait_for_response: bool = True,
197
196
  ) -> typing.Callable[[typing.Callable[..., typing.Any]], PartialFunction]: ...
198
197
  def web_server(
@@ -200,7 +199,7 @@ def web_server(
200
199
  *,
201
200
  startup_timeout: float = 5.0,
202
201
  label: typing.Optional[str] = None,
203
- custom_domains: typing.Optional[typing.Iterable[str]] = None,
202
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
204
203
  ) -> typing.Callable[[typing.Callable[..., typing.Any]], PartialFunction]: ...
205
204
  def build(
206
205
  _warn_parentheses_missing=None, *, force: bool = False, timeout: int = 86400
@@ -214,7 +213,7 @@ def exit(
214
213
  [
215
214
  typing.Union[
216
215
  typing.Callable[
217
- [typing.Any, typing.Optional[typing.Type[BaseException]], typing.Optional[BaseException], typing.Any],
216
+ [typing.Any, typing.Optional[type[BaseException]], typing.Optional[BaseException], typing.Any],
218
217
  typing.Any,
219
218
  ],
220
219
  typing.Callable[[typing.Any], typing.Any],
modal/queue.py CHANGED
@@ -2,7 +2,8 @@
2
2
  import queue # The system library
3
3
  import time
4
4
  import warnings
5
- from typing import Any, AsyncGenerator, AsyncIterator, List, Optional, Type
5
+ from collections.abc import AsyncGenerator, AsyncIterator
6
+ from typing import Any, Optional
6
7
 
7
8
  from grpclib import GRPCError, Status
8
9
  from synchronicity.async_wrap import asynccontextmanager
@@ -113,7 +114,7 @@ class _Queue(_Object, type_prefix="qu"):
113
114
  @classmethod
114
115
  @asynccontextmanager
115
116
  async def ephemeral(
116
- cls: Type["_Queue"],
117
+ cls: type["_Queue"],
117
118
  client: Optional[_Client] = None,
118
119
  environment_name: Optional[str] = None,
119
120
  _heartbeat_sleep: float = EPHEMERAL_OBJECT_HEARTBEAT_SLEEP,
@@ -210,7 +211,7 @@ class _Queue(_Object, type_prefix="qu"):
210
211
  req = api_pb2.QueueDeleteRequest(queue_id=obj.object_id)
211
212
  await retry_transient_errors(obj._client.stub.QueueDelete, req)
212
213
 
213
- async def _get_nonblocking(self, partition: Optional[str], n_values: int) -> List[Any]:
214
+ async def _get_nonblocking(self, partition: Optional[str], n_values: int) -> list[Any]:
214
215
  request = api_pb2.QueueGetRequest(
215
216
  queue_id=self.object_id,
216
217
  partition_key=self.validate_partition_key(partition),
@@ -224,7 +225,7 @@ class _Queue(_Object, type_prefix="qu"):
224
225
  else:
225
226
  return []
226
227
 
227
- async def _get_blocking(self, partition: Optional[str], timeout: Optional[float], n_values: int) -> List[Any]:
228
+ async def _get_blocking(self, partition: Optional[str], timeout: Optional[float], n_values: int) -> list[Any]:
228
229
  if timeout is not None:
229
230
  deadline = time.time() + timeout
230
231
  else:
@@ -294,7 +295,7 @@ class _Queue(_Object, type_prefix="qu"):
294
295
  @live_method
295
296
  async def get_many(
296
297
  self, n_values: int, block: bool = True, timeout: Optional[float] = None, *, partition: Optional[str] = None
297
- ) -> List[Any]:
298
+ ) -> list[Any]:
298
299
  """Remove and return up to `n_values` objects from the queue.
299
300
 
300
301
  If there are fewer than `n_values` items in the queue, return all of them.
@@ -337,7 +338,7 @@ class _Queue(_Object, type_prefix="qu"):
337
338
  @live_method
338
339
  async def put_many(
339
340
  self,
340
- vs: List[Any],
341
+ vs: list[Any],
341
342
  block: bool = True,
342
343
  timeout: Optional[float] = None,
343
344
  *,
@@ -361,7 +362,7 @@ class _Queue(_Object, type_prefix="qu"):
361
362
  await self._put_many_nonblocking(partition, partition_ttl, vs)
362
363
 
363
364
  async def _put_many_blocking(
364
- self, partition: Optional[str], partition_ttl: int, vs: List[Any], timeout: Optional[float] = None
365
+ self, partition: Optional[str], partition_ttl: int, vs: list[Any], timeout: Optional[float] = None
365
366
  ):
366
367
  vs_encoded = [serialize(v) for v in vs]
367
368
 
@@ -390,7 +391,7 @@ class _Queue(_Object, type_prefix="qu"):
390
391
  else:
391
392
  raise exc
392
393
 
393
- async def _put_many_nonblocking(self, partition: Optional[str], partition_ttl: int, vs: List[Any]):
394
+ async def _put_many_nonblocking(self, partition: Optional[str], partition_ttl: int, vs: list[Any]):
394
395
  vs_encoded = [serialize(v) for v in vs]
395
396
  request = api_pb2.QueuePutRequest(
396
397
  queue_id=self.object_id,
modal/queue.pyi CHANGED
@@ -1,3 +1,4 @@
1
+ import collections.abc
1
2
  import modal.client
2
3
  import modal.object
3
4
  import synchronicity.combined_types
@@ -12,7 +13,7 @@ class _Queue(modal.object._Object):
12
13
  def validate_partition_key(partition: typing.Optional[str]) -> bytes: ...
13
14
  @classmethod
14
15
  def ephemeral(
15
- cls: typing.Type[_Queue],
16
+ cls: type[_Queue],
16
17
  client: typing.Optional[modal.client._Client] = None,
17
18
  environment_name: typing.Optional[str] = None,
18
19
  _heartbeat_sleep: float = 300,
@@ -36,10 +37,10 @@ class _Queue(modal.object._Object):
36
37
  client: typing.Optional[modal.client._Client] = None,
37
38
  environment_name: typing.Optional[str] = None,
38
39
  ): ...
39
- async def _get_nonblocking(self, partition: typing.Optional[str], n_values: int) -> typing.List[typing.Any]: ...
40
+ async def _get_nonblocking(self, partition: typing.Optional[str], n_values: int) -> list[typing.Any]: ...
40
41
  async def _get_blocking(
41
42
  self, partition: typing.Optional[str], timeout: typing.Optional[float], n_values: int
42
- ) -> typing.List[typing.Any]: ...
43
+ ) -> list[typing.Any]: ...
43
44
  async def clear(self, *, partition: typing.Optional[str] = None, all: bool = False) -> None: ...
44
45
  async def get(
45
46
  self, block: bool = True, timeout: typing.Optional[float] = None, *, partition: typing.Optional[str] = None
@@ -51,7 +52,7 @@ class _Queue(modal.object._Object):
51
52
  timeout: typing.Optional[float] = None,
52
53
  *,
53
54
  partition: typing.Optional[str] = None,
54
- ) -> typing.List[typing.Any]: ...
55
+ ) -> list[typing.Any]: ...
55
56
  async def put(
56
57
  self,
57
58
  v: typing.Any,
@@ -63,7 +64,7 @@ class _Queue(modal.object._Object):
63
64
  ) -> None: ...
64
65
  async def put_many(
65
66
  self,
66
- vs: typing.List[typing.Any],
67
+ vs: list[typing.Any],
67
68
  block: bool = True,
68
69
  timeout: typing.Optional[float] = None,
69
70
  *,
@@ -74,16 +75,16 @@ class _Queue(modal.object._Object):
74
75
  self,
75
76
  partition: typing.Optional[str],
76
77
  partition_ttl: int,
77
- vs: typing.List[typing.Any],
78
+ vs: list[typing.Any],
78
79
  timeout: typing.Optional[float] = None,
79
80
  ): ...
80
81
  async def _put_many_nonblocking(
81
- self, partition: typing.Optional[str], partition_ttl: int, vs: typing.List[typing.Any]
82
+ self, partition: typing.Optional[str], partition_ttl: int, vs: list[typing.Any]
82
83
  ): ...
83
84
  async def len(self, *, partition: typing.Optional[str] = None, total: bool = False) -> int: ...
84
85
  def iterate(
85
86
  self, *, partition: typing.Optional[str] = None, item_poll_timeout: float = 0.0
86
- ) -> typing.AsyncGenerator[typing.Any, None]: ...
87
+ ) -> collections.abc.AsyncGenerator[typing.Any, None]: ...
87
88
 
88
89
  class Queue(modal.object.Object):
89
90
  def __init__(self): ...
@@ -93,7 +94,7 @@ class Queue(modal.object.Object):
93
94
  def validate_partition_key(partition: typing.Optional[str]) -> bytes: ...
94
95
  @classmethod
95
96
  def ephemeral(
96
- cls: typing.Type[Queue],
97
+ cls: type[Queue],
97
98
  client: typing.Optional[modal.client.Client] = None,
98
99
  environment_name: typing.Optional[str] = None,
99
100
  _heartbeat_sleep: float = 300,
@@ -142,18 +143,18 @@ class Queue(modal.object.Object):
142
143
  delete: __delete_spec
143
144
 
144
145
  class ___get_nonblocking_spec(typing_extensions.Protocol):
145
- def __call__(self, partition: typing.Optional[str], n_values: int) -> typing.List[typing.Any]: ...
146
- async def aio(self, partition: typing.Optional[str], n_values: int) -> typing.List[typing.Any]: ...
146
+ def __call__(self, partition: typing.Optional[str], n_values: int) -> list[typing.Any]: ...
147
+ async def aio(self, partition: typing.Optional[str], n_values: int) -> list[typing.Any]: ...
147
148
 
148
149
  _get_nonblocking: ___get_nonblocking_spec
149
150
 
150
151
  class ___get_blocking_spec(typing_extensions.Protocol):
151
152
  def __call__(
152
153
  self, partition: typing.Optional[str], timeout: typing.Optional[float], n_values: int
153
- ) -> typing.List[typing.Any]: ...
154
+ ) -> list[typing.Any]: ...
154
155
  async def aio(
155
156
  self, partition: typing.Optional[str], timeout: typing.Optional[float], n_values: int
156
- ) -> typing.List[typing.Any]: ...
157
+ ) -> list[typing.Any]: ...
157
158
 
158
159
  _get_blocking: ___get_blocking_spec
159
160
 
@@ -181,7 +182,7 @@ class Queue(modal.object.Object):
181
182
  timeout: typing.Optional[float] = None,
182
183
  *,
183
184
  partition: typing.Optional[str] = None,
184
- ) -> typing.List[typing.Any]: ...
185
+ ) -> list[typing.Any]: ...
185
186
  async def aio(
186
187
  self,
187
188
  n_values: int,
@@ -189,7 +190,7 @@ class Queue(modal.object.Object):
189
190
  timeout: typing.Optional[float] = None,
190
191
  *,
191
192
  partition: typing.Optional[str] = None,
192
- ) -> typing.List[typing.Any]: ...
193
+ ) -> list[typing.Any]: ...
193
194
 
194
195
  get_many: __get_many_spec
195
196
 
@@ -218,7 +219,7 @@ class Queue(modal.object.Object):
218
219
  class __put_many_spec(typing_extensions.Protocol):
219
220
  def __call__(
220
221
  self,
221
- vs: typing.List[typing.Any],
222
+ vs: list[typing.Any],
222
223
  block: bool = True,
223
224
  timeout: typing.Optional[float] = None,
224
225
  *,
@@ -227,7 +228,7 @@ class Queue(modal.object.Object):
227
228
  ) -> None: ...
228
229
  async def aio(
229
230
  self,
230
- vs: typing.List[typing.Any],
231
+ vs: list[typing.Any],
231
232
  block: bool = True,
232
233
  timeout: typing.Optional[float] = None,
233
234
  *,
@@ -242,22 +243,22 @@ class Queue(modal.object.Object):
242
243
  self,
243
244
  partition: typing.Optional[str],
244
245
  partition_ttl: int,
245
- vs: typing.List[typing.Any],
246
+ vs: list[typing.Any],
246
247
  timeout: typing.Optional[float] = None,
247
248
  ): ...
248
249
  async def aio(
249
250
  self,
250
251
  partition: typing.Optional[str],
251
252
  partition_ttl: int,
252
- vs: typing.List[typing.Any],
253
+ vs: list[typing.Any],
253
254
  timeout: typing.Optional[float] = None,
254
255
  ): ...
255
256
 
256
257
  _put_many_blocking: ___put_many_blocking_spec
257
258
 
258
259
  class ___put_many_nonblocking_spec(typing_extensions.Protocol):
259
- def __call__(self, partition: typing.Optional[str], partition_ttl: int, vs: typing.List[typing.Any]): ...
260
- async def aio(self, partition: typing.Optional[str], partition_ttl: int, vs: typing.List[typing.Any]): ...
260
+ def __call__(self, partition: typing.Optional[str], partition_ttl: int, vs: list[typing.Any]): ...
261
+ async def aio(self, partition: typing.Optional[str], partition_ttl: int, vs: list[typing.Any]): ...
261
262
 
262
263
  _put_many_nonblocking: ___put_many_nonblocking_spec
263
264
 
@@ -273,6 +274,6 @@ class Queue(modal.object.Object):
273
274
  ) -> typing.Generator[typing.Any, None, None]: ...
274
275
  def aio(
275
276
  self, *, partition: typing.Optional[str] = None, item_poll_timeout: float = 0.0
276
- ) -> typing.AsyncGenerator[typing.Any, None]: ...
277
+ ) -> collections.abc.AsyncGenerator[typing.Any, None]: ...
277
278
 
278
279
  iterate: __iterate_spec