modal 1.5.2.dev22__tar.gz → 1.5.3.dev1__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 (231) hide show
  1. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/PKG-INFO +1 -1
  2. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/grpc_utils.py +19 -4
  3. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/task_command_router_client.py +21 -161
  4. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/changelog.py +7 -7
  5. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/environment.py +9 -9
  6. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/client.pyi +2 -2
  7. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/container_process.py +1 -13
  8. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/container_process.pyi +0 -27
  9. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/functions.pyi +6 -6
  10. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/parallel_map.py +56 -51
  11. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/sandbox_fs.py +80 -32
  12. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/sandbox_fs.pyi +0 -24
  13. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal.egg-info/PKG-INFO +1 -1
  14. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_proto/api_grpc.py +32 -0
  15. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_proto/api_pb2.py +898 -847
  16. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_proto/api_pb2.pyi +134 -6
  17. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_proto/api_pb2_grpc.py +66 -0
  18. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_proto/api_pb2_grpc.pyi +20 -0
  19. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_proto/modal_api_grpc.py +2 -0
  20. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_version/__init__.py +1 -1
  21. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/LICENSE +0 -0
  22. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/README.md +0 -0
  23. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/__init__.py +0 -0
  24. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/__main__.py +0 -0
  25. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_billing.py +0 -0
  26. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_clustered_functions.py +0 -0
  27. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_clustered_functions.pyi +0 -0
  28. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_container_entrypoint.py +0 -0
  29. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_environments.py +0 -0
  30. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_function_variants.py +0 -0
  31. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_functions.py +0 -0
  32. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_grpc_client.py +0 -0
  33. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_image.py +0 -0
  34. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_ipython.py +0 -0
  35. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_load_context.py +0 -0
  36. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_location.py +0 -0
  37. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_logs.py +0 -0
  38. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_object.py +0 -0
  39. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_output/__init__.py +0 -0
  40. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_output/manager.py +0 -0
  41. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_output/pty.py +0 -0
  42. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_output/rich.py +0 -0
  43. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_output/status.py +0 -0
  44. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_partial_function.py +0 -0
  45. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_resolver.py +0 -0
  46. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_resources.py +0 -0
  47. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_runtime/__init__.py +0 -0
  48. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_runtime/asgi.py +0 -0
  49. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_runtime/container_io_manager.py +0 -0
  50. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_runtime/container_io_manager.pyi +0 -0
  51. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_runtime/execution_context.py +0 -0
  52. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_runtime/execution_context.pyi +0 -0
  53. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  54. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_runtime/task_lifecycle_manager.py +0 -0
  55. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_runtime/task_lifecycle_manager.pyi +0 -0
  56. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_runtime/telemetry.py +0 -0
  57. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_runtime/user_code_event_loop.py +0 -0
  58. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_runtime/user_code_imports.py +0 -0
  59. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_serialization.py +0 -0
  60. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_server.py +0 -0
  61. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_traceback.py +0 -0
  62. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_tunnel.py +0 -0
  63. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_tunnel.pyi +0 -0
  64. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_type_manager.py +0 -0
  65. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/__init__.py +0 -0
  66. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/app_utils.py +0 -0
  67. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/async_utils.py +0 -0
  68. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/auth_token_manager.py +0 -0
  69. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/blob_utils.py +0 -0
  70. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/browser_utils.py +0 -0
  71. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/bytes_io_segment_payload.py +0 -0
  72. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/curl_utils.py +0 -0
  73. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/deprecation.py +0 -0
  74. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/docker_utils.py +0 -0
  75. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/function_utils.py +0 -0
  76. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/git_utils.py +0 -0
  77. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/grpc_testing.py +0 -0
  78. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/hash_utils.py +0 -0
  79. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/http_utils.py +0 -0
  80. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/jwt_utils.py +0 -0
  81. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/logger.py +0 -0
  82. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/mount_utils.py +0 -0
  83. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/name_utils.py +0 -0
  84. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/package_utils.py +0 -0
  85. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/pattern_utils.py +0 -0
  86. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/proxy_support.py +0 -0
  87. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/rand_pb_testing.py +0 -0
  88. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/sandbox_fs_utils.py +0 -0
  89. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/shell_utils.py +0 -0
  90. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_utils/time_utils.py +0 -0
  91. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_vendor/__init__.py +0 -0
  92. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  93. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_vendor/cloudpickle.py +0 -0
  94. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_vendor/tblib.py +0 -0
  95. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_vendor/version.py +0 -0
  96. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_watcher.py +0 -0
  97. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/_workspace.py +0 -0
  98. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/app.py +0 -0
  99. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/app.pyi +0 -0
  100. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/billing.py +0 -0
  101. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/billing.pyi +0 -0
  102. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/builder/2023.12.312.txt +0 -0
  103. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/builder/2023.12.txt +0 -0
  104. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/builder/2024.04.txt +0 -0
  105. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/builder/2024.10.txt +0 -0
  106. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/builder/2025.06.txt +0 -0
  107. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/builder/PREVIEW.txt +0 -0
  108. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/builder/README.md +0 -0
  109. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/builder/base-images.json +0 -0
  110. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/call_graph.py +0 -0
  111. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/__init__.py +0 -0
  112. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/_download.py +0 -0
  113. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/_help.py +0 -0
  114. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/_traceback.py +0 -0
  115. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/app.py +0 -0
  116. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/billing.py +0 -0
  117. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/bootstrap.py +0 -0
  118. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/cluster.py +0 -0
  119. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/config.py +0 -0
  120. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/container.py +0 -0
  121. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/curl.py +0 -0
  122. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/dashboard.py +0 -0
  123. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/dict.py +0 -0
  124. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/endpoint.py +0 -0
  125. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/entry_point.py +0 -0
  126. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/image.py +0 -0
  127. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/import_refs.py +0 -0
  128. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/launch.py +0 -0
  129. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/logo.py +0 -0
  130. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/network_file_system.py +0 -0
  131. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/profile.py +0 -0
  132. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/programs/__init__.py +0 -0
  133. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/programs/run_jupyter.py +0 -0
  134. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/programs/vscode.py +0 -0
  135. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/queues.py +0 -0
  136. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/run.py +0 -0
  137. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/secret.py +0 -0
  138. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/selector.py +0 -0
  139. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/shell.py +0 -0
  140. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/skills.py +0 -0
  141. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/token.py +0 -0
  142. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/utils.py +0 -0
  143. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/volume.py +0 -0
  144. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cli/workspace.py +0 -0
  145. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/client.py +0 -0
  146. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cloud_bucket_mount.py +0 -0
  147. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cloud_bucket_mount.pyi +0 -0
  148. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cls.py +0 -0
  149. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/cls.pyi +0 -0
  150. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/config.py +0 -0
  151. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/dict.py +0 -0
  152. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/dict.pyi +0 -0
  153. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/environments.py +0 -0
  154. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/environments.pyi +0 -0
  155. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/exception.py +0 -0
  156. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/experimental/__init__.py +0 -0
  157. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/experimental/flash.py +0 -0
  158. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/experimental/flash.pyi +0 -0
  159. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/experimental/ipython.py +0 -0
  160. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/file_io.py +0 -0
  161. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/file_io.pyi +0 -0
  162. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/file_pattern_matcher.py +0 -0
  163. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/functions.py +0 -0
  164. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/image.py +0 -0
  165. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/image.pyi +0 -0
  166. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/io_streams.py +0 -0
  167. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/io_streams.pyi +0 -0
  168. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/mount.py +0 -0
  169. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/mount.pyi +0 -0
  170. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/network_file_system.py +0 -0
  171. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/network_file_system.pyi +0 -0
  172. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/object.py +0 -0
  173. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/object.pyi +0 -0
  174. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/output.py +0 -0
  175. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/parallel_map.pyi +0 -0
  176. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/partial_function.py +0 -0
  177. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/partial_function.pyi +0 -0
  178. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/proxy.py +0 -0
  179. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/proxy.pyi +0 -0
  180. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/py.typed +0 -0
  181. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/queue.py +0 -0
  182. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/queue.pyi +0 -0
  183. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/retries.py +0 -0
  184. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/runner.py +0 -0
  185. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/runner.pyi +0 -0
  186. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/running_app.py +0 -0
  187. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/sandbox.py +0 -0
  188. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/sandbox.pyi +0 -0
  189. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/schedule.py +0 -0
  190. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/scheduler_placement.py +0 -0
  191. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/secret.py +0 -0
  192. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/secret.pyi +0 -0
  193. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/server.py +0 -0
  194. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/server.pyi +0 -0
  195. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/serving.py +0 -0
  196. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/serving.pyi +0 -0
  197. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/skills/modal/SKILL.md +0 -0
  198. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/snapshot.py +0 -0
  199. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/snapshot.pyi +0 -0
  200. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/stream_type.py +0 -0
  201. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/token_flow.py +0 -0
  202. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/token_flow.pyi +0 -0
  203. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/types.py +0 -0
  204. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/volume.py +0 -0
  205. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/volume.pyi +0 -0
  206. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/workspace.py +0 -0
  207. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal/workspace.pyi +0 -0
  208. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal.egg-info/SOURCES.txt +0 -0
  209. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal.egg-info/dependency_links.txt +0 -0
  210. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal.egg-info/entry_points.txt +0 -0
  211. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal.egg-info/requires.txt +0 -0
  212. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal.egg-info/top_level.txt +0 -0
  213. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_docs/__init__.py +0 -0
  214. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_docs/gen_cli_docs.py +0 -0
  215. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_docs/gen_cli_docs_main.py +0 -0
  216. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_docs/gen_reference_docs.py +0 -0
  217. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_docs/gen_reference_docs_main.py +0 -0
  218. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_docs/mdmd/__init__.py +0 -0
  219. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_docs/mdmd/mdmd.py +0 -0
  220. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_docs/mdmd/signatures.py +0 -0
  221. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_docs/mdmd/types.py +0 -0
  222. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_proto/__init__.py +0 -0
  223. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_proto/py.typed +0 -0
  224. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_proto/task_command_router_grpc.py +0 -0
  225. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_proto/task_command_router_pb2.py +0 -0
  226. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_proto/task_command_router_pb2.pyi +0 -0
  227. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  228. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  229. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/modal_version/__main__.py +0 -0
  230. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/pyproject.toml +0 -0
  231. {modal-1.5.2.dev22 → modal-1.5.3.dev1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.5.2.dev22
3
+ Version: 1.5.3.dev1
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -164,6 +164,9 @@ RETRYABLE_GRPC_STATUS_CODES = [
164
164
  ]
165
165
  SERVER_RETRY_WARNING_TIME_INTERVAL = 30.0
166
166
  DEFAULT_MAX_RETRIES = 3
167
+ GRPC_KEEPALIVE_TIME_SECS = 30.0
168
+ GRPC_KEEPALIVE_TIMEOUT_SECS = 10.0
169
+ GRPC_WINDOW_SIZE = 64 * 1024 * 1024 # 64 MiB
167
170
 
168
171
 
169
172
  @dataclass
@@ -251,6 +254,21 @@ class CustomProtoStatusDetailsCodec(StatusDetailsCodecBase):
251
254
  custom_detail_codec = CustomProtoStatusDetailsCodec()
252
255
 
253
256
 
257
+ def create_channel_config() -> grpclib.config.Configuration:
258
+ """Shared grpclib channel settings for Modal client connections.
259
+
260
+ HTTP/2 keepalive probes keep idle transports warm through stateful
261
+ middleboxes and surface dead connections before retries reuse them.
262
+ """
263
+ return grpclib.config.Configuration(
264
+ _keepalive_time=GRPC_KEEPALIVE_TIME_SECS,
265
+ _keepalive_timeout=GRPC_KEEPALIVE_TIMEOUT_SECS,
266
+ _keepalive_permit_without_calls=True,
267
+ http2_connection_window_size=GRPC_WINDOW_SIZE,
268
+ http2_stream_window_size=GRPC_WINDOW_SIZE,
269
+ )
270
+
271
+
254
272
  def create_channel(
255
273
  server_url: str,
256
274
  metadata: dict[str, str] = {},
@@ -262,10 +280,7 @@ def create_channel(
262
280
  o = urllib.parse.urlparse(server_url)
263
281
 
264
282
  channel: grpclib.client.Channel
265
- config = grpclib.config.Configuration(
266
- http2_connection_window_size=64 * 1024 * 1024, # 64 MiB
267
- http2_stream_window_size=64 * 1024 * 1024, # 64 MiB
268
- )
283
+ config = create_channel_config()
269
284
 
270
285
  if o.scheme == "unix":
271
286
  channel = grpclib.client.Channel(path=o.path, config=config, status_details_codec=custom_detail_codec)
@@ -1,7 +1,6 @@
1
1
  # Copyright Modal Labs 2025
2
2
  import asyncio
3
3
  import base64
4
- import io
5
4
  import json
6
5
  import socket
7
6
  import ssl
@@ -9,36 +8,24 @@ import time
9
8
  import typing
10
9
  import urllib.parse
11
10
  import weakref
12
- from collections.abc import AsyncGenerator, AsyncIterable, Callable
11
+ from collections.abc import AsyncGenerator, Callable
13
12
  from contextlib import suppress
14
- from typing import BinaryIO, TypeVar
13
+ from typing import TypeVar
15
14
 
16
15
  import grpclib.client
17
- import grpclib.config
18
16
  from grpclib import GRPCError, Status
19
17
  from grpclib.exceptions import StreamTerminatedError
20
18
 
21
19
  from modal.config import logger
22
- from modal.exception import AuthError, ExecTimeoutError, InternalError, ServiceError, TimeoutError as ModalTimeoutError
20
+ from modal.exception import ExecTimeoutError, TimeoutError as ModalTimeoutError
23
21
  from modal_proto import api_pb2, task_command_router_pb2 as sr_pb2
24
22
  from modal_proto.task_command_router_grpc import TaskCommandRouterStub
25
23
 
26
24
  from .._grpc_client import grpc_error_converter
27
- from .._utils.grpc_utils import ModalChannel
25
+ from .._utils.grpc_utils import ModalChannel, create_channel_config
28
26
  from .async_utils import aclosing, retry
29
27
  from .grpc_utils import RETRYABLE_GRPC_STATUS_CODES
30
28
 
31
- STREAMING_STDIN_CHUNK_SIZE = 256 * 1024
32
-
33
- _STREAMING_STDIN_RESUMABLE_EXCEPTIONS = (
34
- AuthError,
35
- InternalError,
36
- ServiceError,
37
- StreamTerminatedError,
38
- OSError,
39
- asyncio.TimeoutError,
40
- )
41
-
42
29
 
43
30
  @retry(n_attempts=34, base_delay=1, max_delay=10, attempt_timeout=10, total_timeout=310)
44
31
  async def _connect_channel(channel: grpclib.client.Channel):
@@ -234,10 +221,7 @@ class TaskCommandRouterClient:
234
221
  host,
235
222
  port,
236
223
  ssl=ssl_context,
237
- config=grpclib.config.Configuration(
238
- http2_connection_window_size=64 * 1024 * 1024, # 64 MiB
239
- http2_stream_window_size=64 * 1024 * 1024, # 64 MiB
240
- ),
224
+ config=create_channel_config(),
241
225
  closed_error_message="Unable to perform operation on a detached sandbox",
242
226
  )
243
227
 
@@ -484,118 +468,6 @@ class TaskCommandRouterClient:
484
468
  lambda: self._call_with_auth_retry(self._stub.TaskExecStdinWrite, request)
485
469
  )
486
470
 
487
- async def exec_stdin_write_stream(
488
- self,
489
- task_id: str,
490
- exec_id: str,
491
- source: BinaryIO,
492
- chunk_size: int = STREAMING_STDIN_CHUNK_SIZE,
493
- max_resume_attempts: int = 9,
494
- ) -> int:
495
- """Stream `source` into the exec's stdin, with bounded resume on transient failures.
496
-
497
- Streams the full contents of `source` in one client-streaming RPC and
498
- closes stdin (EOF) on success. On a resumable error, queries
499
- `exec_stdin_status` for the server's canonical offset, seeks `source`
500
- to that point, and reopens the stream.
501
-
502
- Args:
503
- task_id: The task ID of the task running the exec'd command.
504
- exec_id: The execution ID of the command to write to.
505
- source: A seekable byte source (file, BytesIO, etc.).
506
- chunk_size: Bytes per outbound message.
507
- max_resume_attempts: Upper bound on resume retries before giving up.
508
-
509
- Returns:
510
- The total number of bytes streamed into the exec's stdin.
511
- """
512
- offset = 0
513
- attempt = 0
514
- while True:
515
-
516
- async def _chunks():
517
- while True:
518
- chunk = source.read(chunk_size)
519
- if not chunk:
520
- return
521
- yield chunk
522
-
523
- try:
524
- source.seek(offset)
525
- await self._exec_stdin_write_stream(task_id, exec_id, offset, _chunks())
526
- return source.tell()
527
- except (*_STREAMING_STDIN_RESUMABLE_EXCEPTIONS, AttributeError) as e:
528
- # StreamTerminatedError surfaces as AttributeError in grpclib<=0.4.7;
529
- # see call_with_retries_on_transient_errors.
530
- if isinstance(e, AttributeError) and "_write_appdata" not in str(e):
531
- raise
532
- attempt += 1
533
- if attempt > max_resume_attempts:
534
- raise
535
- status = await self.exec_stdin_status(task_id=task_id, exec_id=exec_id)
536
- if status.closed:
537
- pos = source.tell()
538
- if status.num_bytes_written == pos and source.seek(0, io.SEEK_END) == pos:
539
- logger.debug(f"exec_stdin_write_stream completed but response was lost: {e}")
540
- return pos
541
- raise
542
- offset = status.num_bytes_written
543
- logger.debug(f"exec_stdin_write_stream resuming from offset {offset} after error: {e}")
544
-
545
- async def _exec_stdin_write_stream(
546
- self,
547
- task_id: str,
548
- exec_id: str,
549
- start_offset: int,
550
- chunks: AsyncIterable[bytes],
551
- ) -> sr_pb2.TaskExecStdinWriteStreamResponse | None:
552
- """Single client-streaming attempt: Start, Data chunks, then End (EOF).
553
-
554
- Does not retry; `exec_stdin_write_stream` owns resume.
555
- """
556
- with grpc_error_converter():
557
- stream = self._stub.TaskExecStdinWriteStream.open(metadata=self._get_metadata())
558
- async with stream as s:
559
- start = sr_pb2.TaskExecStdinWriteStreamRequest(
560
- start=sr_pb2.TaskExecStdinWriteStreamStart(
561
- task_id=task_id,
562
- exec_id=exec_id,
563
- offset=start_offset,
564
- ),
565
- )
566
- await s.send_message(start)
567
- async for data in chunks:
568
- if not data:
569
- continue
570
- await s.send_message(sr_pb2.TaskExecStdinWriteStreamRequest(data=data))
571
- # The server closes stdin only on this explicit End message. A
572
- # stream that breaks before it leaves stdin open for resume.
573
- await s.send_message(
574
- sr_pb2.TaskExecStdinWriteStreamRequest(end=sr_pb2.TaskExecStdinWriteStreamEnd()),
575
- end=True,
576
- )
577
- return await s.recv_message()
578
-
579
- async def exec_stdin_status(self, task_id: str, exec_id: str) -> sr_pb2.TaskExecStdinStatusResponse:
580
- """Read the current stdin write status for an exec'd command, to support retries from the right offset.
581
-
582
- Used by streaming clients to find the resume offset after a stream
583
- failure. Evicts any in-flight stdin stream for the exec, so it is not
584
- safe to call for read-only observability.
585
-
586
- Args:
587
- task_id: The task ID of the task running the exec'd command.
588
- exec_id: The execution ID of the command to query.
589
- Raises:
590
- Other errors: If retries are exhausted on transient errors or if there's an error
591
- from the RPC itself.
592
- """
593
- request = sr_pb2.TaskExecStdinStatusRequest(task_id=task_id, exec_id=exec_id)
594
- with grpc_error_converter():
595
- return await call_with_retries_on_transient_errors(
596
- lambda: self._call_with_auth_retry(self._stub.TaskExecStdinStatus, request)
597
- )
598
-
599
471
  async def sandbox_stdin_write_v2(
600
472
  self, task_id: str, offset: int, data: bytes, eof: bool
601
473
  ) -> sr_pb2.SandboxStdinWriteV2Response:
@@ -625,16 +497,7 @@ class TaskCommandRouterClient:
625
497
  TimeoutError: If the sandbox does not become ready within `timeout`.
626
498
  """
627
499
  request = sr_pb2.SandboxWaitUntilReadyTcrRequest(task_id=task_id, timeout=timeout)
628
- with grpc_error_converter():
629
- try:
630
- return await asyncio.wait_for(
631
- call_with_retries_on_transient_errors(
632
- lambda: self._call_with_auth_retry(self._stub.SandboxWaitUntilReady, request, timeout=timeout),
633
- ),
634
- timeout=timeout,
635
- )
636
- except asyncio.TimeoutError:
637
- raise ModalTimeoutError("Timeout expired")
500
+ return await self._unary_call_with_deadline(self._stub.SandboxWaitUntilReady, request, timeout=timeout)
638
501
 
639
502
  async def exec_poll(self, task_id: str, exec_id: str, deadline: float | None = None) -> sr_pb2.TaskExecPollResponse:
640
503
  """Poll for the exit status of an exec'd command, properly retrying on transient errors.
@@ -944,21 +807,14 @@ class TaskCommandRouterClient:
944
807
  window, the call is cancelled and a `modal.exception.TimeoutError` is raised.
945
808
  """
946
809
  request = sr_pb2.TaskReloadVolumesRequest(task_id=task_id)
947
- with grpc_error_converter():
948
- try:
949
- return await asyncio.wait_for(
950
- call_with_retries_on_transient_errors(
951
- lambda: self._call_with_auth_retry(self._stub.TaskReloadVolumes, request, timeout=timeout),
952
- ),
953
- timeout=timeout,
954
- )
955
- except asyncio.TimeoutError:
956
- raise ModalTimeoutError("Timeout expired")
810
+ return await self._unary_call_with_deadline(self._stub.TaskReloadVolumes, request, timeout=timeout)
811
+
812
+ async def _unary_call_with_deadline(self, rpc, request, *, timeout: float, **kwargs):
813
+ """Call a unary RPC with transient-error retries bounded by a total deadline.
957
814
 
958
- async def _snapshot_with_deadline(self, rpc, request, *, timeout: float, **kwargs):
959
- # helper method for snapshot_directory and snapshot_filesystem to handle grpc
960
- # deadlines in a consistent way, converting any error to TimeoutError after passing
961
- # the total deadline budget
815
+ Raises `modal.exception.TimeoutError` once the deadline has elapsed, or when
816
+ the server responds with `DEADLINE_EXCEEDED`.
817
+ """
962
818
  timeout_deadline = time.monotonic() + timeout
963
819
 
964
820
  def call():
@@ -976,17 +832,21 @@ class TaskCommandRouterClient:
976
832
  exclude_status_codes=[Status.DEADLINE_EXCEEDED, Status.CANCELLED],
977
833
  timeout_deadline=timeout_deadline,
978
834
  )
979
- except Exception:
980
- if time.monotonic() >= timeout_deadline:
835
+ except Exception as exc:
836
+ if time.monotonic() >= timeout_deadline or getattr(exc, "_grpc_status", None) == Status.DEADLINE_EXCEEDED:
981
837
  raise ModalTimeoutError("Timeout expired")
982
838
  raise
983
839
 
984
840
  async def snapshot_directory(
985
841
  self, request: sr_pb2.TaskSnapshotDirectoryRequest, *, timeout: float, **kwargs
986
842
  ) -> sr_pb2.TaskSnapshotDirectoryResponse:
987
- return await self._snapshot_with_deadline(self._stub.TaskSnapshotDirectory, request, timeout=timeout, **kwargs)
843
+ return await self._unary_call_with_deadline(
844
+ self._stub.TaskSnapshotDirectory, request, timeout=timeout, **kwargs
845
+ )
988
846
 
989
847
  async def snapshot_filesystem(
990
848
  self, request: sr_pb2.TaskSnapshotFilesystemRequest, *, timeout: float, **kwargs
991
849
  ) -> sr_pb2.TaskSnapshotFilesystemResponse:
992
- return await self._snapshot_with_deadline(self._stub.TaskSnapshotFilesystem, request, timeout=timeout, **kwargs)
850
+ return await self._unary_call_with_deadline(
851
+ self._stub.TaskSnapshotFilesystem, request, timeout=timeout, **kwargs
852
+ )
@@ -120,17 +120,17 @@ def changelog(
120
120
 
121
121
  Examples:
122
122
 
123
- ```bash
124
- modal changelog --since 1.2.0 # Show updates added after a specific version
123
+ ```bash
124
+ modal changelog --since 1.2.0 # Show updates added after a specific version
125
125
 
126
- modal changelog --since 2026-01-01 # Show updates added after a specific date
126
+ modal changelog --since 2026-01-01 # Show updates added after a specific date
127
127
 
128
- modal changelog --newer # Show updates released after the currently installed version
128
+ modal changelog --newer # Show updates released after the currently installed version
129
129
 
130
- modal changelog --last 3 # Show updates included in the 3 most recent releases
130
+ modal changelog --last 3 # Show updates included in the 3 most recent releases
131
131
 
132
- modal changelog --for 1.3.1 # Show the changelog for a specific release
133
- ```
132
+ modal changelog --for 1.3.1 # Show the changelog for a specific release
133
+ ```
134
134
 
135
135
  Note: when using `--since` or `--last`, only changes up to the currently installed version are shown.
136
136
 
@@ -242,21 +242,21 @@ async def environment_billing(
242
242
 
243
243
  Examples:
244
244
 
245
- ```bash
246
- modal environment billing report --start 2025-12-01 --end 2026-01-01
245
+ ```bash
246
+ modal environment billing report --start 2025-12-01 --end 2026-01-01
247
247
 
248
- modal environment billing report --for "last month" --tag-names team,project
248
+ modal environment billing report --for "last month" --tag-names team,project
249
249
 
250
- modal environment billing report test_env --for today --resolution h
250
+ modal environment billing report test_env --for today --resolution h
251
251
 
252
- modal environment billing report test_env --for "this month" --show-resources
252
+ modal environment billing report test_env --for "this month" --show-resources
253
253
 
254
- modal environment billing report prod_env --for yesterday -r h --tz local
254
+ modal environment billing report prod_env --for yesterday -r h --tz local
255
255
 
256
- modal environment billing report main_env --for "last month" --csv > report.csv
256
+ modal environment billing report main_env --for "last month" --csv > report.csv
257
257
 
258
- modal environment billing report main_env --start 2025-12-01 --json > report.json
259
- ```
258
+ modal environment billing report main_env --start 2025-12-01 --json > report.json
259
+ ```
260
260
 
261
261
  """
262
262
  if json and csv:
@@ -35,7 +35,7 @@ class _Client:
35
35
  server_url: str,
36
36
  client_type: int,
37
37
  credentials: typing.Optional[tuple[str, str]],
38
- version: str = "1.5.2.dev22",
38
+ version: str = "1.5.3.dev1",
39
39
  ):
