modal 1.4.4.dev0__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.dev0 → modal-1.4.4.dev2}/PKG-INFO +1 -1
  2. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_runtime/user_code_imports.py +1 -1
  3. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_server.py +5 -2
  4. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/app.py +5 -4
  5. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/app.pyi +4 -4
  6. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/client.pyi +2 -2
  7. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/experimental/flash.py +26 -8
  8. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/experimental/flash.pyi +19 -1
  9. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/sandbox.py +60 -8
  10. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/sandbox.pyi +47 -12
  11. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/server.pyi +1 -1
  12. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal.egg-info/PKG-INFO +1 -1
  13. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_proto/api_grpc.py +16 -0
  14. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_proto/api_pb2.py +825 -785
  15. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_proto/api_pb2.pyi +87 -0
  16. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_proto/api_pb2_grpc.py +33 -0
  17. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_proto/api_pb2_grpc.pyi +10 -0
  18. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_proto/modal_api_grpc.py +1 -0
  19. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_version/__init__.py +1 -1
  20. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/LICENSE +0 -0
  21. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/README.md +0 -0
  22. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/__init__.py +0 -0
  23. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/__main__.py +0 -0
  24. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_billing.py +0 -0
  25. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_clustered_functions.py +0 -0
  26. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_clustered_functions.pyi +0 -0
  27. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_container_entrypoint.py +0 -0
  28. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_environments.py +0 -0
  29. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_function_variants.py +0 -0
  30. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_functions.py +0 -0
  31. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_grpc_client.py +0 -0
  32. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_ipython.py +0 -0
  33. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_load_context.py +0 -0
  34. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_location.py +0 -0
  35. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_logs.py +0 -0
  36. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_object.py +0 -0
  37. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_output/__init__.py +0 -0
  38. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_output/manager.py +0 -0
  39. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_output/pty.py +0 -0
  40. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_output/rich.py +0 -0
  41. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_output/status.py +0 -0
  42. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_partial_function.py +0 -0
  43. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_resolver.py +0 -0
  44. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_resources.py +0 -0
  45. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_runtime/__init__.py +0 -0
  46. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_runtime/asgi.py +0 -0
  47. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_runtime/container_io_manager.py +0 -0
  48. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_runtime/container_io_manager.pyi +0 -0
  49. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_runtime/execution_context.py +0 -0
  50. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_runtime/execution_context.pyi +0 -0
  51. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  52. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_runtime/telemetry.py +0 -0
  53. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_runtime/user_code_event_loop.py +0 -0
  54. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_serialization.py +0 -0
  55. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_traceback.py +0 -0
  56. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_tunnel.py +0 -0
  57. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_tunnel.pyi +0 -0
  58. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_type_manager.py +0 -0
  59. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/__init__.py +0 -0
  60. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/app_utils.py +0 -0
  61. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/async_utils.py +0 -0
  62. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/auth_token_manager.py +0 -0
  63. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/blob_utils.py +0 -0
  64. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/browser_utils.py +0 -0
  65. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/bytes_io_segment_payload.py +0 -0
  66. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/deprecation.py +0 -0
  67. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/docker_utils.py +0 -0
  68. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/function_utils.py +0 -0
  69. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/git_utils.py +0 -0
  70. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/grpc_testing.py +0 -0
  71. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/grpc_utils.py +0 -0
  72. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/hash_utils.py +0 -0
  73. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/http_utils.py +0 -0
  74. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/jwt_utils.py +0 -0
  75. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/logger.py +0 -0
  76. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/mount_utils.py +0 -0
  77. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/name_utils.py +0 -0
  78. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/package_utils.py +0 -0
  79. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/pattern_utils.py +0 -0
  80. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/rand_pb_testing.py +0 -0
  81. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/sandbox_fs_utils.py +0 -0
  82. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/shell_utils.py +0 -0
  83. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/task_command_router_client.py +0 -0
  84. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_utils/time_utils.py +0 -0
  85. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_vendor/__init__.py +0 -0
  86. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  87. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_vendor/cloudpickle.py +0 -0
  88. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_vendor/tblib.py +0 -0
  89. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_vendor/version.py +0 -0
  90. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/_watcher.py +0 -0
  91. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/billing.py +0 -0
  92. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/builder/2023.12.312.txt +0 -0
  93. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/builder/2023.12.txt +0 -0
  94. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/builder/2024.04.txt +0 -0
  95. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/builder/2024.10.txt +0 -0
  96. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/builder/2025.06.txt +0 -0
  97. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/builder/PREVIEW.txt +0 -0
  98. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/builder/README.md +0 -0
  99. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/builder/base-images.json +0 -0
  100. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/call_graph.py +0 -0
  101. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/__init__.py +0 -0
  102. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/_download.py +0 -0
  103. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/_help.py +0 -0
  104. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/_traceback.py +0 -0
  105. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/app.py +0 -0
  106. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/billing.py +0 -0
  107. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/bootstrap.py +0 -0
  108. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/changelog.py +0 -0
  109. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/cluster.py +0 -0
  110. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/config.py +0 -0
  111. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/container.py +0 -0
  112. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/dashboard.py +0 -0
  113. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/dict.py +0 -0
  114. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/entry_point.py +0 -0
  115. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/environment.py +0 -0
  116. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/import_refs.py +0 -0
  117. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/launch.py +0 -0
  118. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/logo.py +0 -0
  119. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/network_file_system.py +0 -0
  120. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/profile.py +0 -0
  121. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/programs/__init__.py +0 -0
  122. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/programs/run_jupyter.py +0 -0
  123. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/programs/vscode.py +0 -0
  124. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/queues.py +0 -0
  125. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/run.py +0 -0
  126. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/secret.py +0 -0
  127. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/selector.py +0 -0
  128. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/shell.py +0 -0
  129. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/token.py +0 -0
  130. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/utils.py +0 -0
  131. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cli/volume.py +0 -0
  132. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/client.py +0 -0
  133. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cloud_bucket_mount.py +0 -0
  134. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cloud_bucket_mount.pyi +0 -0
  135. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cls.py +0 -0
  136. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/cls.pyi +0 -0
  137. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/config.py +0 -0
  138. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/container_process.py +0 -0
  139. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/container_process.pyi +0 -0
  140. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/dict.py +0 -0
  141. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/dict.pyi +0 -0
  142. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/environments.py +0 -0
  143. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/environments.pyi +0 -0
  144. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/exception.py +0 -0
  145. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/experimental/__init__.py +0 -0
  146. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/experimental/ipython.py +0 -0
  147. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/file_io.py +0 -0
  148. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/file_io.pyi +0 -0
  149. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/file_pattern_matcher.py +0 -0
  150. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/functions.py +0 -0
  151. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/functions.pyi +0 -0
  152. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/image.py +0 -0
  153. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/image.pyi +0 -0
  154. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/io_streams.py +0 -0
  155. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/io_streams.pyi +0 -0
  156. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/mount.py +0 -0
  157. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/mount.pyi +0 -0
  158. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/network_file_system.py +0 -0
  159. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/network_file_system.pyi +0 -0
  160. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/object.py +0 -0
  161. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/object.pyi +0 -0
  162. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/output.py +0 -0
  163. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/parallel_map.py +0 -0
  164. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/parallel_map.pyi +0 -0
  165. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/partial_function.py +0 -0
  166. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/partial_function.pyi +0 -0
  167. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/proxy.py +0 -0
  168. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/proxy.pyi +0 -0
  169. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/py.typed +0 -0
  170. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/queue.py +0 -0
  171. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/queue.pyi +0 -0
  172. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/retries.py +0 -0
  173. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/runner.py +0 -0
  174. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/runner.pyi +0 -0
  175. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/running_app.py +0 -0
  176. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/sandbox_fs.py +0 -0
  177. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/sandbox_fs.pyi +0 -0
  178. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/schedule.py +0 -0
  179. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/scheduler_placement.py +0 -0
  180. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/secret.py +0 -0
  181. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/secret.pyi +0 -0
  182. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/server.py +0 -0
  183. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/serving.py +0 -0
  184. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/serving.pyi +0 -0
  185. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/snapshot.py +0 -0
  186. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/snapshot.pyi +0 -0
  187. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/stream_type.py +0 -0
  188. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/token_flow.py +0 -0
  189. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/token_flow.pyi +0 -0
  190. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/volume.py +0 -0
  191. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal/volume.pyi +0 -0
  192. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal.egg-info/SOURCES.txt +0 -0
  193. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal.egg-info/dependency_links.txt +0 -0
  194. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal.egg-info/entry_points.txt +0 -0
  195. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal.egg-info/requires.txt +0 -0
  196. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal.egg-info/top_level.txt +0 -0
  197. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_docs/__init__.py +0 -0
  198. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_docs/gen_cli_docs.py +0 -0
  199. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_docs/gen_cli_docs_main.py +0 -0
  200. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_docs/gen_reference_docs.py +0 -0
  201. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_docs/gen_reference_docs_main.py +0 -0
  202. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_docs/mdmd/__init__.py +0 -0
  203. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_docs/mdmd/mdmd.py +0 -0
  204. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_docs/mdmd/signatures.py +0 -0
  205. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_proto/__init__.py +0 -0
  206. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_proto/py.typed +0 -0
  207. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_proto/task_command_router_grpc.py +0 -0
  208. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_proto/task_command_router_pb2.py +0 -0
  209. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_proto/task_command_router_pb2.pyi +0 -0
  210. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  211. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  212. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/modal_version/__main__.py +0 -0
  213. {modal-1.4.4.dev0 → modal-1.4.4.dev2}/pyproject.toml +0 -0
  214. {modal-1.4.4.dev0 → 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.dev0
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
@@ -337,7 +337,7 @@ class _LifecycleManager:
337
337
  container_io_manager: "modal._runtime.container_io_manager.ContainerIOManager",
338
338
  ):
