modal 0.67.0__py3-none-any.whl → 0.67.22__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 (113) 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 +46 -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 +5 -4
  16. modal/_tunnel.pyi +2 -2
  17. modal/_utils/async_utils.py +53 -17
  18. modal/_utils/blob_utils.py +22 -7
  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 +81 -69
  32. modal/app.pyi +104 -99
  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/import_refs.py +1 -1
  41. modal/cli/launch.py +2 -2
  42. modal/cli/network_file_system.py +1 -1
  43. modal/cli/profile.py +1 -1
  44. modal/cli/programs/run_jupyter.py +2 -2
  45. modal/cli/programs/vscode.py +3 -3
  46. modal/cli/queues.py +1 -1
  47. modal/cli/run.py +6 -6
  48. modal/cli/secret.py +3 -3
  49. modal/cli/utils.py +2 -1
  50. modal/cli/volume.py +3 -3
  51. modal/client.py +6 -11
  52. modal/client.pyi +18 -27
  53. modal/cloud_bucket_mount.py +3 -3
  54. modal/cloud_bucket_mount.pyi +2 -2
  55. modal/cls.py +32 -32
  56. modal/cls.pyi +35 -34
  57. modal/config.py +3 -2
  58. modal/container_process.py +6 -2
  59. modal/dict.py +6 -3
  60. modal/dict.pyi +10 -9
  61. modal/environments.py +3 -3
  62. modal/environments.pyi +3 -3
  63. modal/exception.py +2 -3
  64. modal/functions.py +111 -40
  65. modal/functions.pyi +71 -48
  66. modal/image.py +46 -49
  67. modal/image.pyi +102 -101
  68. modal/io_streams.py +20 -12
  69. modal/io_streams.pyi +24 -14
  70. modal/mount.py +24 -24
  71. modal/mount.pyi +28 -29
  72. modal/network_file_system.py +14 -11
  73. modal/network_file_system.pyi +12 -11
  74. modal/object.py +9 -8
  75. modal/object.pyi +47 -34
  76. modal/output.py +2 -1
  77. modal/parallel_map.py +4 -4
  78. modal/partial_function.py +10 -14
  79. modal/partial_function.pyi +17 -18
  80. modal/queue.py +11 -8
  81. modal/queue.pyi +23 -22
  82. modal/retries.py +38 -0
  83. modal/runner.py +8 -7
  84. modal/runner.pyi +8 -14
  85. modal/running_app.py +3 -3
  86. modal/sandbox.py +20 -13
  87. modal/sandbox.pyi +73 -72
  88. modal/scheduler_placement.py +2 -1
  89. modal/secret.py +7 -7
  90. modal/secret.pyi +12 -12
  91. modal/serving.py +4 -3
  92. modal/serving.pyi +5 -4
  93. modal/token_flow.py +3 -2
  94. modal/token_flow.pyi +3 -3
  95. modal/volume.py +16 -23
  96. modal/volume.pyi +17 -16
  97. {modal-0.67.0.dist-info → modal-0.67.22.dist-info}/METADATA +2 -2
  98. modal-0.67.22.dist-info/RECORD +168 -0
  99. modal_docs/mdmd/signatures.py +1 -2
  100. modal_global_objects/mounts/python_standalone.py +1 -1
  101. modal_proto/api.proto +13 -0
  102. modal_proto/api_grpc.py +16 -0
  103. modal_proto/api_pb2.py +241 -221
  104. modal_proto/api_pb2.pyi +41 -0
  105. modal_proto/api_pb2_grpc.py +33 -0
  106. modal_proto/api_pb2_grpc.pyi +10 -0
  107. modal_proto/modal_api_grpc.py +1 -0
  108. modal_version/_version_generated.py +1 -1
  109. modal-0.67.0.dist-info/RECORD +0 -168
  110. {modal-0.67.0.dist-info → modal-0.67.22.dist-info}/LICENSE +0 -0
  111. {modal-0.67.0.dist-info → modal-0.67.22.dist-info}/WHEEL +0 -0
  112. {modal-0.67.0.dist-info → modal-0.67.22.dist-info}/entry_points.txt +0 -0
  113. {modal-0.67.0.dist-info → modal-0.67.22.dist-info}/top_level.txt +0 -0
