modAL 1.2.7.dev11__tar.gz → 1.2.7.dev13__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/PKG-INFO +5 -5
  2. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/README.md +1 -1
  3. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/__init__.py +2 -2
  4. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_functions.py +12 -6
  5. modal-1.2.7.dev13/modal/_ipython.py +21 -0
  6. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_object.py +16 -0
  7. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/container_io_manager.pyi +42 -44
  8. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_serialization.py +2 -1
  9. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/async_utils.py +310 -2
  10. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/grpc_testing.py +6 -3
  11. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/rand_pb_testing.py +8 -1
  12. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_vendor/cloudpickle.py +144 -48
  13. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/app.py +5 -4
  14. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/app.pyi +11 -11
  15. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/builder/2025.06.txt +2 -1
  16. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/builder/PREVIEW.txt +2 -1
  17. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/builder/base-images.json +4 -2
  18. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/run.py +14 -4
  19. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/client.py +3 -2
  20. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/client.pyi +88 -48
  21. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cls.py +1 -1
  22. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cls.pyi +6 -8
  23. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/config.py +1 -0
  24. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/container_process.pyi +6 -8
  25. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/dict.py +2 -1
  26. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/dict.pyi +84 -57
  27. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/exception.py +4 -0
  28. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/experimental/flash.pyi +28 -30
  29. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/file_io.pyi +105 -62
  30. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/functions.pyi +56 -80
  31. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/image.py +12 -7
  32. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/image.pyi +20 -21
  33. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/io_streams.pyi +4 -6
  34. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/mount.py +1 -0
  35. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/mount.pyi +8 -10
  36. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/network_file_system.pyi +60 -37
  37. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/object.pyi +91 -26
  38. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/parallel_map.pyi +6 -8
  39. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/partial_function.pyi +0 -1
  40. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/queue.py +2 -1
  41. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/queue.pyi +76 -50
  42. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/sandbox.py +3 -2
  43. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/sandbox.pyi +52 -54
  44. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/secret.py +2 -1
  45. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/secret.pyi +7 -9
  46. modal-1.2.7.dev13/modal/snapshot.py +56 -0
  47. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/snapshot.pyi +18 -10
  48. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/token_flow.pyi +4 -6
  49. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/volume.py +15 -5
  50. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/volume.pyi +95 -68
  51. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal.egg-info/PKG-INFO +5 -5
  52. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal.egg-info/requires.txt +2 -2
  53. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_version/__init__.py +1 -1
  54. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/pyproject.toml +5 -3
  55. modal-1.2.7.dev11/modal/_ipython.py +0 -11
  56. modal-1.2.7.dev11/modal/snapshot.py +0 -45
  57. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/LICENSE +0 -0
  58. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/__main__.py +0 -0
  59. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_billing.py +0 -0
  60. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_clustered_functions.py +0 -0
  61. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_clustered_functions.pyi +0 -0
  62. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_container_entrypoint.py +0 -0
  63. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_grpc_client.py +0 -0
  64. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_load_context.py +0 -0
  65. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_location.py +0 -0
  66. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_output.py +0 -0
  67. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_partial_function.py +0 -0
  68. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_pty.py +0 -0
  69. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_resolver.py +0 -0
  70. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_resources.py +0 -0
  71. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/__init__.py +0 -0
  72. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/asgi.py +0 -0
  73. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/container_io_manager.py +0 -0
  74. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/execution_context.py +0 -0
  75. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/execution_context.pyi +0 -0
  76. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  77. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/telemetry.py +0 -0
  78. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/user_code_event_loop.py +0 -0
  79. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/user_code_imports.py +0 -0
  80. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_traceback.py +0 -0
  81. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_tunnel.py +0 -0
  82. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_tunnel.pyi +0 -0
  83. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_type_manager.py +0 -0
  84. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/__init__.py +0 -0
  85. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/app_utils.py +0 -0
  86. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/auth_token_manager.py +0 -0
  87. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/blob_utils.py +0 -0
  88. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/bytes_io_segment_payload.py +0 -0
  89. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/deprecation.py +0 -0
  90. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/docker_utils.py +0 -0
  91. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/function_utils.py +0 -0
  92. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/git_utils.py +0 -0
  93. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/grpc_utils.py +0 -0
  94. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/hash_utils.py +0 -0
  95. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/http_utils.py +0 -0
  96. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/jwt_utils.py +0 -0
  97. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/logger.py +0 -0
  98. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/mount_utils.py +0 -0
  99. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/name_utils.py +0 -0
  100. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/package_utils.py +0 -0
  101. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/pattern_utils.py +0 -0
  102. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/shell_utils.py +0 -0
  103. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/task_command_router_client.py +0 -0
  104. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/time_utils.py +0 -0
  105. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_vendor/__init__.py +0 -0
  106. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  107. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_vendor/tblib.py +0 -0
  108. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_watcher.py +0 -0
  109. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/billing.py +0 -0
  110. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/builder/2023.12.312.txt +0 -0
  111. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/builder/2023.12.txt +0 -0
  112. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/builder/2024.04.txt +0 -0
  113. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/builder/2024.10.txt +0 -0
  114. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/builder/README.md +0 -0
  115. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/call_graph.py +0 -0
  116. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/__init__.py +0 -0
  117. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/_download.py +0 -0
  118. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/_traceback.py +0 -0
  119. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/app.py +0 -0
  120. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/cluster.py +0 -0
  121. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/config.py +0 -0
  122. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/container.py +0 -0
  123. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/dict.py +0 -0
  124. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/entry_point.py +0 -0
  125. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/environment.py +0 -0
  126. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/import_refs.py +0 -0
  127. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/launch.py +0 -0
  128. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/network_file_system.py +0 -0
  129. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/profile.py +0 -0
  130. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/programs/__init__.py +0 -0
  131. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/programs/run_jupyter.py +0 -0
  132. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/programs/vscode.py +0 -0
  133. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/queues.py +0 -0
  134. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/secret.py +0 -0
  135. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/shell.py +0 -0
  136. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/token.py +0 -0
  137. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/utils.py +0 -0
  138. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/volume.py +0 -0
  139. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cloud_bucket_mount.py +0 -0
  140. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cloud_bucket_mount.pyi +0 -0
  141. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/container_process.py +0 -0
  142. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/environments.py +0 -0
  143. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/environments.pyi +0 -0
  144. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/experimental/__init__.py +0 -0
  145. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/experimental/flash.py +0 -0
  146. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/experimental/ipython.py +0 -0
  147. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/file_io.py +0 -0
  148. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/file_pattern_matcher.py +0 -0
  149. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/functions.py +0 -0
  150. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/gpu.py +0 -0
  151. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/io_streams.py +0 -0
  152. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/network_file_system.py +0 -0
  153. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/object.py +0 -0
  154. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/output.py +0 -0
  155. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/parallel_map.py +0 -0
  156. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/partial_function.py +0 -0
  157. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/proxy.py +0 -0
  158. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/proxy.pyi +0 -0
  159. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/py.typed +0 -0
  160. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/retries.py +0 -0
  161. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/runner.py +0 -0
  162. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/runner.pyi +0 -0
  163. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/running_app.py +0 -0
  164. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/schedule.py +0 -0
  165. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/scheduler_placement.py +0 -0
  166. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/serving.py +0 -0
  167. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/serving.pyi +0 -0
  168. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/stream_type.py +0 -0
  169. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/token_flow.py +0 -0
  170. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal.egg-info/SOURCES.txt +0 -0
  171. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal.egg-info/dependency_links.txt +0 -0
  172. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal.egg-info/entry_points.txt +0 -0
  173. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal.egg-info/top_level.txt +0 -0
  174. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_docs/__init__.py +0 -0
  175. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_docs/gen_cli_docs.py +0 -0
  176. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_docs/gen_reference_docs.py +0 -0
  177. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_docs/mdmd/__init__.py +0 -0
  178. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_docs/mdmd/mdmd.py +0 -0
  179. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_docs/mdmd/signatures.py +0 -0
  180. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/__init__.py +0 -0
  181. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/api.proto +0 -0
  182. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/api_grpc.py +0 -0
  183. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/api_pb2.py +0 -0
  184. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/api_pb2.pyi +0 -0
  185. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/api_pb2_grpc.py +0 -0
  186. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/api_pb2_grpc.pyi +0 -0
  187. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/modal_api_grpc.py +0 -0
  188. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/py.typed +0 -0
  189. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/task_command_router.proto +0 -0
  190. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/task_command_router_grpc.py +0 -0
  191. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/task_command_router_pb2.py +0 -0
  192. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/task_command_router_pb2.pyi +0 -0
  193. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  194. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  195. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_version/__main__.py +0 -0
  196. {modal-1.2.7.dev11 → modal-1.2.7.dev13}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.7.dev11