40
40
  """mdmd:hidden
41
41
  The Modal client object is not intended to be instantiated directly by users.
@@ -205,7 +205,7 @@ class Client:
205
205
  server_url: str,
206
206
  client_type: int,
207
207
  credentials: typing.Optional[tuple[str, str]],
208
- version: str = "1.5.2.dev22",
208
+ version: str = "1.5.3.dev1",
209
209
  ):
210
210
  """mdmd:hidden
211
211
  The Modal client object is not intended to be instantiated directly by users.
@@ -1,7 +1,7 @@
1
1
  # Copyright Modal Labs 2024
2
2
  import asyncio
3
3
  import platform
4
- from typing import BinaryIO, Generic, TypeVar
4
+ from typing import Generic, TypeVar
5
5
 
6
6
  from modal_proto import api_pb2
7
7
 
@@ -117,18 +117,6 @@ class _ContainerProcess(Generic[T]):
117
117
  )
118
118
  return self._returncode
119
119
 
120
- async def _stdin_write_stream(self, source: BinaryIO) -> int:
121
- """mdmd:hidden
122
- Stream `source` into the process's stdin and close it (EOF) on success.
123
-
124
- Returns the total bytes streamed.
125
- """
126
- return await self._command_router_client.exec_stdin_write_stream(
127
- task_id=self._task_id,
128
- exec_id=self._process_id,
129
- source=source,
130
- )
131
-
132
120
  async def poll(self) -> int | None:
