modal 0.73.45__py3-none-any.whl → 0.73.47__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/_runtime/container_io_manager.pyi +395 -0
- modal/_runtime/execution_context.pyi +23 -0
- modal/client.pyi +2 -2
- {modal-0.73.45.dist-info → modal-0.73.47.dist-info}/METADATA +13 -11
- {modal-0.73.45.dist-info → modal-0.73.47.dist-info}/RECORD +10 -17
- {modal-0.73.45.dist-info → modal-0.73.47.dist-info}/WHEEL +1 -1
- {modal-0.73.45.dist-info → modal-0.73.47.dist-info}/top_level.txt +0 -1
- modal_version/_version_generated.py +1 -1
- modal_docs/mdmd/__init__.py +0 -1
- modal_docs/mdmd/mdmd.py +0 -195
- modal_docs/mdmd/signatures.py +0 -76
- modal_global_objects/__init__.py +0 -1
- modal_global_objects/images/__init__.py +0 -1
- modal_global_objects/images/base_images.py +0 -28
- modal_global_objects/mounts/__init__.py +0 -1
- modal_global_objects/mounts/modal_client_package.py +0 -29
- modal_global_objects/mounts/python_standalone.py +0 -53
- {modal-0.73.45.dist-info → modal-0.73.47.dist-info}/LICENSE +0 -0
- {modal-0.73.45.dist-info → modal-0.73.47.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,395 @@
|
|
1
|
+
import asyncio
|
2
|
+
import asyncio.locks
|
3
|
+
import asyncio.queues
|
4
|
+
import collections.abc
|
5
|
+
import modal._runtime.user_code_imports
|
6
|
+
import modal.client
|
7
|
+
import modal_proto.api_pb2
|
8
|
+
import synchronicity.combined_types
|
9
|
+
import typing
|
10
|
+
import typing_extensions
|
11
|
+
|
12
|
+
class UserException(Exception): ...
|
13
|
+
class Sentinel: ...
|
14
|
+
|
15
|
+
class IOContext:
|
16
|
+
input_ids: list[str]
|
17
|
+
function_call_ids: list[str]
|
18
|
+
finalized_function: modal._runtime.user_code_imports.FinalizedFunction
|
19
|
+
_cancel_issued: bool
|
20
|
+
_cancel_callback: typing.Optional[collections.abc.Callable[[], None]]
|
21
|
+
|
22
|
+
def __init__(
|
23
|
+
self,
|
24
|
+
input_ids: list[str],
|
25
|
+
function_call_ids: list[str],
|
26
|
+
finalized_function: modal._runtime.user_code_imports.FinalizedFunction,
|
27
|
+
function_inputs: list[modal_proto.api_pb2.FunctionInput],
|
28
|
+
is_batched: bool,
|
29
|
+
client: modal.client._Client,
|
30
|
+
): ...
|
31
|
+
@classmethod
|
32
|
+
async def create(
|
33
|
+
cls,
|
34
|
+
client: modal.client._Client,
|
35
|
+
finalized_functions: dict[str, modal._runtime.user_code_imports.FinalizedFunction],
|
36
|
+
inputs: list[tuple[str, str, modal_proto.api_pb2.FunctionInput]],
|
37
|
+
is_batched: bool,
|
38
|
+
) -> IOContext: ...
|
39
|
+
def set_cancel_callback(self, cb: collections.abc.Callable[[], None]): ...
|
40
|
+
def cancel(self): ...
|
41
|
+
def _args_and_kwargs(self) -> tuple[tuple[typing.Any, ...], dict[str, list[typing.Any]]]: ...
|
42
|
+
def call_finalized_function(self) -> typing.Any: ...
|
43
|
+
def validate_output_data(self, data: typing.Any) -> list[typing.Any]: ...
|
44
|
+
|
45
|
+
class InputSlots:
|
46
|
+
active: int
|
47
|
+
value: int
|
48
|
+
waiter: typing.Optional[asyncio.Future]
|
49
|
+
closed: bool
|
50
|
+
|
51
|
+
def __init__(self, value: int) -> None: ...
|
52
|
+
async def acquire(self) -> None: ...
|
53
|
+
def _wake_waiter(self) -> None: ...
|
54
|
+
def release(self) -> None: ...
|
55
|
+
def set_value(self, value: int) -> None: ...
|
56
|
+
async def close(self) -> None: ...
|
57
|
+
|
58
|
+
class _ContainerIOManager:
|
59
|
+
task_id: str
|
60
|
+
function_id: str
|
61
|
+
app_id: str
|
62
|
+
function_def: modal_proto.api_pb2.Function
|
63
|
+
checkpoint_id: typing.Optional[str]
|
64
|
+
calls_completed: int
|
65
|
+
total_user_time: float
|
66
|
+
current_input_id: typing.Optional[str]
|
67
|
+
current_inputs: dict[str, IOContext]
|
68
|
+
current_input_started_at: typing.Optional[float]
|
69
|
+
_target_concurrency: int
|
70
|
+
_max_concurrency: int
|
71
|
+
_concurrency_loop: typing.Optional[asyncio.Task]
|
72
|
+
_input_slots: InputSlots
|
73
|
+
_environment_name: str
|
74
|
+
_heartbeat_loop: typing.Optional[asyncio.Task]
|
75
|
+
_heartbeat_condition: typing.Optional[asyncio.locks.Condition]
|
76
|
+
_waiting_for_memory_snapshot: bool
|
77
|
+
_is_interactivity_enabled: bool
|
78
|
+
_fetching_inputs: bool
|
79
|
+
_client: modal.client._Client
|
80
|
+
_GENERATOR_STOP_SENTINEL: typing.ClassVar[Sentinel]
|
81
|
+
_singleton: typing.ClassVar[typing.Optional[_ContainerIOManager]]
|
82
|
+
|
83
|
+
def _init(self, container_args: modal_proto.api_pb2.ContainerArguments, client: modal.client._Client): ...
|
84
|
+
@property
|
85
|
+
def heartbeat_condition(self) -> asyncio.locks.Condition: ...
|
86
|
+
@staticmethod
|
87
|
+
def __new__(
|
88
|
+
cls, container_args: modal_proto.api_pb2.ContainerArguments, client: modal.client._Client
|
89
|
+
) -> _ContainerIOManager: ...
|
90
|
+
@classmethod
|
91
|
+
def _reset_singleton(cls): ...
|
92
|
+
async def hello(self): ...
|
93
|
+
async def _run_heartbeat_loop(self): ...
|
94
|
+
async def _heartbeat_handle_cancellations(self) -> bool: ...
|
95
|
+
def heartbeats(self, wait_for_mem_snap: bool) -> typing.AsyncContextManager[None]: ...
|
96
|
+
def stop_heartbeat(self): ...
|
97
|
+
def dynamic_concurrency_manager(self) -> typing.AsyncContextManager[None]: ...
|
98
|
+
async def _dynamic_concurrency_loop(self): ...
|
99
|
+
async def get_serialized_function(
|
100
|
+
self,
|
101
|
+
) -> tuple[typing.Optional[typing.Any], typing.Optional[collections.abc.Callable[..., typing.Any]]]: ...
|
102
|
+
def serialize(self, obj: typing.Any) -> bytes: ...
|
103
|
+
def deserialize(self, data: bytes) -> typing.Any: ...
|
104
|
+
def serialize_data_format(self, obj: typing.Any, data_format: int) -> bytes: ...
|
105
|
+
async def format_blob_data(self, data: bytes) -> dict[str, typing.Any]: ...
|
106
|
+
def get_data_in(self, function_call_id: str) -> collections.abc.AsyncIterator[typing.Any]: ...
|
107
|
+
async def put_data_out(
|
108
|
+
self, function_call_id: str, start_index: int, data_format: int, serialized_messages: list[typing.Any]
|
109
|
+
) -> None: ...
|
110
|
+
async def generator_output_task(
|
111
|
+
self, function_call_id: str, data_format: int, message_rx: asyncio.queues.Queue
|
112
|
+
) -> None: ...
|
113
|
+
async def _queue_create(self, size: int) -> asyncio.queues.Queue: ...
|
114
|
+
async def _queue_put(self, queue: asyncio.queues.Queue, value: typing.Any) -> None: ...
|
115
|
+
def get_average_call_time(self) -> float: ...
|
116
|
+
def get_max_inputs_to_fetch(self): ...
|
117
|
+
def _generate_inputs(
|
118
|
+
self, batch_max_size: int, batch_wait_ms: int
|
119
|
+
) -> collections.abc.AsyncIterator[list[tuple[str, str, modal_proto.api_pb2.FunctionInput]]]: ...
|
120
|
+
def run_inputs_outputs(
|
121
|
+
self,
|
122
|
+
finalized_functions: dict[str, modal._runtime.user_code_imports.FinalizedFunction],
|
123
|
+
batch_max_size: int = 0,
|
124
|
+
batch_wait_ms: int = 0,
|
125
|
+
) -> collections.abc.AsyncIterator[IOContext]: ...
|
126
|
+
async def _push_outputs(
|
127
|
+
self,
|
128
|
+
io_context: IOContext,
|
129
|
+
started_at: float,
|
130
|
+
data_format: int,
|
131
|
+
results: list[modal_proto.api_pb2.GenericResult],
|
132
|
+
) -> None: ...
|
133
|
+
def serialize_exception(self, exc: BaseException) -> bytes: ...
|
134
|
+
def serialize_traceback(self, exc: BaseException) -> tuple[typing.Optional[bytes], typing.Optional[bytes]]: ...
|
135
|
+
def handle_user_exception(self) -> typing.AsyncContextManager[None]: ...
|
136
|
+
def handle_input_exception(self, io_context: IOContext, started_at: float) -> typing.AsyncContextManager[None]: ...
|
137
|
+
def exit_context(self, started_at, input_ids: list[str]): ...
|
138
|
+
async def push_outputs(
|
139
|
+
self, io_context: IOContext, started_at: float, data: typing.Any, data_format: int
|
140
|
+
) -> None: ...
|
141
|
+
async def memory_restore(self) -> None: ...
|
142
|
+
async def memory_snapshot(self) -> None: ...
|
143
|
+
async def volume_commit(self, volume_ids: list[str]) -> None: ...
|
144
|
+
async def interact(self, from_breakpoint: bool = False): ...
|
145
|
+
@property
|
146
|
+
def target_concurrency(self) -> int: ...
|
147
|
+
@property
|
148
|
+
def max_concurrency(self) -> int: ...
|
149
|
+
@classmethod
|
150
|
+
def get_input_concurrency(cls) -> int: ...
|
151
|
+
@classmethod
|
152
|
+
def set_input_concurrency(cls, concurrency: int): ...
|
153
|
+
@classmethod
|
154
|
+
def stop_fetching_inputs(cls): ...
|
155
|
+
|
156
|
+
SUPERSELF = typing.TypeVar("SUPERSELF", covariant=True)
|
157
|
+
|
158
|
+
class ContainerIOManager:
|
159
|
+
task_id: str
|
160
|
+
function_id: str
|
161
|
+
app_id: str
|
162
|
+
function_def: modal_proto.api_pb2.Function
|
163
|
+
checkpoint_id: typing.Optional[str]
|
164
|
+
calls_completed: int
|
165
|
+
total_user_time: float
|
166
|
+
current_input_id: typing.Optional[str]
|
167
|
+
current_inputs: dict[str, IOContext]
|
168
|
+
current_input_started_at: typing.Optional[float]
|
169
|
+
_target_concurrency: int
|
170
|
+
_max_concurrency: int
|
171
|
+
_concurrency_loop: typing.Optional[asyncio.Task]
|
172
|
+
_input_slots: InputSlots
|
173
|
+
_environment_name: str
|
174
|
+
_heartbeat_loop: typing.Optional[asyncio.Task]
|
175
|
+
_heartbeat_condition: typing.Optional[asyncio.locks.Condition]
|
176
|
+
_waiting_for_memory_snapshot: bool
|
177
|
+
_is_interactivity_enabled: bool
|
178
|
+
_fetching_inputs: bool
|
179
|
+
_client: modal.client.Client
|
180
|
+
_GENERATOR_STOP_SENTINEL: typing.ClassVar[Sentinel]
|
181
|
+
_singleton: typing.ClassVar[typing.Optional[ContainerIOManager]]
|
182
|
+
|
183
|
+
def __init__(self, /, *args, **kwargs): ...
|
184
|
+
def _init(self, container_args: modal_proto.api_pb2.ContainerArguments, client: modal.client.Client): ...
|
185
|
+
@property
|
186
|
+
def heartbeat_condition(self) -> asyncio.locks.Condition: ...
|
187
|
+
@classmethod
|
188
|
+
def _reset_singleton(cls): ...
|
189
|
+
|
190
|
+
class __hello_spec(typing_extensions.Protocol[SUPERSELF]):
|
191
|
+
def __call__(self): ...
|
192
|
+
async def aio(self): ...
|
193
|
+
|
194
|
+
hello: __hello_spec[typing_extensions.Self]
|
195
|
+
|
196
|
+
class ___run_heartbeat_loop_spec(typing_extensions.Protocol[SUPERSELF]):
|
197
|
+
def __call__(self): ...
|
198
|
+
async def aio(self): ...
|
199
|
+
|
200
|
+
_run_heartbeat_loop: ___run_heartbeat_loop_spec[typing_extensions.Self]
|
201
|
+
|
202
|
+
class ___heartbeat_handle_cancellations_spec(typing_extensions.Protocol[SUPERSELF]):
|
203
|
+
def __call__(self) -> bool: ...
|
204
|
+
async def aio(self) -> bool: ...
|
205
|
+
|
206
|
+
_heartbeat_handle_cancellations: ___heartbeat_handle_cancellations_spec[typing_extensions.Self]
|
207
|
+
|
208
|
+
class __heartbeats_spec(typing_extensions.Protocol[SUPERSELF]):
|
209
|
+
def __call__(
|
210
|
+
self, wait_for_mem_snap: bool
|
211
|
+
) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]: ...
|
212
|
+
def aio(self, wait_for_mem_snap: bool) -> typing.AsyncContextManager[None]: ...
|
213
|
+
|
214
|
+
heartbeats: __heartbeats_spec[typing_extensions.Self]
|
215
|
+
|
216
|
+
def stop_heartbeat(self): ...
|
217
|
+
|
218
|
+
class __dynamic_concurrency_manager_spec(typing_extensions.Protocol[SUPERSELF]):
|
219
|
+
def __call__(self) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]: ...
|
220
|
+
def aio(self) -> typing.AsyncContextManager[None]: ...
|
221
|
+
|
222
|
+
dynamic_concurrency_manager: __dynamic_concurrency_manager_spec[typing_extensions.Self]
|
223
|
+
|
224
|
+
class ___dynamic_concurrency_loop_spec(typing_extensions.Protocol[SUPERSELF]):
|
225
|
+
def __call__(self): ...
|
226
|
+
async def aio(self): ...
|
227
|
+
|
228
|
+
_dynamic_concurrency_loop: ___dynamic_concurrency_loop_spec[typing_extensions.Self]
|
229
|
+
|
230
|
+
class __get_serialized_function_spec(typing_extensions.Protocol[SUPERSELF]):
|
231
|
+
def __call__(
|
232
|
+
self,
|
233
|
+
) -> tuple[typing.Optional[typing.Any], typing.Optional[collections.abc.Callable[..., typing.Any]]]: ...
|
234
|
+
async def aio(
|
235
|
+
self,
|
236
|
+
) -> tuple[typing.Optional[typing.Any], typing.Optional[collections.abc.Callable[..., typing.Any]]]: ...
|
237
|
+
|
238
|
+
get_serialized_function: __get_serialized_function_spec[typing_extensions.Self]
|
239
|
+
|
240
|
+
def serialize(self, obj: typing.Any) -> bytes: ...
|
241
|
+
def deserialize(self, data: bytes) -> typing.Any: ...
|
242
|
+
def serialize_data_format(self, obj: typing.Any, data_format: int) -> bytes: ...
|
243
|
+
|
244
|
+
class __format_blob_data_spec(typing_extensions.Protocol[SUPERSELF]):
|
245
|
+
def __call__(self, data: bytes) -> dict[str, typing.Any]: ...
|
246
|
+
async def aio(self, data: bytes) -> dict[str, typing.Any]: ...
|
247
|
+
|
248
|
+
format_blob_data: __format_blob_data_spec[typing_extensions.Self]
|
249
|
+
|
250
|
+
class __get_data_in_spec(typing_extensions.Protocol[SUPERSELF]):
|
251
|
+
def __call__(self, function_call_id: str) -> typing.Iterator[typing.Any]: ...
|
252
|
+
def aio(self, function_call_id: str) -> collections.abc.AsyncIterator[typing.Any]: ...
|
253
|
+
|
254
|
+
get_data_in: __get_data_in_spec[typing_extensions.Self]
|
255
|
+
|
256
|
+
class __put_data_out_spec(typing_extensions.Protocol[SUPERSELF]):
|
257
|
+
def __call__(
|
258
|
+
self, function_call_id: str, start_index: int, data_format: int, serialized_messages: list[typing.Any]
|
259
|
+
) -> None: ...
|
260
|
+
async def aio(
|
261
|
+
self, function_call_id: str, start_index: int, data_format: int, serialized_messages: list[typing.Any]
|
262
|
+
) -> None: ...
|
263
|
+
|
264
|
+
put_data_out: __put_data_out_spec[typing_extensions.Self]
|
265
|
+
|
266
|
+
class __generator_output_task_spec(typing_extensions.Protocol[SUPERSELF]):
|
267
|
+
def __call__(self, function_call_id: str, data_format: int, message_rx: asyncio.queues.Queue) -> None: ...
|
268
|
+
async def aio(self, function_call_id: str, data_format: int, message_rx: asyncio.queues.Queue) -> None: ...
|
269
|
+
|
270
|
+
generator_output_task: __generator_output_task_spec[typing_extensions.Self]
|
271
|
+
|
272
|
+
class ___queue_create_spec(typing_extensions.Protocol[SUPERSELF]):
|
273
|
+
def __call__(self, size: int) -> asyncio.queues.Queue: ...
|
274
|
+
async def aio(self, size: int) -> asyncio.queues.Queue: ...
|
275
|
+
|
276
|
+
_queue_create: ___queue_create_spec[typing_extensions.Self]
|
277
|
+
|
278
|
+
class ___queue_put_spec(typing_extensions.Protocol[SUPERSELF]):
|
279
|
+
def __call__(self, queue: asyncio.queues.Queue, value: typing.Any) -> None: ...
|
280
|
+
async def aio(self, queue: asyncio.queues.Queue, value: typing.Any) -> None: ...
|
281
|
+
|
282
|
+
_queue_put: ___queue_put_spec[typing_extensions.Self]
|
283
|
+
|
284
|
+
def get_average_call_time(self) -> float: ...
|
285
|
+
def get_max_inputs_to_fetch(self): ...
|
286
|
+
|
287
|
+
class ___generate_inputs_spec(typing_extensions.Protocol[SUPERSELF]):
|
288
|
+
def __call__(
|
289
|
+
self, batch_max_size: int, batch_wait_ms: int
|
290
|
+
) -> typing.Iterator[list[tuple[str, str, modal_proto.api_pb2.FunctionInput]]]: ...
|
291
|
+
def aio(
|
292
|
+
self, batch_max_size: int, batch_wait_ms: int
|
293
|
+
) -> collections.abc.AsyncIterator[list[tuple[str, str, modal_proto.api_pb2.FunctionInput]]]: ...
|
294
|
+
|
295
|
+
_generate_inputs: ___generate_inputs_spec[typing_extensions.Self]
|
296
|
+
|
297
|
+
class __run_inputs_outputs_spec(typing_extensions.Protocol[SUPERSELF]):
|
298
|
+
def __call__(
|
299
|
+
self,
|
300
|
+
finalized_functions: dict[str, modal._runtime.user_code_imports.FinalizedFunction],
|
301
|
+
batch_max_size: int = 0,
|
302
|
+
batch_wait_ms: int = 0,
|
303
|
+
) -> typing.Iterator[IOContext]: ...
|
304
|
+
def aio(
|
305
|
+
self,
|
306
|
+
finalized_functions: dict[str, modal._runtime.user_code_imports.FinalizedFunction],
|
307
|
+
batch_max_size: int = 0,
|
308
|
+
batch_wait_ms: int = 0,
|
309
|
+
) -> collections.abc.AsyncIterator[IOContext]: ...
|
310
|
+
|
311
|
+
run_inputs_outputs: __run_inputs_outputs_spec[typing_extensions.Self]
|
312
|
+
|
313
|
+
class ___push_outputs_spec(typing_extensions.Protocol[SUPERSELF]):
|
314
|
+
def __call__(
|
315
|
+
self,
|
316
|
+
io_context: IOContext,
|
317
|
+
started_at: float,
|
318
|
+
data_format: int,
|
319
|
+
results: list[modal_proto.api_pb2.GenericResult],
|
320
|
+
) -> None: ...
|
321
|
+
async def aio(
|
322
|
+
self,
|
323
|
+
io_context: IOContext,
|
324
|
+
started_at: float,
|
325
|
+
data_format: int,
|
326
|
+
results: list[modal_proto.api_pb2.GenericResult],
|
327
|
+
) -> None: ...
|
328
|
+
|
329
|
+
_push_outputs: ___push_outputs_spec[typing_extensions.Self]
|
330
|
+
|
331
|
+
def serialize_exception(self, exc: BaseException) -> bytes: ...
|
332
|
+
def serialize_traceback(self, exc: BaseException) -> tuple[typing.Optional[bytes], typing.Optional[bytes]]: ...
|
333
|
+
|
334
|
+
class __handle_user_exception_spec(typing_extensions.Protocol[SUPERSELF]):
|
335
|
+
def __call__(self) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]: ...
|
336
|
+
def aio(self) -> typing.AsyncContextManager[None]: ...
|
337
|
+
|
338
|
+
handle_user_exception: __handle_user_exception_spec[typing_extensions.Self]
|
339
|
+
|
340
|
+
class __handle_input_exception_spec(typing_extensions.Protocol[SUPERSELF]):
|
341
|
+
def __call__(
|
342
|
+
self, io_context: IOContext, started_at: float
|
343
|
+
) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]: ...
|
344
|
+
def aio(self, io_context: IOContext, started_at: float) -> typing.AsyncContextManager[None]: ...
|
345
|
+
|
346
|
+
handle_input_exception: __handle_input_exception_spec[typing_extensions.Self]
|
347
|
+
|
348
|
+
def exit_context(self, started_at, input_ids: list[str]): ...
|
349
|
+
|
350
|
+
class __push_outputs_spec(typing_extensions.Protocol[SUPERSELF]):
|
351
|
+
def __call__(self, io_context: IOContext, started_at: float, data: typing.Any, data_format: int) -> None: ...
|
352
|
+
async def aio(self, io_context: IOContext, started_at: float, data: typing.Any, data_format: int) -> None: ...
|
353
|
+
|
354
|
+
push_outputs: __push_outputs_spec[typing_extensions.Self]
|
355
|
+
|
356
|
+
class __memory_restore_spec(typing_extensions.Protocol[SUPERSELF]):
|
357
|
+
def __call__(self) -> None: ...
|
358
|
+
async def aio(self) -> None: ...
|
359
|
+
|
360
|
+
memory_restore: __memory_restore_spec[typing_extensions.Self]
|
361
|
+
|
362
|
+
class __memory_snapshot_spec(typing_extensions.Protocol[SUPERSELF]):
|
363
|
+
def __call__(self) -> None: ...
|
364
|
+
async def aio(self) -> None: ...
|
365
|
+
|
366
|
+
memory_snapshot: __memory_snapshot_spec[typing_extensions.Self]
|
367
|
+
|
368
|
+
class __volume_commit_spec(typing_extensions.Protocol[SUPERSELF]):
|
369
|
+
def __call__(self, volume_ids: list[str]) -> None: ...
|
370
|
+
async def aio(self, volume_ids: list[str]) -> None: ...
|
371
|
+
|
372
|
+
volume_commit: __volume_commit_spec[typing_extensions.Self]
|
373
|
+
|
374
|
+
class __interact_spec(typing_extensions.Protocol[SUPERSELF]):
|
375
|
+
def __call__(self, from_breakpoint: bool = False): ...
|
376
|
+
async def aio(self, from_breakpoint: bool = False): ...
|
377
|
+
|
378
|
+
interact: __interact_spec[typing_extensions.Self]
|
379
|
+
|
380
|
+
@property
|
381
|
+
def target_concurrency(self) -> int: ...
|
382
|
+
@property
|
383
|
+
def max_concurrency(self) -> int: ...
|
384
|
+
@classmethod
|
385
|
+
def get_input_concurrency(cls) -> int: ...
|
386
|
+
@classmethod
|
387
|
+
def set_input_concurrency(cls, concurrency: int): ...
|
388
|
+
@classmethod
|
389
|
+
def stop_fetching_inputs(cls): ...
|
390
|
+
|
391
|
+
def check_fastapi_pydantic_compatibility(exc: ImportError) -> None: ...
|
392
|
+
|
393
|
+
MAX_OUTPUT_BATCH_SIZE: int
|
394
|
+
|
395
|
+
RTT_S: float
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import collections.abc
|
2
|
+
import contextvars
|
3
|
+
import typing
|
4
|
+
import typing_extensions
|
5
|
+
|
6
|
+
def is_local() -> bool: ...
|
7
|
+
async def _interact() -> None: ...
|
8
|
+
|
9
|
+
class __interact_spec(typing_extensions.Protocol):
|
10
|
+
def __call__(self) -> None: ...
|
11
|
+
async def aio(self) -> None: ...
|
12
|
+
|
13
|
+
interact: __interact_spec
|
14
|
+
|
15
|
+
def current_input_id() -> typing.Optional[str]: ...
|
16
|
+
def current_function_call_id() -> typing.Optional[str]: ...
|
17
|
+
def _set_current_context_ids(
|
18
|
+
input_ids: list[str], function_call_ids: list[str]
|
19
|
+
) -> collections.abc.Callable[[], None]: ...
|
20
|
+
|
21
|
+
_current_input_id: contextvars.ContextVar
|
22
|
+
|
23
|
+
_current_function_call_id: contextvars.ContextVar
|
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.
|
30
|
+
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.47"
|
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.
|
88
|
+
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.47"
|
89
89
|
): ...
|
90
90
|
def is_closed(self) -> bool: ...
|
91
91
|
@property
|
@@ -1,11 +1,13 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.2
|
2
2
|
Name: modal
|
3
|
-
Version: 0.73.
|
3
|
+
Version: 0.73.47
|
4
4
|
Summary: Python client library for Modal
|
5
|
-
Author: Modal Labs
|
6
|
-
|
5
|
+
Author-email: Modal Labs <support@modal.com>
|
6
|
+
License: Apache-2.0
|
7
7
|
Project-URL: Homepage, https://modal.com
|
8
8
|
Project-URL: Source, https://github.com/modal-labs/modal-client
|
9
|
+
Project-URL: Documentation, https://modal.com/docs
|
10
|
+
Project-URL: Issue Tracker, https://github.com/modal-labs/modal-client/issues
|
9
11
|
Keywords: modal,client,cloud,serverless,infrastructure
|
10
12
|
Classifier: Topic :: System :: Distributed Computing
|
11
13
|
Classifier: Operating System :: OS Independent
|
@@ -16,18 +18,18 @@ Description-Content-Type: text/markdown
|
|
16
18
|
License-File: LICENSE
|
17
19
|
Requires-Dist: aiohttp
|
18
20
|
Requires-Dist: certifi
|
19
|
-
Requires-Dist: click
|
21
|
+
Requires-Dist: click>=8.1.0
|
20
22
|
Requires-Dist: fastapi
|
21
|
-
Requires-Dist: grpclib
|
22
|
-
Requires-Dist: protobuf
|
23
|
-
Requires-Dist: rich
|
24
|
-
Requires-Dist: synchronicity
|
23
|
+
Requires-Dist: grpclib==0.4.7
|
24
|
+
Requires-Dist: protobuf!=4.24.0,<6.0,>=3.19
|
25
|
+
Requires-Dist: rich>=12.0.0
|
26
|
+
Requires-Dist: synchronicity~=0.9.10
|
25
27
|
Requires-Dist: toml
|
26
|
-
Requires-Dist: typer
|
28
|
+
Requires-Dist: typer>=0.9
|
27
29
|
Requires-Dist: types-certifi
|
28
30
|
Requires-Dist: types-toml
|
29
31
|
Requires-Dist: watchfiles
|
30
|
-
Requires-Dist:
|
32
|
+
Requires-Dist: typing_extensions~=4.6
|
31
33
|
|
32
34
|
# Modal Python Library
|
33
35
|
|
@@ -22,7 +22,7 @@ modal/app.py,sha256=rCOPD51gVyow8muyaqMuV65qfTnAZKf_w1OCZdSF_6o,44636
|
|
22
22
|
modal/app.pyi,sha256=0MMCgskIL4r3eq8oBcfm2lLyeao2gXjS3iXaIfmaJ-o,25959
|
23
23
|
modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
|
24
24
|
modal/client.py,sha256=8SQawr7P1PNUCq1UmJMUQXG2jIo4Nmdcs311XqrNLRE,15276
|
25
|
-
modal/client.pyi,sha256=
|
25
|
+
modal/client.pyi,sha256=5qG22FLFyDb4OjKfcnpVlfFwBYCVD6O_SzR9Rh2llaA,7593
|
26
26
|
modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
|
27
27
|
modal/cloud_bucket_mount.pyi,sha256=30T3K1a89l6wzmEJ_J9iWv9SknoGqaZDx59Xs-ZQcmk,1607
|
28
28
|
modal/cls.py,sha256=nJhJr-YuttOmdNWxtMHcBV-q6iQmY5qXkEy9yO43clY,31130
|
@@ -85,7 +85,9 @@ modal/volume.pyi,sha256=kTsXarphjZILXci84LQy7EyC84eXUs5-7D62IM5q3eE,12491
|
|
85
85
|
modal/_runtime/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
86
86
|
modal/_runtime/asgi.py,sha256=vIxpGrCZhdeThwazQckmrqoNKgDQYOyv8emzBHr8CiU,22154
|
87
87
|
modal/_runtime/container_io_manager.py,sha256=3VPj0RWtSdvVZD96l5ZpO8MjhLRjAi_P_ZtpNK3nGn0,43593
|
88
|
+
modal/_runtime/container_io_manager.pyi,sha256=sEGpOvlDOQCwUiJn4CAyE8TT2lCBKNBEqGWExfvVKsY,16661
|
88
89
|
modal/_runtime/execution_context.py,sha256=E6ofm6j1POXGPxS841X3V7JU6NheVb8OkQc7JpLq4Kg,2712
|
90
|
+
modal/_runtime/execution_context.pyi,sha256=wQZwMNADExkeNdB9yKX0PPojovxlFHbap3441wAsiMY,634
|
89
91
|
modal/_runtime/gpu_memory_snapshot.py,sha256=tA3m1d1cwnmHpvpCeN_WijDd6n8byn7LWlpicbIxiOI,3144
|
90
92
|
modal/_runtime/telemetry.py,sha256=T1RoAGyjBDr1swiM6pPsGRSITm7LI5FDK18oNXxY08U,5163
|
91
93
|
modal/_runtime/user_code_imports.py,sha256=qDasIvffN3SJjUeT1DHcpN35lWNepnbomS0Z8yD65mA,14740
|
@@ -145,15 +147,6 @@ modal/requirements/base-images.json,sha256=kLNo5Sqmnhp9H6Hr9IcaGJFrRaRg1yfuepUWk
|
|
145
147
|
modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
|
146
148
|
modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
|
147
149
|
modal_docs/gen_reference_docs.py,sha256=aDcUSSDtAAZ4eeFWyroeIg2TOzyRoYcic-d9Zh9TdLY,6656
|
148
|
-
modal_docs/mdmd/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
|
149
|
-
modal_docs/mdmd/mdmd.py,sha256=Irx49MCCTlBOP4FBdLR--JrpA3-WhsVeriq0LGgsRic,6232
|
150
|
-
modal_docs/mdmd/signatures.py,sha256=XJaZrK7Mdepk5fdX51A8uENiLFNil85Ud0d4MH8H5f0,3218
|
151
|
-
modal_global_objects/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
|
152
|
-
modal_global_objects/images/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
153
|
-
modal_global_objects/images/base_images.py,sha256=tFc7tzQRJHtq23kURd6DTrnnO4Yp5ujr34WdJOM5ubI,775
|
154
|
-
modal_global_objects/mounts/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
155
|
-
modal_global_objects/mounts/modal_client_package.py,sha256=W0E_yShsRojPzWm6LtIQqNVolapdnrZkm2hVEQuZK_4,767
|
156
|
-
modal_global_objects/mounts/python_standalone.py,sha256=EsC-hdPtiAPOwgW9emHN6muNUkrJwR8dYxroVArxHxM,1841
|
157
150
|
modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
158
151
|
modal_proto/api.proto,sha256=hM-iLwpYycp-wGyvoAieAEM_km42yI0jZTigPQLGPC0,86712
|
159
152
|
modal_proto/api_grpc.py,sha256=FYGqDegM_w_qxdtlxum8k31mDibKoMvmNxv_p9cKdKs,109056
|
@@ -172,10 +165,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
|
|
172
165
|
modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
173
166
|
modal_version/__init__.py,sha256=wiJQ53c-OMs0Xf1UeXOxQ7FwlV1VzIjnX6o-pRYZ_Pk,470
|
174
167
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
175
|
-
modal_version/_version_generated.py,sha256=
|
176
|
-
modal-0.73.
|
177
|
-
modal-0.73.
|
178
|
-
modal-0.73.
|
179
|
-
modal-0.73.
|
180
|
-
modal-0.73.
|
181
|
-
modal-0.73.
|
168
|
+
modal_version/_version_generated.py,sha256=5cj8cqKxfu-44XR4MQVL7vocSJ_677tLG2jtW72Zc7U,149
|
169
|
+
modal-0.73.47.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
170
|
+
modal-0.73.47.dist-info/METADATA,sha256=JSgSze5rgpMBFjrdIbIjQqqlzvFPjddyU-bPzU206I4,2452
|
171
|
+
modal-0.73.47.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
172
|
+
modal-0.73.47.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
173
|
+
modal-0.73.47.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
|
174
|
+
modal-0.73.47.dist-info/RECORD,,
|
modal_docs/mdmd/__init__.py
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2023
|
modal_docs/mdmd/mdmd.py
DELETED
@@ -1,195 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2023
|
2
|
-
"""mdmd - MoDal MarkDown"""
|
3
|
-
|
4
|
-
import inspect
|
5
|
-
import warnings
|
6
|
-
from enum import Enum, EnumMeta
|
7
|
-
from types import ModuleType
|
8
|
-
from typing import Callable
|
9
|
-
|
10
|
-
import synchronicity.synchronizer
|
11
|
-
|
12
|
-
from .signatures import get_signature
|
13
|
-
|
14
|
-
|
15
|
-
def format_docstring(docstring: str):
|
16
|
-
if docstring is None:
|
17
|
-
docstring = ""
|
18
|
-
else:
|
19
|
-
docstring = inspect.cleandoc(docstring)
|
20
|
-
|
21
|
-
if docstring and not docstring.endswith("\n"):
|
22
|
-
docstring += "\n"
|
23
|
-
|
24
|
-
return docstring
|
25
|
-
|
26
|
-
|
27
|
-
def function_str(name: str, func):
|
28
|
-
signature = get_signature(name, func)
|
29
|
-
decl = f"""```python
|
30
|
-
{signature}
|
31
|
-
```\n\n"""
|
32
|
-
docstring = format_docstring(func.__doc__)
|
33
|
-
return decl + docstring
|
34
|
-
|
35
|
-
|
36
|
-
def class_str(name, obj, title_level="##"):
|
37
|
-
def qual_name(cls):
|
38
|
-
if cls.__module__ == "builtins":
|
39
|
-
return cls.__name__
|
40
|
-
return f"{cls.__module__}.{cls.__name__}"
|
41
|
-
|
42
|
-
bases = [qual_name(b) for b in obj.__bases__]
|
43
|
-
bases_str = f"({', '.join(bases)})" if bases else ""
|
44
|
-
decl = f"""```python
|
45
|
-
class {name}{bases_str}
|
46
|
-
```\n\n"""
|
47
|
-
parts = [decl]
|
48
|
-
docstring = format_docstring(obj.__doc__)
|
49
|
-
|
50
|
-
if isinstance(obj, EnumMeta) and not docstring:
|
51
|
-
# Python 3.11 removed the docstring from enums
|
52
|
-
docstring = "An enumeration.\n"
|
53
|
-
|
54
|
-
if docstring:
|
55
|
-
parts.append(docstring + "\n")
|
56
|
-
|
57
|
-
if isinstance(obj, EnumMeta):
|
58
|
-
enum_vals = "\n".join(f"* `{k}`" for k in obj.__members__.keys())
|
59
|
-
parts.append(f"The possible values are:\n\n{enum_vals}\n")
|
60
|
-
|
61
|
-
else:
|
62
|
-
init = inspect.unwrap(obj.__init__)
|
63
|
-
|
64
|
-
if (inspect.isfunction(init) or inspect.ismethod(init)) and not object_is_private("constructor", init):
|
65
|
-
parts.append(function_str("__init__", init))
|
66
|
-
|
67
|
-
member_title_level = title_level + "#"
|
68
|
-
|
69
|
-
entries = {}
|
70
|
-
|
71
|
-
def rec_update_attributes(cls):
|
72
|
-
# first bases, then class itself
|
73
|
-
for base_cls in cls.__bases__:
|
74
|
-
rec_update_attributes(base_cls)
|
75
|
-
entries.update(cls.__dict__)
|
76
|
-
|
77
|
-
rec_update_attributes(obj)
|
78
|
-
|
79
|
-
for member_name, member in entries.items():
|
80
|
-
if isinstance(member, classmethod) or isinstance(member, staticmethod):
|
81
|
-
# get the original function definition instead of the descriptor object
|
82
|
-
member = getattr(obj, member_name)
|
83
|
-
elif isinstance(member, property):
|
84
|
-
member = member.fget
|
85
|
-
elif isinstance(member, (synchronicity.synchronizer.FunctionWithAio, synchronicity.synchronizer.MethodWithAio)):
|
86
|
-
member = member._func
|
87
|
-
|
88
|
-
if object_is_private(member_name, member):
|
89
|
-
continue
|
90
|
-
|
91
|
-
if callable(member):
|
92
|
-
parts.append(f"{member_title_level} {member_name}\n\n")
|
93
|
-
parts.append(function_str(member_name, member))
|
94
|
-
|
95
|
-
return "".join(parts)
|
96
|
-
|
97
|
-
|
98
|
-
def module_str(header, module, title_level="#", filter_items: Callable[[ModuleType, str], bool] = None):
|
99
|
-
header = [f"{title_level} {header}\n\n"]
|
100
|
-
docstring = format_docstring(module.__doc__)
|
101
|
-
if docstring:
|
102
|
-
header.append(docstring + "\n")
|
103
|
-
|
104
|
-
object_docs = []
|
105
|
-
member_title_level = title_level + "#"
|
106
|
-
for qual_name, name, item in module_items(module, filter_items):
|
107
|
-
try:
|
108
|
-
if hasattr(item, "__wrapped__"):
|
109
|
-
item = item.__wrapped__
|
110
|
-
except KeyError:
|
111
|
-
pass
|
112
|
-
except:
|
113
|
-
print("failed on", qual_name, name, item)
|
114
|
-
raise
|
115
|
-
if inspect.isclass(item):
|
116
|
-
classdoc = class_str(name, item, title_level=member_title_level)
|
117
|
-
object_docs.append(f"{member_title_level} {qual_name}\n\n")
|
118
|
-
object_docs.append(classdoc)
|
119
|
-
elif callable(item):
|
120
|
-
funcdoc = function_str(name, item)
|
121
|
-
object_docs.append(f"{member_title_level} {qual_name}\n\n")
|
122
|
-
object_docs.append(funcdoc)
|
123
|
-
else:
|
124
|
-
item_doc = getattr(module, f"__doc__{name}", None)
|
125
|
-
if item_doc:
|
126
|
-
# variable documentation
|
127
|
-
object_docs.append(f"{member_title_level} {qual_name}\n\n")
|
128
|
-
object_docs.append(item_doc)
|
129
|
-
else:
|
130
|
-
warnings.warn(f"Not sure how to document: {name} ({item}")
|
131
|
-
|
132
|
-
if object_docs:
|
133
|
-
return "".join(header + object_docs)
|
134
|
-
return ""
|
135
|
-
|
136
|
-
|
137
|
-
def object_is_private(name, obj):
|
138
|
-
docstring = inspect.getdoc(obj)
|
139
|
-
if docstring is None:
|
140
|
-
docstring = ""
|
141
|
-
module = getattr(obj, "__module__", None) # obj is class
|
142
|
-
if not module:
|
143
|
-
cls = getattr(obj, "__class__", None) # obj is instance
|
144
|
-
if cls:
|
145
|
-
module = getattr(cls, "__module__", None)
|
146
|
-
if module == "builtins":
|
147
|
-
return True
|
148
|
-
|
149
|
-
if docstring.lstrip().startswith("mdmd:hidden") or name.startswith("_"):
|
150
|
-
return True
|
151
|
-
|
152
|
-
return False
|
153
|
-
|
154
|
-
|
155
|
-
def default_filter(module, item_name):
|
156
|
-
"""Include non-private objects defined in the module itself"""
|
157
|
-
item = getattr(module, item_name)
|
158
|
-
if object_is_private(item_name, item) or inspect.ismodule(item):
|
159
|
-
return False
|
160
|
-
member_module = getattr(item, "__module__", type(item).__module__)
|
161
|
-
return member_module == module.__name__
|
162
|
-
|
163
|
-
|
164
|
-
def package_filter(module_prefix: str):
|
165
|
-
"""Include non-private objects defined in any module with the prefix `module_prefix`"""
|
166
|
-
|
167
|
-
def return_filter(module, item_name):
|
168
|
-
item = getattr(module, item_name)
|
169
|
-
if object_is_private(item_name, item) or inspect.ismodule(item):
|
170
|
-
return False
|
171
|
-
member_module = getattr(item, "__module__", type(item).__module__)
|
172
|
-
return member_module.startswith(module_prefix)
|
173
|
-
|
174
|
-
return return_filter
|
175
|
-
|
176
|
-
|
177
|
-
def module_items(module, filter_items: Callable[[ModuleType, str], bool] = None):
|
178
|
-
"""Returns filtered members of module"""
|
179
|
-
if filter_items is None:
|
180
|
-
# default filter is to only include classes and functions declared (or whose type is declared) in the file
|
181
|
-
filter_items = default_filter
|
182
|
-
|
183
|
-
for member_name, member in inspect.getmembers(module):
|
184
|
-
# only modal items
|
185
|
-
if not filter_items(module, member_name):
|
186
|
-
continue
|
187
|
-
|
188
|
-
qual_name = f"{module.__name__}.{member_name}"
|
189
|
-
yield qual_name, member_name, member
|
190
|
-
|
191
|
-
|
192
|
-
class Category(Enum):
|
193
|
-
FUNCTION = "function"
|
194
|
-
CLASS = "class"
|
195
|
-
MODULE = "module"
|
modal_docs/mdmd/signatures.py
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2023
|
2
|
-
import ast
|
3
|
-
import inspect
|
4
|
-
import re
|
5
|
-
import textwrap
|
6
|
-
import warnings
|
7
|
-
|
8
|
-
from synchronicity.synchronizer import FunctionWithAio
|
9
|
-
|
10
|
-
|
11
|
-
def _signature_from_ast(func) -> tuple[str, str]:
|
12
|
-
"""Get function signature, including decorators and comments, from source code
|
13
|
-
|
14
|
-
Traverses functools.wraps-wrappings to get source of underlying function.
|
15
|
-
|
16
|
-
Has the advantage over inspect.signature that it can get decorators, default arguments and comments verbatim
|
17
|
-
from the function definition.
|
18
|
-
"""
|
19
|
-
src = inspect.getsource(func)
|
20
|
-
src = textwrap.dedent(src)
|
21
|
-
|
22
|
-
def get_source_segment(src, fromline, fromcol, toline, tocol) -> str:
|
23
|
-
lines = src.split("\n")
|
24
|
-
lines = lines[fromline - 1 : toline]
|
25
|
-
lines[-1] = lines[-1][:tocol]
|
26
|
-
lines[0] = lines[0][fromcol:]
|
27
|
-
return "\n".join(lines)
|
28
|
-
|
29
|
-
tree = ast.parse(src)
|
30
|
-
func_def = list(ast.iter_child_nodes(tree))[0]
|
31
|
-
assert isinstance(func_def, (ast.FunctionDef, ast.AsyncFunctionDef))
|
32
|
-
decorator_starts = [(item.lineno, item.col_offset - 1) for item in func_def.decorator_list]
|
33
|
-
declaration_start = min([(func_def.lineno, func_def.col_offset)] + decorator_starts)
|
34
|
-
body_start = min((item.lineno, item.col_offset) for item in func_def.body)
|
35
|
-
|
36
|
-
return (
|
37
|
-
func_def.name,
|
38
|
-
get_source_segment(src, declaration_start[0], declaration_start[1], body_start[0], body_start[1] - 1).strip(),
|
39
|
-
)
|
40
|
-
|
41
|
-
|
42
|
-
def get_signature(name, callable) -> str:
|
43
|
-
"""A problem with using *only* this method is that the wrapping method signature will not be respected.
|
44
|
-
TODO: use source parsing *only* to extract default arguments, comments (and possibly decorators) and "merge"
|
45
|
-
that definition with the outer-most definition."""
|
46
|
-
|
47
|
-
if not (inspect.isfunction(callable) or inspect.ismethod(callable) or isinstance(callable, FunctionWithAio)):
|
48
|
-
assert hasattr(callable, "__call__")
|
49
|
-
callable = callable.__call__
|
50
|
-
|
51
|
-
try:
|
52
|
-
original_name, definition_source = _signature_from_ast(callable)
|
53
|
-
except Exception:
|
54
|
-
warnings.warn(f"Could not get source signature for {name}. Using fallback.")
|
55
|
-
original_name = name
|
56
|
-
definition_source = f"def {name}{inspect.signature(callable)}"
|
57
|
-
|
58
|
-
if original_name != name:
|
59
|
-
# ugly name and definition replacement hack when needed
|
60
|
-
definition_source = definition_source.replace(f"def {original_name}", f"def {name}")
|
61
|
-
|
62
|
-
if (
|
63
|
-
"async def" in definition_source
|
64
|
-
and not inspect.iscoroutinefunction(callable)
|
65
|
-
and not inspect.isasyncgenfunction(callable)
|
66
|
-
):
|
67
|
-
# hack to "reset" signature to a blocking one if the underlying source definition is async
|
68
|
-
# but the wrapper function isn't (like when synchronicity wraps an async function as a blocking one)
|
69
|
-
definition_source = definition_source.replace("async def", "def")
|
70
|
-
definition_source = definition_source.replace("asynccontextmanager", "contextmanager")
|
71
|
-
definition_source = definition_source.replace("AsyncIterator", "Iterator")
|
72
|
-
|
73
|
-
# remove any synchronicity-internal decorators
|
74
|
-
definition_source, _ = re.subn(r"^\s*@synchronizer\..*\n", "", definition_source)
|
75
|
-
|
76
|
-
return definition_source
|
modal_global_objects/__init__.py
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2022
|
@@ -1 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2024
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2022
|
2
|
-
import os
|
3
|
-
import sys
|
4
|
-
from typing import cast
|
5
|
-
|
6
|
-
import modal
|
7
|
-
from modal.image import SUPPORTED_PYTHON_SERIES, ImageBuilderVersion
|
8
|
-
|
9
|
-
|
10
|
-
def dummy():
|
11
|
-
pass
|
12
|
-
|
13
|
-
|
14
|
-
if __name__ == "__main__":
|
15
|
-
_, name = sys.argv
|
16
|
-
constructor = getattr(modal.Image, name)
|
17
|
-
|
18
|
-
builder_version = os.environ.get("MODAL_IMAGE_BUILDER_VERSION")
|
19
|
-
assert builder_version, "Script requires MODAL_IMAGE_BUILDER_VERSION environment variable"
|
20
|
-
python_versions = SUPPORTED_PYTHON_SERIES[cast(ImageBuilderVersion, builder_version)]
|
21
|
-
|
22
|
-
app = modal.App(f"build-{name.replace('_', '-')}-image")
|
23
|
-
for v in python_versions:
|
24
|
-
app.function(image=constructor(python_version=v), name=f"{v}")(dummy)
|
25
|
-
|
26
|
-
with modal.enable_output():
|
27
|
-
with app.run():
|
28
|
-
pass
|
@@ -1 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2024
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2022
|
2
|
-
from modal.config import config
|
3
|
-
from modal.mount import (
|
4
|
-
client_mount_name,
|
5
|
-
create_client_mount,
|
6
|
-
)
|
7
|
-
from modal_proto import api_pb2
|
8
|
-
|
9
|
-
|
10
|
-
def publish_client_mount(client):
|
11
|
-
mount = create_client_mount()
|
12
|
-
name = client_mount_name()
|
13
|
-
profile_environment = config.get("environment")
|
14
|
-
# TODO: change how namespaces work, so we don't have to use unrelated workspaces when deploying to global?.
|
15
|
-
mount._deploy(
|
16
|
-
client_mount_name(),
|
17
|
-
api_pb2.DEPLOYMENT_NAMESPACE_GLOBAL,
|
18
|
-
client=client,
|
19
|
-
environment_name=profile_environment,
|
20
|
-
)
|
21
|
-
print(f"✅ Deployed client mount {name} to global namespace.")
|
22
|
-
|
23
|
-
|
24
|
-
def main(client=None):
|
25
|
-
publish_client_mount(client)
|
26
|
-
|
27
|
-
|
28
|
-
if __name__ == "__main__":
|
29
|
-
main()
|
@@ -1,53 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2022
|
2
|
-
import shutil
|
3
|
-
import tempfile
|
4
|
-
import urllib.request
|
5
|
-
|
6
|
-
from modal.config import config
|
7
|
-
from modal.exception import NotFoundError
|
8
|
-
from modal.mount import (
|
9
|
-
PYTHON_STANDALONE_VERSIONS,
|
10
|
-
Mount,
|
11
|
-
python_standalone_mount_name,
|
12
|
-
)
|
13
|
-
from modal_proto import api_pb2
|
14
|
-
|
15
|
-
|
16
|
-
def publish_python_standalone_mount(client, version: str) -> None:
|
17
|
-
release, full_version = PYTHON_STANDALONE_VERSIONS[version]
|
18
|
-
|
19
|
-
libc = "gnu"
|
20
|
-
arch = "x86_64_v3"
|
21
|
-
url = (
|
22
|
-
"https://github.com/indygreg/python-build-standalone/releases/download"
|
23
|
-
+ f"/{release}/cpython-{full_version}+{release}-{arch}-unknown-linux-gnu-install_only.tar.gz"
|
24
|
-
)
|
25
|
-
|
26
|
-
profile_environment = config.get("environment")
|
27
|
-
mount_name = python_standalone_mount_name(f"{version}-{libc}")
|
28
|
-
try:
|
29
|
-
Mount.from_name(mount_name, namespace=api_pb2.DEPLOYMENT_NAMESPACE_GLOBAL).hydrate(client)
|
30
|
-
print(f"✅ Found existing mount {mount_name} in global namespace.")
|
31
|
-
except NotFoundError:
|
32
|
-
print(f"📦 Unpacking python-build-standalone for {version}-{libc}.")
|
33
|
-
with tempfile.TemporaryDirectory() as d:
|
34
|
-
urllib.request.urlretrieve(url, f"{d}/cpython.tar.gz")
|
35
|
-
shutil.unpack_archive(f"{d}/cpython.tar.gz", d)
|
36
|
-
print(f"🌐 Downloaded and unpacked archive to {d}.")
|
37
|
-
python_mount = Mount._from_local_dir(f"{d}/python")
|
38
|
-
python_mount._deploy(
|
39
|
-
mount_name,
|
40
|
-
api_pb2.DEPLOYMENT_NAMESPACE_GLOBAL,
|
41
|
-
client=client,
|
42
|
-
environment_name=profile_environment,
|
43
|
-
)
|
44
|
-
print(f"✅ Deployed mount {mount_name} to global namespace.")
|
45
|
-
|
46
|
-
|
47
|
-
def main(client=None):
|
48
|
-
for version in PYTHON_STANDALONE_VERSIONS:
|
49
|
-
publish_python_standalone_mount(client, version)
|
50
|
-
|
51
|
-
|
52
|
-
if __name__ == "__main__":
|
53
|
-
main()
|
File without changes
|
File without changes
|