339
339
  # Identify the "enter" methods to run after resuming from a snapshot.
340
- flash_entry = _FlashContainerEntry(self.function_def.http_config)
340
+ flash_entry = _FlashContainerEntry(self.function_def.http_config, is_server=self.function_def.is_server)
341
341
  if not self.function_def.is_auto_snapshot:
342
342
  post_snapshot_methods = _find_callables_for_obj(
343
343
  self.user_cls_instance, _PartialFunctionFlags.ENTER_POST_SNAPSHOT
@@ -24,6 +24,7 @@ def validate_http_server_config(
24
24
  proxy_regions: list[str], # The regions to proxy the HTTP server to.
25
25
  startup_timeout: int, # Maximum number of seconds to wait for the HTTP server to start.
26
26
  exit_grace_period: Optional[int], # The time to wait for the HTTP server to exit gracefully.
27
+ is_server: bool = False, # Whether this validates a `_experimental_server` config.
27
28
  ):
28
29
  if not isinstance(port, int) or port < 1 or port > 65535:
29
30
  raise InvalidError("Port must be a positive integer between 1 and 65535.")
@@ -31,10 +32,12 @@ def validate_http_server_config(
31
32
  raise InvalidError("The `startup_timeout` argument must be positive.")
32
33
  if exit_grace_period is not None and exit_grace_period < 0:
33
34
  raise InvalidError("The `exit_grace_period` argument must be non-negative.")
34
- if exit_grace_period is not None and exit_grace_period > 25:
35
+ if not is_server and exit_grace_period is not None and exit_grace_period > 25:
35
36
  raise InvalidError("The `exit_grace_period` argument must not exceed 25 seconds.")
36
37
 
37
38
  if not proxy_regions:
39
+ if is_server:
40
+ raise InvalidError("The `routing_regions` argument must be non-empty.")
38
41
  raise InvalidError("The `proxy_regions` argument must be non-empty.")
39
42
 
40
43
 
@@ -47,7 +50,7 @@ class _Server:
47
50
  Instead, use the [`@app._experimental_server()`](https://modal.com/docs/reference/modal.App#server) decorator.
48
51
 
49
52
  ```python notest
50
- @app._experimental_server(port=8000, proxy_regions=["us-east", "us-west"])
53
+ @app._experimental_server(port=8000, routing_regions=["us-east", "us-west"])
51
54
  class MyServer:
52
55
  @modal.enter()
53
56
  def start_server(self):
@@ -1156,7 +1156,7 @@ class _App:
1156
1156
  port: int = 8000, # Port the HTTP server listens on
1157
1157
  startup_timeout: int = 30, # Maximum startup time in seconds
1158
1158
  exit_grace_period: int = 0, # Grace period for in-flight requests on shutdown
1159
- proxy_regions: Optional[Sequence[str]] = ["us-east"], # Required: Regions to deploy proxy endpoints
1159
+ routing_regions: list[str] = ["us-east"], # Required: Regions to deploy proxy endpoints
1160
1160
  h2_enabled: bool = False, # Enable HTTP/2
1161
1161
  target_concurrency: Optional[int] = None, # Target concurrency for the server
1162
1162
  cloud: Optional[str] = None, # Cloud provider (aws, gcp, oci, auto)
@@ -1178,7 +1178,7 @@ class _App:
1178
1178
  Example:
1179
1179
 
1180
1180
  ```python
1181
- @app._experimental_server(port=8000, proxy_regions=["us-east"])
1181
+ @app._experimental_server(port=8000, routing_regions=["us-east"])
1182
1182
  class MyServer:
1183
1183
  @modal.enter()
1184
1184
  def start(self):
@@ -1195,9 +1195,10 @@ class _App:
1195
1195
  # Validate HTTP server config
1196
1196
  validate_http_server_config(
1197
1197
  port=port,
1198
- proxy_regions=proxy_regions,
1198
+ proxy_regions=routing_regions,
1199
1199
  startup_timeout=startup_timeout,
1200
1200
  exit_grace_period=exit_grace_period,
1201
+ is_server=True,
1201
1202
  )
1202
1203
 
1203
1204
  if target_concurrency is not None:
@@ -1206,7 +1207,7 @@ class _App:
1206
1207
 
1207
1208
  http_config = api_pb2.HTTPConfig(
1208
1209
  port=port,
1209
- proxy_regions=proxy_regions,
1210
+ proxy_regions=routing_regions,
1210
1211
  startup_timeout=startup_timeout,
1211
1212
  exit_grace_period=exit_grace_period,
1212
1213
  h2_enabled=h2_enabled,
@@ -577,7 +577,7 @@ class _App:
577
577
  port: int = 8000,
578
578
  startup_timeout: int = 30,
579
579
  exit_grace_period: int = 0,
580
- proxy_regions: typing.Optional[collections.abc.Sequence[str]] = ["us-east"],
580
+ routing_regions: list[str] = ["us-east"],
581
581
  h2_enabled: bool = False,
582
582
  target_concurrency: typing.Optional[int] = None,
583
583
  cloud: typing.Optional[str] = None,
@@ -599,7 +599,7 @@ class _App:
599
599
  Example:
600
600
 
601
601
  ```python
602
- @app._experimental_server(port=8000, proxy_regions=["us-east"])
602
+ @app._experimental_server(port=8000, routing_regions=["us-east"])
603
603
  class MyServer:
604
604
  @modal.enter()
605
605
  def start(self):
@@ -1297,7 +1297,7 @@ class App:
1297
1297
  port: int = 8000,
1298
1298
  startup_timeout: int = 30,
1299
1299
  exit_grace_period: int = 0,
1300
- proxy_regions: typing.Optional[collections.abc.Sequence[str]] = ["us-east"],
1300
+ routing_regions: list[str] = ["us-east"],
1301
1301
  h2_enabled: bool = False,
1302
1302
  target_concurrency: typing.Optional[int] = None,
1303
1303
  cloud: typing.Optional[str] = None,
@@ -1317,7 +1317,7 @@ class App:
1317
1317
  Example:
1318
1318
 
1319
1319
  ```python
1320
- @app._experimental_server(port=8000, proxy_regions=["us-east"])
1320
+ @app._experimental_server(port=8000, routing_regions=["us-east"])
1321
1321
  class MyServer:
1322
1322
  @modal.enter()
1323
1323
  def start(self):
@@ -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.dev0",
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.dev0",
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.
@@ -37,6 +37,7 @@ class _FlashManager:
37
37
  startup_timeout: int = 30,
38
38
  exit_grace_period: int = 0,
39
39
  h2_enabled: bool = False,
40
+ is_server: bool = False,
40
41
  ):
41
42
  self.client = client
42
43
  self.port = port
@@ -46,9 +47,11 @@ class _FlashManager:
46
47
  self.startup_timeout = startup_timeout
47
48
  self.exit_grace_period = exit_grace_period
48
49
  self.tunnel_manager = _forward_tunnel(port, h2_enabled=h2_enabled, client=client)
50
+ self.is_server = is_server
49
51
  self.stopped = False
50
52
  self.num_heartbeat_failures = 0
51
53
  self.task_id = os.environ["MODAL_TASK_ID"]
54
+ self.heartbeat_task = None
52
55
 
53
56
  async def is_port_connection_healthy(
54
57
  self, process: Optional[subprocess.Popen], timeout: float = 0.5
@@ -84,13 +87,22 @@ class _FlashManager:
84
87
  host = parsed_url.hostname
85
88
  port = parsed_url.port or 443
86
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:
87
100
  try:
88
101
  await self._wait_for_port_success(host, port)
89
102
  except (Exception, KeyboardInterrupt, asyncio.CancelledError):
90
103
  await self._deregister()
91
104
  await self.tunnel_manager.__aexit__(*sys.exc_info())
92
105
  raise
93
-
94
106
  self.heartbeat_task = asyncio.create_task(self._run_heartbeat(host, port))
95
107
  self.drain_task = asyncio.create_task(self._drain_container())
96
108
 
@@ -207,22 +219,24 @@ class _FlashManager:
207
219
  if self.heartbeat_task:
208
220
  self.heartbeat_task.cancel()
209
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.
210
224
  await asyncio.wait_for(self.heartbeat_task, timeout=5)
225
+ logger.warning(f"[Modal Flash] Stopping heartbeat task on {self.tunnel.url}.")
211
226
  except (asyncio.TimeoutError, asyncio.CancelledError):
212
227
  logger.warning("[Modal Flash] Heartbeat task did not stop within 5s.")
213
228
  except Exception as e:
214
229
  logger.error(f"[Modal Flash] Error stopping: {e}")
215
230
  self.stopped = True
216
- logger.warning(f"[Modal Flash] No longer accepting new requests on {self.tunnel.url}.")
217
-
218
- # NOTE(gongy): We skip calling TunnelStop to avoid interrupting in-flight requests.
219
- # It is up to the user to wait after calling .stop() to drain in-flight requests.
220
231
 
221
232
  async def close(self):
222
233
  if not self.stopped:
223
234
  await self.stop()
224
235
 
225
- await asyncio.sleep(self.exit_grace_period)
236
+ # Server tasks drain via the worker-side HTTP relay, so skip the
237
+ # Python-side sleep here to avoid double-counting the grace period.
238
+ if not self.is_server:
239
+ await asyncio.sleep(self.exit_grace_period)
226
240
 
227
241
  logger.warning(f"[Modal Flash] Closing tunnel on {self.tunnel.url}.")
228
242
  await self.tunnel_manager.__aexit__(*sys.exc_info())
@@ -239,6 +253,7 @@ async def flash_forward(
239
253
  startup_timeout: int = 30,
240
254
  exit_grace_period: int = 0,
241
255
  h2_enabled: bool = False,
256
+ is_server: bool = False,
242
257
  ) -> _FlashManager:
243
258
  """
244
259
  Forward a port to the Modal Flash service, exposing that port as a stable endpoint.
@@ -255,6 +270,7 @@ async def flash_forward(
255
270
  startup_timeout=startup_timeout,
256
271
  exit_grace_period=exit_grace_period,
257
272
  h2_enabled=h2_enabled,
273
+ is_server=is_server,
258
274
  )
259
275
  await manager._start()
260
276
  return manager
@@ -716,7 +732,7 @@ def _http_server(
716
732
  raise InvalidError(
717
733
  "Positional arguments are not allowed. Did you forget parentheses? Suggestion: `@modal.http_server()`."
718
734
  )
719
- validate_http_server_config(port, proxy_regions, startup_timeout, exit_grace_period)
735
+ validate_http_server_config(port, proxy_regions, startup_timeout, exit_grace_period, is_server=False)
720
736
 
721
737
  from modal._partial_function import _PartialFunction, _PartialFunctionParams
722
738
 
@@ -757,9 +773,10 @@ class _FlashContainerEntry:
757
773
 
758
774
  flash_manager: Optional[FlashManager] # type: ignore
759
775
 
760
- def __init__(self, http_config: api_pb2.HTTPConfig):
776
+ def __init__(self, http_config: api_pb2.HTTPConfig, is_server: bool = False):
761
777
  self.http_config: api_pb2.HTTPConfig = http_config
762
778
  self.flash_manager = None
779
+ self.is_server = is_server
763
780
 
764
781
  def enter(self):
765
782
  if self.http_config != api_pb2.HTTPConfig():
@@ -775,6 +792,7 @@ class _FlashContainerEntry:
775
792
  startup_timeout=self.http_config.startup_timeout,
776
793
  exit_grace_period=self.http_config.exit_grace_period,
777
794
  h2_enabled=self.http_config.h2_enabled,
795
+ is_server=self.is_server,
778
796
  )
779
797
  except Exception as e:
780
798
  logger.warning(f"[Modal Flash] Startup failed: {e}")
@@ -14,6 +14,7 @@ class _FlashManager:
14
14
  startup_timeout: int = 30,
15
15
  exit_grace_period: int = 0,
16
16
  h2_enabled: bool = False,
17
+ is_server: bool = False,
17
18
  ):
18
19
  """Initialize self. See help(type(self)) for accurate signature."""
19
20
  ...
@@ -22,6 +23,8 @@ class _FlashManager:
22
23
  self, process: typing.Optional[subprocess.Popen], timeout: float = 0.5
23
24
  ) -> tuple[bool, typing.Optional[Exception]]: ...
24
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: ...
25
28
  async def _deregister(self): ...
26
29
  async def _drain_container(self):
27
30
  """Background task that checks if we've encountered too many failures and drains the container if so."""
@@ -43,6 +46,7 @@ class FlashManager:
43
46
  startup_timeout: int = 30,
44
47
  exit_grace_period: int = 0,
45
48
  h2_enabled: bool = False,
49
+ is_server: bool = False,
46
50
  ): ...
47
51
 
48
52
  class __is_port_connection_healthy_spec(typing_extensions.Protocol):
@@ -61,6 +65,18 @@ class FlashManager:
61
65
 
62
66
  _start: ___start_spec
63
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
+
64
80
  class ___deregister_spec(typing_extensions.Protocol):
65
81
  def __call__(self, /): ...
66
82
  async def aio(self, /): ...
@@ -114,6 +130,7 @@ class __flash_forward_spec(typing_extensions.Protocol):
114
130
  startup_timeout: int = 30,
115
131
  exit_grace_period: int = 0,
116
132
  h2_enabled: bool = False,
133
+ is_server: bool = False,
117
134
  ) -> FlashManager:
118
135
  """Forward a port to the Modal Flash service, exposing that port as a stable endpoint.
119
136
  This is a highly experimental method that can break or be removed at any time without warning.
@@ -130,6 +147,7 @@ class __flash_forward_spec(typing_extensions.Protocol):
130
147
  startup_timeout: int = 30,
131
148
  exit_grace_period: int = 0,
132
149
  h2_enabled: bool = False,
150
+ is_server: bool = False,
133
151
  ) -> FlashManager:
134
152
  """Forward a port to the Modal Flash service, exposing that port as a stable endpoint.
135
153
  This is a highly experimental method that can break or be removed at any time without warning.
@@ -450,7 +468,7 @@ class _FlashContainerEntry:
450
468
 
451
469
  flash_manager: typing.Optional[FlashManager]
452
470
 
453
- def __init__(self, http_config: modal_proto.api_pb2.HTTPConfig):
471
+ def __init__(self, http_config: modal_proto.api_pb2.HTTPConfig, is_server: bool = False):
454
472
  """Initialize self. See help(type(self)) for accurate signature."""
455
473
  ...
456
474
 
@@ -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
@@ -669,8 +706,17 @@ class _Sandbox(_Object, type_prefix="sb"):
669
706
  ) -> "_Sandbox":
670
707
  """Create a sandbox using the V2 backend.
671
708
 
672
- Features like tags, snapshots, exec, volumes, network file systems,
673
- GPUs, custom domains, and proxies are not supported.
709
+ Supported features include exec, encrypted tunnels, wait/poll/terminate,
710
+ CPU and memory configuration, region placement,
711
+ and filesystem snapshots.
712
+
713
+ Features like tags, memory snapshots, volumes, network file systems, GPUs,
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.
674
720
  """
675
721
  from .app import _App
676
722
 
@@ -904,10 +950,18 @@ class _Sandbox(_Object, type_prefix="sb"):
904
950
  if client is None:
905
951
  client = await _Client.from_env()
906
952
 
953
+ sandbox_version = _get_sandbox_version(sandbox_id)
954
+ is_v2 = sandbox_version == SandboxVersion.V2
907
955
  req = api_pb2.SandboxWaitRequest(sandbox_id=sandbox_id, timeout=0)
908
- 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)
909
962
 
