modal 0.73.26__py3-none-any.whl → 0.73.28__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.
@@ -24,6 +24,10 @@ from typing import TYPE_CHECKING, Any, Callable, Optional
24
24
  from google.protobuf.message import Message
25
25
 
26
26
  from modal._clustered_functions import initialize_clustered_function
27
+ from modal._partial_function import (
28
+ _find_callables_for_obj,
29
+ _PartialFunctionFlags,
30
+ )
27
31
  from modal._proxy_tunnel import proxy_tunnel
28
32
  from modal._serialization import deserialize_params
29
33
  from modal._utils.async_utils import TaskContext, synchronizer
@@ -34,10 +38,6 @@ from modal.app import App, _App
34
38
  from modal.client import Client, _Client
35
39
  from modal.config import logger
36
40
  from modal.exception import ExecutionError, InputCancellation, InvalidError
37
- from modal.partial_function import (
38
- _find_callables_for_obj,
39
- _PartialFunctionFlags,
40
- )
41
41
  from modal.running_app import RunningApp, running_app_from_layout
42
42
  from modal_proto import api_pb2
43
43
 
@@ -322,6 +322,16 @@ def call_function(
322
322
  user_code_event_loop.run(run_concurrent_inputs())
323
323
  else:
324
324
  for io_context in container_io_manager.run_inputs_outputs(finalized_functions, batch_max_size, batch_wait_ms):
325
+ # This goes to a registered signal handler for sync Modal functions, or to the
326
+ # `UserCodeEventLoop` for async functions.
327
+ #
328
+ # We only send this signal on functions that do not have concurrent inputs enabled.
329
+ # This allows us to do fine-grained input cancellation. On sync functions, the
330
+ # SIGUSR1 signal should interrupt the main thread where user code is running,
331
+ # raising an InputCancellation() exception. On async functions, the signal should
332
+ # reach a handler in UserCodeEventLoop, which cancels the task.
333
+ io_context.set_cancel_callback(lambda: os.kill(os.getpid(), signal.SIGUSR1))
334
+
325
335
  if io_context.finalized_function.is_async:
326
336
  user_code_event_loop.run(run_input_async(io_context))
327
337
  else:
modal/_functions.py CHANGED
@@ -86,6 +86,7 @@ from .secret import _Secret
86
86
  from .volume import _Volume
87
87
 
88
88
  if TYPE_CHECKING:
89
+ import modal._partial_function
89
90
  import modal.app
90
91
  import modal.cls
91
92
  import modal.partial_function
@@ -405,7 +406,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
405
406
  self,
406
407
  user_cls,
407
408
  method_name: str,
408
- partial_function: "modal.partial_function._PartialFunction",
409
+ partial_function: "modal._partial_function._PartialFunction",
409
410
  ):
410
411
  """mdmd:hidden
411
412
 
@@ -480,7 +481,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
480
481
  ) -> "_Function":
481
482
  """mdmd:hidden"""
482
483
  # Needed to avoid circular imports
483
- from .partial_function import _find_partial_methods_for_user_cls, _PartialFunctionFlags
484
+ from ._partial_function import _find_partial_methods_for_user_cls, _PartialFunctionFlags
484
485
 
485
486
  tag = info.get_tag()
486
487