modal 1.4.4.dev1__tar.gz → 1.4.4.dev2__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 (214) hide show
  1. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/PKG-INFO +1 -1
  2. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/client.pyi +2 -2
  3. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/experimental/flash.py +14 -5
  4. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/experimental/flash.pyi +14 -0
  5. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/sandbox.py +53 -3
  6. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/sandbox.pyi +29 -6
  7. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal.egg-info/PKG-INFO +1 -1
  8. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_proto/api_grpc.py +16 -0
  9. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_proto/api_pb2.py +825 -785
  10. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_proto/api_pb2.pyi +87 -0
  11. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_proto/api_pb2_grpc.py +33 -0
  12. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_proto/api_pb2_grpc.pyi +10 -0
  13. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_proto/modal_api_grpc.py +1 -0
  14. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_version/__init__.py +1 -1
  15. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/LICENSE +0 -0
  16. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/README.md +0 -0
  17. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/__init__.py +0 -0
  18. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/__main__.py +0 -0
  19. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_billing.py +0 -0
  20. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_clustered_functions.py +0 -0
  21. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_clustered_functions.pyi +0 -0
  22. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_container_entrypoint.py +0 -0
  23. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_environments.py +0 -0
  24. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_function_variants.py +0 -0
  25. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_functions.py +0 -0
  26. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_grpc_client.py +0 -0
  27. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_ipython.py +0 -0
  28. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_load_context.py +0 -0
  29. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_location.py +0 -0
  30. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_logs.py +0 -0
  31. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_object.py +0 -0
  32. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_output/__init__.py +0 -0
  33. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_output/manager.py +0 -0
  34. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_output/pty.py +0 -0
  35. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_output/rich.py +0 -0
  36. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_output/status.py +0 -0
  37. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_partial_function.py +0 -0
  38. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_resolver.py +0 -0
  39. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_resources.py +0 -0
  40. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_runtime/__init__.py +0 -0
  41. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_runtime/asgi.py +0 -0
  42. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_runtime/container_io_manager.py +0 -0
  43. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_runtime/container_io_manager.pyi +0 -0
  44. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_runtime/execution_context.py +0 -0
  45. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_runtime/execution_context.pyi +0 -0
  46. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  47. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_runtime/telemetry.py +0 -0
  48. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_runtime/user_code_event_loop.py +0 -0
  49. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_runtime/user_code_imports.py +0 -0
  50. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_serialization.py +0 -0
  51. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_server.py +0 -0
  52. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_traceback.py +0 -0
  53. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_tunnel.py +0 -0
  54. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_tunnel.pyi +0 -0
  55. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_type_manager.py +0 -0
  56. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/__init__.py +0 -0
  57. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/app_utils.py +0 -0
  58. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/async_utils.py +0 -0
  59. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/auth_token_manager.py +0 -0
  60. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/blob_utils.py +0 -0
  61. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/browser_utils.py +0 -0
  62. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/bytes_io_segment_payload.py +0 -0
  63. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/deprecation.py +0 -0
  64. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/docker_utils.py +0 -0
  65. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/function_utils.py +0 -0
  66. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/git_utils.py +0 -0
  67. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/grpc_testing.py +0 -0
  68. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/grpc_utils.py +0 -0
  69. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/hash_utils.py +0 -0
  70. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/http_utils.py +0 -0
  71. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/jwt_utils.py +0 -0
  72. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/logger.py +0 -0
  73. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/mount_utils.py +0 -0
  74. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/name_utils.py +0 -0
  75. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/package_utils.py +0 -0
  76. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/pattern_utils.py +0 -0
  77. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/rand_pb_testing.py +0 -0
  78. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/sandbox_fs_utils.py +0 -0
  79. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/shell_utils.py +0 -0
  80. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/task_command_router_client.py +0 -0
  81. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_utils/time_utils.py +0 -0
  82. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_vendor/__init__.py +0 -0
  83. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  84. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_vendor/cloudpickle.py +0 -0
  85. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_vendor/tblib.py +0 -0
  86. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_vendor/version.py +0 -0
  87. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/_watcher.py +0 -0
  88. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/app.py +0 -0
  89. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/app.pyi +0 -0
  90. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/billing.py +0 -0
  91. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/builder/2023.12.312.txt +0 -0
  92. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/builder/2023.12.txt +0 -0
  93. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/builder/2024.04.txt +0 -0
  94. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/builder/2024.10.txt +0 -0
  95. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/builder/2025.06.txt +0 -0
  96. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/builder/PREVIEW.txt +0 -0
  97. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/builder/README.md +0 -0
  98. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/builder/base-images.json +0 -0
  99. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/call_graph.py +0 -0
  100. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/__init__.py +0 -0
  101. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/_download.py +0 -0
  102. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/_help.py +0 -0
  103. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/_traceback.py +0 -0
  104. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/app.py +0 -0
  105. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/billing.py +0 -0
  106. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/bootstrap.py +0 -0
  107. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/changelog.py +0 -0
  108. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/cluster.py +0 -0
  109. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/config.py +0 -0
  110. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/container.py +0 -0
  111. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/dashboard.py +0 -0
  112. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/dict.py +0 -0
  113. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/entry_point.py +0 -0
  114. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/environment.py +0 -0
  115. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/import_refs.py +0 -0
  116. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/launch.py +0 -0
  117. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/logo.py +0 -0
  118. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/network_file_system.py +0 -0
  119. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/profile.py +0 -0
  120. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/programs/__init__.py +0 -0
  121. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/programs/run_jupyter.py +0 -0
  122. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/programs/vscode.py +0 -0
  123. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/queues.py +0 -0
  124. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/run.py +0 -0
  125. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/secret.py +0 -0
  126. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/selector.py +0 -0
  127. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/shell.py +0 -0
  128. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/token.py +0 -0
  129. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/utils.py +0 -0
  130. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cli/volume.py +0 -0
  131. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/client.py +0 -0
  132. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cloud_bucket_mount.py +0 -0
  133. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cloud_bucket_mount.pyi +0 -0
  134. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cls.py +0 -0
  135. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/cls.pyi +0 -0
  136. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/config.py +0 -0
  137. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/container_process.py +0 -0
  138. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/container_process.pyi +0 -0
  139. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/dict.py +0 -0
  140. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/dict.pyi +0 -0
  141. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/environments.py +0 -0
  142. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/environments.pyi +0 -0
  143. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/exception.py +0 -0
  144. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/experimental/__init__.py +0 -0
  145. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/experimental/ipython.py +0 -0
  146. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/file_io.py +0 -0
  147. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/file_io.pyi +0 -0
  148. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/file_pattern_matcher.py +0 -0
  149. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/functions.py +0 -0
  150. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/functions.pyi +0 -0
  151. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/image.py +0 -0
  152. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/image.pyi +0 -0
  153. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/io_streams.py +0 -0
  154. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/io_streams.pyi +0 -0
  155. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/mount.py +0 -0
  156. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/mount.pyi +0 -0
  157. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/network_file_system.py +0 -0
  158. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/network_file_system.pyi +0 -0
  159. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/object.py +0 -0
  160. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/object.pyi +0 -0
  161. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/output.py +0 -0
  162. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/parallel_map.py +0 -0
  163. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/parallel_map.pyi +0 -0
  164. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/partial_function.py +0 -0
  165. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/partial_function.pyi +0 -0
  166. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/proxy.py +0 -0
  167. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/proxy.pyi +0 -0
  168. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/py.typed +0 -0
  169. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/queue.py +0 -0
  170. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/queue.pyi +0 -0
  171. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/retries.py +0 -0
  172. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/runner.py +0 -0
  173. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/runner.pyi +0 -0
  174. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/running_app.py +0 -0
  175. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/sandbox_fs.py +0 -0
  176. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/sandbox_fs.pyi +0 -0
  177. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/schedule.py +0 -0
  178. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/scheduler_placement.py +0 -0
  179. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/secret.py +0 -0
  180. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/secret.pyi +0 -0
  181. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/server.py +0 -0
  182. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/server.pyi +0 -0
  183. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/serving.py +0 -0
  184. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/serving.pyi +0 -0
  185. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/snapshot.py +0 -0
  186. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/snapshot.pyi +0 -0
  187. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/stream_type.py +0 -0
  188. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/token_flow.py +0 -0
  189. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/token_flow.pyi +0 -0
  190. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/volume.py +0 -0
  191. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal/volume.pyi +0 -0
  192. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal.egg-info/SOURCES.txt +0 -0
  193. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal.egg-info/dependency_links.txt +0 -0
  194. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal.egg-info/entry_points.txt +0 -0
  195. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal.egg-info/requires.txt +0 -0
  196. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal.egg-info/top_level.txt +0 -0
  197. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_docs/__init__.py +0 -0
  198. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_docs/gen_cli_docs.py +0 -0
  199. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_docs/gen_cli_docs_main.py +0 -0
  200. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_docs/gen_reference_docs.py +0 -0
  201. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_docs/gen_reference_docs_main.py +0 -0
  202. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_docs/mdmd/__init__.py +0 -0
  203. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_docs/mdmd/mdmd.py +0 -0
  204. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_docs/mdmd/signatures.py +0 -0
  205. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_proto/__init__.py +0 -0
  206. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_proto/py.typed +0 -0
  207. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_proto/task_command_router_grpc.py +0 -0
  208. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_proto/task_command_router_pb2.py +0 -0
  209. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_proto/task_command_router_pb2.pyi +0 -0
  210. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  211. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  212. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/modal_version/__main__.py +0 -0
  213. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/pyproject.toml +0 -0
  214. {modal-1.4.4.dev1 → modal-1.4.4.dev2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.4.4.dev1
3
+ Version: 1.4.4.dev2
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -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.4.4.dev1",
38
+ version: str = "1.4.4.dev2",
39
39
  ):