910
963
  obj = _Sandbox._new_hydrated(sandbox_id, client, None)
964
+ obj._is_v2 = is_v2
911
965
 
912
966
  if resp.result.status:
913
967
  obj._result = resp.result
@@ -951,11 +1005,9 @@ class _Sandbox(_Object, type_prefix="sb"):
951
1005
  `timeout` If the snapshot does not return within that window, the call is cancelled
952
1006
  and `modal.exception.TimeoutError` is raised.
953
1007
  """
954
- if os.environ.get("MODAL_USE_LEGACY_FILESYSTEM_SNAPSHOT") == "1":
1008
+ if os.environ.get("MODAL_USE_LEGACY_FILESYSTEM_SNAPSHOT") == "1" and not self._is_v2:
955
1009
  return await self._legacy_snapshot_filesystem(timeout)
956
1010
 
957
- self._ensure_v1("snapshot_filesystem")
958
-
959
1011
  task_id = await self._get_task_id()
960
1012
  command_router_client = await self._get_command_router_client(task_id)
961
1013
 
@@ -998,7 +1050,7 @@ class _Sandbox(_Object, type_prefix="sb"):
998
1050
  # You can later mount this snapshot to another Sandbox:
999
1051
  sandbox_session_2 = modal.Sandbox.create(...)
1000
1052
  sandbox_session_2.mount_image("/user_project", user_project_snapshot)
1001
- sandbox_session_2.ls("/user_project")
1053
+ sandbox_session_2.filesystem.list_files("/user_project")
1002
1054
  ```
1003
1055
  """