modal/cls.pyi CHANGED
@@ -1,3 +1,4 @@
1
+ import collections.abc
1
2
  import google.protobuf.message
2
3
  import inspect
3
4
  import modal.app
@@ -20,10 +21,10 @@ def _use_annotation_parameters(user_cls) -> bool: ...
20
21
  def _get_class_constructor_signature(user_cls: type) -> inspect.Signature: ...
21
22
 
22
23
  class _Obj:
23
- _functions: typing.Dict[str, modal.functions._Function]
24
- _entered: bool
24
+ _functions: dict[str, modal.functions._Function]
25
+ _has_entered: bool
25
26
  _user_cls_instance: typing.Optional[typing.Any]
26
- _construction_args: typing.Tuple[tuple, typing.Dict[str, typing.Any]]
27
+ _construction_args: tuple[tuple, dict[str, typing.Any]]
27
28
  _instance_service_function: typing.Optional[modal.functions._Function]
28
29
 
29
30
  def _uses_common_service_function(self): ...
@@ -31,7 +32,7 @@ class _Obj:
31
32
  self,
32
33
  user_cls: type,
33
34
  class_service_function: typing.Optional[modal.functions._Function],
34
- classbound_methods: typing.Dict[str, modal.functions._Function],
35
+ classbound_methods: dict[str, modal.functions._Function],
35
36
  from_other_workspace: bool,
36
37
  options: typing.Optional[modal_proto.api_pb2.FunctionOptions],
37
38
  args,
@@ -40,26 +41,26 @@ class _Obj:
40
41
  def _new_user_cls_instance(self): ...
41
42
  async def keep_warm(self, warm_pool_size: int) -> None: ...
42
43
  def _cached_user_cls_instance(self): ...
43
- def enter(self): ...
44
+ def _enter(self): ...
44
45
  @property
45
- def entered(self): ...
46
- @entered.setter
47
- def entered(self, val): ...
48
- async def aenter(self): ...
46
+ def _entered(self) -> bool: ...
47
+ @_entered.setter
48
+ def _entered(self, val: bool): ...
49
+ async def _aenter(self): ...
49
50
  def __getattr__(self, k): ...
50
51
 
51
52
  class Obj:
52
- _functions: typing.Dict[str, modal.functions.Function]
53
- _entered: bool
53
+ _functions: dict[str, modal.functions.Function]
54
+ _has_entered: bool
54
55
  _user_cls_instance: typing.Optional[typing.Any]
55
- _construction_args: typing.Tuple[tuple, typing.Dict[str, typing.Any]]
56
+ _construction_args: tuple[tuple, dict[str, typing.Any]]
56
57
  _instance_service_function: typing.Optional[modal.functions.Function]
57
58
 
