modal 1.4.2.dev7__tar.gz → 1.4.2.dev9__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 (209) hide show
  1. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/PKG-INFO +1 -1
  2. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/task_command_router_client.py +6 -0
  3. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/client.py +7 -0
  4. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/client.pyi +14 -2
  5. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/sandbox.py +29 -7
  6. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/sandbox.pyi +54 -21
  7. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal.egg-info/PKG-INFO +1 -1
  8. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_version/__init__.py +1 -1
  9. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/pyproject.toml +3 -3
  10. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/LICENSE +0 -0
  11. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/README.md +0 -0
  12. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/__init__.py +0 -0
  13. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/__main__.py +0 -0
  14. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_billing.py +0 -0
  15. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_clustered_functions.py +0 -0
  16. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_clustered_functions.pyi +0 -0
  17. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_container_entrypoint.py +0 -0
  18. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_functions.py +0 -0
  19. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_grpc_client.py +0 -0
  20. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_ipython.py +0 -0
  21. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_load_context.py +0 -0
  22. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_location.py +0 -0
  23. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_logs.py +0 -0
  24. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_object.py +0 -0
  25. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_output/__init__.py +0 -0
  26. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_output/manager.py +0 -0
  27. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_output/pty.py +0 -0
  28. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_output/rich.py +0 -0
  29. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_output/status.py +0 -0
  30. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_partial_function.py +0 -0
  31. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_resolver.py +0 -0
  32. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_resources.py +0 -0
  33. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/__init__.py +0 -0
  34. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/asgi.py +0 -0
  35. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/container_io_manager.py +0 -0
  36. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/container_io_manager.pyi +0 -0
  37. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/execution_context.py +0 -0
  38. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/execution_context.pyi +0 -0
  39. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  40. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/telemetry.py +0 -0
  41. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/user_code_event_loop.py +0 -0
  42. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/user_code_imports.py +0 -0
  43. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_serialization.py +0 -0
  44. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_server.py +0 -0
  45. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_traceback.py +0 -0
  46. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_tunnel.py +0 -0
  47. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_tunnel.pyi +0 -0
  48. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_type_manager.py +0 -0
  49. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/__init__.py +0 -0
  50. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/app_utils.py +0 -0
  51. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/async_utils.py +0 -0
  52. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/auth_token_manager.py +0 -0
  53. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/blob_utils.py +0 -0
  54. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/browser_utils.py +0 -0
  55. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/bytes_io_segment_payload.py +0 -0
  56. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/deprecation.py +0 -0
  57. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/docker_utils.py +0 -0
  58. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/function_utils.py +0 -0
  59. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/git_utils.py +0 -0
  60. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/grpc_testing.py +0 -0
  61. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/grpc_utils.py +0 -0
  62. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/hash_utils.py +0 -0
  63. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/http_utils.py +0 -0
  64. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/jwt_utils.py +0 -0
  65. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/logger.py +0 -0
  66. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/mount_utils.py +0 -0
  67. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/name_utils.py +0 -0
  68. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/package_utils.py +0 -0
  69. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/pattern_utils.py +0 -0
  70. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/rand_pb_testing.py +0 -0
  71. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/sandbox_fs_utils.py +0 -0
  72. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/shell_utils.py +0 -0
  73. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/time_utils.py +0 -0
  74. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_vendor/__init__.py +0 -0
  75. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  76. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_vendor/cloudpickle.py +0 -0
  77. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_vendor/tblib.py +0 -0
  78. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_vendor/version.py +0 -0
  79. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_watcher.py +0 -0
  80. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/app.py +0 -0
  81. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/app.pyi +0 -0
  82. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/billing.py +0 -0
  83. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/builder/2023.12.312.txt +0 -0
  84. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/builder/2023.12.txt +0 -0
  85. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/builder/2024.04.txt +0 -0
  86. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/builder/2024.10.txt +0 -0
  87. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/builder/2025.06.txt +0 -0
  88. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/builder/PREVIEW.txt +0 -0
  89. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/builder/README.md +0 -0
  90. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/builder/base-images.json +0 -0
  91. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/call_graph.py +0 -0
  92. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/__init__.py +0 -0
  93. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/_download.py +0 -0
  94. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/_traceback.py +0 -0
  95. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/app.py +0 -0
  96. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/billing.py +0 -0
  97. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/changelog.py +0 -0
  98. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/cluster.py +0 -0
  99. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/config.py +0 -0
  100. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/container.py +0 -0
  101. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/dashboard.py +0 -0
  102. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/dict.py +0 -0
  103. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/entry_point.py +0 -0
  104. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/environment.py +0 -0
  105. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/import_refs.py +0 -0
  106. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/launch.py +0 -0
  107. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/network_file_system.py +0 -0
  108. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/profile.py +0 -0
  109. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/programs/__init__.py +0 -0
  110. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/programs/run_jupyter.py +0 -0
  111. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/programs/vscode.py +0 -0
  112. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/queues.py +0 -0
  113. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/run.py +0 -0
  114. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/secret.py +0 -0
  115. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/selector.py +0 -0
  116. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/shell.py +0 -0
  117. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/token.py +0 -0
  118. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/utils.py +0 -0
  119. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/volume.py +0 -0
  120. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cloud_bucket_mount.py +0 -0
  121. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cloud_bucket_mount.pyi +0 -0
  122. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cls.py +0 -0
  123. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cls.pyi +0 -0
  124. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/config.py +0 -0
  125. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/container_process.py +0 -0
  126. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/container_process.pyi +0 -0
  127. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/dict.py +0 -0
  128. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/dict.pyi +0 -0
  129. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/environments.py +0 -0
  130. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/environments.pyi +0 -0
  131. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/exception.py +0 -0
  132. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/experimental/__init__.py +0 -0
  133. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/experimental/flash.py +0 -0
  134. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/experimental/flash.pyi +0 -0
  135. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/experimental/ipython.py +0 -0
  136. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/file_io.py +0 -0
  137. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/file_io.pyi +0 -0
  138. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/file_pattern_matcher.py +0 -0
  139. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/functions.py +0 -0
  140. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/functions.pyi +0 -0
  141. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/image.py +0 -0
  142. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/image.pyi +0 -0
  143. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/io_streams.py +0 -0
  144. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/io_streams.pyi +0 -0
  145. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/mount.py +0 -0
  146. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/mount.pyi +0 -0
  147. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/network_file_system.py +0 -0
  148. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/network_file_system.pyi +0 -0
  149. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/object.py +0 -0
  150. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/object.pyi +0 -0
  151. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/output.py +0 -0
  152. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/parallel_map.py +0 -0
  153. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/parallel_map.pyi +0 -0
  154. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/partial_function.py +0 -0
  155. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/partial_function.pyi +0 -0
  156. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/proxy.py +0 -0
  157. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/proxy.pyi +0 -0
  158. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/py.typed +0 -0
  159. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/queue.py +0 -0
  160. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/queue.pyi +0 -0
  161. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/retries.py +0 -0
  162. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/runner.py +0 -0
  163. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/runner.pyi +0 -0
  164. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/running_app.py +0 -0
  165. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/sandbox_fs.py +0 -0
  166. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/sandbox_fs.pyi +0 -0
  167. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/schedule.py +0 -0
  168. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/scheduler_placement.py +0 -0
  169. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/secret.py +0 -0
  170. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/secret.pyi +0 -0
  171. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/server.py +0 -0
  172. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/server.pyi +0 -0
  173. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/serving.py +0 -0
  174. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/serving.pyi +0 -0
  175. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/snapshot.py +0 -0
  176. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/snapshot.pyi +0 -0
  177. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/stream_type.py +0 -0
  178. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/token_flow.py +0 -0
  179. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/token_flow.pyi +0 -0
  180. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/volume.py +0 -0
  181. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/volume.pyi +0 -0
  182. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal.egg-info/SOURCES.txt +0 -0
  183. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal.egg-info/dependency_links.txt +0 -0
  184. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal.egg-info/entry_points.txt +0 -0
  185. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal.egg-info/requires.txt +0 -0
  186. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal.egg-info/top_level.txt +0 -0
  187. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_docs/__init__.py +0 -0
  188. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_docs/gen_cli_docs.py +0 -0
  189. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_docs/gen_cli_docs_main.py +0 -0
  190. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_docs/gen_reference_docs.py +0 -0
  191. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_docs/gen_reference_docs_main.py +0 -0
  192. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_docs/mdmd/__init__.py +0 -0
  193. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_docs/mdmd/mdmd.py +0 -0
  194. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_docs/mdmd/signatures.py +0 -0
  195. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/__init__.py +0 -0
  196. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/api_grpc.py +0 -0
  197. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/api_pb2.py +0 -0
  198. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/api_pb2.pyi +0 -0
  199. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/api_pb2_grpc.py +0 -0
  200. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/api_pb2_grpc.pyi +0 -0
  201. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/modal_api_grpc.py +0 -0
  202. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/py.typed +0 -0
  203. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/task_command_router_grpc.py +0 -0
  204. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/task_command_router_pb2.py +0 -0
  205. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/task_command_router_pb2.pyi +0 -0
  206. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  207. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  208. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_version/__main__.py +0 -0
  209. {modal-1.4.2.dev7 → modal-1.4.2.dev9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.4.2.dev7
3
+ Version: 1.4.2.dev9
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -617,6 +617,12 @@ class TaskCommandRouterClient:
617
617
  lambda: self._call_with_auth_retry(self._stub.TaskMountDirectory, request)
618
618
  )