1004
1056
  self._ensure_v1("mount_image")
@@ -1069,7 +1121,7 @@ class _Sandbox(_Object, type_prefix="sb"):
1069
1121
  # You can later mount this snapshot to another Sandbox:
1070
1122
  sandbox_session_2 = modal.Sandbox.create(...)
1071
1123
  sandbox_session_2.mount_image("/user_project", user_project_snapshot)
1072
- sandbox_session_2.ls("/user_project")
1124
+ sandbox_session_2.filesystem.list_files("/user_project")
1073
1125
  ```
1074
1126
  """
1075
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
 
@@ -327,8 +335,17 @@ class _Sandbox(modal._object._Object):
327
335
  ) -> _Sandbox:
328
336
  """Create a sandbox using the V2 backend.
329
337
 
330
- Features like tags, snapshots, exec, volumes, network file systems,
331
- GPUs, custom domains, and proxies are not supported.
338
+ Supported features include exec, encrypted tunnels, wait/poll/terminate,
339
+ CPU and memory configuration, region placement,
340
+ and filesystem snapshots.
341
+
342
+ Features like tags, memory snapshots, volumes, network file systems, GPUs,
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.
332
349
  """
333
350
  ...
334
351
 
@@ -413,7 +430,7 @@ class _Sandbox(modal._object._Object):
413
430
  # You can later mount this snapshot to another Sandbox:
414
431
  sandbox_session_2 = modal.Sandbox.create(...)
415
432
  sandbox_session_2.mount_image("/user_project", user_project_snapshot)
416
- sandbox_session_2.ls("/user_project")
433
+ sandbox_session_2.filesystem.list_files("/user_project")
417
434
  ```
418
435
  """
419
436
  ...
@@ -439,7 +456,7 @@ class _Sandbox(modal._object._Object):
439
456
  # You can later mount this snapshot to another Sandbox:
440
457
  sandbox_session_2 = modal.Sandbox.create(...)
441
458
  sandbox_session_2.mount_image("/user_project", user_project_snapshot)
442
- sandbox_session_2.ls("/user_project")
459
+ sandbox_session_2.filesystem.list_files("/user_project")
443
460
  ```
444
461
  """
445
462
  ...
@@ -1209,8 +1226,17 @@ class Sandbox(modal.object.Object):
1209
1226
  ) -> Sandbox:
1210
1227
  """Create a sandbox using the V2 backend.
1211
1228
 
1212
- Features like tags, snapshots, exec, volumes, network file systems,
1213
- GPUs, custom domains, and proxies are not supported.
1229
+ Supported features include exec, encrypted tunnels, wait/poll/terminate,
1230
+ CPU and memory configuration, region placement,
1231
+ and filesystem snapshots.
1232
+
1233
+ Features like tags, memory snapshots, volumes, network file systems, GPUs,
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.
1214
1240
  """
1215
1241
  ...
1216
1242
 
@@ -1243,8 +1269,17 @@ class Sandbox(modal.object.Object):
1243
1269
  ) -> Sandbox:
1244
1270
  """Create a sandbox using the V2 backend.
1245
1271
 
1246
- Features like tags, snapshots, exec, volumes, network file systems,
1247
- GPUs, custom domains, and proxies are not supported.
1272
+ Supported features include exec, encrypted tunnels, wait/poll/terminate,
1273
+ CPU and memory configuration, region placement,
1274
+ and filesystem snapshots.
1275
+
1276
+ Features like tags, memory snapshots, volumes, network file systems, GPUs,
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.
1248
1283
  """
1249
1284
  ...
1250
1285
 
@@ -1408,7 +1443,7 @@ class Sandbox(modal.object.Object):
1408
1443
  # You can later mount this snapshot to another Sandbox:
1409
1444
  sandbox_session_2 = modal.Sandbox.create(...)
1410
1445
  sandbox_session_2.mount_image("/user_project", user_project_snapshot)
1411
- sandbox_session_2.ls("/user_project")
1446
+ sandbox_session_2.filesystem.list_files("/user_project")
1412
1447
  ```
1413
1448
  """
1414
1449
  ...
@@ -1433,7 +1468,7 @@ class Sandbox(modal.object.Object):
1433
1468
  # You can later mount this snapshot to another Sandbox:
1434
1469
  sandbox_session_2 = modal.Sandbox.create(...)
1435
1470
  sandbox_session_2.mount_image("/user_project", user_project_snapshot)
1436
- sandbox_session_2.ls("/user_project")
1471
+ sandbox_session_2.filesystem.list_files("/user_project")
1437
1472
  ```