40
40
  """mdmd:hidden
41
41
  The Modal client object is not intended to be instantiated directly by users.
@@ -175,7 +175,7 @@ class Client:
175
175
  server_url: str,
176
176
  client_type: int,
177
177
  credentials: typing.Optional[tuple[str, str]],
178
- version: str = "1.4.4.dev1",
178
+ version: str = "1.4.4.dev2",
179
179
  ):
180
180
  """mdmd:hidden
181
181
  The Modal client object is not intended to be instantiated directly by users.
@@ -51,6 +51,7 @@ class _FlashManager:
51
51
  self.stopped = False
52
52
  self.num_heartbeat_failures = 0
53
53
  self.task_id = os.environ["MODAL_TASK_ID"]
54
+ self.heartbeat_task = None
54
55
 
55
56
  async def is_port_connection_healthy(
56
57
  self, process: Optional[subprocess.Popen], timeout: float = 0.5
@@ -86,13 +87,22 @@ class _FlashManager:
86
87
  host = parsed_url.hostname
87
88
  port = parsed_url.port or 443
88
89
 
90
+ if self.is_server:
91
+ await self._start_server_tunnel()
92
+ return
93
+ await self._start_flash_registration(host, port)
94
+
95
+ async def _start_server_tunnel(self) -> None:
96
+ # Worker-side HTTP relay owns Flash registration and drain for server tasks.
97
+ logger.warning(f"[Modal Flash] Server tunnel opened at {self.tunnel.url}.")
98
+
99
+ async def _start_flash_registration(self, host: str, port: int) -> None:
89
100
  try:
90
101
  await self._wait_for_port_success(host, port)
91
102
  except (Exception, KeyboardInterrupt, asyncio.CancelledError):
92
103
  await self._deregister()
93
104
  await self.tunnel_manager.__aexit__(*sys.exc_info())
94
105
  raise
95
-
96
106
  self.heartbeat_task = asyncio.create_task(self._run_heartbeat(host, port))
97
107
  self.drain_task = asyncio.create_task(self._drain_container())
98
108
 
@@ -209,16 +219,15 @@ class _FlashManager:
209
219
  if self.heartbeat_task:
210
220
  self.heartbeat_task.cancel()
211
221
  try:
222
+ # NOTE(gongy): We skip calling TunnelStop to avoid interrupting in-flight requests.
223
+ # It is up to the user to wait after calling .stop() to drain in-flight requests.
212
224
  await asyncio.wait_for(self.heartbeat_task, timeout=5)
225
+ logger.warning(f"[Modal Flash] Stopping heartbeat task on {self.tunnel.url}.")
213
226
  except (asyncio.TimeoutError, asyncio.CancelledError):
214
227
  logger.warning("[Modal Flash] Heartbeat task did not stop within 5s.")
215
228
  except Exception as e:
216
229
  logger.error(f"[Modal Flash] Error stopping: {e}")
217
230
  self.stopped = True
218
- logger.warning(f"[Modal Flash] No longer accepting new requests on {self.tunnel.url}.")
219
-
220
- # NOTE(gongy): We skip calling TunnelStop to avoid interrupting in-flight requests.
221
- # It is up to the user to wait after calling .stop() to drain in-flight requests.
222
231
 
223
232
  async def close(self):
224
233
  if not self.stopped:
@@ -23,6 +23,8 @@ class _FlashManager:
23
23
  self, process: typing.Optional[subprocess.Popen], timeout: float = 0.5
24
24
  ) -> tuple[bool, typing.Optional[Exception]]: ...
