modal 1.1.1.dev41__py3-none-any.whl → 1.1.2__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.

Potentially problematic release.


This version of modal might be problematic. Click here for more details.

Files changed (68) hide show
  1. modal/__main__.py +1 -2
  2. modal/_container_entrypoint.py +18 -7
  3. modal/_functions.py +135 -13
  4. modal/_object.py +13 -2
  5. modal/_partial_function.py +8 -8
  6. modal/_runtime/asgi.py +3 -2
  7. modal/_runtime/container_io_manager.py +20 -14
  8. modal/_runtime/container_io_manager.pyi +38 -13
  9. modal/_runtime/execution_context.py +18 -2
  10. modal/_runtime/execution_context.pyi +4 -1
  11. modal/_runtime/gpu_memory_snapshot.py +158 -54
  12. modal/_utils/blob_utils.py +83 -24
  13. modal/_utils/function_utils.py +4 -3
  14. modal/_utils/time_utils.py +28 -4
  15. modal/app.py +8 -4
  16. modal/app.pyi +8 -8
  17. modal/cli/dict.py +14 -11
  18. modal/cli/entry_point.py +9 -3
  19. modal/cli/launch.py +102 -4
  20. modal/cli/profile.py +1 -0
  21. modal/cli/programs/launch_instance_ssh.py +94 -0
  22. modal/cli/programs/run_marimo.py +95 -0
  23. modal/cli/queues.py +49 -19
  24. modal/cli/secret.py +45 -18
  25. modal/cli/volume.py +14 -16
  26. modal/client.pyi +2 -10
  27. modal/cls.py +12 -2
  28. modal/cls.pyi +9 -1
  29. modal/config.py +7 -7
  30. modal/dict.py +206 -12
  31. modal/dict.pyi +358 -4
  32. modal/experimental/__init__.py +130 -0
  33. modal/file_io.py +1 -1
  34. modal/file_io.pyi +2 -2
  35. modal/file_pattern_matcher.py +25 -16
  36. modal/functions.pyi +111 -11
  37. modal/image.py +9 -3
  38. modal/image.pyi +7 -7
  39. modal/mount.py +20 -13
  40. modal/mount.pyi +16 -3
  41. modal/network_file_system.py +8 -2
  42. modal/object.pyi +3 -0
  43. modal/parallel_map.py +346 -101
  44. modal/parallel_map.pyi +108 -0
  45. modal/proxy.py +2 -1
  46. modal/queue.py +199 -9
  47. modal/queue.pyi +357 -3
  48. modal/sandbox.py +6 -5
  49. modal/sandbox.pyi +17 -14
  50. modal/secret.py +196 -3
  51. modal/secret.pyi +372 -0
  52. modal/volume.py +239 -23
  53. modal/volume.pyi +405 -10
  54. {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/METADATA +2 -2
  55. {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/RECORD +68 -66
  56. modal_docs/mdmd/mdmd.py +11 -1
  57. modal_proto/api.proto +37 -10
  58. modal_proto/api_grpc.py +32 -0
  59. modal_proto/api_pb2.py +627 -597
  60. modal_proto/api_pb2.pyi +107 -19
  61. modal_proto/api_pb2_grpc.py +67 -2
  62. modal_proto/api_pb2_grpc.pyi +24 -8
  63. modal_proto/modal_api_grpc.py +2 -0
  64. modal_version/__init__.py +1 -1
  65. {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/WHEEL +0 -0
  66. {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/entry_points.txt +0 -0
  67. {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/licenses/LICENSE +0 -0
  68. {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/top_level.txt +0 -0
modal/dict.py CHANGED
@@ -2,25 +2,32 @@
2
2
  from collections.abc import AsyncIterator, Mapping
3
3
  from dataclasses import dataclass
4
4
  from datetime import datetime
5
- from typing import Any, Optional
5
+ from typing import Any, Optional, Union
6
6
 
7
7
  from google.protobuf.message import Message
8
- from grpclib import GRPCError
8
+ from grpclib import GRPCError, Status
9
+ from synchronicity import classproperty
9
10
  from synchronicity.async_wrap import asynccontextmanager
10
11
 
11
12
  from modal_proto import api_pb2
12
13
 
13
- from ._object import EPHEMERAL_OBJECT_HEARTBEAT_SLEEP, _get_environment_name, _Object, live_method, live_method_gen
14
+ from ._object import (
15
+ EPHEMERAL_OBJECT_HEARTBEAT_SLEEP,
16
+ _get_environment_name,
17
+ _Object,
18
+ live_method,
19
+ live_method_gen,
20
+ )
14
21
  from ._resolver import Resolver
15
22
  from ._serialization import deserialize, serialize
16
23
  from ._utils.async_utils import TaskContext, synchronize_api
17
24
  from ._utils.deprecation import deprecation_warning, warn_if_passing_namespace
18
25
  from ._utils.grpc_utils import retry_transient_errors
19
26
  from ._utils.name_utils import check_object_name
20
- from ._utils.time_utils import timestamp_to_localized_dt
27
+ from ._utils.time_utils import as_timestamp, timestamp_to_localized_dt
21
28
  from .client import _Client
22
29
  from .config import logger
23
- from .exception import RequestSizeError
30
+ from .exception import AlreadyExistsError, InvalidError, NotFoundError, RequestSizeError
24
31
 
25
32
 
26
33
  def _serialize_dict(data):
@@ -29,7 +36,7 @@ def _serialize_dict(data):
29
36
 
30
37
  @dataclass
31
38
  class DictInfo:
32
- """Information about the Dict object."""
39
+ """Information about a Dict object."""
33
40
 
34
41
  # This dataclass should be limited to information that is unchanging over the lifetime of the Dict,
35
42
  # since it is transmitted from the server when the object is hydrated and could be stale when accessed.
@@ -39,6 +46,173 @@ class DictInfo:
39
46
  created_by: Optional[str]
40
47
 
41
48
 
49
+ class _DictManager:
50
+ """Namespace with methods for managing named Dict objects."""
51
+
52
+ @staticmethod
53
+ async def create(
54
+ name: str, # Name to use for the new Dict
55
+ *,
56
+ allow_existing: bool = False, # If True, no-op when the Dict already exists
57
+ environment_name: Optional[str] = None, # Uses active environment if not specified
58
+ client: Optional[_Client] = None, # Optional client with Modal credentials
59
+ ) -> None:
60
+ """Create a new Dict object.
61
+
62
+ **Examples:**
63
+
64
+ ```python notest
65
+ modal.Dict.objects.create("my-dict")
66
+ ```
67
+
68
+ Dicts will be created in the active environment, or another one can be specified:
69
+
70
+ ```python notest
71
+ modal.Dict.objects.create("my-dict", environment_name="dev")
72
+ ```
73
+
74
+ By default, an error will be raised if the Dict already exists, but passing
75
+ `allow_existing=True` will make the creation attempt a no-op in this case.
76
+
77
+ ```python notest
78
+ modal.Dict.objects.create("my-dict", allow_existing=True)
79
+ ```
80
+
81
+ Note that this method does not return a local instance of the Dict. You can use
82
+ `modal.Dict.from_name` to perform a lookup after creation.
83
+
84
+ Added in v1.1.2.
85
+
86
+ """
87
+ check_object_name(name, "Dict")
88
+ client = await _Client.from_env() if client is None else client
89
+ object_creation_type = (
90
+ api_pb2.OBJECT_CREATION_TYPE_CREATE_IF_MISSING
91
+ if allow_existing
92
+ else api_pb2.OBJECT_CREATION_TYPE_CREATE_FAIL_IF_EXISTS
93
+ )
94
+ req = api_pb2.DictGetOrCreateRequest(
95
+ deployment_name=name,
96
+ environment_name=_get_environment_name(environment_name),
97
+ object_creation_type=object_creation_type,
98
+ )
99
+ try:
100
+ await retry_transient_errors(client.stub.DictGetOrCreate, req)
101
+ except GRPCError as exc:
102
+ if exc.status == Status.ALREADY_EXISTS and not allow_existing:
103
+ raise AlreadyExistsError(exc.message)
104
+ else:
105
+ raise
106
+
107
+ @staticmethod
108
+ async def list(
109
+ *,
110
+ max_objects: Optional[int] = None, # Limit results to this size
111
+ created_before: Optional[Union[datetime, str]] = None, # Limit based on creation date
112
+ environment_name: str = "", # Uses active environment if not specified
113
+ client: Optional[_Client] = None, # Optional client with Modal credentials
114
+ ) -> list["_Dict"]:
115
+ """Return a list of hydrated Dict objects.
116
+
117
+ **Examples:**
118
+
119
+ ```python
120
+ dicts = modal.Dict.objects.list()
121
+ print([d.name for d in dicts])
122
+ ```
123
+
124
+ Dicts will be retreived from the active environment, or another one can be specified:
125
+
126
+ ```python notest
127
+ dev_dicts = modal.Dict.objects.list(environment_name="dev")
128
+ ```
129
+
130
+ By default, all named Dict are returned, newest to oldest. It's also possible to limit the
131
+ number of results and to filter by creation date:
132
+
133
+ ```python
134
+ dicts = modal.Dict.objects.list(max_objects=10, created_before="2025-01-01")
135
+ ```
136
+
137
+ Added in v1.1.2.
138
+
139
+ """
140
+ client = await _Client.from_env() if client is None else client
141
+ if max_objects is not None and max_objects < 0:
142
+ raise InvalidError("max_objects cannot be negative")
143
+
144
+ items: list[api_pb2.DictListResponse.DictInfo] = []
145
+
146
+ async def retrieve_page(created_before: float) -> bool:
147
+ max_page_size = 100 if max_objects is None else min(100, max_objects - len(items))
148
+ pagination = api_pb2.ListPagination(max_objects=max_page_size, created_before=created_before)
149
+ req = api_pb2.DictListRequest(
150
+ environment_name=_get_environment_name(environment_name), pagination=pagination
151
+ )
152
+ resp = await retry_transient_errors(client.stub.DictList, req)
153
+ items.extend(resp.dicts)
154
+ finished = (len(resp.dicts) < max_page_size) or (max_objects is not None and len(items) >= max_objects)
155
+ return finished
156
+
157
+ finished = await retrieve_page(as_timestamp(created_before))
158
+ while True:
159
+ if finished:
160
+ break
161
+ finished = await retrieve_page(items[-1].metadata.creation_info.created_at)
162
+
163
+ dicts = [
164
+ _Dict._new_hydrated(
165
+ item.dict_id,
166
+ client,
167
+ item.metadata,
168
+ is_another_app=True,
169
+ rep=_Dict._repr(item.name, environment_name),
170
+ )
171
+ for item in items
172
+ ]
173
+ return dicts[:max_objects] if max_objects is not None else dicts
174
+
175
+ @staticmethod
176
+ async def delete(
177
+ name: str, # Name of the Dict to delete
178
+ *,
179
+ allow_missing: bool = False, # If True, don't raise an error if the Dict doesn't exist
180
+ environment_name: Optional[str] = None, # Uses active environment if not specified
181
+ client: Optional[_Client] = None, # Optional client with Modal credentials
182
+ ):
183
+ """Delete a named Dict.
184
+
185
+ Warning: This deletes an *entire Dict*, not just a specific key.
186
+ Deletion is irreversible and will affect any Apps currently using the Dict.
187
+
188
+ **Examples:**
189
+
190
+ ```python notest
191
+ await modal.Dict.objects.delete("my-dict")
192
+ ```
193
+
194
+ Dicts will be deleted from the active environment, or another one can be specified:
195
+
196
+ ```python notest
197
+ await modal.Dict.objects.delete("my-dict", environment_name="dev")
198
+ ```
199
+
200
+ Added in v1.1.2.
201
+
202
+ """
203
+ try:
204
+ obj = await _Dict.from_name(name, environment_name=environment_name).hydrate(client)
205
+ except NotFoundError:
206
+ if not allow_missing:
207
+ raise
208
+ else:
209
+ req = api_pb2.DictDeleteRequest(dict_id=obj.object_id)
210
+ await retry_transient_errors(obj._client.stub.DictDelete, req)
211
+
212
+
213
+ DictManager = synchronize_api(_DictManager)
214
+
215
+
42
216
  class _Dict(_Object, type_prefix="di"):
43
217
  """Distributed dictionary for storage in Modal apps.
44
218
 
@@ -90,6 +264,10 @@ class _Dict(_Object, type_prefix="di"):
90
264
  "`Dict(...)` constructor is not allowed. Please use `Dict.from_name` or `Dict.ephemeral` instead"
91
265
  )
92
266
 
267
+ @classproperty
268
+ def objects(cls) -> _DictManager:
269
+ return _DictManager
270
+
93
271
  @property
94
272
  def name(self) -> Optional[str]:
95
273
  return self._name
@@ -111,7 +289,7 @@ class _Dict(_Object, type_prefix="di"):
111
289
  data: Optional[dict] = None, # DEPRECATED
112
290
  client: Optional[_Client] = None,
113
291
  environment_name: Optional[str] = None,
114
- _heartbeat_sleep: float = EPHEMERAL_OBJECT_HEARTBEAT_SLEEP,
292
+ _heartbeat_sleep: float = EPHEMERAL_OBJECT_HEARTBEAT_SLEEP, # mdmd:line-hidden
115
293
  ) -> AsyncIterator["_Dict"]:
116
294
  """Creates a new ephemeral Dict within a context manager:
117
295
 
@@ -145,7 +323,13 @@ class _Dict(_Object, type_prefix="di"):
145
323
  async with TaskContext() as tc:
146
324
  request = api_pb2.DictHeartbeatRequest(dict_id=response.dict_id)
147
325
  tc.infinite_loop(lambda: client.stub.DictHeartbeat(request), sleep=_heartbeat_sleep)
148
- yield cls._new_hydrated(response.dict_id, client, response.metadata, is_another_app=True)
326
+ yield cls._new_hydrated(
327
+ response.dict_id,
328
+ client,
329
+ response.metadata,
330
+ is_another_app=True,
331
+ rep="modal.Dict.ephemeral()",
332
+ )
149
333
 
150
334
  @staticmethod
151
335
  def from_name(
@@ -188,7 +372,8 @@ class _Dict(_Object, type_prefix="di"):
188
372
  logger.debug(f"Created dict with id {response.dict_id}")
189
373
  self._hydrate(response.dict_id, resolver.client, response.metadata)
190
374
 
191
- return _Dict._from_loader(_load, "Dict()", is_another_app=True, hydrate_lazily=True, name=name)
375
+ rep = _Dict._repr(name, environment_name)
376
+ return _Dict._from_loader(_load, rep, is_another_app=True, hydrate_lazily=True, name=name)
192
377
 
193
378
  @staticmethod
194
379
  async def lookup(
@@ -238,9 +423,18 @@ class _Dict(_Object, type_prefix="di"):
238
423
  client: Optional[_Client] = None,
239
424
  environment_name: Optional[str] = None,
240
425
  ):
241
- obj = await _Dict.from_name(name, environment_name=environment_name).hydrate(client)
242
- req = api_pb2.DictDeleteRequest(dict_id=obj.object_id)
243
- await retry_transient_errors(obj._client.stub.DictDelete, req)
426
+ """mdmd:hidden
427
+ Delete a named Dict object.
428
+
429
+ Warning: This deletes an *entire Dict*, not just a specific key.
430
+ Deletion is irreversible and will affect any Apps currently using the Dict.
431
+
432
+ DEPRECATED: This method is deprecated; we recommend using `modal.Dict.objects.delete` instead.
433
+ """
434
+ deprecation_warning(
435
+ (2025, 8, 6), "`modal.Dict.delete` is deprecated; we recommend using `modal.Dict.objects.delete` instead."
436
+ )
437
+ await _Dict.objects.delete(name, environment_name=environment_name, client=client)
244
438
 
245
439
  @live_method
246
440
  async def info(self) -> DictInfo:
modal/dict.pyi CHANGED
@@ -5,6 +5,7 @@ import modal._object
5
5
  import modal.client
6
6
  import modal.object
7
7
  import modal_proto.api_pb2
8
+ import synchronicity
8
9
  import synchronicity.combined_types
9
10
  import typing
10
11
  import typing_extensions
@@ -12,7 +13,7 @@ import typing_extensions
12
13
  def _serialize_dict(data): ...
13
14
 
14
15
  class DictInfo:
15
- """Information about the Dict object."""
16
+ """Information about a Dict object."""
16
17
 
17
18
  name: typing.Optional[str]
18
19
  created_at: datetime.datetime
@@ -32,6 +33,326 @@ class DictInfo:
32
33
  """Return self==value."""
33
34
  ...
34
35
 
36
+ class _DictManager:
37
+ """Namespace with methods for managing named Dict objects."""
38
+ @staticmethod
39
+ async def create(
40
+ name: str,
41
+ *,
42
+ allow_existing: bool = False,
43
+ environment_name: typing.Optional[str] = None,
44
+ client: typing.Optional[modal.client._Client] = None,
45
+ ) -> None:
46
+ """Create a new Dict object.
47
+
48
+ **Examples:**
49
+
50
+ ```python notest
51
+ modal.Dict.objects.create("my-dict")
52
+ ```
53
+
54
+ Dicts will be created in the active environment, or another one can be specified:
55
+
56
+ ```python notest
57
+ modal.Dict.objects.create("my-dict", environment_name="dev")
58
+ ```
59
+
60
+ By default, an error will be raised if the Dict already exists, but passing
61
+ `allow_existing=True` will make the creation attempt a no-op in this case.
62
+
63
+ ```python notest
64
+ modal.Dict.objects.create("my-dict", allow_existing=True)
65
+ ```
66
+
67
+ Note that this method does not return a local instance of the Dict. You can use
68
+ `modal.Dict.from_name` to perform a lookup after creation.
69
+
70
+ Added in v1.1.2.
71
+ """
72
+ ...
73
+
74
+ @staticmethod
75
+ async def list(
76
+ *,
77
+ max_objects: typing.Optional[int] = None,
78
+ created_before: typing.Union[datetime.datetime, str, None] = None,
79
+ environment_name: str = "",
80
+ client: typing.Optional[modal.client._Client] = None,
81
+ ) -> list[_Dict]:
82
+ """Return a list of hydrated Dict objects.
83
+
84
+ **Examples:**
85
+
86
+ ```python
87
+ dicts = modal.Dict.objects.list()
88
+ print([d.name for d in dicts])
89
+ ```
90
+
91
+ Dicts will be retreived from the active environment, or another one can be specified:
92
+
93
+ ```python notest
94
+ dev_dicts = modal.Dict.objects.list(environment_name="dev")
95
+ ```
96
+
97
+ By default, all named Dict are returned, newest to oldest. It's also possible to limit the
98
+ number of results and to filter by creation date:
99
+
100
+ ```python
101
+ dicts = modal.Dict.objects.list(max_objects=10, created_before="2025-01-01")
102
+ ```
103
+
104
+ Added in v1.1.2.
105
+ """
106
+ ...
107
+
108
+ @staticmethod
109
+ async def delete(
110
+ name: str,
111
+ *,
112
+ allow_missing: bool = False,
113
+ environment_name: typing.Optional[str] = None,
114
+ client: typing.Optional[modal.client._Client] = None,
115
+ ):
116
+ """Delete a named Dict.
117
+
118
+ Warning: This deletes an *entire Dict*, not just a specific key.
119
+ Deletion is irreversible and will affect any Apps currently using the Dict.
120
+
121
+ **Examples:**
122
+
123
+ ```python notest
124
+ await modal.Dict.objects.delete("my-dict")
125
+ ```
126
+
127
+ Dicts will be deleted from the active environment, or another one can be specified:
128
+
129
+ ```python notest
130
+ await modal.Dict.objects.delete("my-dict", environment_name="dev")
131
+ ```
132
+
133
+ Added in v1.1.2.
134
+ """
135
+ ...
136
+
137
+ class DictManager:
138
+ """Namespace with methods for managing named Dict objects."""
139
+ def __init__(self, /, *args, **kwargs):
140
+ """Initialize self. See help(type(self)) for accurate signature."""
141
+ ...
142
+
143
+ class __create_spec(typing_extensions.Protocol):
144
+ def __call__(
145
+ self,
146
+ /,
147
+ name: str,
148
+ *,
149
+ allow_existing: bool = False,
150
+ environment_name: typing.Optional[str] = None,
151
+ client: typing.Optional[modal.client.Client] = None,
152
+ ) -> None:
153
+ """Create a new Dict object.
154
+
155
+ **Examples:**
156
+
157
+ ```python notest
158
+ modal.Dict.objects.create("my-dict")
159
+ ```
160
+
161
+ Dicts will be created in the active environment, or another one can be specified:
162
+
163
+ ```python notest
164
+ modal.Dict.objects.create("my-dict", environment_name="dev")
165
+ ```
166
+
167
+ By default, an error will be raised if the Dict already exists, but passing
168
+ `allow_existing=True` will make the creation attempt a no-op in this case.
169
+
170
+ ```python notest
171
+ modal.Dict.objects.create("my-dict", allow_existing=True)
172
+ ```
173
+
174
+ Note that this method does not return a local instance of the Dict. You can use
175
+ `modal.Dict.from_name` to perform a lookup after creation.
176
+
177
+ Added in v1.1.2.
178
+ """
179
+ ...
180
+
181
+ async def aio(
182
+ self,
183
+ /,
184
+ name: str,
185
+ *,
186
+ allow_existing: bool = False,
187
+ environment_name: typing.Optional[str] = None,
188
+ client: typing.Optional[modal.client.Client] = None,
189
+ ) -> None:
190
+ """Create a new Dict object.
191
+
192
+ **Examples:**
193
+
194
+ ```python notest
195
+ modal.Dict.objects.create("my-dict")
196
+ ```
197
+
198
+ Dicts will be created in the active environment, or another one can be specified:
199
+
200
+ ```python notest
201
+ modal.Dict.objects.create("my-dict", environment_name="dev")
202
+ ```
203
+
204
+ By default, an error will be raised if the Dict already exists, but passing
205
+ `allow_existing=True` will make the creation attempt a no-op in this case.
206
+
207
+ ```python notest
208
+ modal.Dict.objects.create("my-dict", allow_existing=True)
209
+ ```
210
+
211
+ Note that this method does not return a local instance of the Dict. You can use
212
+ `modal.Dict.from_name` to perform a lookup after creation.
213
+
214
+ Added in v1.1.2.
215
+ """
216
+ ...
217
+
218
+ create: __create_spec
219
+
220
+ class __list_spec(typing_extensions.Protocol):
221
+ def __call__(
222
+ self,
223
+ /,
224
+ *,
225
+ max_objects: typing.Optional[int] = None,
226
+ created_before: typing.Union[datetime.datetime, str, None] = None,
227
+ environment_name: str = "",
228
+ client: typing.Optional[modal.client.Client] = None,
229
+ ) -> list[Dict]:
230
+ """Return a list of hydrated Dict objects.
231
+
232
+ **Examples:**
233
+
234
+ ```python
235
+ dicts = modal.Dict.objects.list()
236
+ print([d.name for d in dicts])
237
+ ```
238
+
239
+ Dicts will be retreived from the active environment, or another one can be specified:
240
+
241
+ ```python notest
242
+ dev_dicts = modal.Dict.objects.list(environment_name="dev")
243
+ ```
244
+
245
+ By default, all named Dict are returned, newest to oldest. It's also possible to limit the
246
+ number of results and to filter by creation date:
247
+
248
+ ```python
249
+ dicts = modal.Dict.objects.list(max_objects=10, created_before="2025-01-01")
250
+ ```
251
+
252
+ Added in v1.1.2.
253
+ """
254
+ ...
255
+
256
+ async def aio(
257
+ self,
258
+ /,
259
+ *,
260
+ max_objects: typing.Optional[int] = None,
261
+ created_before: typing.Union[datetime.datetime, str, None] = None,
262
+ environment_name: str = "",
263
+ client: typing.Optional[modal.client.Client] = None,
264
+ ) -> list[Dict]:
265
+ """Return a list of hydrated Dict objects.
266
+
267
+ **Examples:**
268
+
269
+ ```python
270
+ dicts = modal.Dict.objects.list()
271
+ print([d.name for d in dicts])
272
+ ```
273
+
274
+ Dicts will be retreived from the active environment, or another one can be specified:
275
+
276
+ ```python notest
277
+ dev_dicts = modal.Dict.objects.list(environment_name="dev")
278
+ ```
279
+
280
+ By default, all named Dict are returned, newest to oldest. It's also possible to limit the
281
+ number of results and to filter by creation date:
282
+
283
+ ```python
284
+ dicts = modal.Dict.objects.list(max_objects=10, created_before="2025-01-01")
285
+ ```
286
+
287
+ Added in v1.1.2.
288
+ """
289
+ ...
290
+
291
+ list: __list_spec
292
+
293
+ class __delete_spec(typing_extensions.Protocol):
294
+ def __call__(
295
+ self,
296
+ /,
297
+ name: str,
298
+ *,
299
+ allow_missing: bool = False,
300
+ environment_name: typing.Optional[str] = None,
301
+ client: typing.Optional[modal.client.Client] = None,
302
+ ):
303
+ """Delete a named Dict.
304
+
305
+ Warning: This deletes an *entire Dict*, not just a specific key.
306
+ Deletion is irreversible and will affect any Apps currently using the Dict.
307
+
308
+ **Examples:**
309
+
310
+ ```python notest
311
+ await modal.Dict.objects.delete("my-dict")
312
+ ```
313
+
314
+ Dicts will be deleted from the active environment, or another one can be specified:
315
+
316
+ ```python notest
317
+ await modal.Dict.objects.delete("my-dict", environment_name="dev")
318
+ ```
319
+
320
+ Added in v1.1.2.
321
+ """
322
+ ...
323
+
324
+ async def aio(
325
+ self,
326
+ /,
327
+ name: str,
328
+ *,
329
+ allow_missing: bool = False,
330
+ environment_name: typing.Optional[str] = None,
331
+ client: typing.Optional[modal.client.Client] = None,
332
+ ):
333
+ """Delete a named Dict.
334
+
335
+ Warning: This deletes an *entire Dict*, not just a specific key.
336
+ Deletion is irreversible and will affect any Apps currently using the Dict.
337
+
338
+ **Examples:**
339
+
340
+ ```python notest
341
+ await modal.Dict.objects.delete("my-dict")
342
+ ```
343
+
344
+ Dicts will be deleted from the active environment, or another one can be specified:
345
+
346
+ ```python notest
347
+ await modal.Dict.objects.delete("my-dict", environment_name="dev")
348
+ ```
349
+
350
+ Added in v1.1.2.
351
+ """
352
+ ...
353
+
354
+ delete: __delete_spec
355
+
35
356
  class _Dict(modal._object._Object):
36
357
  """Distributed dictionary for storage in Modal apps.
37
358
 
@@ -81,6 +402,8 @@ class _Dict(modal._object._Object):
81
402
  """mdmd:hidden"""
82
403
  ...
83
404
 
405
+ @synchronicity.classproperty
406
+ def objects(cls) -> _DictManager: ...
84
407
  @property
85
408
  def name(self) -> typing.Optional[str]: ...
86
409
  def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
@@ -162,7 +485,17 @@ class _Dict(modal._object._Object):
162
485
  *,
163
486
  client: typing.Optional[modal.client._Client] = None,
164
487
  environment_name: typing.Optional[str] = None,
165
- ): ...
488
+ ):
489
+ """mdmd:hidden
490
+ Delete a named Dict object.
491
+
492
+ Warning: This deletes an *entire Dict*, not just a specific key.
493
+ Deletion is irreversible and will affect any Apps currently using the Dict.
494
+
495
+ DEPRECATED: This method is deprecated; we recommend using `modal.Dict.objects.delete` instead.
496
+ """
497
+ ...
498
+
166
499
  async def info(self) -> DictInfo:
167
500
  """Return information about the Dict object."""
168
501
  ...
@@ -308,6 +641,8 @@ class Dict(modal.object.Object):
308
641
  """mdmd:hidden"""
309
642
  ...
310
643
 
644
+ @synchronicity.classproperty
645
+ def objects(cls) -> DictManager: ...
311
646
  @property
312
647
  def name(self) -> typing.Optional[str]: ...
313
648
  def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
@@ -420,7 +755,17 @@ class Dict(modal.object.Object):
420
755
  *,
421
756
  client: typing.Optional[modal.client.Client] = None,
422
757
  environment_name: typing.Optional[str] = None,
423
- ): ...
758
+ ):
759
+ """mdmd:hidden
760
+ Delete a named Dict object.
761
+
762
+ Warning: This deletes an *entire Dict*, not just a specific key.
763
+ Deletion is irreversible and will affect any Apps currently using the Dict.
764
+
765
+ DEPRECATED: This method is deprecated; we recommend using `modal.Dict.objects.delete` instead.
766
+ """
767
+ ...
768
+
424
769
  async def aio(
425
770
  self,
426
771
  /,
@@ -428,7 +773,16 @@ class Dict(modal.object.Object):
428
773
  *,
429
774
  client: typing.Optional[modal.client.Client] = None,
430
775
  environment_name: typing.Optional[str] = None,
431
- ): ...
776
+ ):
777
+ """mdmd:hidden
778
+ Delete a named Dict object.
779
+
780
+ Warning: This deletes an *entire Dict*, not just a specific key.
781
+ Deletion is irreversible and will affect any Apps currently using the Dict.
782
+
783
+ DEPRECATED: This method is deprecated; we recommend using `modal.Dict.objects.delete` instead.
784
+ """
785
+ ...
432
786
 
433
787
  delete: __delete_spec
434
788