58
59
  def __init__(
59
60
  self,
60
61
  user_cls: type,
61
62
  class_service_function: typing.Optional[modal.functions.Function],
62
- classbound_methods: typing.Dict[str, modal.functions.Function],
63
+ classbound_methods: dict[str, modal.functions.Function],
63
64
  from_other_workspace: bool,
64
65
  options: typing.Optional[modal_proto.api_pb2.FunctionOptions],
65
66
  args,
@@ -75,26 +76,26 @@ class Obj:
75
76
  keep_warm: __keep_warm_spec
76
77
 
77
78
  def _cached_user_cls_instance(self): ...
78
- def enter(self): ...
79
+ def _enter(self): ...
79
80
  @property
80
- def entered(self): ...
81
- @entered.setter
82
- def entered(self, val): ...
83
- async def aenter(self): ...
81
+ def _entered(self) -> bool: ...
82
+ @_entered.setter
83
+ def _entered(self, val: bool): ...
84
+ async def _aenter(self): ...
84
85
  def __getattr__(self, k): ...
85
86
 
86
87
  class _Cls(modal.object._Object):
87
88
  _user_cls: typing.Optional[type]
88
89
  _class_service_function: typing.Optional[modal.functions._Function]
89
- _method_functions: typing.Optional[typing.Dict[str, modal.functions._Function]]
90
+ _method_functions: typing.Optional[dict[str, modal.functions._Function]]
90
91
  _options: typing.Optional[modal_proto.api_pb2.FunctionOptions]
91
- _callables: typing.Dict[str, typing.Callable[..., typing.Any]]
92
+ _callables: dict[str, typing.Callable[..., typing.Any]]
92
93
  _from_other_workspace: typing.Optional[bool]
93
94
  _app: typing.Optional[modal.app._App]
94
95
 
95
96
  def _initialize_from_empty(self): ...
96
97
  def _initialize_from_other(self, other: _Cls): ...
97
- def _get_partial_functions(self) -> typing.Dict[str, modal.partial_function._PartialFunction]: ...
98
+ def _get_partial_functions(self) -> dict[str, modal.partial_function._PartialFunction]: ...
98
99
  def _hydrate_metadata(self, metadata: google.protobuf.message.Message): ...
99
100
  @staticmethod
100
101
  def validate_construction_mechanism(user_cls): ...
@@ -103,7 +104,7 @@ class _Cls(modal.object._Object):
103
104
  def _uses_common_service_function(self): ...
104
105
  @classmethod
105
106
  def from_name(
106
- cls: typing.Type[_Cls],
107
+ cls: type[_Cls],
107
108
  app_name: str,
108
109
  tag: str,
109
110
  namespace=1,
@@ -112,11 +113,11 @@ class _Cls(modal.object._Object):
112
113
  ) -> _Cls: ...
113
114
  def with_options(
114
115
  self: _Cls,
115
- cpu: typing.Union[float, typing.Tuple[float, float], None] = None,
116
- memory: typing.Union[int, typing.Tuple[int, int], None] = None,
116
+ cpu: typing.Union[float, tuple[float, float], None] = None,
117
+ memory: typing.Union[int, tuple[int, int], None] = None,
117
118
  gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
118
- secrets: typing.Collection[modal.secret._Secret] = (),
119
- volumes: typing.Dict[typing.Union[str, os.PathLike], modal.volume._Volume] = {},
119
+ secrets: collections.abc.Collection[modal.secret._Secret] = (),
120
+ volumes: dict[typing.Union[str, os.PathLike], modal.volume._Volume] = {},
120
121
  retries: typing.Union[int, modal.retries.Retries, None] = None,
121
122
  timeout: typing.Optional[int] = None,
122
123
  concurrency_limit: typing.Optional[int] = None,
@@ -138,16 +139,16 @@ class _Cls(modal.object._Object):
138
139
  class Cls(modal.object.Object):
139
140
  _user_cls: typing.Optional[type]
140
141
  _class_service_function: typing.Optional[modal.functions.Function]
141
- _method_functions: typing.Optional[typing.Dict[str, modal.functions.Function]]
142
+ _method_functions: typing.Optional[dict[str, modal.functions.Function]]
142
143
  _options: typing.Optional[modal_proto.api_pb2.FunctionOptions]
143
- _callables: typing.Dict[str, typing.Callable[..., typing.Any]]
144
+ _callables: dict[str, typing.Callable[..., typing.Any]]
144
145
  _from_other_workspace: typing.Optional[bool]
145
146
  _app: typing.Optional[modal.app.App]
146
147
 
147
148
  def __init__(self, *args, **kwargs): ...
148
149
  def _initialize_from_empty(self): ...
149
150
  def _initialize_from_other(self, other: Cls): ...
150
- def _get_partial_functions(self) -> typing.Dict[str, modal.partial_function.PartialFunction]: ...
151
+ def _get_partial_functions(self) -> dict[str, modal.partial_function.PartialFunction]: ...
151
152
  def _hydrate_metadata(self, metadata: google.protobuf.message.Message): ...
152
153
  @staticmethod
153
154
  def validate_construction_mechanism(user_cls): ...
@@ -156,7 +157,7 @@ class Cls(modal.object.Object):
156
157
  def _uses_common_service_function(self): ...
157
158
  @classmethod
158
159
  def from_name(
159
- cls: typing.Type[Cls],
160
+ cls: type[Cls],
160
161
  app_name: str,
161
162
  tag: str,
162
163
  namespace=1,
@@ -165,11 +166,11 @@ class Cls(modal.object.Object):
165
166
  ) -> Cls: ...
166
167
  def with_options(
167
168
  self: Cls,
168
- cpu: typing.Union[float, typing.Tuple[float, float], None] = None,
169
- memory: typing.Union[int, typing.Tuple[int, int], None] = None,
169
+ cpu: typing.Union[float, tuple[float, float], None] = None,
170
+ memory: typing.Union[int, tuple[int, int], None] = None,
170
171
  gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
171
- secrets: typing.Collection[modal.secret.Secret] = (),
172
- volumes: typing.Dict[typing.Union[str, os.PathLike], modal.volume.Volume] = {},
172
+ secrets: collections.abc.Collection[modal.secret.Secret] = (),
173
+ volumes: dict[typing.Union[str, os.PathLike], modal.volume.Volume] = {},
173
174
  retries: typing.Union[int, modal.retries.Retries, None] = None,
174
175
  timeout: typing.Optional[int] = None,
175
176
  concurrency_limit: typing.Optional[int] = None,
modal/config.py CHANGED
@@ -80,7 +80,7 @@ import os
80
80
  import typing
81
81
  import warnings
82
82
  from textwrap import dedent
83
- from typing import Any, Dict, Optional
83
+ from typing import Any, Optional
84
84
 
85
85
  from google.protobuf.empty_pb2 import Empty
86
86
 
@@ -221,6 +221,7 @@ _SETTINGS = {
221
221
  "image_builder_version": _Setting(),
222
222
  "strict_parameters": _Setting(False, transform=_to_boolean), # For internal/experimental use
223
223
  "snapshot_debug": _Setting(False, transform=_to_boolean),
224
+ "client_retries": _Setting(False, transform=_to_boolean), # For internal testing.
224
225
  }
225
226
 
226
227
 
@@ -282,7 +283,7 @@ configure_logger(logger, config["loglevel"], config["log_format"])
282
283
 
283
284
 
284
285
  def _store_user_config(
285
- new_settings: Dict[str, Any], profile: Optional[str] = None, active_profile: Optional[str] = None
286
+ new_settings: dict[str, Any], profile: Optional[str] = None, active_profile: Optional[str] = None
286
287
  ):
287
288
  """Internal method, used by the CLI to set tokens."""
288
289
  if profile is None:
@@ -128,12 +128,16 @@ class _ContainerProcess(Generic[T]):
128
128
  on_connect = asyncio.Event()
129
129
 
130
130
  async def _write_to_fd_loop(stream: _StreamReader):
131
- async for line in stream:
131
+ # Don't skip empty messages so we can detect when the process has booted.
132
+ async for chunk in stream._get_logs(skip_empty_messages=False):
133
+ if chunk is None:
134
+ break
135
+
132
136
  if not on_connect.is_set():
133
137
  connecting_status.stop()
134
138
  on_connect.set()
135
139
 
136
- await write_to_fd(stream.file_descriptor, line.encode("utf-8"))
140
+ await write_to_fd(stream.file_descriptor, chunk)
137
141
 
138
142
  async def _handle_input(data: bytes, message_index: int):
139
143
  self.stdin.write(data)
modal/dict.py CHANGED
@@ -1,5 +1,6 @@
1
1
  # Copyright Modal Labs 2022
2
- from typing import Any, AsyncIterator, Optional, Tuple, Type
2
+ from collections.abc import AsyncIterator
3
+ from typing import Any, Optional
3
4
 
4
5
  from grpclib import GRPCError
5
6
  from synchronicity.async_wrap import asynccontextmanager
@@ -74,7 +75,7 @@ class _Dict(_Object, type_prefix="di"):
74
75
  @classmethod
75
76
  @asynccontextmanager
76
77
  async def ephemeral(
77
- cls: Type["_Dict"],
78
+ cls: type["_Dict"],
78
79
  data: Optional[dict] = None,
79
80
  client: Optional[_Client] = None,
80
81
  environment_name: Optional[str] = None,
@@ -88,7 +89,9 @@ class _Dict(_Object, type_prefix="di"):
88
89
 
89
90
  with Dict.ephemeral() as d:
90
91
  d["foo"] = "bar"
92
+ ```
91
93
 
94
+ ```python notest
92
95
  async with Dict.ephemeral() as d:
93
96
  await d.put.aio("foo", "bar")
94
97
  ```
@@ -314,7 +317,7 @@ class _Dict(_Object, type_prefix="di"):
314
317
  yield deserialize(resp.value, self._client)
315
318
 
316
319
  @live_method_gen
317
- async def items(self) -> AsyncIterator[Tuple[Any, Any]]:
320
+ async def items(self) -> AsyncIterator[tuple[Any, Any]]:
318
321
  """Return an iterator over the (key, value) tuples in this dictionary.
319
322
 
320
323
  Note that (unlike with Python dicts) the return value is a simple iterator,
modal/dict.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 _Dict(modal.object._Object):
12
13
  def __init__(self, data={}): ...
13
14
  @classmethod
14
15
  def ephemeral(
15
- cls: typing.Type[_Dict],
16
+ cls: type[_Dict],
16
17
  data: typing.Optional[dict] = None,
17
18
  client: typing.Optional[modal.client._Client] = None,
18
19
  environment_name: typing.Optional[str] = None,
@@ -53,9 +54,9 @@ class _Dict(modal.object._Object):
53
54
  async def pop(self, key: typing.Any) -> typing.Any: ...
54
55
  async def __delitem__(self, key: typing.Any) -> typing.Any: ...
55
56
  async def __contains__(self, key: typing.Any) -> bool: ...
56
- def keys(self) -> typing.AsyncIterator[typing.Any]: ...
57
- def values(self) -> typing.AsyncIterator[typing.Any]: ...
58
- def items(self) -> typing.AsyncIterator[typing.Tuple[typing.Any, typing.Any]]: ...
57
+ def keys(self) -> collections.abc.AsyncIterator[typing.Any]: ...
58
+ def values(self) -> collections.abc.AsyncIterator[typing.Any]: ...
59
+ def items(self) -> collections.abc.AsyncIterator[tuple[typing.Any, typing.Any]]: ...
59
60
 
60
61
  class Dict(modal.object.Object):
61
62
  def __init__(self, data={}): ...
@@ -63,7 +64,7 @@ class Dict(modal.object.Object):
63
64
  def new(data: typing.Optional[dict] = None): ...
64
65
  @classmethod
65
66
  def ephemeral(
66
- cls: typing.Type[Dict],
67
+ cls: type[Dict],
67
68
  data: typing.Optional[dict] = None,
68
69
  client: typing.Optional[modal.client.Client] = None,
69
70
  environment_name: typing.Optional[str] = None,
@@ -186,18 +187,18 @@ class Dict(modal.object.Object):
186
187
 
187
188
  class __keys_spec(typing_extensions.Protocol):
188
189
  def __call__(self) -> typing.Iterator[typing.Any]: ...
189
- def aio(self) -> typing.AsyncIterator[typing.Any]: ...
190
+ def aio(self) -> collections.abc.AsyncIterator[typing.Any]: ...
190
191
 
191
192
  keys: __keys_spec
192
193
 
193
194
  class __values_spec(typing_extensions.Protocol):
194
195
  def __call__(self) -> typing.Iterator[typing.Any]: ...
195
- def aio(self) -> typing.AsyncIterator[typing.Any]: ...
196
+ def aio(self) -> collections.abc.AsyncIterator[typing.Any]: ...
196
197
 
197
198
  values: __values_spec
198
199
 
199
200
  class __items_spec(typing_extensions.Protocol):
200
- def __call__(self) -> typing.Iterator[typing.Tuple[typing.Any, typing.Any]]: ...
201
- def aio(self) -> typing.AsyncIterator[typing.Tuple[typing.Any, typing.Any]]: ...
201
+ def __call__(self) -> typing.Iterator[tuple[typing.Any, typing.Any]]: ...
202
+ def aio(self) -> collections.abc.AsyncIterator[tuple[typing.Any, typing.Any]]: ...
202
203
 
203
204
  items: __items_spec
modal/environments.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # Copyright Modal Labs 2023
2
2
  from dataclasses import dataclass
3
- from typing import Dict, List, Optional
3
+ from typing import Optional
4
4
 
5
5
  from google.protobuf.empty_pb2 import Empty
6
6
  from google.protobuf.message import Message
@@ -98,7 +98,7 @@ Environment = synchronize_api(_Environment)
98
98
 
99
99
 
100
100
  # Needs to be after definition; synchronicity interferes with forward references?
101
- ENVIRONMENT_CACHE: Dict[str, _Environment] = {}
101
+ ENVIRONMENT_CACHE: dict[str, _Environment] = {}
102
102
 
103
103
 
104
104
  async def _get_environment_cached(name: str, client: _Client) -> _Environment:
@@ -151,7 +151,7 @@ async def create_environment(name: str, client: Optional[_Client] = None):
151
151
 
152
152
 
153
153
  @synchronizer.create_blocking
154
- async def list_environments(client: Optional[_Client] = None) -> List[api_pb2.EnvironmentListItem]:
154
+ async def list_environments(client: Optional[_Client] = None) -> list[api_pb2.EnvironmentListItem]:
155
155
  if client is None:
156
156
  client = await _Client.from_env()
157
157
  resp = await client.stub.EnvironmentList(Empty())
modal/environments.pyi CHANGED
@@ -87,13 +87,13 @@ create_environment: __create_environment_spec
87
87
  class __list_environments_spec(typing_extensions.Protocol):
88
88
  def __call__(
89
89
  self, client: typing.Optional[modal.client.Client] = None
90
- ) -> typing.List[modal_proto.api_pb2.EnvironmentListItem]: ...
90
+ ) -> list[modal_proto.api_pb2.EnvironmentListItem]: ...
91
91
  async def aio(
92
92
  self, client: typing.Optional[modal.client.Client] = None
93
- ) -> typing.List[modal_proto.api_pb2.EnvironmentListItem]: ...
93
+ ) -> list[modal_proto.api_pb2.EnvironmentListItem]: ...
94
94
 
95
95
  list_environments: __list_environments_spec
96
96
 
97
97
  def ensure_env(environment_name: typing.Optional[str] = None) -> str: ...
98
98
 
99
- ENVIRONMENT_CACHE: typing.Dict[str, _Environment]
99
+ ENVIRONMENT_CACHE: dict[str, _Environment]
modal/exception.py CHANGED
@@ -4,7 +4,6 @@ import signal
4
4
  import sys
5
5
  import warnings
6
6
  from datetime import date
7
- from typing import Tuple
8
7
 
9
8
 
10
9
  class Error(Exception):
@@ -132,12 +131,12 @@ def _is_internal_frame(frame):
132
131
  return module in _INTERNAL_MODULES
133
132
 
134
133
 
135
- def deprecation_error(deprecated_on: Tuple[int, int, int], msg: str):
134
+ def deprecation_error(deprecated_on: tuple[int, int, int], msg: str):
136
135
  raise DeprecationError(f"Deprecated on {date(*deprecated_on)}: {msg}")
137
136
 
138
137
 
139
138
  def deprecation_warning(
140
- deprecated_on: Tuple[int, int, int], msg: str, *, pending: bool = False, show_source: bool = True
139
+ deprecated_on: tuple[int, int, int], msg: str, *, pending: bool = False, show_source: bool = True
141
140
  ) -> None:
142
141
  """Utility for getting the proper stack entry.
143
142