3
+ Version: 1.2.7.dev13
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -13,17 +13,17 @@ Classifier: Topic :: System :: Distributed Computing
13
13
  Classifier: Operating System :: OS Independent
14
14
  Classifier: License :: OSI Approved :: Apache Software License
15
15
  Classifier: Programming Language :: Python :: 3
16
- Requires-Python: <3.14,>=3.10
16
+ Requires-Python: <3.15,>=3.10
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
19
  Requires-Dist: aiohttp
20
20
  Requires-Dist: cbor2
21
21
  Requires-Dist: certifi
22
22
  Requires-Dist: click~=8.1
23
- Requires-Dist: grpclib<0.4.9,>=0.4.7
23
+ Requires-Dist: grpclib<0.4.10,>=0.4.7
24
24
  Requires-Dist: protobuf!=4.24.0,<7.0,>=3.19
25
25
  Requires-Dist: rich>=12.0.0
26
- Requires-Dist: synchronicity~=0.10.2
26
+ Requires-Dist: synchronicity~=0.11.1
27
27
  Requires-Dist: toml
28
28
  Requires-Dist: typer>=0.9
29
29
  Requires-Dist: types-certifi
@@ -51,7 +51,7 @@ a [user guide](https://modal.com/docs/guide), and the detailed
51
51
 
52
52
  ## Installation
53
53
 
54
- **This library requires Python 3.10 – 3.13.**
54
+ **This library requires Python 3.10 – 3.14.**
55
55
 
56
56
  Install the package with `uv` or `pip`:
57
57
 
@@ -17,7 +17,7 @@ a [user guide](https://modal.com/docs/guide), and the detailed
17
17
 
18
18
  ## Installation
19
19
 
20
- **This library requires Python 3.10 – 3.13.**
20
+ **This library requires Python 3.10 – 3.14.**
21
21
 
22
22
  Install the package with `uv` or `pip`:
23
23
 
@@ -3,8 +3,8 @@ import sys
3
3
 
4
4
  if sys.version_info[:2] < (3, 10):
5
5
  raise RuntimeError("This version of Modal requires at least Python 3.10")
6
- if sys.version_info[:2] >= (3, 14):
7
- raise RuntimeError("This version of Modal does not support Python 3.14+")
6
+ if sys.version_info[:2] >= (3, 15):
7
+ raise RuntimeError("This version of Modal does not support Python 3.15+")
8
8
 
9
9
  from modal_version import __version__
10
10
 
@@ -38,6 +38,7 @@ from ._utils.async_utils import (
38
38
  aclosing,
39
39
  async_merge,
40
40
  callable_to_agen,
41
+ deprecate_aio_usage,
41
42
  synchronizer,
42
43
  warn_if_generator_is_not_consumed,
43
44
  )
@@ -96,6 +97,7 @@ from .volume import _Volume
96
97
  if TYPE_CHECKING:
97
98
  import modal.app
98
99
  import modal.cls
100
+ import modal.functions
99
101
 
100
102
  MAX_INTERNAL_FAILURE_COUNT = 8
101
103
  TERMINAL_STATUSES = (
@@ -2025,8 +2027,11 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
2025
2027
  assert self._client and self._client.stub
2026
2028
  await self._client.stub.FunctionCallCancel(request)
2027
2029
 
2028
- @staticmethod
2029
- async def from_id(function_call_id: str, client: Optional[_Client] = None) -> "_FunctionCall[Any]":
2030
+ @deprecate_aio_usage((2025, 11, 14), "FunctionCall.from_id")
2031
+ @classmethod
2032
+ def from_id(
2033
+ cls, function_call_id: str, client: Optional["modal.client.Client"] = None
2034
+ ) -> "modal.functions.FunctionCall[Any]":
2030
2035
  """Instantiate a FunctionCall object from an existing ID.
2031
2036
 
2032
2037
  Examples:
@@ -2037,7 +2042,7 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
2037
2042
  fc_id = fc.object_id
2038
2043
 
2039
2044
  # Later, use the ID to re-instantiate the FunctionCall object
2040
- fc = _FunctionCall.from_id(fc_id)
2045
+ fc = FunctionCall.from_id(fc_id)
2041
2046
  result = fc.get()
2042
2047
  ```
2043
2048
 
@@ -2045,6 +2050,7 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
2045
2050
  if you no longer have access to the original object returned from `Function.spawn`.
2046
2051
 
2047
2052
  """
2053
+ _client = typing.cast(_Client, synchronizer._translate_in(client))
2048
2054
 
2049
2055
  async def _load(
2050
2056
  self: _FunctionCall, resolver: Resolver, load_context: LoadContext, existing_object_id: Optional[str]
@@ -2053,10 +2059,10 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
2053
2059
  self._hydrate(function_call_id, load_context.client, None)
2054
2060
 
2055
2061
  rep = f"FunctionCall.from_id({function_call_id!r})"
2056
-
2057
- return _FunctionCall._from_loader(
2058
- _load, rep, hydrate_lazily=True, load_context_overrides=LoadContext(client=client)
2062
+ impl_instance = _FunctionCall._from_loader(
2063
+ _load, rep, hydrate_lazily=True, load_context_overrides=LoadContext(client=_client)
2059
2064
  )
2065
+ return typing.cast("modal.functions.FunctionCall[Any]", synchronizer._translate_out(impl_instance))
2060
2066
 
2061
2067
  @staticmethod
2062
2068
  async def gather(*function_calls: "_FunctionCall[T]") -> typing.Sequence[T]:
@@ -0,0 +1,21 @@
1
+ # Copyright Modal Labs 2022
2
+ import sys
3
+
4
+
5
+ def is_interactive_ipython():
6
+ """
7
+ Detect if we're running in an interactive IPython session.
8
+
9
+ Returns True for IPython shells (including Jupyter notebooks), False otherwise.
10
+ """
11
+ try:
12
+ # Check if IPython is available and get the current instance
13
+ ipython = sys.modules.get("IPython")
14
+ if ipython is None:
15
+ return False
16
+
17
+ # Try to get the active IPython instance
18
+ shell = ipython.get_ipython()
19
+ return shell is not None
20
+ except Exception:
21
+ return False
@@ -1,4 +1,5 @@
1
1
  # Copyright Modal Labs 2022
2
+ import contextlib
2
3
  import typing
3
4
  import uuid
4
5
  from collections.abc import Awaitable, Hashable, Sequence
@@ -350,3 +351,18 @@ def live_method_gen(method):
350
351
  yield item
351
352
 
352
353
  return wrapped
354
+
355
+
356
+ def live_method_contextmanager(method):
357
+ # make sure a wrapped function returning an async context manager
358
+ # will not require both an `await func.aio()` and `async with`
359
+ # which would have been the case if it was wrapped in live_method
360
+
361
+ @wraps(method)
362
+ @contextlib.asynccontextmanager
363
+ async def wrapped(self, *args, **kwargs):
364
+ await self.hydrate()
365
+ async with method(self, *args, **kwargs) as ctx:
366
+ yield ctx
367
+
368
+ return wrapped
@@ -252,8 +252,6 @@ class _ContainerIOManager:
252
252
  @classmethod
253
253
  def stop_fetching_inputs(cls): ...
254
254
 
255
- SUPERSELF = typing.TypeVar("SUPERSELF", covariant=True)
256
-
257
255
  class ContainerIOManager:
258
256
  """Synchronizes all RPC calls and network operations for a running container.
259
257
 
@@ -298,47 +296,47 @@ class ContainerIOManager:
298
296
  """Only used for tests."""
299
297
  ...
300
298
 
301
- class __hello_spec(typing_extensions.Protocol[SUPERSELF]):
299
+ class __hello_spec(typing_extensions.Protocol):
302
300
  def __call__(self, /): ...
303
301
  async def aio(self, /): ...
304
302
 
305
- hello: __hello_spec[typing_extensions.Self]
303
+ hello: __hello_spec
306
304
 
307
- class ___run_heartbeat_loop_spec(typing_extensions.Protocol[SUPERSELF]):
305
+ class ___run_heartbeat_loop_spec(typing_extensions.Protocol):
308
306
  def __call__(self, /): ...
309
307
  async def aio(self, /): ...
310
308
 
311
- _run_heartbeat_loop: ___run_heartbeat_loop_spec[typing_extensions.Self]
309
+ _run_heartbeat_loop: ___run_heartbeat_loop_spec
312
310
 
313
- class ___heartbeat_handle_cancellations_spec(typing_extensions.Protocol[SUPERSELF]):
311
+ class ___heartbeat_handle_cancellations_spec(typing_extensions.Protocol):
314
312
  def __call__(self, /) -> bool: ...
315
313
  async def aio(self, /) -> bool: ...
316
314
 
317
- _heartbeat_handle_cancellations: ___heartbeat_handle_cancellations_spec[typing_extensions.Self]
315
+ _heartbeat_handle_cancellations: ___heartbeat_handle_cancellations_spec
318
316
 
319
- class __heartbeats_spec(typing_extensions.Protocol[SUPERSELF]):
317
+ class __heartbeats_spec(typing_extensions.Protocol):
320
318
  def __call__(
321
319
  self, /, wait_for_mem_snap: bool
322
320
  ) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]: ...
323
321
  def aio(self, /, wait_for_mem_snap: bool) -> typing.AsyncContextManager[None]: ...
324
322
 
325
- heartbeats: __heartbeats_spec[typing_extensions.Self]
323
+ heartbeats: __heartbeats_spec
326
324
 
327
325
  def stop_heartbeat(self): ...
328
326
 
329
- class __dynamic_concurrency_manager_spec(typing_extensions.Protocol[SUPERSELF]):
327
+ class __dynamic_concurrency_manager_spec(typing_extensions.Protocol):
330
328
  def __call__(self, /) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]: ...
331
329
  def aio(self, /) -> typing.AsyncContextManager[None]: ...
332
330
 
333
- dynamic_concurrency_manager: __dynamic_concurrency_manager_spec[typing_extensions.Self]
331
+ dynamic_concurrency_manager: __dynamic_concurrency_manager_spec
334
332
 
335
- class ___dynamic_concurrency_loop_spec(typing_extensions.Protocol[SUPERSELF]):
333
+ class ___dynamic_concurrency_loop_spec(typing_extensions.Protocol):
336
334
  def __call__(self, /): ...
337
335
  async def aio(self, /): ...
338
336
 
339
- _dynamic_concurrency_loop: ___dynamic_concurrency_loop_spec[typing_extensions.Self]
337
+ _dynamic_concurrency_loop: ___dynamic_concurrency_loop_spec
340
338
 
341
- class __get_data_in_spec(typing_extensions.Protocol[SUPERSELF]):
339
+ class __get_data_in_spec(typing_extensions.Protocol):
342
340
  def __call__(
343
341
  self, /, function_call_id: str, attempt_token: typing.Optional[str]
344
342
  ) -> typing.Iterator[typing.Any]:
@@ -351,9 +349,9 @@ class ContainerIOManager:
351
349
  """Read from the `data_in` stream of a function call."""
352
350
  ...
353
351
 
354
- get_data_in: __get_data_in_spec[typing_extensions.Self]
352
+ get_data_in: __get_data_in_spec
355
353
 
356
- class __put_data_out_spec(typing_extensions.Protocol[SUPERSELF]):
354
+ class __put_data_out_spec(typing_extensions.Protocol):
357
355
  def __call__(
358
356
  self,
359
357
  /,
@@ -388,9 +386,9 @@ class ContainerIOManager:
388
386
  """
389
387
  ...
390
388
 
391
- put_data_out: __put_data_out_spec[typing_extensions.Self]
389
+ put_data_out: __put_data_out_spec
392
390
 
393
- class __generator_output_sender_spec(typing_extensions.Protocol[SUPERSELF]):
391
+ class __generator_output_sender_spec(typing_extensions.Protocol):
394
392
  def __call__(
395
393
  self, /, function_call_id: str, attempt_token: str, data_format: int, message_rx: asyncio.queues.Queue
396
394
  ) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]:
@@ -403,9 +401,9 @@ class ContainerIOManager:
403
401
  """Runs background task that feeds generator outputs into a function call's `data_out` stream."""
404
402
  ...
405
403
 
406
- generator_output_sender: __generator_output_sender_spec[typing_extensions.Self]
404
+ generator_output_sender: __generator_output_sender_spec
407
405
 
408
- class ___queue_create_spec(typing_extensions.Protocol[SUPERSELF]):
406
+ class ___queue_create_spec(typing_extensions.Protocol):
409
407
  def __call__(self, /, size: int) -> asyncio.queues.Queue:
410
408
  """Create a queue, on the synchronicity event loop (needed on Python 3.8 and 3.9)."""
411
409
  ...
@@ -414,9 +412,9 @@ class ContainerIOManager:
414
412
  """Create a queue, on the synchronicity event loop (needed on Python 3.8 and 3.9)."""
415
413
  ...
416
414
 
417
- _queue_create: ___queue_create_spec[typing_extensions.Self]
415
+ _queue_create: ___queue_create_spec
418
416
 
419
- class ___queue_put_spec(typing_extensions.Protocol[SUPERSELF]):
417
+ class ___queue_put_spec(typing_extensions.Protocol):
420
418
  def __call__(self, /, queue: asyncio.queues.Queue, value: typing.Any) -> None:
421
419
  """Put a value onto a queue, using the synchronicity event loop."""
422
420
  ...
@@ -425,12 +423,12 @@ class ContainerIOManager:
425
423
  """Put a value onto a queue, using the synchronicity event loop."""
426
424
  ...
427
425
 
428
- _queue_put: ___queue_put_spec[typing_extensions.Self]
426
+ _queue_put: ___queue_put_spec
429
427
 
430
428
  def get_average_call_time(self) -> float: ...
431
429
  def get_max_inputs_to_fetch(self): ...
432
430
 
433
- class ___generate_inputs_spec(typing_extensions.Protocol[SUPERSELF]):
431
+ class ___generate_inputs_spec(typing_extensions.Protocol):
434
432
  def __call__(
435
433
  self, /, batch_max_size: int, batch_wait_ms: int
436
434
  ) -> typing.Iterator[list[tuple[str, int, str, str, modal_proto.api_pb2.FunctionInput]]]: ...
@@ -438,9 +436,9 @@ class ContainerIOManager:
438
436
  self, /, batch_max_size: int, batch_wait_ms: int
439
437
  ) -> collections.abc.AsyncIterator[list[tuple[str, int, str, str, modal_proto.api_pb2.FunctionInput]]]: ...
440
438
 
441
- _generate_inputs: ___generate_inputs_spec[typing_extensions.Self]
439
+ _generate_inputs: ___generate_inputs_spec
442
440
 
443
- class __run_inputs_outputs_spec(typing_extensions.Protocol[SUPERSELF]):
441
+ class __run_inputs_outputs_spec(typing_extensions.Protocol):
444
442
  def __call__(
445
443
  self,
446
444
  /,
@@ -456,9 +454,9 @@ class ContainerIOManager:
456
454
  batch_wait_ms: int = 0,
457
455
  ) -> collections.abc.AsyncIterator[IOContext]: ...
458
456
 
459
- run_inputs_outputs: __run_inputs_outputs_spec[typing_extensions.Self]
457
+ run_inputs_outputs: __run_inputs_outputs_spec
460
458
 
461
- class ___send_outputs_spec(typing_extensions.Protocol[SUPERSELF]):
459
+ class ___send_outputs_spec(typing_extensions.Protocol):
462
460
  def __call__(self, /, started_at: float, outputs: list[modal_proto.api_pb2.FunctionPutOutputsItem]) -> None:
463
461
  """Send pre-built output items with retry and chunking."""
464
462
  ...
@@ -467,9 +465,9 @@ class ContainerIOManager:
467
465
  """Send pre-built output items with retry and chunking."""
468
466
  ...
469
467
 
470
- _send_outputs: ___send_outputs_spec[typing_extensions.Self]
468
+ _send_outputs: ___send_outputs_spec
471
469
 
472
- class __handle_user_exception_spec(typing_extensions.Protocol[SUPERSELF]):
470
+ class __handle_user_exception_spec(typing_extensions.Protocol):
473
471
  def __call__(self, /) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]:
474
472
  """Sets the task as failed in a way where it's not retried.
475
473
 
@@ -486,9 +484,9 @@ class ContainerIOManager:
486
484
  """
487
485
  ...
488
486
 
489
- handle_user_exception: __handle_user_exception_spec[typing_extensions.Self]
487
+ handle_user_exception: __handle_user_exception_spec
490
488
 
491
- class __handle_input_exception_spec(typing_extensions.Protocol[SUPERSELF]):
489
+ class __handle_input_exception_spec(typing_extensions.Protocol):
492
490
  def __call__(
493
491
  self, /, io_context: IOContext, started_at: float
494
492
  ) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]:
@@ -499,23 +497,23 @@ class ContainerIOManager:
499
497
  """Handle an exception while processing a function input."""
500
498
  ...
501
499
 
502
- handle_input_exception: __handle_input_exception_spec[typing_extensions.Self]
500
+ handle_input_exception: __handle_input_exception_spec
503
501
 
504
502
  def exit_context(self, started_at, input_ids: list[str]): ...
505
503
 
506
- class __push_outputs_spec(typing_extensions.Protocol[SUPERSELF]):
504
+ class __push_outputs_spec(typing_extensions.Protocol):
507
505
  def __call__(self, /, io_context: IOContext, started_at: float, output_data: list[typing.Any]) -> None: ...
508
506
  async def aio(self, /, io_context: IOContext, started_at: float, output_data: list[typing.Any]) -> None: ...
509
507
 
510
- push_outputs: __push_outputs_spec[typing_extensions.Self]
508
+ push_outputs: __push_outputs_spec
511
509
 
512
- class __memory_restore_spec(typing_extensions.Protocol[SUPERSELF]):
510
+ class __memory_restore_spec(typing_extensions.Protocol):
513
511
  def __call__(self, /) -> None: ...
514
512
  async def aio(self, /) -> None: ...
515
513
 
516
- memory_restore: __memory_restore_spec[typing_extensions.Self]
514
+ memory_restore: __memory_restore_spec
517
515
 
518
- class __memory_snapshot_spec(typing_extensions.Protocol[SUPERSELF]):
516
+ class __memory_snapshot_spec(typing_extensions.Protocol):
519
517
  def __call__(self, /) -> None:
520
518
  """Message server indicating that function is ready to be checkpointed."""
521
519
  ...
@@ -524,9 +522,9 @@ class ContainerIOManager:
524
522
  """Message server indicating that function is ready to be checkpointed."""
525
523
  ...
526
524
 
527
- memory_snapshot: __memory_snapshot_spec[typing_extensions.Self]
525
+ memory_snapshot: __memory_snapshot_spec
528
526
 
529
- class __volume_commit_spec(typing_extensions.Protocol[SUPERSELF]):
527
+ class __volume_commit_spec(typing_extensions.Protocol):
530
528
  def __call__(self, /, volume_ids: list[str]) -> None:
531
529
  """Perform volume commit for given `volume_ids`.
532
530
  Only used on container exit to persist uncommitted changes on behalf of user.
@@ -539,13 +537,13 @@ class ContainerIOManager:
539
537
  """
540
538
  ...
541
539
 
542
- volume_commit: __volume_commit_spec[typing_extensions.Self]
540
+ volume_commit: __volume_commit_spec
543
541
 
544
- class __interact_spec(typing_extensions.Protocol[SUPERSELF]):
542
+ class __interact_spec(typing_extensions.Protocol):
545
543
  def __call__(self, /, from_breakpoint: bool = False): ...
546
544
  async def aio(self, /, from_breakpoint: bool = False): ...
547
545
 
548
- interact: __interact_spec[typing_extensions.Self]
546
+ interact: __interact_spec
549
547
 
550
548
  @property
551
549
  def target_concurrency(self) -> int: ...
@@ -420,7 +420,8 @@ def check_valid_cls_constructor_arg(key, obj):
420
420
  try:
421
421
  ClsConstructorPickler(buf).dump(obj)
422
422
  return True
423
- except (AttributeError, ValueError):
423
+ except (AttributeError, ValueError, pickle.PicklingError):
424
+ # Python 3.14+ now raises an PicklingError for certain types of `dump` failures
424
425
  raise ValueError(
425
426
  f"Only pickle-able types are allowed in remote class constructors: argument {key} of type {type(obj)}."
426
427
  )