25
25
  async def _start(self): ...
26
+ async def _start_server_tunnel(self) -> None: ...
27
+ async def _start_flash_registration(self, host: str, port: int) -> None: ...
26
28
  async def _deregister(self): ...
27
29
  async def _drain_container(self):
28
30
  """Background task that checks if we've encountered too many failures and drains the container if so."""
@@ -63,6 +65,18 @@ class FlashManager:
63
65
 
64
66
  _start: ___start_spec
65
67
 
68
+ class ___start_server_tunnel_spec(typing_extensions.Protocol):
69
+ def __call__(self, /) -> None: ...
70
+ async def aio(self, /) -> None: ...
71
+
72
+ _start_server_tunnel: ___start_server_tunnel_spec
73
+
74
+ class ___start_flash_registration_spec(typing_extensions.Protocol):
75
+ def __call__(self, /, host: str, port: int) -> None: ...
76
+ async def aio(self, /, host: str, port: int) -> None: ...
77
+
78
+ _start_flash_registration: ___start_flash_registration_spec
79
+
66
80
  class ___deregister_spec(typing_extensions.Protocol):
67
81
  def __call__(self, /): ...
68
82
  async def aio(self, /): ...
@@ -1,6 +1,7 @@
1
1
  # Copyright Modal Labs 2022