619
619
 
620
+ async def unmount_image(self, request: sr_pb2.TaskUnmountDirectoryRequest):
621
+ with grpc_error_converter():
622
+ return await call_with_retries_on_transient_errors(
623
+ lambda: self._call_with_auth_retry(self._stub.TaskUnmountDirectory, request)
624
+ )
625
+
620
626
  async def snapshot_directory(
621
627
  self, request: sr_pb2.TaskSnapshotDirectoryRequest
622
628
  ) -> sr_pb2.TaskSnapshotDirectoryResponse:
@@ -239,6 +239,10 @@ class _Client:
239
239
  """
240
240
  Constructor based on token credentials; useful for managing Modal on behalf of third-party users.
241
241
 
242
+ Also useful when it's necessary to explicitly manage the lifecycle of the client
243
+ (e.g. when running Modal in a forked subprocess) — see
244
+ [troubleshooting](/docs/guide/troubleshooting#connection-issues-in-forked-processes).
245
+
242
246
  **Usage:**
243
247
 
244
248
  ```python notest
@@ -309,6 +313,9 @@ class _Client:
309
313
  return await coro
310
314
 
311
315
  async def _reset_on_pid_change(self):
316
+ # Best-effort recovery after os.fork(). The client singleton may be inherited
317
+ # from the parent with stale gRPC state. For reliable post-fork usage, create
318
+ # a fresh client via Client.from_credentials() instead of relying on this.
312
319
  if self._owner_pid and self._owner_pid != os.getpid():
313
320
  # not calling .close() since that would also interact with stale resources
314
321
  # just reset the internal state
@@ -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.2.dev7",
38
+ version: str = "1.4.2.dev9",
39
39
  ):
40
40
  """mdmd:hidden