1438
1473
  """
1439
1474
  ...
@@ -1474,7 +1509,7 @@ class Sandbox(modal.object.Object):
1474
1509
  # You can later mount this snapshot to another Sandbox:
1475
1510
  sandbox_session_2 = modal.Sandbox.create(...)
1476
1511
  sandbox_session_2.mount_image("/user_project", user_project_snapshot)
1477
- sandbox_session_2.ls("/user_project")
1512
+ sandbox_session_2.filesystem.list_files("/user_project")
1478
1513
  ```
1479
1514
  """
1480
1515
  ...
@@ -1491,7 +1526,7 @@ class Sandbox(modal.object.Object):
1491
1526
  # You can later mount this snapshot to another Sandbox:
1492
1527
  sandbox_session_2 = modal.Sandbox.create(...)
1493
1528
  sandbox_session_2.mount_image("/user_project", user_project_snapshot)
1494
- sandbox_session_2.ls("/user_project")
1529
+ sandbox_session_2.filesystem.list_files("/user_project")
1495
1530
  ```
1496
1531
  """
1497
1532
  ...
@@ -14,7 +14,7 @@ class Server:
14
14
  Instead, use the [`@app._experimental_server()`](https://modal.com/docs/reference/modal.App#server) decorator.
15
15
 
16
16
  ```python notest
17
- @app._experimental_server(port=8000, proxy_regions=["us-east", "us-west"])
17
+ @app._experimental_server(port=8000, routing_regions=["us-east", "us-west"])
18
18
  class MyServer:
19
19
  @modal.enter()
20
20
  def start_server(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.4.4.dev0
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',