133
121
  """Check if the container process has finished running.
134
122
 
@@ -53,14 +53,6 @@ class _ContainerProcess(typing.Generic[T]):
53
53
 
54
54
  @property
55
55
  def returncode(self) -> int: ...
56
- async def _stdin_write_stream(self, source: typing.BinaryIO) -> int:
57
- """mdmd:hidden
58
- Stream `source` into the process's stdin and close it (EOF) on success.
59
-
60
- Returns the total bytes streamed.
61
- """
62
- ...
63
-
64
56
  async def poll(self) -> typing.Optional[int]:
65
57
  """Check if the container process has finished running.
66
58
 
@@ -113,25 +105,6 @@ class ContainerProcess(typing.Generic[T]):
113
105
  @property
114
106
  def returncode(self) -> int: ...
115
107
 
116
- class ___stdin_write_stream_spec(typing_extensions.Protocol):
117
- def __call__(self, /, source: typing.BinaryIO) -> int:
118
- """mdmd:hidden
119
- Stream `source` into the process's stdin and close it (EOF) on success.
120
-
121
- Returns the total bytes streamed.
122
- """
123
- ...
124
-
125
- async def aio(self, /, source: typing.BinaryIO) -> int:
126
- """mdmd:hidden
127
- Stream `source` into the process's stdin and close it (EOF) on success.
128
-
129
- Returns the total bytes streamed.
130
- """
131
- ...
132
-
133
- _stdin_write_stream: ___stdin_write_stream_spec
134
-
135
108
  class __poll_spec(typing_extensions.Protocol):
136
109
  def __call__(self, /) -> typing.Optional[int]:
137
110
  """Check if the container process has finished running.
@@ -491,7 +491,7 @@ class Function(
491
491
 
492
492
  _call_generator: ___call_generator_spec
493
493
 
494
- class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
494
+ class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
495
495
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
496
496
  """Calls the function remotely, executing it with the given arguments and returning the execution's result.
497
497
 
@@ -516,7 +516,7 @@ class Function(
516
516
  """
517
517
  ...
518
518
 
519
- remote: __remote_spec[modal._functions.ReturnType, modal._functions.P]
519
+ remote: __remote_spec[modal._functions.P, modal._functions.ReturnType]
520
520
 
521
521
  class __remote_gen_spec(typing_extensions.Protocol):
522
522
  def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
@@ -566,7 +566,7 @@ class Function(
566
566
  """
567
567
  ...
568
568
 
569
- class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
569
+ class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
570
570
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
571
571
  """[Experimental] Calls the function with the given arguments, without waiting for the results.
572
572
 
@@ -599,7 +599,7 @@ class Function(
599
599
  """
600
600
  ...
601
601
 
602
- _experimental_spawn: ___experimental_spawn_spec[modal._functions.ReturnType, modal._functions.P]
602
+ _experimental_spawn: ___experimental_spawn_spec[modal._functions.P, modal._functions.ReturnType]
603
603
 
604
604
  class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER]):
605
605
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> None: ...
@@ -607,7 +607,7 @@ class Function(
607
607
 
608
608
  _spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P]
609
609
 
610
- class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
610
+ class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
611
611
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
612
612
  """Calls the function with the given arguments, without waiting for the results.
613
613
 
@@ -640,7 +640,7 @@ class Function(
640
640
  """
641
641
  ...
642
642
 
643
- spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P]
643
+ spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType]
644
644
 
645
645
  def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
646
646
  """Return the inner Python object wrapped by this Modal Function.