2
2
  import asyncio
3
3
  import builtins
4
+ import enum
4
5
  import json
5
6
  import os
6
7
  import time
@@ -75,11 +76,47 @@ _default_image: _Image = _Image.debian_slim()
75
76
  # e.g. 'runsc exec ...'. So we use 2**16 as the limit.
76
77
  ARG_MAX_BYTES = 2**16
77
78
  TTL_NO_EXPIRY_SENTINEL = -1
79
+ _V1_SANDBOX_ID_ALPHABET = frozenset("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
80
+ _ULID_ALPHABET = frozenset("0123456789ABCDEFGHJKMNPQRSTVWXYZ")
78
81
 
79
82
  if TYPE_CHECKING:
80
83
  import modal.app
81
84
 
82
85
 
86
+ class SandboxVersion(enum.Enum):
87
+ V1 = 1
88
+ V2 = 2
89
+
90
+
91
+ def _is_v1_sandbox_id(sandbox_id: str) -> bool:
92
+ prefix, separator, suffix = sandbox_id.partition("-")
93
+ return (
94
+ prefix == "sb"
95
+ and separator == "-"
96
+ and len(suffix) == 22
97
+ and all(ch in _V1_SANDBOX_ID_ALPHABET for ch in suffix)
98
+ )
99
+
100
+
101
+ def _is_v2_sandbox_id(sandbox_id: str) -> bool:
102
+ prefix, separator, suffix = sandbox_id.partition("-")
103
+ return (
104
+ prefix == "sb"
105
+ and separator == "-"
106
+ and len(suffix) == 26
107
+ and suffix[0] in "01234567"
108
+ and all(ch in _ULID_ALPHABET for ch in suffix)
109
+ )
110
+
111
+
112
+ def _get_sandbox_version(sandbox_id: str) -> SandboxVersion:
113
+ if _is_v2_sandbox_id(sandbox_id):
114
+ return SandboxVersion.V2
115
+ if _is_v1_sandbox_id(sandbox_id):
116
+ return SandboxVersion.V1
117
+ raise InvalidError(f"Invalid Sandbox ID: {sandbox_id!r}")
118
+
119
+
83
120
  def _result_returncode(result: Optional[api_pb2.GenericResult]) -> Optional[int]:
84
121
  if result is None or result.status == api_pb2.GenericResult.GENERIC_STATUS_UNSPECIFIED:
85
122
  return None
@@ -675,6 +712,11 @@ class _Sandbox(_Object, type_prefix="sb"):
675
712
 
676
713
  Features like tags, memory snapshots, volumes, network file systems, GPUs,
677
714
  custom domains, OIDC identity tokens, and proxies are not supported.
715
+
716
+ V2 sandboxes created with this method are not currently returned by
717
+ `Sandbox.list()` and cannot be looked up with `Sandbox.from_name()`.
718
+ Store `sandbox.object_id` if you need to retrieve the sandbox later, and
719
+ use `Sandbox.from_id(sandbox.object_id)` to reattach.
678
720
  """
679
721
  from .app import _App
680
722
 
@@ -908,10 +950,18 @@ class _Sandbox(_Object, type_prefix="sb"):
908
950
  if client is None:
909
951
  client = await _Client.from_env()
910
952
 
953
+ sandbox_version = _get_sandbox_version(sandbox_id)
954
+ is_v2 = sandbox_version == SandboxVersion.V2
911
955
  req = api_pb2.SandboxWaitRequest(sandbox_id=sandbox_id, timeout=0)
912
- resp = await client.stub.SandboxWait(req)
956
+ if is_v2:
957
+ assert client._auth_token_manager
958
+ auth_token = await client._auth_token_manager.get_token()
959
+ resp = await client.stub.SandboxWaitV2(req, metadata=[("x-modal-auth-token", auth_token)])
960
+ else:
961
+ resp = await client.stub.SandboxWait(req)
913
962
 
914
963
  obj = _Sandbox._new_hydrated(sandbox_id, client, None)
964
+ obj._is_v2 = is_v2
915
965
 
916
966
  if resp.result.status:
917
967
  obj._result = resp.result
@@ -1000,7 +1050,7 @@ class _Sandbox(_Object, type_prefix="sb"):
1000
1050
  # You can later mount this snapshot to another Sandbox:
1001
1051
  sandbox_session_2 = modal.Sandbox.create(...)
1002
1052
  sandbox_session_2.mount_image("/user_project", user_project_snapshot)
1003
- sandbox_session_2.ls("/user_project")
1053
+ sandbox_session_2.filesystem.list_files("/user_project")
1004
1054
  ```
1005
1055
  """
1006
1056
  self._ensure_v1("mount_image")
@@ -1071,7 +1121,7 @@ class _Sandbox(_Object, type_prefix="sb"):
1071
1121
  # You can later mount this snapshot to another Sandbox:
1072
1122
  sandbox_session_2 = modal.Sandbox.create(...)
1073
1123
  sandbox_session_2.mount_image("/user_project", user_project_snapshot)
1074
- sandbox_session_2.ls("/user_project")
1124
+ sandbox_session_2.filesystem.list_files("/user_project")
1075
1125
  ```
1076
1126
  """
1077
1127
  self._ensure_v1("snapshot_directory")
@@ -1,5 +1,6 @@
1
1
  import _typeshed
2
2
  import collections.abc
3
+ import enum
3
4
  import google.protobuf.message
4
5
  import modal._object
5
6
  import modal._tunnel
@@ -27,6 +28,13 @@ import pathlib
27
28
  import typing
28
29
  import typing_extensions
29
30
 
31
+ class SandboxVersion(enum.Enum):
32
+ V1 = 1
33
+ V2 = 2
34
+
35
+ def _is_v1_sandbox_id(sandbox_id: str) -> bool: ...
36
+ def _is_v2_sandbox_id(sandbox_id: str) -> bool: ...
37
+ def _get_sandbox_version(sandbox_id: str) -> SandboxVersion: ...
30
38
  def _result_returncode(result: typing.Optional[modal_proto.api_pb2.GenericResult]) -> typing.Optional[int]: ...
31
39
  def _validate_exec_args(args: collections.abc.Sequence[str]) -> None: ...
32
40
 
@@ -333,6 +341,11 @@ class _Sandbox(modal._object._Object):
333
341
 
334
342
  Features like tags, memory snapshots, volumes, network file systems, GPUs,
335
343
  custom domains, OIDC identity tokens, and proxies are not supported.
344
+
345
+ V2 sandboxes created with this method are not currently returned by
346
+ `Sandbox.list()` and cannot be looked up with `Sandbox.from_name()`.
347
+ Store `sandbox.object_id` if you need to retrieve the sandbox later, and
348
+ use `Sandbox.from_id(sandbox.object_id)` to reattach.
336
349
  """
337
350
  ...
338
351
 
@@ -417,7 +430,7 @@ class _Sandbox(modal._object._Object):
417
430
  # You can later mount this snapshot to another Sandbox:
418
431
  sandbox_session_2 = modal.Sandbox.create(...)
419
432
  sandbox_session_2.mount_image("/user_project", user_project_snapshot)
420
- sandbox_session_2.ls("/user_project")
433
+ sandbox_session_2.filesystem.list_files("/user_project")
421
434
  ```
422
435
  """
423
436
  ...
@@ -443,7 +456,7 @@ class _Sandbox(modal._object._Object):
443
456
  # You can later mount this snapshot to another Sandbox:
444
457
  sandbox_session_2 = modal.Sandbox.create(...)
445
458
  sandbox_session_2.mount_image("/user_project", user_project_snapshot)
446
- sandbox_session_2.ls("/user_project")
459
+ sandbox_session_2.filesystem.list_files("/user_project")
447
460
  ```
448
461
  """
449
462
  ...
@@ -1219,6 +1232,11 @@ class Sandbox(modal.object.Object):
1219
1232
 
1220
1233
  Features like tags, memory snapshots, volumes, network file systems, GPUs,
1221
1234
  custom domains, OIDC identity tokens, and proxies are not supported.
1235
+
1236
+ V2 sandboxes created with this method are not currently returned by
1237
+ `Sandbox.list()` and cannot be looked up with `Sandbox.from_name()`.
1238
+ Store `sandbox.object_id` if you need to retrieve the sandbox later, and
1239
+ use `Sandbox.from_id(sandbox.object_id)` to reattach.
1222
1240
  """
1223
1241
  ...
1224
1242
 
@@ -1257,6 +1275,11 @@ class Sandbox(modal.object.Object):
1257
1275
 
1258
1276
  Features like tags, memory snapshots, volumes, network file systems, GPUs,
1259
1277
  custom domains, OIDC identity tokens, and proxies are not supported.
1278
+
1279
+ V2 sandboxes created with this method are not currently returned by
1280
+ `Sandbox.list()` and cannot be looked up with `Sandbox.from_name()`.
1281
+ Store `sandbox.object_id` if you need to retrieve the sandbox later, and
1282
+ use `Sandbox.from_id(sandbox.object_id)` to reattach.
1260
1283
  """
1261
1284
  ...
1262
1285
 
@@ -1420,7 +1443,7 @@ class Sandbox(modal.object.Object):
1420
1443
  # You can later mount this snapshot to another Sandbox:
1421
1444
  sandbox_session_2 = modal.Sandbox.create(...)
1422
1445
  sandbox_session_2.mount_image("/user_project", user_project_snapshot)
1423
- sandbox_session_2.ls("/user_project")
1446
+ sandbox_session_2.filesystem.list_files("/user_project")
1424
1447
  ```
1425
1448
  """
1426
1449
  ...
@@ -1445,7 +1468,7 @@ class Sandbox(modal.object.Object):
1445
1468
  # You can later mount this snapshot to another Sandbox:
1446
1469
  sandbox_session_2 = modal.Sandbox.create(...)
1447
1470
  sandbox_session_2.mount_image("/user_project", user_project_snapshot)
1448
- sandbox_session_2.ls("/user_project")
1471
+ sandbox_session_2.filesystem.list_files("/user_project")
1449
1472
  ```
1450
1473
  """
1451
1474
  ...
@@ -1486,7 +1509,7 @@ class Sandbox(modal.object.Object):
1486
1509
  # You can later mount this snapshot to another Sandbox:
1487
1510
  sandbox_session_2 = modal.Sandbox.create(...)
1488
1511
  sandbox_session_2.mount_image("/user_project", user_project_snapshot)
1489
- sandbox_session_2.ls("/user_project")
1512
+ sandbox_session_2.filesystem.list_files("/user_project")
1490
1513
  ```
1491
1514
  """
1492
1515
  ...
@@ -1503,7 +1526,7 @@ class Sandbox(modal.object.Object):
1503
1526
  # You can later mount this snapshot to another Sandbox:
1504
1527
  sandbox_session_2 = modal.Sandbox.create(...)
1505
1528
  sandbox_session_2.mount_image("/user_project", user_project_snapshot)
1506
- sandbox_session_2.ls("/user_project")
1529
+ sandbox_session_2.filesystem.list_files("/user_project")
1507
1530
  ```
1508
1531
  """
1509
1532
  ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.4.4.dev1
3
+ Version: 1.4.4.dev2
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -263,6 +263,10 @@ class ModalClientBase(abc.ABC):
263
263
  async def EndpointCreate(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.EndpointCreateRequest, modal_proto.api_pb2.EndpointCreateResponse]') -> None:
264
264
  pass
265
265
 
266
+ @abc.abstractmethod
267
+ async def EndpointList(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.EndpointListRequest, modal_proto.api_pb2.EndpointListResponse]') -> None:
268
+ pass
269
+
266
270
  @abc.abstractmethod
267
271
  async def EnvironmentCreate(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.EnvironmentCreateRequest, google.protobuf.empty_pb2.Empty]') -> None:
268
272
  pass
@@ -1183,6 +1187,12 @@ class ModalClientBase(abc.ABC):
1183
1187
  modal_proto.api_pb2.EndpointCreateRequest,
1184
1188
  modal_proto.api_pb2.EndpointCreateResponse,
1185
1189
  ),
1190
+ '/modal.client.ModalClient/EndpointList': grpclib.const.Handler(
1191
+ self.EndpointList,
1192
+ grpclib.const.Cardinality.UNARY_UNARY,
1193
+ modal_proto.api_pb2.EndpointListRequest,
1194
+ modal_proto.api_pb2.EndpointListResponse,
1195
+ ),
1186
1196
  '/modal.client.ModalClient/EnvironmentCreate': grpclib.const.Handler(
1187
1197
  self.EnvironmentCreate,
1188
1198
  grpclib.const.Cardinality.UNARY_UNARY,
@@ -2383,6 +2393,12 @@ class ModalClientStub:
2383
2393
  modal_proto.api_pb2.EndpointCreateRequest,
2384
2394
  modal_proto.api_pb2.EndpointCreateResponse,
2385
2395
  )
2396
+ self.EndpointList = grpclib.client.UnaryUnaryMethod(
2397
+ channel,
2398
+ '/modal.client.ModalClient/EndpointList',
2399
+ modal_proto.api_pb2.EndpointListRequest,
2400
+ modal_proto.api_pb2.EndpointListResponse,
2401
+ )
2386
2402
  self.EnvironmentCreate = grpclib.client.UnaryUnaryMethod(
2387
2403
  channel,
2388
2404
  '/modal.client.ModalClient/EnvironmentCreate',