modal 0.73.158__py3-none-any.whl → 0.73.160__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/_container_entrypoint.py +22 -31
- modal/_runtime/asgi.py +1 -1
- modal/_runtime/user_code_imports.py +73 -37
- modal/app.py +18 -2
- modal/app.pyi +4 -4
- modal/client.pyi +2 -2
- modal/cls.py +1 -1
- modal/functions.pyi +6 -6
- {modal-0.73.158.dist-info → modal-0.73.160.dist-info}/METADATA +1 -1
- {modal-0.73.158.dist-info → modal-0.73.160.dist-info}/RECORD +15 -15
- modal_version/_version_generated.py +1 -1
- {modal-0.73.158.dist-info → modal-0.73.160.dist-info}/LICENSE +0 -0
- {modal-0.73.158.dist-info → modal-0.73.160.dist-info}/WHEEL +0 -0
- {modal-0.73.158.dist-info → modal-0.73.160.dist-info}/entry_points.txt +0 -0
- {modal-0.73.158.dist-info → modal-0.73.160.dist-info}/top_level.txt +0 -0
modal/_container_entrypoint.py
CHANGED
@@ -2,7 +2,12 @@
|
|
2
2
|
# ruff: noqa: E402
|
3
3
|
import os
|
4
4
|
|
5
|
-
from modal._runtime.user_code_imports import
|
5
|
+
from modal._runtime.user_code_imports import (
|
6
|
+
Service,
|
7
|
+
get_active_app_fallback,
|
8
|
+
import_class_service,
|
9
|
+
import_single_function_service,
|
10
|
+
)
|
6
11
|
|
7
12
|
telemetry_socket = os.environ.get("MODAL_TELEMETRY_SOCKET")
|
8
13
|
if telemetry_socket:
|
@@ -349,32 +354,6 @@ def call_function(
|
|
349
354
|
signal.signal(signal.SIGUSR1, usr1_handler) # reset signal handler
|
350
355
|
|
351
356
|
|
352
|
-
def get_active_app_fallback(function_def: api_pb2.Function) -> _App:
|
353
|
-
# This branch is reached in the special case that the imported function/class is:
|
354
|
-
# 1) not serialized, and
|
355
|
-
# 2) isn't a FunctionHandle - i.e, not decorated at definition time
|
356
|
-
# Look at all instantiated apps - if there is only one with the indicated name, use that one
|
357
|
-
app_name: Optional[str] = function_def.app_name or None # coalesce protobuf field to None
|
358
|
-
matching_apps = _App._all_apps.get(app_name, [])
|
359
|
-
if len(matching_apps) == 1:
|
360
|
-
active_app: _App = matching_apps[0]
|
361
|
-
return active_app
|
362
|
-
|
363
|
-
if len(matching_apps) > 1:
|
364
|
-
if app_name is not None:
|
365
|
-
warning_sub_message = f"app with the same name ('{app_name}')"
|
366
|
-
else:
|
367
|
-
warning_sub_message = "unnamed app"
|
368
|
-
logger.warning(
|
369
|
-
f"You have more than one {warning_sub_message}. "
|
370
|
-
"It's recommended to name all your Apps uniquely when using multiple apps"
|
371
|
-
)
|
372
|
-
|
373
|
-
# If we don't have an active app, create one on the fly
|
374
|
-
# The app object is used to carry the app layout etc
|
375
|
-
return _App()
|
376
|
-
|
377
|
-
|
378
357
|
def call_lifecycle_functions(
|
379
358
|
event_loop: UserCodeEventLoop,
|
380
359
|
container_io_manager, #: ContainerIOManager, TODO: this type is generated at runtime
|
@@ -416,9 +395,9 @@ def main(container_args: api_pb2.ContainerArguments, client: Client):
|
|
416
395
|
with container_io_manager.heartbeats(is_snapshotting_function), UserCodeEventLoop() as event_loop:
|
417
396
|
# If this is a serialized function, fetch the definition from the server
|
418
397
|
if function_def.definition_type == api_pb2.Function.DEFINITION_TYPE_SERIALIZED:
|
419
|
-
|
398
|
+
ser_usr_cls, ser_fun = container_io_manager.get_serialized_function()
|
420
399
|
else:
|
421
|
-
|
400
|
+
ser_usr_cls, ser_fun = None, None
|
422
401
|
|
423
402
|
# Initialize the function, importing user code.
|
424
403
|
with container_io_manager.handle_user_exception():
|
@@ -429,16 +408,28 @@ def main(container_args: api_pb2.ContainerArguments, client: Client):
|
|
429
408
|
param_kwargs = {}
|
430
409
|
|
431
410
|
if function_def.is_class:
|
411
|
+
# this is a bit ugly - match the function and class based on function name to get metadata
|
412
|
+
# This metadata is required in order to hydrate the class in case it's not globally
|
413
|
+
# decorated (or serialized)
|
414
|
+
service_base_function_id = container_args.app_layout.function_ids[function_def.function_name]
|
415
|
+
service_function_hydration_data = [
|
416
|
+
o for o in container_args.app_layout.objects if o.object_id == service_base_function_id
|
417
|
+
][0]
|
418
|
+
class_id = container_args.app_layout.class_ids[function_def.function_name.removesuffix(".*")]
|
419
|
+
|
432
420
|
service = import_class_service(
|
433
421
|
function_def,
|
434
|
-
|
422
|
+
service_function_hydration_data,
|
423
|
+
class_id,
|
424
|
+
client,
|
425
|
+
ser_usr_cls,
|
435
426
|
param_args,
|
436
427
|
param_kwargs,
|
437
428
|
)
|
438
429
|
else:
|
439
430
|
service = import_single_function_service(
|
440
431
|
function_def,
|
441
|
-
|
432
|
+
ser_usr_cls,
|
442
433
|
ser_fun,
|
443
434
|
param_args,
|
444
435
|
param_kwargs,
|
modal/_runtime/asgi.py
CHANGED
@@ -473,7 +473,7 @@ async def _proxy_lifespan_request(base_url, scope, receive, send) -> None:
|
|
473
473
|
read_bufsize=1024 * 1024, # 1 MiB
|
474
474
|
connector=aiohttp.TCPConnector(
|
475
475
|
limit=1000
|
476
|
-
), # 100 is the default max, but 1000 is the max for
|
476
|
+
), # 100 is the default max, but 1000 is the max for `@modal.concurrent`.
|
477
477
|
# Note: these values will need to be kept in sync.
|
478
478
|
**(
|
479
479
|
# These options were introduced in aiohttp 3.9, and we can remove the
|
@@ -10,9 +10,10 @@ import modal._runtime.container_io_manager
|
|
10
10
|
import modal.cls
|
11
11
|
from modal import Function
|
12
12
|
from modal._functions import _Function
|
13
|
-
from modal._partial_function import _find_partial_methods_for_user_cls, _PartialFunctionFlags
|
14
13
|
from modal._utils.async_utils import synchronizer
|
15
14
|
from modal._utils.function_utils import LocalFunctionError, is_async as get_is_async, is_global_object
|
15
|
+
from modal.app import _App
|
16
|
+
from modal.config import logger
|
16
17
|
from modal.exception import ExecutionError, InvalidError
|
17
18
|
from modal_proto import api_pb2
|
18
19
|
|
@@ -144,14 +145,13 @@ class ImportedClass(Service):
|
|
144
145
|
self, fun_def: api_pb2.Function, container_io_manager: "modal._runtime.container_io_manager.ContainerIOManager"
|
145
146
|
) -> dict[str, "FinalizedFunction"]:
|
146
147
|
finalized_functions = {}
|
147
|
-
for method_name,
|
148
|
-
|
149
|
-
user_func = partial.raw_f
|
148
|
+
for method_name, _partial in self._partial_functions.items():
|
149
|
+
user_func = _partial.raw_f
|
150
150
|
# Check this property before we turn it into a method (overriden by webhooks)
|
151
151
|
is_async = get_is_async(user_func)
|
152
152
|
# Use the function definition for whether this is a generator (overriden by webhooks)
|
153
|
-
is_generator =
|
154
|
-
webhook_config =
|
153
|
+
is_generator = _partial.params.is_generator
|
154
|
+
webhook_config = _partial.params.webhook_config
|
155
155
|
|
156
156
|
bound_func = user_func.__get__(self.user_cls_instance)
|
157
157
|
|
@@ -178,22 +178,20 @@ class ImportedClass(Service):
|
|
178
178
|
return finalized_functions
|
179
179
|
|
180
180
|
|
181
|
-
def get_user_class_instance(
|
181
|
+
def get_user_class_instance(_cls: modal.cls._Cls, args: tuple, kwargs: dict[str, Any]) -> typing.Any:
|
182
182
|
"""Returns instance of the underlying class to be used as the `self`
|
183
183
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
if isinstance(cls, modal.cls.Cls):
|
188
|
-
# globally @app.cls-decorated class
|
189
|
-
modal_obj: modal.cls.Obj = cls(*args, **kwargs)
|
190
|
-
modal_obj._entered = True # ugly but prevents .local() from triggering additional enter-logic
|
191
|
-
# TODO: unify lifecycle logic between .local() and container_entrypoint
|
192
|
-
user_cls_instance = modal_obj._cached_user_cls_instance()
|
193
|
-
else:
|
194
|
-
# undecorated class (non-global decoration or serialized)
|
195
|
-
user_cls_instance = cls(*args, **kwargs)
|
184
|
+
For the time being, this is an instance of the underlying user defined type, with
|
185
|
+
some extra attributes like parameter values and _modal_functions set, allowing
|
186
|
+
its methods to be used as modal Function objects with .remote() and .local() etc.
|
196
187
|
|
188
|
+
TODO: Could possibly change this to use an Obj to clean up the data model? would invalidate isinstance checks though
|
189
|
+
"""
|
190
|
+
cls = synchronizer._translate_out(_cls) # ugly
|
191
|
+
modal_obj: modal.cls.Obj = cls(*args, **kwargs)
|
192
|
+
modal_obj._entered = True # ugly but prevents .local() from triggering additional enter-logic
|
193
|
+
# TODO: unify lifecycle logic between .local() and container_entrypoint
|
194
|
+
user_cls_instance = modal_obj._cached_user_cls_instance()
|
197
195
|
return user_cls_instance
|
198
196
|
|
199
197
|
|
@@ -293,7 +291,10 @@ def import_single_function_service(
|
|
293
291
|
|
294
292
|
def import_class_service(
|
295
293
|
function_def: api_pb2.Function,
|
296
|
-
|
294
|
+
service_function_hydration_data: api_pb2.Object,
|
295
|
+
class_id: str,
|
296
|
+
client: "modal.client.Client",
|
297
|
+
ser_user_cls: Optional[type],
|
297
298
|
cls_args,
|
298
299
|
cls_kwargs,
|
299
300
|
) -> Service:
|
@@ -304,11 +305,11 @@ def import_class_service(
|
|
304
305
|
"""
|
305
306
|
active_app: Optional["modal.app._App"]
|
306
307
|
service_deps: Optional[Sequence["modal._object._Object"]]
|
307
|
-
|
308
|
+
cls_or_user_cls: typing.Union[type, modal.cls.Cls]
|
308
309
|
|
309
310
|
if function_def.definition_type == api_pb2.Function.DEFINITION_TYPE_SERIALIZED:
|
310
|
-
assert
|
311
|
-
|
311
|
+
assert ser_user_cls is not None
|
312
|
+
cls_or_user_cls = ser_user_cls
|
312
313
|
else:
|
313
314
|
# Load the module dynamically
|
314
315
|
module = importlib.import_module(function_def.module_name)
|
@@ -327,22 +328,31 @@ def import_class_service(
|
|
327
328
|
|
328
329
|
assert not function_def.use_method_name # new "placeholder methods" should not be invoked directly!
|
329
330
|
cls_name = parts[0]
|
330
|
-
|
331
|
-
|
332
|
-
if isinstance(
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
service_deps = service_function.deps(only_explicit_mounts=True)
|
338
|
-
active_app = service_function.app
|
331
|
+
cls_or_user_cls = getattr(module, cls_name)
|
332
|
+
|
333
|
+
if isinstance(cls_or_user_cls, modal.cls.Cls):
|
334
|
+
_cls = synchronizer._translate_in(cls_or_user_cls)
|
335
|
+
class_service_function: _Function = _cls._get_class_service_function()
|
336
|
+
service_deps = class_service_function.deps(only_explicit_mounts=True)
|
337
|
+
active_app = class_service_function.app
|
339
338
|
else:
|
340
|
-
# Undecorated user class
|
341
|
-
|
342
|
-
|
343
|
-
|
339
|
+
# Undecorated user class (serialized or local scope-decoration).
|
340
|
+
service_deps = None # we can't infer service deps for now
|
341
|
+
active_app = get_active_app_fallback(function_def)
|
342
|
+
_client: "modal.client._Client" = synchronizer._translate_in(client)
|
343
|
+
_service_function: modal._functions._Function[Any, Any, Any] = modal._functions._Function._new_hydrated(
|
344
|
+
service_function_hydration_data.object_id,
|
345
|
+
_client,
|
346
|
+
service_function_hydration_data.function_handle_metadata,
|
347
|
+
is_another_app=True, # this skips re-loading the function, which is required since it doesn't have a loader
|
348
|
+
)
|
349
|
+
_cls = modal.cls._Cls.from_local(cls_or_user_cls, active_app, _service_function)
|
350
|
+
# hydration of the class itself - just sets the id and triggers some side effects
|
351
|
+
# that transfers metadata from the service function to the class. TODO: cleanup!
|
352
|
+
_cls._hydrate(class_id, _client, api_pb2.ClassHandleMetadata())
|
344
353
|
|
345
|
-
|
354
|
+
method_partials: dict[str, "modal._partial_function._PartialFunction"] = _cls._get_partial_functions()
|
355
|
+
user_cls_instance = get_user_class_instance(_cls, cls_args, cls_kwargs)
|
346
356
|
|
347
357
|
return ImportedClass(
|
348
358
|
user_cls_instance,
|
@@ -351,3 +361,29 @@ def import_class_service(
|
|
351
361
|
# TODO (elias/deven): instead of using method_partials here we should use a set of api_pb2.MethodDefinition
|
352
362
|
method_partials,
|
353
363
|
)
|
364
|
+
|
365
|
+
|
366
|
+
def get_active_app_fallback(function_def: api_pb2.Function) -> _App:
|
367
|
+
# This branch is reached in the special case that the imported function/class is:
|
368
|
+
# 1) not serialized, and
|
369
|
+
# 2) isn't a FunctionHandle - i.e, not decorated at definition time
|
370
|
+
# Look at all instantiated apps - if there is only one with the indicated name, use that one
|
371
|
+
app_name: Optional[str] = function_def.app_name or None # coalesce protobuf field to None
|
372
|
+
matching_apps = _App._all_apps.get(app_name, [])
|
373
|
+
if len(matching_apps) == 1:
|
374
|
+
active_app: _App = matching_apps[0]
|
375
|
+
return active_app
|
376
|
+
|
377
|
+
if len(matching_apps) > 1:
|
378
|
+
if app_name is not None:
|
379
|
+
warning_sub_message = f"app with the same name ('{app_name}')"
|
380
|
+
else:
|
381
|
+
warning_sub_message = "unnamed app"
|
382
|
+
logger.warning(
|
383
|
+
f"You have more than one {warning_sub_message}. "
|
384
|
+
"It's recommended to name all your Apps uniquely when using multiple apps"
|
385
|
+
)
|
386
|
+
|
387
|
+
# If we don't have an active app, create one on the fly
|
388
|
+
# The app object is used to carry the app layout etc
|
389
|
+
return _App()
|
modal/app.py
CHANGED
@@ -598,7 +598,6 @@ class _App:
|
|
598
598
|
scaledown_window: Optional[int] = None, # Max amount of time a container can remain idle before scaling down.
|
599
599
|
proxy: Optional[_Proxy] = None, # Reference to a Modal Proxy to use in front of this function.
|
600
600
|
retries: Optional[Union[int, Retries]] = None, # Number of times to retry each input in case of failure.
|
601
|
-
allow_concurrent_inputs: Optional[int] = None, # Number of inputs the container may fetch to run concurrently.
|
602
601
|
timeout: Optional[int] = None, # Maximum execution time of the function in seconds.
|
603
602
|
name: Optional[str] = None, # Sets the Modal name of the function within the app
|
604
603
|
is_generator: Optional[
|
@@ -625,6 +624,7 @@ class _App:
|
|
625
624
|
keep_warm: Optional[int] = None, # Replaced with `min_containers`
|
626
625
|
concurrency_limit: Optional[int] = None, # Replaced with `max_containers`
|
627
626
|
container_idle_timeout: Optional[int] = None, # Replaced with `scaledown_window`
|
627
|
+
allow_concurrent_inputs: Optional[int] = None, # Replaced with the `@modal.concurrent` decorator
|
628
628
|
_experimental_buffer_containers: Optional[int] = None, # Now stable API with `buffer_containers`
|
629
629
|
) -> _FunctionDecoratorType:
|
630
630
|
"""Decorator to register a new Modal [Function](/docs/reference/modal.Function) with this App."""
|
@@ -637,6 +637,14 @@ class _App:
|
|
637
637
|
if image is None:
|
638
638
|
image = self._get_default_image()
|
639
639
|
|
640
|
+
if allow_concurrent_inputs is not None:
|
641
|
+
deprecation_warning(
|
642
|
+
(2025, 4, 9),
|
643
|
+
"The `allow_concurrent_inputs` parameter is deprecated."
|
644
|
+
" Please use the `@modal.concurrent` decorator instead."
|
645
|
+
"\n\nSee https://modal.com/docs/guide/modal-1-0-migration for more information.",
|
646
|
+
)
|
647
|
+
|
640
648
|
secrets = [*self._secrets, *secrets]
|
641
649
|
|
642
650
|
def wrapped(
|
@@ -819,7 +827,6 @@ class _App:
|
|
819
827
|
scaledown_window: Optional[int] = None, # Max amount of time a container can remain idle before scaling down.
|
820
828
|
proxy: Optional[_Proxy] = None, # Reference to a Modal Proxy to use in front of this function.
|
821
829
|
retries: Optional[Union[int, Retries]] = None, # Number of times to retry each input in case of failure.
|
822
|
-
allow_concurrent_inputs: Optional[int] = None, # Number of inputs the container may fetch to run concurrently.
|
823
830
|
timeout: Optional[int] = None, # Maximum execution time of the function in seconds.
|
824
831
|
cloud: Optional[str] = None, # Cloud provider to run the function on. Possible values are aws, gcp, oci, auto.
|
825
832
|
region: Optional[Union[str, Sequence[str]]] = None, # Region or regions to run the function on.
|
@@ -840,6 +847,7 @@ class _App:
|
|
840
847
|
keep_warm: Optional[int] = None, # Replaced with `min_containers`
|
841
848
|
concurrency_limit: Optional[int] = None, # Replaced with `max_containers`
|
842
849
|
container_idle_timeout: Optional[int] = None, # Replaced with `scaledown_window`
|
850
|
+
allow_concurrent_inputs: Optional[int] = None, # Replaced with the `@modal.concurrent` decorator
|
843
851
|
_experimental_buffer_containers: Optional[int] = None, # Now stable API with `buffer_containers`
|
844
852
|
) -> Callable[[Union[CLS_T, _PartialFunction]], CLS_T]:
|
845
853
|
"""
|
@@ -854,6 +862,14 @@ class _App:
|
|
854
862
|
raise InvalidError("`region` and `_experimental_scheduler_placement` cannot be used together")
|
855
863
|
scheduler_placement = SchedulerPlacement(region=region)
|
856
864
|
|
865
|
+
if allow_concurrent_inputs is not None:
|
866
|
+
deprecation_warning(
|
867
|
+
(2025, 4, 9),
|
868
|
+
"The `allow_concurrent_inputs` parameter is deprecated."
|
869
|
+
" Please use the `@modal.concurrent` decorator instead."
|
870
|
+
"\n\nSee https://modal.com/docs/guide/modal-1-0-migration for more information.",
|
871
|
+
)
|
872
|
+
|
857
873
|
def wrapper(wrapped_cls: Union[CLS_T, _PartialFunction]) -> CLS_T:
|
858
874
|
# Check if the decorated object is a class
|
859
875
|
if isinstance(wrapped_cls, _PartialFunction):
|
modal/app.pyi
CHANGED
@@ -182,7 +182,6 @@ class _App:
|
|
182
182
|
scaledown_window: typing.Optional[int] = None,
|
183
183
|
proxy: typing.Optional[modal.proxy._Proxy] = None,
|
184
184
|
retries: typing.Union[int, modal.retries.Retries, None] = None,
|
185
|
-
allow_concurrent_inputs: typing.Optional[int] = None,
|
186
185
|
timeout: typing.Optional[int] = None,
|
187
186
|
name: typing.Optional[str] = None,
|
188
187
|
is_generator: typing.Optional[bool] = None,
|
@@ -200,6 +199,7 @@ class _App:
|
|
200
199
|
keep_warm: typing.Optional[int] = None,
|
201
200
|
concurrency_limit: typing.Optional[int] = None,
|
202
201
|
container_idle_timeout: typing.Optional[int] = None,
|
202
|
+
allow_concurrent_inputs: typing.Optional[int] = None,
|
203
203
|
_experimental_buffer_containers: typing.Optional[int] = None,
|
204
204
|
) -> _FunctionDecoratorType: ...
|
205
205
|
@typing_extensions.dataclass_transform(
|
@@ -232,7 +232,6 @@ class _App:
|
|
232
232
|
scaledown_window: typing.Optional[int] = None,
|
233
233
|
proxy: typing.Optional[modal.proxy._Proxy] = None,
|
234
234
|
retries: typing.Union[int, modal.retries.Retries, None] = None,
|
235
|
-
allow_concurrent_inputs: typing.Optional[int] = None,
|
236
235
|
timeout: typing.Optional[int] = None,
|
237
236
|
cloud: typing.Optional[str] = None,
|
238
237
|
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
@@ -247,6 +246,7 @@ class _App:
|
|
247
246
|
keep_warm: typing.Optional[int] = None,
|
248
247
|
concurrency_limit: typing.Optional[int] = None,
|
249
248
|
container_idle_timeout: typing.Optional[int] = None,
|
249
|
+
allow_concurrent_inputs: typing.Optional[int] = None,
|
250
250
|
_experimental_buffer_containers: typing.Optional[int] = None,
|
251
251
|
) -> collections.abc.Callable[[typing.Union[CLS_T, modal._partial_function._PartialFunction]], CLS_T]: ...
|
252
252
|
async def spawn_sandbox(
|
@@ -422,7 +422,6 @@ class App:
|
|
422
422
|
scaledown_window: typing.Optional[int] = None,
|
423
423
|
proxy: typing.Optional[modal.proxy.Proxy] = None,
|
424
424
|
retries: typing.Union[int, modal.retries.Retries, None] = None,
|
425
|
-
allow_concurrent_inputs: typing.Optional[int] = None,
|
426
425
|
timeout: typing.Optional[int] = None,
|
427
426
|
name: typing.Optional[str] = None,
|
428
427
|
is_generator: typing.Optional[bool] = None,
|
@@ -440,6 +439,7 @@ class App:
|
|
440
439
|
keep_warm: typing.Optional[int] = None,
|
441
440
|
concurrency_limit: typing.Optional[int] = None,
|
442
441
|
container_idle_timeout: typing.Optional[int] = None,
|
442
|
+
allow_concurrent_inputs: typing.Optional[int] = None,
|
443
443
|
_experimental_buffer_containers: typing.Optional[int] = None,
|
444
444
|
) -> _FunctionDecoratorType: ...
|
445
445
|
@typing_extensions.dataclass_transform(
|
@@ -472,7 +472,6 @@ class App:
|
|
472
472
|
scaledown_window: typing.Optional[int] = None,
|
473
473
|
proxy: typing.Optional[modal.proxy.Proxy] = None,
|
474
474
|
retries: typing.Union[int, modal.retries.Retries, None] = None,
|
475
|
-
allow_concurrent_inputs: typing.Optional[int] = None,
|
476
475
|
timeout: typing.Optional[int] = None,
|
477
476
|
cloud: typing.Optional[str] = None,
|
478
477
|
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
@@ -487,6 +486,7 @@ class App:
|
|
487
486
|
keep_warm: typing.Optional[int] = None,
|
488
487
|
concurrency_limit: typing.Optional[int] = None,
|
489
488
|
container_idle_timeout: typing.Optional[int] = None,
|
489
|
+
allow_concurrent_inputs: typing.Optional[int] = None,
|
490
490
|
_experimental_buffer_containers: typing.Optional[int] = None,
|
491
491
|
) -> collections.abc.Callable[[typing.Union[CLS_T, modal.partial_function.PartialFunction]], CLS_T]: ...
|
492
492
|
|
modal/client.pyi
CHANGED
@@ -31,7 +31,7 @@ class _Client:
|
|
31
31
|
server_url: str,
|
32
32
|
client_type: int,
|
33
33
|
credentials: typing.Optional[tuple[str, str]],
|
34
|
-
version: str = "0.73.
|
34
|
+
version: str = "0.73.160",
|
35
35
|
): ...
|
36
36
|
def is_closed(self) -> bool: ...
|
37
37
|
@property
|
@@ -93,7 +93,7 @@ class Client:
|
|
93
93
|
server_url: str,
|
94
94
|
client_type: int,
|
95
95
|
credentials: typing.Optional[tuple[str, str]],
|
96
|
-
version: str = "0.73.
|
96
|
+
version: str = "0.73.160",
|
97
97
|
): ...
|
98
98
|
def is_closed(self) -> bool: ...
|
99
99
|
@property
|
modal/cls.py
CHANGED
@@ -139,7 +139,7 @@ def _bind_instance_method(cls: "_Cls", service_function: _Function, method_name:
|
|
139
139
|
# ugly - needed for .local() TODO (elias): Clean up!
|
140
140
|
partial_function.raw_f,
|
141
141
|
user_cls=cls._user_cls,
|
142
|
-
serialized=service_function.info.is_serialized(),
|
142
|
+
serialized=True, # service_function.info.is_serialized(),
|
143
143
|
)
|
144
144
|
|
145
145
|
fun._obj = service_function._obj
|
modal/functions.pyi
CHANGED
@@ -200,11 +200,11 @@ class Function(
|
|
200
200
|
|
201
201
|
_call_generator_nowait: ___call_generator_nowait_spec[typing_extensions.Self]
|
202
202
|
|
203
|
-
class __remote_spec(typing_extensions.Protocol[
|
203
|
+
class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
204
204
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
|
205
205
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
|
206
206
|
|
207
|
-
remote: __remote_spec[modal._functions.
|
207
|
+
remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
|
208
208
|
|
209
209
|
class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
|
210
210
|
def __call__(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
|
@@ -219,19 +219,19 @@ class Function(
|
|
219
219
|
self, *args: modal._functions.P.args, **kwargs: modal._functions.P.kwargs
|
220
220
|
) -> modal._functions.OriginalReturnType: ...
|
221
221
|
|
222
|
-
class ___experimental_spawn_spec(typing_extensions.Protocol[
|
222
|
+
class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
223
223
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
224
224
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
225
225
|
|
226
226
|
_experimental_spawn: ___experimental_spawn_spec[
|
227
|
-
modal._functions.
|
227
|
+
modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
|
228
228
|
]
|
229
229
|
|
230
|
-
class __spawn_spec(typing_extensions.Protocol[
|
230
|
+
class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
231
231
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
232
232
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
233
233
|
|
234
|
-
spawn: __spawn_spec[modal._functions.
|
234
|
+
spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
|
235
235
|
|
236
236
|
def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]: ...
|
237
237
|
|
@@ -2,7 +2,7 @@ modal/__init__.py,sha256=7wz1AT_bpWJJEzXsAo3QMb7i87y7UGXwfneb0bGDhRg,2502
|
|
2
2
|
modal/__main__.py,sha256=CgIjP8m1xJjjd4AXc-delmR6LdBCZclw2A_V38CFIio,2870
|
3
3
|
modal/_clustered_functions.py,sha256=kTf-9YBXY88NutC1akI-gCbvf01RhMPCw-zoOI_YIUE,2700
|
4
4
|
modal/_clustered_functions.pyi,sha256=vllkegc99A0jrUOWa8mdlSbdp6uz36TsHhGxysAOpaQ,771
|
5
|
-
modal/_container_entrypoint.py,sha256=
|
5
|
+
modal/_container_entrypoint.py,sha256=Dhv6YV2ejwluaWi3pHTxIja8U7IXtgD1vsCeH9wHCKM,29002
|
6
6
|
modal/_functions.py,sha256=M94gzMA9xfW9086djoG2yYFVihcslKnsleacmNbVrG0,74996
|
7
7
|
modal/_ipython.py,sha256=TW1fkVOmZL3YYqdS2YlM1hqpf654Yf8ZyybHdBnlhSw,301
|
8
8
|
modal/_location.py,sha256=joiX-0ZeutEUDTrrqLF1GHXCdVLF-rHzstocbMcd_-k,366
|
@@ -19,14 +19,14 @@ modal/_tunnel.py,sha256=zTBxBiuH1O22tS1OliAJdIsSmaZS8PlnifS_6S5z-mk,6320
|
|
19
19
|
modal/_tunnel.pyi,sha256=JmmDYAy9F1FpgJ_hWx0xkom2nTOFQjn4mTPYlU3PFo4,1245
|
20
20
|
modal/_type_manager.py,sha256=DWjgmjYJuOagw2erin506UUbG2H5UzZCFEekS-7hmfA,9087
|
21
21
|
modal/_watcher.py,sha256=K6LYnlmSGQB4tWWI9JADv-tvSvQ1j522FwT71B51CX8,3584
|
22
|
-
modal/app.py,sha256=
|
23
|
-
modal/app.pyi,sha256=
|
22
|
+
modal/app.py,sha256=bJp7W3liuVG2VwWkG31tMFogDh84EKppzP8YJFWl3eQ,48140
|
23
|
+
modal/app.pyi,sha256=SkqXNrdnGIZ4MmNNvpGtzNLoUdyuvi9IjQQR_DRiRHk,26968
|
24
24
|
modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
|
25
25
|
modal/client.py,sha256=U-YKSw0n7J1ZLREt9cbEJCtmHe5YoPKFxl0xlkan2yc,15565
|
26
|
-
modal/client.pyi,sha256=
|
26
|
+
modal/client.pyi,sha256=LAaMk1gBW_D0PsrEYs-n0asL1e1sqvKdqT2ew4QV9d4,7661
|
27
27
|
modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
|
28
28
|
modal/cloud_bucket_mount.pyi,sha256=30T3K1a89l6wzmEJ_J9iWv9SknoGqaZDx59Xs-ZQcmk,1607
|
29
|
-
modal/cls.py,sha256=
|
29
|
+
modal/cls.py,sha256=8tvSw7QFTS1FnX2MXaxagu3KwuR6y_DMwhqHv3MZ0Nk,32963
|
30
30
|
modal/cls.pyi,sha256=pTYO9JsRENmsa5pDgzfoRJGm_NpCvEjEx--vs-jJkj8,10902
|
31
31
|
modal/config.py,sha256=FlqVyh6LVukMahhmEGQVTwWtwtfoPfHqEo3GDn13EOA,11687
|
32
32
|
modal/container_process.py,sha256=vvyK3DVPUMsuqvkKdUiQ49cDLF9JawGrxpglLk5vfgI,6208
|
@@ -40,7 +40,7 @@ modal/file_io.py,sha256=lcMs_E9Xfm0YX1t9U2wNIBPnqHRxmImqjLW1GHqVmyg,20945
|
|
40
40
|
modal/file_io.pyi,sha256=NTRft1tbPSWf9TlWVeZmTlgB5AZ_Zhu2srWIrWr7brk,9445
|
41
41
|
modal/file_pattern_matcher.py,sha256=trosX-Bp7dOubudN1bLLhRAoidWy1TcoaR4Pv8CedWw,6497
|
42
42
|
modal/functions.py,sha256=kcNHvqeGBxPI7Cgd57NIBBghkfbeFJzXO44WW0jSmao,325
|
43
|
-
modal/functions.pyi,sha256=
|
43
|
+
modal/functions.pyi,sha256=m1PL2pwO-lnGV0uZDVCmzZ_v7Mu8ISRtxmxS15aEIAQ,14785
|
44
44
|
modal/gpu.py,sha256=Kbhs_u49FaC2Zi0TjCdrpstpRtT5eZgecynmQi5IZVE,6752
|
45
45
|
modal/image.py,sha256=HtkKomhX4inozqSRi7lf5Vt9IEqCnVHn5bEo59hD64A,92835
|
46
46
|
modal/image.pyi,sha256=iWclz2rxaP-LSsYMgU0X3ZcN5mEFvpyKzIPKJbohmsg,25591
|
@@ -82,14 +82,14 @@ modal/token_flow.pyi,sha256=0XV3d-9CGQL3qjPdw3RgwIFVqqxo8Z-u044_mkgAM3o,2064
|
|
82
82
|
modal/volume.py,sha256=JAWeDvoAG95tMBv-fYIERyHsJPS_X_xGpxRRmYtb6j0,30096
|
83
83
|
modal/volume.pyi,sha256=kTsXarphjZILXci84LQy7EyC84eXUs5-7D62IM5q3eE,12491
|
84
84
|
modal/_runtime/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
85
|
-
modal/_runtime/asgi.py,sha256=
|
85
|
+
modal/_runtime/asgi.py,sha256=KNarxvZI9z8fnmZl2vbkWTjnoLXs9kqOahkrbsTLkyc,22429
|
86
86
|
modal/_runtime/container_io_manager.py,sha256=-EpE47kL759b87SsQaaGMuqRBbvS8gRHoyAOIKzGRTY,44045
|
87
87
|
modal/_runtime/container_io_manager.pyi,sha256=wRd2wHMFru0NmNgiCBVdDTrJGkeVZsZvWwA1fzn8wi8,17009
|
88
88
|
modal/_runtime/execution_context.py,sha256=E6ofm6j1POXGPxS841X3V7JU6NheVb8OkQc7JpLq4Kg,2712
|
89
89
|
modal/_runtime/execution_context.pyi,sha256=wQZwMNADExkeNdB9yKX0PPojovxlFHbap3441wAsiMY,634
|
90
90
|
modal/_runtime/gpu_memory_snapshot.py,sha256=tA3m1d1cwnmHpvpCeN_WijDd6n8byn7LWlpicbIxiOI,3144
|
91
91
|
modal/_runtime/telemetry.py,sha256=T1RoAGyjBDr1swiM6pPsGRSITm7LI5FDK18oNXxY08U,5163
|
92
|
-
modal/_runtime/user_code_imports.py,sha256=
|
92
|
+
modal/_runtime/user_code_imports.py,sha256=kAv37Pl1TmGKduv0Kozum0xNTD42bDLloSIsT7zf84o,16884
|
93
93
|
modal/_utils/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
|
94
94
|
modal/_utils/app_utils.py,sha256=88BT4TPLWfYAQwKTHcyzNQRHg8n9B-QE2UyJs96iV-0,108
|
95
95
|
modal/_utils/async_utils.py,sha256=b2TJyKY1Hq7df7M-fo3qlFM95mGdo3dCuqRPPcV5hsE,27445
|
@@ -170,10 +170,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
|
|
170
170
|
modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
171
171
|
modal_version/__init__.py,sha256=wiJQ53c-OMs0Xf1UeXOxQ7FwlV1VzIjnX6o-pRYZ_Pk,470
|
172
172
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
173
|
-
modal_version/_version_generated.py,sha256=
|
174
|
-
modal-0.73.
|
175
|
-
modal-0.73.
|
176
|
-
modal-0.73.
|
177
|
-
modal-0.73.
|
178
|
-
modal-0.73.
|
179
|
-
modal-0.73.
|
173
|
+
modal_version/_version_generated.py,sha256=r_EYxPHmCmDo6PJZdlVut-xOD_e83qaBcdIllk231Is,150
|
174
|
+
modal-0.73.160.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
175
|
+
modal-0.73.160.dist-info/METADATA,sha256=Rt5Xjuo-Iv-03D7FM0yjkhqbjnwINr9ZxIVTRw2oNVg,2453
|
176
|
+
modal-0.73.160.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
177
|
+
modal-0.73.160.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
178
|
+
modal-0.73.160.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
|
179
|
+
modal-0.73.160.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|