modal 1.4.3.dev5__tar.gz → 1.4.3.dev7__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 (212) hide show
  1. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/PKG-INFO +1 -1
  2. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/async_utils.py +1 -1
  3. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/sandbox_fs_utils.py +60 -30
  4. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/client.pyi +2 -2
  5. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/exception.py +4 -4
  6. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/file_io.py +1 -1
  7. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/sandbox.py +38 -30
  8. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/sandbox.pyi +15 -3
  9. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/sandbox_fs.py +242 -146
  10. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/sandbox_fs.pyi +375 -233
  11. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal.egg-info/PKG-INFO +1 -1
  12. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_proto/api_pb2.py +396 -394
  13. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_proto/api_pb2.pyi +1 -4
  14. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_proto/task_command_router_pb2.py +14 -14
  15. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_proto/task_command_router_pb2.pyi +5 -1
  16. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_version/__init__.py +1 -1
  17. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/LICENSE +0 -0
  18. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/README.md +0 -0
  19. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/__init__.py +0 -0
  20. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/__main__.py +0 -0
  21. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_billing.py +0 -0
  22. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_clustered_functions.py +0 -0
  23. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_clustered_functions.pyi +0 -0
  24. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_container_entrypoint.py +0 -0
  25. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_functions.py +0 -0
  26. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_grpc_client.py +0 -0
  27. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_ipython.py +0 -0
  28. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_load_context.py +0 -0
  29. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_location.py +0 -0
  30. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_logs.py +0 -0
  31. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_object.py +0 -0
  32. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_output/__init__.py +0 -0
  33. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_output/manager.py +0 -0
  34. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_output/pty.py +0 -0
  35. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_output/rich.py +0 -0
  36. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_output/status.py +0 -0
  37. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_partial_function.py +0 -0
  38. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_resolver.py +0 -0
  39. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_resources.py +0 -0
  40. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_runtime/__init__.py +0 -0
  41. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_runtime/asgi.py +0 -0
  42. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_runtime/container_io_manager.py +0 -0
  43. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_runtime/container_io_manager.pyi +0 -0
  44. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_runtime/execution_context.py +0 -0
  45. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_runtime/execution_context.pyi +0 -0
  46. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  47. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_runtime/telemetry.py +0 -0
  48. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_runtime/user_code_event_loop.py +0 -0
  49. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_runtime/user_code_imports.py +0 -0
  50. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_serialization.py +0 -0
  51. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_server.py +0 -0
  52. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_traceback.py +0 -0
  53. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_tunnel.py +0 -0
  54. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_tunnel.pyi +0 -0
  55. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_type_manager.py +0 -0
  56. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/__init__.py +0 -0
  57. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/app_utils.py +0 -0
  58. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/auth_token_manager.py +0 -0
  59. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/blob_utils.py +0 -0
  60. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/browser_utils.py +0 -0
  61. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/bytes_io_segment_payload.py +0 -0
  62. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/deprecation.py +0 -0
  63. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/docker_utils.py +0 -0
  64. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/function_utils.py +0 -0
  65. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/git_utils.py +0 -0
  66. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/grpc_testing.py +0 -0
  67. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/grpc_utils.py +0 -0
  68. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/hash_utils.py +0 -0
  69. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/http_utils.py +0 -0
  70. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/jwt_utils.py +0 -0
  71. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/logger.py +0 -0
  72. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/mount_utils.py +0 -0
  73. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/name_utils.py +0 -0
  74. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/package_utils.py +0 -0
  75. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/pattern_utils.py +0 -0
  76. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/rand_pb_testing.py +0 -0
  77. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/shell_utils.py +0 -0
  78. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/task_command_router_client.py +0 -0
  79. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_utils/time_utils.py +0 -0
  80. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_vendor/__init__.py +0 -0
  81. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  82. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_vendor/cloudpickle.py +0 -0
  83. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_vendor/tblib.py +0 -0
  84. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_vendor/version.py +0 -0
  85. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/_watcher.py +0 -0
  86. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/app.py +0 -0
  87. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/app.pyi +0 -0
  88. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/billing.py +0 -0
  89. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/builder/2023.12.312.txt +0 -0
  90. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/builder/2023.12.txt +0 -0
  91. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/builder/2024.04.txt +0 -0
  92. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/builder/2024.10.txt +0 -0
  93. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/builder/2025.06.txt +0 -0
  94. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/builder/PREVIEW.txt +0 -0
  95. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/builder/README.md +0 -0
  96. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/builder/base-images.json +0 -0
  97. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/call_graph.py +0 -0
  98. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/__init__.py +0 -0
  99. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/_download.py +0 -0
  100. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/_help.py +0 -0
  101. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/_traceback.py +0 -0
  102. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/app.py +0 -0
  103. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/billing.py +0 -0
  104. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/bootstrap.py +0 -0
  105. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/changelog.py +0 -0
  106. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/cluster.py +0 -0
  107. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/config.py +0 -0
  108. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/container.py +0 -0
  109. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/dashboard.py +0 -0
  110. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/dict.py +0 -0
  111. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/entry_point.py +0 -0
  112. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/environment.py +0 -0
  113. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/import_refs.py +0 -0
  114. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/launch.py +0 -0
  115. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/logo.py +0 -0
  116. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/network_file_system.py +0 -0
  117. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/profile.py +0 -0
  118. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/programs/__init__.py +0 -0
  119. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/programs/run_jupyter.py +0 -0
  120. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/programs/vscode.py +0 -0
  121. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/queues.py +0 -0
  122. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/run.py +0 -0
  123. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/secret.py +0 -0
  124. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/selector.py +0 -0
  125. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/shell.py +0 -0
  126. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/token.py +0 -0
  127. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/utils.py +0 -0
  128. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cli/volume.py +0 -0
  129. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/client.py +0 -0
  130. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cloud_bucket_mount.py +0 -0
  131. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cloud_bucket_mount.pyi +0 -0
  132. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cls.py +0 -0
  133. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/cls.pyi +0 -0
  134. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/config.py +0 -0
  135. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/container_process.py +0 -0
  136. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/container_process.pyi +0 -0
  137. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/dict.py +0 -0
  138. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/dict.pyi +0 -0
  139. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/environments.py +0 -0
  140. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/environments.pyi +0 -0
  141. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/experimental/__init__.py +0 -0
  142. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/experimental/flash.py +0 -0
  143. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/experimental/flash.pyi +0 -0
  144. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/experimental/ipython.py +0 -0
  145. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/file_io.pyi +0 -0
  146. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/file_pattern_matcher.py +0 -0
  147. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/functions.py +0 -0
  148. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/functions.pyi +0 -0
  149. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/image.py +0 -0
  150. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/image.pyi +0 -0
  151. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/io_streams.py +0 -0
  152. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/io_streams.pyi +0 -0
  153. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/mount.py +0 -0
  154. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/mount.pyi +0 -0
  155. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/network_file_system.py +0 -0
  156. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/network_file_system.pyi +0 -0
  157. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/object.py +0 -0
  158. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/object.pyi +0 -0
  159. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/output.py +0 -0
  160. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/parallel_map.py +0 -0
  161. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/parallel_map.pyi +0 -0
  162. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/partial_function.py +0 -0
  163. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/partial_function.pyi +0 -0
  164. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/proxy.py +0 -0
  165. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/proxy.pyi +0 -0
  166. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/py.typed +0 -0
  167. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/queue.py +0 -0
  168. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/queue.pyi +0 -0
  169. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/retries.py +0 -0
  170. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/runner.py +0 -0
  171. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/runner.pyi +0 -0
  172. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/running_app.py +0 -0
  173. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/schedule.py +0 -0
  174. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/scheduler_placement.py +0 -0
  175. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/secret.py +0 -0
  176. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/secret.pyi +0 -0
  177. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/server.py +0 -0
  178. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/server.pyi +0 -0
  179. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/serving.py +0 -0
  180. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/serving.pyi +0 -0
  181. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/snapshot.py +0 -0
  182. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/snapshot.pyi +0 -0
  183. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/stream_type.py +0 -0
  184. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/token_flow.py +0 -0
  185. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/token_flow.pyi +0 -0
  186. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/volume.py +0 -0
  187. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal/volume.pyi +0 -0
  188. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal.egg-info/SOURCES.txt +0 -0
  189. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal.egg-info/dependency_links.txt +0 -0
  190. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal.egg-info/entry_points.txt +0 -0
  191. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal.egg-info/requires.txt +0 -0
  192. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal.egg-info/top_level.txt +0 -0
  193. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_docs/__init__.py +0 -0
  194. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_docs/gen_cli_docs.py +0 -0
  195. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_docs/gen_cli_docs_main.py +0 -0
  196. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_docs/gen_reference_docs.py +0 -0
  197. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_docs/gen_reference_docs_main.py +0 -0
  198. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_docs/mdmd/__init__.py +0 -0
  199. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_docs/mdmd/mdmd.py +0 -0
  200. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_docs/mdmd/signatures.py +0 -0
  201. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_proto/__init__.py +0 -0
  202. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_proto/api_grpc.py +0 -0
  203. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_proto/api_pb2_grpc.py +0 -0
  204. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_proto/api_pb2_grpc.pyi +0 -0
  205. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_proto/modal_api_grpc.py +0 -0
  206. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_proto/py.typed +0 -0
  207. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_proto/task_command_router_grpc.py +0 -0
  208. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  209. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  210. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/modal_version/__main__.py +0 -0
  211. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/pyproject.toml +0 -0
  212. {modal-1.4.3.dev5 → modal-1.4.3.dev7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.4.3.dev5
3
+ Version: 1.4.3.dev7
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -1115,7 +1115,7 @@ async def async_merge(
1115
1115
  new_output_task = asyncio.create_task(queue.get())
1116
1116
 
1117
1117
  finally:
1118
- unfinished_tasks = [t for t in tasks | {new_output_task} if not t.done()]
1118
+ unfinished_tasks: list[asyncio.Task[Any]] = [t for t in tasks | {new_output_task} if not t.done()]
1119
1119
  for t in unfinished_tasks:
1120
1120
  t.cancel()
1121
1121
  try:
@@ -60,27 +60,6 @@ def try_parse_error_payload(stderr: Union[str, bytes]) -> Optional[ErrorPayload]
60
60
  return ErrorPayload(error_kind=error_kind, message=message, detail=detail)
61
61
 
62
62
 
63
- def raise_read_file_error(returncode: int, stderr: Union[str, bytes], remote_path: str) -> NoReturn:
64
- if payload := try_parse_error_payload(stderr):
65
- logger.debug(
66
- f"sandbox-fs-tools read error: path={remote_path}, "
67
- f"error_kind={payload.error_kind}, message={payload.message}, detail={payload.detail}"
68
- )
69
- if payload.error_kind == "NotFound":
70
- raise SandboxFilesystemNotFoundError(f"{payload.message}: {remote_path}")
71
- if payload.error_kind == "IsDirectory":
72
- raise SandboxFilesystemIsADirectoryError(f"{payload.message}: {remote_path}")
73
- if payload.error_kind == "PermissionDenied":
74
- raise SandboxFilesystemPermissionError(f"{payload.message}: {remote_path}")
75
- if payload.error_kind == "FileTooLarge":
76
- raise SandboxFilesystemFileTooLargeError(f"{payload.message}: {remote_path}")
77
- raise SandboxFilesystemError(payload.message)
78
-
79
- if stderr_text := _stderr_to_text(stderr):
80
- logger.debug(f"Unstructured modal-sandbox-fs-tools stderr: {stderr_text}")
81
- raise SandboxFilesystemError(f"Operation on '{remote_path}' failed with exit code {returncode}")
82
-
83
-
84
63
  def _extract_support_error_code(exc: Exception) -> Optional[str]:
85
64
  if match := re.search(r"Error code:\s*([A-Z0-9]{8})", str(exc)):
86
65
  return match.group(1)
@@ -144,26 +123,66 @@ def make_write_file_command(remote_path: str) -> str:
144
123
  return json.dumps({"WriteFile": {"path": remote_path}})
145
124
 
146
125
 
147
- def make_read_file_command(remote_path: str) -> str:
148
- """Build the JSON command string for a ReadFile operation.
126
+ def raise_list_files_error(returncode: int, stderr: Union[str, bytes], remote_path: str) -> NoReturn:
127
+ if payload := try_parse_error_payload(stderr):
128
+ logger.debug(
129
+ f"sandbox-fs-tools list_files error: path={remote_path}, "
130
+ f"error_kind={payload.error_kind}, message={payload.message}, detail={payload.detail}"
131
+ )
132
+ if payload.error_kind == "NotFound":
133
+ raise SandboxFilesystemNotFoundError(f"{payload.message}: {remote_path}")
134
+ if payload.error_kind in ("IsFile", "NotDirectory"):
135
+ raise SandboxFilesystemNotADirectoryError(f"{payload.message}: {remote_path}")
136
+ if payload.error_kind == "PermissionDenied":
137
+ raise SandboxFilesystemPermissionError(f"{payload.message}: {remote_path}")
138
+ raise SandboxFilesystemError(payload.message)
139
+
140
+ if stderr_text := _stderr_to_text(stderr):
141
+ logger.debug(f"Unstructured modal-sandbox-fs-tools stderr: {stderr_text}")
142
+ raise SandboxFilesystemError(f"Operation on '{remote_path}' failed with exit code {returncode}")
143
+
144
+
145
+ def make_list_files_command(remote_path: str) -> str:
146
+ """Build the JSON command string for a ListFiles operation.
149
147
 
150
148
  The returned JSON must match the `Command` enum in the modal-sandbox-fs-tools
151
149
  Rust crate (crates/modal-sandbox-fs-tools/src/lib.rs). Treat changes to
152
150
  this schema like protobuf changes: fields must not be removed or renamed,
153
151
  only added with backwards-compatible defaults.
154
152
  """
155
- return json.dumps({"ReadFile": {"path": remote_path}})
153
+ return json.dumps({"ListFiles": {"path": remote_path}})
156
154
 
157
155
 
158
- def make_remove_command(remote_path: str, recursive: bool) -> str:
159
- """Build the JSON command string for a Remove operation.
156
+ def raise_read_file_error(returncode: int, stderr: Union[str, bytes], remote_path: str) -> NoReturn:
157
+ if payload := try_parse_error_payload(stderr):
158
+ logger.debug(
159
+ f"sandbox-fs-tools read error: path={remote_path}, "
160
+ f"error_kind={payload.error_kind}, message={payload.message}, detail={payload.detail}"
161
+ )
162
+ if payload.error_kind == "NotFound":
163
+ raise SandboxFilesystemNotFoundError(f"{payload.message}: {remote_path}")
164
+ if payload.error_kind == "IsDirectory":
165
+ raise SandboxFilesystemIsADirectoryError(f"{payload.message}: {remote_path}")
166
+ if payload.error_kind == "PermissionDenied":
167
+ raise SandboxFilesystemPermissionError(f"{payload.message}: {remote_path}")
168
+ if payload.error_kind == "FileTooLarge":
169
+ raise SandboxFilesystemFileTooLargeError(f"{payload.message}: {remote_path}")
170
+ raise SandboxFilesystemError(payload.message)
171
+
172
+ if stderr_text := _stderr_to_text(stderr):
173
+ logger.debug(f"Unstructured modal-sandbox-fs-tools stderr: {stderr_text}")
174
+ raise SandboxFilesystemError(f"Operation on '{remote_path}' failed with exit code {returncode}")
175
+
176
+
177
+ def make_read_file_command(remote_path: str) -> str:
178
+ """Build the JSON command string for a ReadFile operation.
160
179
 
161
180
  The returned JSON must match the `Command` enum in the modal-sandbox-fs-tools
162
181
  Rust crate (crates/modal-sandbox-fs-tools/src/lib.rs). Treat changes to
163
182
  this schema like protobuf changes: fields must not be removed or renamed,
164
183
  only added with backwards-compatible defaults.
165
184
  """
166
- return json.dumps({"Remove": {"path": remote_path, "recursive": recursive}})
185
+ return json.dumps({"ReadFile": {"path": remote_path}})
167
186
 
168
187
 
169
188
  def raise_remove_error(returncode: int, stderr: Union[str, bytes], remote_path: str) -> NoReturn:
@@ -189,15 +208,15 @@ def raise_remove_error(returncode: int, stderr: Union[str, bytes], remote_path:
189
208
  raise SandboxFilesystemError(f"Operation on '{remote_path}' failed with exit code {returncode}")
190
209
 
191
210
 
192
- def make_make_directory_command(remote_path: str, create_parents: bool) -> str:
193
- """Build the JSON command string for a MakeDirectory operation.
211
+ def make_remove_command(remote_path: str, recursive: bool) -> str:
212
+ """Build the JSON command string for a Remove operation.
194
213
 
195
214
  The returned JSON must match the `Command` enum in the modal-sandbox-fs-tools
196
215
  Rust crate (crates/modal-sandbox-fs-tools/src/lib.rs). Treat changes to
197
216
  this schema like protobuf changes: fields must not be removed or renamed,
198
217
  only added with backwards-compatible defaults.
199
218
  """
200
- return json.dumps({"MakeDirectory": {"path": remote_path, "parents": create_parents}})
219
+ return json.dumps({"Remove": {"path": remote_path, "recursive": recursive}})
201
220
 
202
221
 
203
222
  def raise_make_directory_error(returncode: int, stderr: Union[str, bytes], remote_path: str) -> NoReturn:
@@ -225,6 +244,17 @@ def raise_make_directory_error(returncode: int, stderr: Union[str, bytes], remot
225
244
  raise SandboxFilesystemError(f"Operation on '{remote_path}' failed with exit code {returncode}")
226
245
 
227
246
 
247
+ def make_make_directory_command(remote_path: str, create_parents: bool) -> str:
248
+ """Build the JSON command string for a MakeDirectory operation.
249
+
250
+ The returned JSON must match the `Command` enum in the modal-sandbox-fs-tools
251
+ Rust crate (crates/modal-sandbox-fs-tools/src/lib.rs). Treat changes to
252
+ this schema like protobuf changes: fields must not be removed or renamed,
253
+ only added with backwards-compatible defaults.
254
+ """
255
+ return json.dumps({"MakeDirectory": {"path": remote_path, "parents": create_parents}})
256
+
257
+
228
258
  def validate_absolute_remote_path(remote_path: str, operation: str) -> None:
229
259
  if not PurePosixPath(remote_path).is_absolute():
230
260
  raise InvalidError(f"Sandbox.filesystem.{operation}() currently only supports absolute remote_path values")
@@ -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.3.dev5",
38
+ version: str = "1.4.3.dev7",
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.3.dev5",
178
+ version: str = "1.4.3.dev7",
179
179
  ):
180
180
  """mdmd:hidden
181
181
  The Modal client object is not intended to be instantiated directly by users.
@@ -90,7 +90,7 @@ class _GRPCErrorWrapper(grpclib.GRPCError):
90
90
  def __repr__(self) -> str:
91
91
  return f"{type(self).__name__}({self._message!r})"
92
92
 
93
- def _warn_on_grpc_error_attribute_access(self) -> None:
93
+ def _attribute_warning(self) -> None:
94
94
  from ._utils.deprecation import deprecation_warning # Avoid circular import
95
95
 
96
96
  exc_type = type(self).__name__
@@ -104,7 +104,7 @@ class _GRPCErrorWrapper(grpclib.GRPCError):
104
104
 
105
105
  @property
106
106
  def message(self) -> str:
107
- self._warn_on_grpc_error_attribute_access()
107
+ self._attribute_warning()
108
108
  return self._grpc_message
109
109
 
110
110
  @message.setter
@@ -113,7 +113,7 @@ class _GRPCErrorWrapper(grpclib.GRPCError):
113
113
 
114
114
  @property
115
115
  def status(self) -> grpclib.Status:
116
- self._warn_on_grpc_error_attribute_access()
116
+ self._attribute_warning()
117
117
  return self._grpc_status
118
118
 
119
119
  @status.setter
@@ -122,7 +122,7 @@ class _GRPCErrorWrapper(grpclib.GRPCError):
122
122
 
123
123
  @property
124
124
  def details(self) -> Any:
125
- self._warn_on_grpc_error_attribute_access()
125
+ self._attribute_warning()
126
126
  return self._grpc_details
127
127
 
128
128
  @details.setter
@@ -396,7 +396,7 @@ class _FileIO(Generic[T]):
396
396
  """List the contents of the provided directory."""
397
397
  deprecation_warning(
398
398
  (2026, 3, 9),
399
- "`FileIO.ls()` is deprecated. Use `Sandbox.ls()` instead.",
399
+ "`FileIO.ls()` is deprecated. Use `Sandbox.filesystem.list_files()` instead.",
400
400
  pending=True,
401
401
  )
402
402
  return await ls(path, client, task_id)
@@ -268,22 +268,28 @@ class _Sandbox(_Object, type_prefix="sb"):
268
268
  if pty:
269
269
  pty_info = _Sandbox._default_pty_info()
270
270
 
271
- def _deps() -> list[_Object]:
272
- deps: list[_Object] = [image] + list(mounts) + list(secrets)
271
+ async def _load(
272
+ self: _Sandbox, resolver: Resolver, load_context: LoadContext, _existing_object_id: Optional[str]
273
+ ):
274
+ # An already-hydrated image (e.g. one returned by
275
+ # `Sandbox.snapshot_directory`) is skipped — there's nothing to load.
276
+ dep_tasks: list = []
277
+ if not image._is_hydrated:
278
+ dep_tasks.append(resolver.load(image, load_context))
279
+ for dep in list(mounts) + list(secrets):
280
+ dep_tasks.append(resolver.load(dep, load_context))
273
281
  for _, vol in validated_network_file_systems:
274
- deps.append(vol)
282
+ dep_tasks.append(resolver.load(vol, load_context))
275
283
  for _, vol in validated_volumes:
276
- deps.append(vol)
284
+ dep_tasks.append(resolver.load(vol, load_context))
277
285
  for _, cloud_bucket_mount in cloud_bucket_mounts:
278
286
  if cloud_bucket_mount.secret:
279
- deps.append(cloud_bucket_mount.secret)
287
+ dep_tasks.append(resolver.load(cloud_bucket_mount.secret, load_context))
280
288
  if proxy:
281
- deps.append(proxy)
282
- return deps
289
+ dep_tasks.append(resolver.load(proxy, load_context))
290
+ if dep_tasks:
291
+ await asyncio.gather(*dep_tasks)
283
292
 
284
- async def _load(
285
- self: _Sandbox, resolver: Resolver, load_context: LoadContext, _existing_object_id: Optional[str]
286
- ):
287
293
  # Validate that the same volume (by object_id) isn't mounted at multiple paths
288
294
  validate_volumes_by_object_id(validated_volumes)
289
295
 
@@ -363,7 +369,7 @@ class _Sandbox(_Object, type_prefix="sb"):
363
369
  sandbox_id = create_resp.sandbox_id
364
370
  self._hydrate(sandbox_id, load_context.client, None)
365
371
 
366
- return _Sandbox._from_loader(_load, "Sandbox()", deps=_deps, load_context_overrides=LoadContext.empty())
372
+ return _Sandbox._from_loader(_load, "Sandbox()", load_context_overrides=LoadContext.empty())
367
373
 
368
374
  @staticmethod
369
375
  async def create(
@@ -689,12 +695,17 @@ class _Sandbox(_Object, type_prefix="sb"):
689
695
  allowed_cidrs=cidr_allowlist,
690
696
  )
691
697
 
692
- def _deps() -> list[_Object]:
693
- return [image] + list(secrets)
694
-
695
698
  async def _load(
696
699
  self: _Sandbox, resolver: Resolver, load_context: LoadContext, _existing_object_id: Optional[str]
697
700
  ):
701
+ dep_tasks: list = []
702
+ if not image._is_hydrated:
703
+ dep_tasks.append(resolver.load(image, load_context))
704
+ for secret in secrets:
705
+ dep_tasks.append(resolver.load(secret, load_context))
706
+ if dep_tasks:
707
+ await asyncio.gather(*dep_tasks)
708
+
698
709
  definition = api_pb2.Sandbox(
699
710
  entrypoint_args=args,
700
711
  image_id=image.object_id,
@@ -732,7 +743,7 @@ class _Sandbox(_Object, type_prefix="sb"):
732
743
  for t in create_resp.tunnels
733
744
  }
734
745
 
735
- obj = _Sandbox._from_loader(_load, "Sandbox()", deps=_deps, load_context_overrides=LoadContext.empty())
746
+ obj = _Sandbox._from_loader(_load, "Sandbox()", load_context_overrides=LoadContext.empty())
736
747
 
737
748
  app_id: Optional[str] = None
738
749
  app_client: Optional[_Client] = None
@@ -906,19 +917,7 @@ class _Sandbox(_Object, type_prefix="sb"):
906
917
  if resp.result.status != api_pb2.GenericResult.GENERIC_STATUS_SUCCESS:
907
918
  raise ExecutionError(resp.result.exception)
908
919
 
909
- image_id = resp.image_id
910
- metadata = resp.image_metadata
911
-
912
- async def _load(self: _Image, resolver: Resolver, load_context: LoadContext, existing_object_id: Optional[str]):
913
- # no need to hydrate again since we do it eagerly below
914
- pass
915
-
916
- rep = "Image()"
917
- # TODO: use ._new_hydrated instead
918
- image = _Image._from_loader(_load, rep, hydrate_lazily=True, load_context_overrides=LoadContext.empty())
919
- image._hydrate(image_id, self._client, metadata) # hydrating eagerly since we have all of the data
920
-
921
- return image
920
+ return _Image._new_hydrated(resp.image_id, self._client, resp.image_metadata)
922
921
 
923
922
  async def mount_image(self, path: Union[PurePosixPath, str], image: _Image):
924
923
  """Mount an Image at a specified path in a running Sandbox.
@@ -1032,7 +1031,8 @@ class _Sandbox(_Object, type_prefix="sb"):
1032
1031
  raise InvalidError(f"Snapshot path must be absolute; got: {posix_path}")
1033
1032
  path_bytes = posix_path.as_posix().encode("utf8")
1034
1033
 
1035
- req = sr_pb2.TaskSnapshotDirectoryRequest(task_id=task_id, path=path_bytes)
1034
+ snapshot_id = str(uuid.uuid4())
1035
+ req = sr_pb2.TaskSnapshotDirectoryRequest(task_id=task_id, path=path_bytes, snapshot_id=snapshot_id)
1036
1036
  res = await command_router_client.snapshot_directory(req)
1037
1037
  return _Image._new_hydrated(res.image_id, self._client, None)
1038
1038
 
@@ -1641,8 +1641,16 @@ class _Sandbox(_Object, type_prefix="sb"):
1641
1641
  return await _FileIO.create(path, mode, self._client, task_id)
1642
1642
 
1643
1643
  async def ls(self, path: str) -> builtins.list[str]:
1644
- """[Alpha] List the contents of a directory in the Sandbox."""
1644
+ """[Alpha] List the contents of a directory in the Sandbox.
1645
+
1646
+ .. deprecated:: 2026-04-15
1647
+ Use `Sandbox.filesystem.list_files()` instead."""
1645
1648
  self._ensure_v1("ls")
1649
+ deprecation_warning(
1650
+ (2026, 4, 15),
1651
+ "`Sandbox.ls()` is deprecated. Use `Sandbox.filesystem.list_files()` instead.",
1652
+ pending=True,
1653
+ )
1646
1654
  task_id = await self._get_task_id()
1647
1655
  return await ls(path, self._client, task_id)
1648
1656
 
@@ -613,7 +613,11 @@ class _Sandbox(modal._object._Object):
613
613
  @typing.overload
614
614
  async def open(self, path: str, mode: _typeshed.OpenBinaryMode) -> modal.file_io._FileIO[bytes]: ...
615
615
  async def ls(self, path: str) -> list[str]:
616
- """[Alpha] List the contents of a directory in the Sandbox."""
616
+ """[Alpha] List the contents of a directory in the Sandbox.
617
+
618
+ .. deprecated:: 2026-04-15
619
+ Use `Sandbox.filesystem.list_files()` instead.
620
+ """
617
621
  ...
618
622
 
619
623
  async def mkdir(self, path: str, parents: bool = False) -> None:
@@ -1908,11 +1912,19 @@ class Sandbox(modal.object.Object):
1908
1912
 
1909
1913
  class __ls_spec(typing_extensions.Protocol):
1910
1914
  def __call__(self, /, path: str) -> list[str]:
1911
- """[Alpha] List the contents of a directory in the Sandbox."""
1915
+ """[Alpha] List the contents of a directory in the Sandbox.
1916
+
1917
+ .. deprecated:: 2026-04-15
1918
+ Use `Sandbox.filesystem.list_files()` instead.
1919
+ """
1912
1920
  ...
1913
1921
 
1914
1922
  async def aio(self, /, path: str) -> list[str]:
1915
- """[Alpha] List the contents of a directory in the Sandbox."""
1923
+ """[Alpha] List the contents of a directory in the Sandbox.
1924
+
1925
+ .. deprecated:: 2026-04-15
1926
+ Use `Sandbox.filesystem.list_files()` instead.
1927
+ """
1916
1928
  ...
1917
1929
 
1918
1930
  ls: __ls_spec