41
41
  The Modal client object is not intended to be instantiated directly by users.
@@ -97,6 +97,10 @@ class _Client:
97
97
  async def from_credentials(cls, token_id: str, token_secret: str) -> _Client:
98
98
  """Constructor based on token credentials; useful for managing Modal on behalf of third-party users.
99
99
 
100
+ Also useful when it's necessary to explicitly manage the lifecycle of the client
101
+ (e.g. when running Modal in a forked subprocess) — see
102
+ [troubleshooting](/docs/guide/troubleshooting#connection-issues-in-forked-processes).
103
+
100
104
  **Usage:**
101
105
 
102
106
  ```python notest
@@ -171,7 +175,7 @@ class Client:
171
175
  server_url: str,
172
176
  client_type: int,
173
177
  credentials: typing.Optional[tuple[str, str]],
174
- version: str = "1.4.2.dev7",
178
+ version: str = "1.4.2.dev9",
175
179
  ):
176
180
  """mdmd:hidden
177
181
  The Modal client object is not intended to be instantiated directly by users.
@@ -283,6 +287,10 @@ class Client:
283
287
  def __call__(self, /, token_id: str, token_secret: str) -> Client:
284
288
  """Constructor based on token credentials; useful for managing Modal on behalf of third-party users.
285
289
 
290
+ Also useful when it's necessary to explicitly manage the lifecycle of the client
291
+ (e.g. when running Modal in a forked subprocess) — see
292
+ [troubleshooting](/docs/guide/troubleshooting#connection-issues-in-forked-processes).
293
+
286
294
  **Usage:**
287
295
 
288
296
  ```python notest
@@ -296,6 +304,10 @@ class Client:
296
304
  async def aio(self, /, token_id: str, token_secret: str) -> Client:
297
305
  """Constructor based on token credentials; useful for managing Modal on behalf of third-party users.
