modal 1.2.1.dev23__tar.gz → 1.2.2.dev3__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.

Potentially problematic release.


This version of modal might be problematic. Click here for more details.

Files changed (198) hide show
  1. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/PKG-INFO +1 -1
  2. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/mount_utils.py +26 -1
  3. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/client.pyi +2 -2
  4. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/container_process.py +2 -3
  5. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/image.py +21 -0
  6. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/image.pyi +4 -0
  7. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/io_streams.py +7 -0
  8. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/io_streams.pyi +16 -0
  9. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/volume.py +1 -1
  10. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal.egg-info/PKG-INFO +1 -1
  11. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_version/__init__.py +1 -1
  12. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/LICENSE +0 -0
  13. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/README.md +0 -0
  14. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/__init__.py +0 -0
  15. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/__main__.py +0 -0
  16. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_billing.py +0 -0
  17. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_clustered_functions.py +0 -0
  18. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_clustered_functions.pyi +0 -0
  19. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_container_entrypoint.py +0 -0
  20. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_functions.py +0 -0
  21. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_ipython.py +0 -0
  22. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_location.py +0 -0
  23. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_object.py +0 -0
  24. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_output.py +0 -0
  25. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_partial_function.py +0 -0
  26. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_pty.py +0 -0
  27. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_resolver.py +0 -0
  28. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_resources.py +0 -0
  29. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_runtime/__init__.py +0 -0
  30. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_runtime/asgi.py +0 -0
  31. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_runtime/container_io_manager.py +0 -0
  32. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_runtime/container_io_manager.pyi +0 -0
  33. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_runtime/execution_context.py +0 -0
  34. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_runtime/execution_context.pyi +0 -0
  35. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  36. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_runtime/telemetry.py +0 -0
  37. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_runtime/user_code_imports.py +0 -0
  38. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_serialization.py +0 -0
  39. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_traceback.py +0 -0
  40. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_tunnel.py +0 -0
  41. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_tunnel.pyi +0 -0
  42. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_type_manager.py +0 -0
  43. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/__init__.py +0 -0
  44. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/app_utils.py +0 -0
  45. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/async_utils.py +0 -0
  46. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/auth_token_manager.py +0 -0
  47. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/blob_utils.py +0 -0
  48. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/bytes_io_segment_payload.py +0 -0
  49. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/deprecation.py +0 -0
  50. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/docker_utils.py +0 -0
  51. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/function_utils.py +0 -0
  52. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/git_utils.py +0 -0
  53. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/grpc_testing.py +0 -0
  54. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/grpc_utils.py +0 -0
  55. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/hash_utils.py +0 -0
  56. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/http_utils.py +0 -0
  57. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/jwt_utils.py +0 -0
  58. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/logger.py +0 -0
  59. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/name_utils.py +0 -0
  60. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/package_utils.py +0 -0
  61. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/pattern_utils.py +0 -0
  62. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/rand_pb_testing.py +0 -0
  63. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/shell_utils.py +0 -0
  64. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/task_command_router_client.py +0 -0
  65. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_utils/time_utils.py +0 -0
  66. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_vendor/__init__.py +0 -0
  67. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  68. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_vendor/cloudpickle.py +0 -0
  69. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_vendor/tblib.py +0 -0
  70. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/_watcher.py +0 -0
  71. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/app.py +0 -0
  72. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/app.pyi +0 -0
  73. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/billing.py +0 -0
  74. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/builder/2023.12.312.txt +0 -0
  75. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/builder/2023.12.txt +0 -0
  76. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/builder/2024.04.txt +0 -0
  77. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/builder/2024.10.txt +0 -0
  78. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/builder/2025.06.txt +0 -0
  79. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/builder/PREVIEW.txt +0 -0
  80. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/builder/README.md +0 -0
  81. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/builder/base-images.json +0 -0
  82. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/call_graph.py +0 -0
  83. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/__init__.py +0 -0
  84. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/_download.py +0 -0
  85. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/_traceback.py +0 -0
  86. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/app.py +0 -0
  87. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/cluster.py +0 -0
  88. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/config.py +0 -0
  89. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/container.py +0 -0
  90. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/dict.py +0 -0
  91. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/entry_point.py +0 -0
  92. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/environment.py +0 -0
  93. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/import_refs.py +0 -0
  94. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/launch.py +0 -0
  95. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/network_file_system.py +0 -0
  96. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/profile.py +0 -0
  97. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/programs/__init__.py +0 -0
  98. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/programs/launch_instance_ssh.py +0 -0
  99. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/programs/run_jupyter.py +0 -0
  100. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/programs/run_marimo.py +0 -0
  101. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/programs/vscode.py +0 -0
  102. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/queues.py +0 -0
  103. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/run.py +0 -0
  104. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/secret.py +0 -0
  105. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/token.py +0 -0
  106. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/utils.py +0 -0
  107. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cli/volume.py +0 -0
  108. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/client.py +0 -0
  109. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cloud_bucket_mount.py +0 -0
  110. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cloud_bucket_mount.pyi +0 -0
  111. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cls.py +0 -0
  112. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/cls.pyi +0 -0
  113. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/config.py +0 -0
  114. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/container_process.pyi +0 -0
  115. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/dict.py +0 -0
  116. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/dict.pyi +0 -0
  117. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/environments.py +0 -0
  118. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/environments.pyi +0 -0
  119. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/exception.py +0 -0
  120. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/experimental/__init__.py +0 -0
  121. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/experimental/flash.py +0 -0
  122. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/experimental/flash.pyi +0 -0
  123. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/experimental/ipython.py +0 -0
  124. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/file_io.py +0 -0
  125. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/file_io.pyi +0 -0
  126. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/file_pattern_matcher.py +0 -0
  127. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/functions.py +0 -0
  128. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/functions.pyi +0 -0
  129. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/gpu.py +0 -0
  130. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/mount.py +0 -0
  131. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/mount.pyi +0 -0
  132. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/network_file_system.py +0 -0
  133. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/network_file_system.pyi +0 -0
  134. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/object.py +0 -0
  135. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/object.pyi +0 -0
  136. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/output.py +0 -0
  137. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/parallel_map.py +0 -0
  138. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/parallel_map.pyi +0 -0
  139. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/partial_function.py +0 -0
  140. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/partial_function.pyi +0 -0
  141. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/proxy.py +0 -0
  142. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/proxy.pyi +0 -0
  143. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/py.typed +0 -0
  144. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/queue.py +0 -0
  145. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/queue.pyi +0 -0
  146. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/retries.py +0 -0
  147. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/runner.py +0 -0
  148. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/runner.pyi +0 -0
  149. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/running_app.py +0 -0
  150. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/sandbox.py +0 -0
  151. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/sandbox.pyi +0 -0
  152. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/schedule.py +0 -0
  153. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/scheduler_placement.py +0 -0
  154. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/secret.py +0 -0
  155. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/secret.pyi +0 -0
  156. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/serving.py +0 -0
  157. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/serving.pyi +0 -0
  158. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/snapshot.py +0 -0
  159. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/snapshot.pyi +0 -0
  160. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/stream_type.py +0 -0
  161. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/token_flow.py +0 -0
  162. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/token_flow.pyi +0 -0
  163. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal/volume.pyi +0 -0
  164. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal.egg-info/SOURCES.txt +0 -0
  165. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal.egg-info/dependency_links.txt +0 -0
  166. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal.egg-info/entry_points.txt +0 -0
  167. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal.egg-info/requires.txt +0 -0
  168. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal.egg-info/top_level.txt +0 -0
  169. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_docs/__init__.py +0 -0
  170. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_docs/gen_cli_docs.py +0 -0
  171. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_docs/gen_reference_docs.py +0 -0
  172. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_docs/mdmd/__init__.py +0 -0
  173. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_docs/mdmd/mdmd.py +0 -0
  174. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_docs/mdmd/signatures.py +0 -0
  175. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/__init__.py +0 -0
  176. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/api.proto +0 -0
  177. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/api_grpc.py +0 -0
  178. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/api_pb2.py +0 -0
  179. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/api_pb2.pyi +0 -0
  180. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/api_pb2_grpc.py +0 -0
  181. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/api_pb2_grpc.pyi +0 -0
  182. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/modal_api_grpc.py +0 -0
  183. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/py.typed +0 -0
  184. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/sandbox_router.proto +0 -0
  185. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/sandbox_router_grpc.py +0 -0
  186. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/sandbox_router_pb2.py +0 -0
  187. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/sandbox_router_pb2.pyi +0 -0
  188. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/sandbox_router_pb2_grpc.py +0 -0
  189. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/sandbox_router_pb2_grpc.pyi +0 -0
  190. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/task_command_router.proto +0 -0
  191. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/task_command_router_grpc.py +0 -0
  192. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/task_command_router_pb2.py +0 -0
  193. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/task_command_router_pb2.pyi +0 -0
  194. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  195. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  196. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/modal_version/__main__.py +0 -0
  197. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/pyproject.toml +0 -0
  198. {modal-1.2.1.dev23 → modal-1.2.2.dev3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.1.dev23
3
+ Version: 1.2.2.dev3
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -3,7 +3,9 @@ import posixpath
3
3
  import typing
4
4
  from collections.abc import Mapping, Sequence
5
5
  from pathlib import PurePath, PurePosixPath
6
- from typing import Union
6
+ from typing import Optional, Union
7
+
8
+ from typing_extensions import TypeGuard
7
9
 
8
10
  from ..cloud_bucket_mount import _CloudBucketMount
9
11
  from ..exception import InvalidError
@@ -76,3 +78,26 @@ def validate_volumes(
76
78
  )
77
79
 
78
80
  return validated_volumes
81
+
82
+
83
+ def validate_only_modal_volumes(
84
+ volumes: Optional[Optional[dict[Union[str, PurePosixPath], _Volume]]],
85
+ caller_name: str,
86
+ ) -> Sequence[tuple[str, _Volume]]:
87
+ """Validate all volumes are `modal.Volume`."""
88
+ if volumes is None:
89
+ return []
90
+
91
+ validated_volumes = validate_volumes(volumes)
92
+
93
+ # Although the typing forbids `_CloudBucketMount` for type checking, one can still pass a `_CloudBucketMount`
94
+ # during runtime, so we'll check the type here.
95
+ def all_modal_volumes(
96
+ vols: Sequence[tuple[str, Union[_Volume, _CloudBucketMount]]],
97
+ ) -> TypeGuard[Sequence[tuple[str, _Volume]]]:
98
+ return all(isinstance(v, _Volume) for _, v in vols)
99
+
100
+ if not all_modal_volumes(validated_volumes):
101
+ raise InvalidError(f"{caller_name} only supports volumes that are modal.Volume")
102
+
103
+ return validated_volumes
@@ -33,7 +33,7 @@ class _Client:
33
33
  server_url: str,
34
34
  client_type: int,
35
35
  credentials: typing.Optional[tuple[str, str]],
36
- version: str = "1.2.1.dev23",
36
+ version: str = "1.2.2.dev3",
37
37
  ):
38
38
  """mdmd:hidden
39
39
  The Modal client object is not intended to be instantiated directly by users.
@@ -164,7 +164,7 @@ class Client:
164
164
  server_url: str,
165
165
  client_type: int,
166
166
  credentials: typing.Optional[tuple[str, str]],
167
- version: str = "1.2.1.dev23",
167
+ version: str = "1.2.2.dev3",
168
168
  ):
169
169
  """mdmd:hidden
170
170
  The Modal client object is not intended to be instantiated directly by users.
@@ -101,6 +101,7 @@ class _ContainerProcessThroughServer(Generic[T]):
101
101
 
102
102
  Returns `None` if the process is still running, else returns the exit code.
103
103
  """
104
+ assert self._process_id
104
105
  if self._returncode is not None:
105
106
  return self._returncode
106
107
  if self._exec_deadline and time.monotonic() >= self._exec_deadline:
@@ -119,6 +120,7 @@ class _ContainerProcessThroughServer(Generic[T]):
119
120
  return None
120
121
 
121
122
  async def _wait_for_completion(self) -> int:
123
+ assert self._process_id
122
124
  while True:
123
125
  req = api_pb2.ContainerExecWaitRequest(exec_id=self._process_id, timeout=10)
124
126
  resp: api_pb2.ContainerExecWaitResponse = await retry_transient_errors(
@@ -169,9 +171,6 @@ class _ContainerProcessThroughServer(Generic[T]):
169
171
  stream_impl = stream._impl
170
172
  # Don't skip empty messages so we can detect when the process has booted.
171
173
  async for chunk in stream_impl._get_logs(skip_empty_messages=False):
172
- if chunk is None:
173
- break
174
-
175
174
  if not on_connect.is_set():
176
175
  connecting_status.stop()
177
176
  on_connect.set()
@@ -39,6 +39,7 @@ from ._utils.docker_utils import (
39
39
  )
40
40
  from ._utils.function_utils import FunctionInfo
41
41
  from ._utils.grpc_utils import RETRYABLE_GRPC_STATUS_CODES, retry_transient_errors
42
+ from ._utils.mount_utils import validate_only_modal_volumes
42
43
  from .client import _Client
43
44
  from .cloud_bucket_mount import _CloudBucketMount
44
45
  from .config import config, logger, user_config_path
@@ -487,6 +488,7 @@ class _Image(_Object, type_prefix="im"):
487
488
  context_mount_function: Optional[Callable[[], Optional[_Mount]]] = None,
488
489
  force_build: bool = False,
489
490
  build_args: dict[str, str] = {},
491
+ validated_volumes: Optional[Sequence[tuple[str, _Volume]]] = None,
490
492
  # For internal use only.
491
493
  _namespace: "api_pb2.DeploymentNamespace.ValueType" = api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
492
494
  _do_assert_no_mount_layers: bool = True,
@@ -494,6 +496,9 @@ class _Image(_Object, type_prefix="im"):
494
496
  if base_images is None:
495
497
  base_images = {}
496
498
 
499
+ if validated_volumes is None:
500
+ validated_volumes = []
501
+
497
502
  if secrets is None:
498
503
  secrets = []
499
504
  if gpu_config is None:
@@ -514,6 +519,8 @@ class _Image(_Object, type_prefix="im"):
514
519
  deps += (build_function,)
515
520
  if image_registry_config and image_registry_config.secret:
516
521
  deps += (image_registry_config.secret,)
522
+ for _, vol in validated_volumes:
523
+ deps += (vol,)
517
524
  return deps
518
525
 
519
526
  async def _load(self: _Image, resolver: Resolver, existing_object_id: Optional[str]):
@@ -592,6 +599,17 @@ class _Image(_Object, type_prefix="im"):
592
599
  build_function_id = ""
593
600
  _build_function = None
594
601
 
602
+ # Relies on dicts being ordered (true as of Python 3.6).
603
+ volume_mounts = [
604
+ api_pb2.VolumeMount(
605
+ mount_path=path,
606
+ volume_id=volume.object_id,
607
+ allow_background_commits=True,
608
+ read_only=volume._read_only,
609
+ )
610
+ for path, volume in validated_volumes
611
+ ]
612
+
595
613
  image_definition = api_pb2.Image(
596
614
  base_images=base_images_pb2s,
597
615
  dockerfile_commands=dockerfile.commands,
@@ -604,6 +622,7 @@ class _Image(_Object, type_prefix="im"):
604
622
  runtime_debug=config.get("function_runtime_debug"),
605
623
  build_function=_build_function,
606
624
  build_args=build_args,
625
+ volume_mounts=volume_mounts,
607
626
  )
608
627
 
609
628
  req = api_pb2.ImageGetOrCreateRequest(
@@ -1690,6 +1709,7 @@ class _Image(_Object, type_prefix="im"):
1690
1709
  *commands: Union[str, list[str]],
1691
1710
  env: Optional[dict[str, Optional[str]]] = None,
1692
1711
  secrets: Optional[Collection[_Secret]] = None,
1712
+ volumes: Optional[dict[Union[str, PurePosixPath], _Volume]] = None,
1693
1713
  gpu: GPU_T = None,
1694
1714
  force_build: bool = False, # Ignore cached builds, similar to 'docker build --no-cache'
1695
1715
  ) -> "_Image":
@@ -1712,6 +1732,7 @@ class _Image(_Object, type_prefix="im"):
1712
1732
  secrets=secrets,
1713
1733
  gpu_config=parse_gpu_config(gpu),
1714
1734
  force_build=self.force_build or force_build,
1735
+ validated_volumes=validate_only_modal_volumes(volumes, "Image.run_commands"),
1715
1736
  )
1716
1737
 
1717
1738
  @staticmethod
@@ -176,6 +176,7 @@ class _Image(modal._object._Object):
176
176
  ] = None,
177
177
  force_build: bool = False,
178
178
  build_args: dict[str, str] = {},
179
+ validated_volumes: typing.Optional[collections.abc.Sequence[tuple[str, modal.volume._Volume]]] = None,
179
180
  _namespace: int = 1,
180
181
  _do_assert_no_mount_layers: bool = True,
181
182
  ): ...
@@ -668,6 +669,7 @@ class _Image(modal._object._Object):
668
669
  *commands: typing.Union[str, list[str]],
669
670
  env: typing.Optional[dict[str, typing.Optional[str]]] = None,
670
671
  secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
672
+ volumes: typing.Optional[dict[typing.Union[str, pathlib.PurePosixPath], modal.volume._Volume]] = None,
671
673
  gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
672
674
  force_build: bool = False,
673
675
  ) -> _Image:
@@ -1091,6 +1093,7 @@ class Image(modal.object.Object):
1091
1093
  ] = None,
1092
1094
  force_build: bool = False,
1093
1095
  build_args: dict[str, str] = {},
1096
+ validated_volumes: typing.Optional[collections.abc.Sequence[tuple[str, modal.volume.Volume]]] = None,
1094
1097
  _namespace: int = 1,
1095
1098
  _do_assert_no_mount_layers: bool = True,
1096
1099
  ): ...
@@ -1648,6 +1651,7 @@ class Image(modal.object.Object):
1648
1651
  *commands: typing.Union[str, list[str]],
1649
1652
  env: typing.Optional[dict[str, typing.Optional[str]]] = None,
1650
1653
  secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
1654
+ volumes: typing.Optional[dict[typing.Union[str, pathlib.PurePosixPath], modal.volume.Volume]] = None,
1651
1655
  gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
1652
1656
  force_build: bool = False,
1653
1657
  ) -> Image:
@@ -509,6 +509,13 @@ class _StreamReader(Generic[T]):
509
509
  ```
510
510
  """
511
511
 
512
+ _impl: Union[
513
+ _StreamReaderThroughServer,
514
+ _DevnullStreamReader,
515
+ _TextStreamReaderThroughCommandRouter,
516
+ _BytesStreamReaderThroughCommandRouter,
517
+ ]
518
+
512
519
  def __init__(
513
520
  self,
514
521
  file_descriptor: "api_pb2.FileDescriptor.ValueType",
@@ -198,6 +198,14 @@ class _StreamReader(typing.Generic[T]):
198
198
  print(f"Message: {message}")
199
199
  ```
200
200
  """
201
+
202
+ _impl: typing.Union[
203
+ _StreamReaderThroughServer,
204
+ _DevnullStreamReader,
205
+ _TextStreamReaderThroughCommandRouter,
206
+ _BytesStreamReaderThroughCommandRouter,
207
+ ]
208
+
201
209
  def __init__(
202
210
  self,
203
211
  file_descriptor: int,
@@ -390,6 +398,14 @@ class StreamReader(typing.Generic[T]):
390
398
  print(f"Message: {message}")
391
399
  ```
392
400
  """
401
+
402
+ _impl: typing.Union[
403
+ _StreamReaderThroughServer,
404
+ _DevnullStreamReader,
405
+ _TextStreamReaderThroughCommandRouter,
406
+ _BytesStreamReaderThroughCommandRouter,
407
+ ]
408
+
393
409
  def __init__(
394
410
  self,
395
411
  file_descriptor: int,
@@ -1265,7 +1265,7 @@ async def _put_missing_blocks(
1265
1265
  file_progress.pending_blocks.add(missing_block.block_index)
1266
1266
  task_progress_cb = functools.partial(progress_cb, task_id=file_progress.task_id)
1267
1267
 
1268
- @retry(n_attempts=5, base_delay=0.5, timeout=None)
1268
+ @retry(n_attempts=11, base_delay=0.5, timeout=None)
1269
1269
  async def put_missing_block_attempt(payload: BytesIOSegmentPayload) -> bytes:
1270
1270
  with payload.reset_on_error(subtract_progress=True):
1271
1271
  async with ClientSessionRegistry.get_session().put(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.1.dev23
3
+ Version: 1.2.2.dev3
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2025
2
2
  """Supplies the current version of the modal client library."""
3
3
 
4
- __version__ = "1.2.1.dev23"
4
+ __version__ = "1.2.2.dev3"
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