298
306
 
307
+ Also useful when it's necessary to explicitly manage the lifecycle of the client
308
+ (e.g. when running Modal in a forked subprocess) — see
309
+ [troubleshooting](/docs/guide/troubleshooting#connection-issues-in-forked-processes).
310
+
299
311
  **Usage:**
300
312
 
301
313
  ```python notest
@@ -923,14 +923,15 @@ class _Sandbox(_Object, type_prefix="sb"):
923
923
  async def mount_image(self, path: Union[PurePosixPath, str], image: _Image):
924
924
  """Mount an Image at a specified path in a running Sandbox.
925
925
 
926
- `path` should be a directory. If it doesn't exist it will be created. If it exists and contains
927
- data, the previous directory will be replaced by the mount.
926
+ `path` should be a directory that is **not** the root path (`/`). If the path doesn't exist
927
+ it will be created. If it exists and contains data, the previous directory will be replaced
928
+ by the mount.
928
929
 
929
- The `image` argument currently only supports Images that are either:
930
- - prebuilt using `image.build()`
931
- - referenced by image id, e.g. `Image.from_id(...)`
932
- - filesystem/directory snapshots e.g. created by `.snapshot_directory()`
933
- or `.snapshot_filesystem()`"
930
+ The `image` argument supports any Image that has an object ID, including:
931
+ - Images built using `image.build()`
932
+ - Images referenced by ID, e.g. `Image.from_id(...)`
933
+ - Filesystem/directory snapshots, e.g. created by `.snapshot_directory()` or `.snapshot_filesystem()`
934
+ - Empty images created with `Image.from_scratch()`
934
935
 
935
936
  Usage:
936
937
  ```py notest
@@ -982,6 +983,27 @@ class _Sandbox(_Object, type_prefix="sb"):
982
983
  req = sr_pb2.TaskMountDirectoryRequest(task_id=task_id, path=path_bytes, image_id=image_id)
983
984
  await command_router_client.mount_image(req)
984
985
 
986
+ async def unmount_image(self, path: Union[PurePosixPath, str]):
987
+ """Unmount a previously mounted Image from a running Sandbox.
988
+
989
+ `path` must be the exact mount point that was passed to `.mount_image()`.
990
+ After unmounting, the underlying Sandbox filesystem at that path becomes
991
+ visible again.
992
+ """
993
+ self._ensure_v1("unmount_image")
994
+
995
+ task_id = await self._get_task_id()
996
+ if (command_router_client := await self._get_command_router_client(task_id)) is None:
997
+ raise InvalidError("Unmounting directories requires direct Sandbox control - please contact Modal support.")
998
+
999
+ posix_path = PurePosixPath(path)
1000
+ if not posix_path.is_absolute():
1001
+ raise InvalidError(f"Unmount path must be absolute; got: {posix_path}")
1002
+ path_bytes = posix_path.as_posix().encode("utf8")
1003
+
1004
+ req = sr_pb2.TaskUnmountDirectoryRequest(task_id=task_id, path=path_bytes)
1005
+ await command_router_client.unmount_image(req)
1006
+
985
1007
  async def snapshot_directory(self, path: Union[PurePosixPath, str]) -> _Image:
986
1008
  """Snapshot a directory in a running Sandbox, creating a new Image with its content.
987
1009
 
@@ -384,14 +384,15 @@ class _Sandbox(modal._object._Object):
384
384
  async def mount_image(self, path: typing.Union[pathlib.PurePosixPath, str], image: modal.image._Image):
385
385
  """Mount an Image at a specified path in a running Sandbox.
386
386
 
387
- `path` should be a directory. If it doesn't exist it will be created. If it exists and contains
388
- data, the previous directory will be replaced by the mount.
387
+ `path` should be a directory that is **not** the root path (`/`). If the path doesn't exist
388
+ it will be created. If it exists and contains data, the previous directory will be replaced
389
+ by the mount.
389
390
 
390
- The `image` argument currently only supports Images that are either:
391
- - prebuilt using `image.build()`
392
- - referenced by image id, e.g. `Image.from_id(...)`
393
- - filesystem/directory snapshots e.g. created by `.snapshot_directory()`
394
- or `.snapshot_filesystem()`"
391
+ The `image` argument supports any Image that has an object ID, including:
392
+ - Images built using `image.build()`
393
+ - Images referenced by ID, e.g. `Image.from_id(...)`
394
+ - Filesystem/directory snapshots, e.g. created by `.snapshot_directory()` or `.snapshot_filesystem()`
395
+ - Empty images created with `Image.from_scratch()`
395
396
 
396
397
  Usage:
397
398
  ```py notest
@@ -405,6 +406,15 @@ class _Sandbox(modal._object._Object):
405
406
  """
406
407
  ...
407
408
 
409
+ async def unmount_image(self, path: typing.Union[pathlib.PurePosixPath, str]):
410
+ """Unmount a previously mounted Image from a running Sandbox.
411
+
412
+ `path` must be the exact mount point that was passed to `.mount_image()`.
413
+ After unmounting, the underlying Sandbox filesystem at that path becomes
414
+ visible again.
415
+ """
416
+ ...
417
+
408
418
  async def snapshot_directory(self, path: typing.Union[pathlib.PurePosixPath, str]) -> modal.image._Image:
409
419
  """Snapshot a directory in a running Sandbox, creating a new Image with its content.
410
420
 
@@ -1351,14 +1361,15 @@ class Sandbox(modal.object.Object):
1351
1361
  def __call__(self, /, path: typing.Union[pathlib.PurePosixPath, str], image: modal.image.Image):
1352
1362
  """Mount an Image at a specified path in a running Sandbox.
1353
1363
 
1354
- `path` should be a directory. If it doesn't exist it will be created. If it exists and contains
1355
- data, the previous directory will be replaced by the mount.
1364
+ `path` should be a directory that is **not** the root path (`/`). If the path doesn't exist
1365
+ it will be created. If it exists and contains data, the previous directory will be replaced
1366
+ by the mount.
1356
1367
 
1357
- The `image` argument currently only supports Images that are either:
1358
- - prebuilt using `image.build()`
1359
- - referenced by image id, e.g. `Image.from_id(...)`
1360
- - filesystem/directory snapshots e.g. created by `.snapshot_directory()`
1361
- or `.snapshot_filesystem()`"
1368
+ The `image` argument supports any Image that has an object ID, including:
1369
+ - Images built using `image.build()`
1370
+ - Images referenced by ID, e.g. `Image.from_id(...)`
1371
+ - Filesystem/directory snapshots, e.g. created by `.snapshot_directory()` or `.snapshot_filesystem()`
1372
+ - Empty images created with `Image.from_scratch()`
1362
1373
 
1363
1374
  Usage:
1364
1375
  ```py notest
@@ -1375,14 +1386,15 @@ class Sandbox(modal.object.Object):
1375
1386
  async def aio(self, /, path: typing.Union[pathlib.PurePosixPath, str], image: modal.image.Image):
1376
1387
  """Mount an Image at a specified path in a running Sandbox.
1377
1388
 
1378
- `path` should be a directory. If it doesn't exist it will be created. If it exists and contains
1379
- data, the previous directory will be replaced by the mount.
1389
+ `path` should be a directory that is **not** the root path (`/`). If the path doesn't exist
1390
+ it will be created. If it exists and contains data, the previous directory will be replaced
1391
+ by the mount.
1380
1392
 
1381
- The `image` argument currently only supports Images that are either:
1382
- - prebuilt using `image.build()`
1383
- - referenced by image id, e.g. `Image.from_id(...)`
1384
- - filesystem/directory snapshots e.g. created by `.snapshot_directory()`
1385
- or `.snapshot_filesystem()`"
1393
+ The `image` argument supports any Image that has an object ID, including:
1394
+ - Images built using `image.build()`
1395
+ - Images referenced by ID, e.g. `Image.from_id(...)`
1396
+ - Filesystem/directory snapshots, e.g. created by `.snapshot_directory()` or `.snapshot_filesystem()`
1397
+ - Empty images created with `Image.from_scratch()`
1386
1398
 
1387
1399
  Usage:
1388
1400
  ```py notest
@@ -1398,6 +1410,27 @@ class Sandbox(modal.object.Object):
1398
1410
 
1399
1411
  mount_image: __mount_image_spec
1400
1412
 
1413
+ class __unmount_image_spec(typing_extensions.Protocol):
1414
+ def __call__(self, /, path: typing.Union[pathlib.PurePosixPath, str]):
1415
+ """Unmount a previously mounted Image from a running Sandbox.
1416
+
1417
+ `path` must be the exact mount point that was passed to `.mount_image()`.
1418
+ After unmounting, the underlying Sandbox filesystem at that path becomes
1419
+ visible again.
1420
+ """
1421
+ ...
1422
+
1423
+ async def aio(self, /, path: typing.Union[pathlib.PurePosixPath, str]):
1424
+ """Unmount a previously mounted Image from a running Sandbox.
1425
+
1426
+ `path` must be the exact mount point that was passed to `.mount_image()`.
1427
+ After unmounting, the underlying Sandbox filesystem at that path becomes
1428
+ visible again.
1429
+ """
1430
+ ...
1431
+
1432
+ unmount_image: __unmount_image_spec
1433
+
1401
1434
  class __snapshot_directory_spec(typing_extensions.Protocol):
1402
1435
  def __call__(self, /, path: typing.Union[pathlib.PurePosixPath, str]) -> modal.image.Image:
1403
1436
  """Snapshot a directory in a running Sandbox, creating a new Image with its content.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.4.2.dev7
3
+ Version: 1.4.2.dev9
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2026
2
2
  """Supplies the current version of the modal client library."""
3
3
 
4
- __version__ = "1.4.2.dev7"
4
+ __version__ = "1.4.2.dev9"
@@ -50,7 +50,7 @@ dev = [
50
50
  "mypy~=1.18.2",
51
51
  "packaging>=23.1",
52
52
  "pytest~=8.4.0",
53
- "pytest-asyncio @ git+https://github.com/modal-labs/pytest-asyncio.git@af3f2d721b842309749cd26e5bbdd210e17d80c8",
53
+ "pytest-asyncio~=1.3.0",
54
54
  "pytest-env~=1.1.5",
55
55
  "pytest-markdown-docs==0.9.1",
56
56
  "pytest-timeout~=2.4.0",
@@ -119,6 +119,8 @@ module = [
119
119
  ignore_errors = true
120
120
 
121
121
  [tool.pytest.ini_options]
122
+ asyncio_default_fixture_loop_scope = "session"
123
+ asyncio_default_test_loop_scope = "session"
122
124
  timeout = 300
123
125
  addopts = "--ignore=modal/cli/programs"
124
126
  filterwarnings = [
@@ -126,9 +128,7 @@ filterwarnings = [
126
128
  "ignore:Type google._upb.*MapContainer uses PyType_Spec.*Python 3.14:DeprecationWarning",
127
129
  "error::modal.exception.DeprecationError",
128
130
  "error::modal.exception.AsyncUsageWarning",
129
- "ignore:There is no current event loop:DeprecationWarning", # pytest-asyncio internals
130
131
  "ignore:distutils Version classes are deprecated:DeprecationWarning", # pytest-freezegun internals
131
- "ignore:'asyncio.iscoroutinefunction' is deprecated:DeprecationWarning", # pytest-asyncio internals
132
132
  ]
133
133
 
134
134
  [tool.ruff]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes