modal 1.4.4.dev6__tar.gz → 1.4.4.dev8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/PKG-INFO +1 -1
  2. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_runtime/asgi.py +1 -1
  3. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/shell.py +12 -10
  4. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/client.pyi +2 -2
  5. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/io_streams.py +1 -1
  6. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/io_streams.pyi +2 -0
  7. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/sandbox.py +78 -20
  8. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/sandbox.pyi +88 -33
  9. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/sandbox_fs.py +21 -16
  10. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/sandbox_fs.pyi +9 -2
  11. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal.egg-info/PKG-INFO +1 -1
  12. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_version/__init__.py +1 -1
  13. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/LICENSE +0 -0
  14. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/README.md +0 -0
  15. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/__init__.py +0 -0
  16. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/__main__.py +0 -0
  17. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_billing.py +0 -0
  18. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_clustered_functions.py +0 -0
  19. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_clustered_functions.pyi +0 -0
  20. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_container_entrypoint.py +0 -0
  21. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_environments.py +0 -0
  22. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_function_variants.py +0 -0
  23. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_functions.py +0 -0
  24. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_grpc_client.py +0 -0
  25. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_ipython.py +0 -0
  26. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_load_context.py +0 -0
  27. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_location.py +0 -0
  28. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_logs.py +0 -0
  29. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_object.py +0 -0
  30. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_output/__init__.py +0 -0
  31. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_output/manager.py +0 -0
  32. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_output/pty.py +0 -0
  33. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_output/rich.py +0 -0
  34. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_output/status.py +0 -0
  35. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_partial_function.py +0 -0
  36. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_resolver.py +0 -0
  37. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_resources.py +0 -0
  38. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_runtime/__init__.py +0 -0
  39. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_runtime/container_io_manager.py +0 -0
  40. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_runtime/container_io_manager.pyi +0 -0
  41. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_runtime/execution_context.py +0 -0
  42. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_runtime/execution_context.pyi +0 -0
  43. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  44. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_runtime/telemetry.py +0 -0
  45. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_runtime/user_code_event_loop.py +0 -0
  46. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_runtime/user_code_imports.py +0 -0
  47. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_serialization.py +0 -0
  48. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_server.py +0 -0
  49. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_traceback.py +0 -0
  50. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_tunnel.py +0 -0
  51. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_tunnel.pyi +0 -0
  52. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_type_manager.py +0 -0
  53. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/__init__.py +0 -0
  54. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/app_utils.py +0 -0
  55. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/async_utils.py +0 -0
  56. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/auth_token_manager.py +0 -0
  57. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/blob_utils.py +0 -0
  58. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/browser_utils.py +0 -0
  59. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/bytes_io_segment_payload.py +0 -0
  60. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/deprecation.py +0 -0
  61. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/docker_utils.py +0 -0
  62. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/function_utils.py +0 -0
  63. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/git_utils.py +0 -0
  64. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/grpc_testing.py +0 -0
  65. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/grpc_utils.py +0 -0
  66. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/hash_utils.py +0 -0
  67. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/http_utils.py +0 -0
  68. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/jwt_utils.py +0 -0
  69. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/logger.py +0 -0
  70. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/mount_utils.py +0 -0
  71. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/name_utils.py +0 -0
  72. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/package_utils.py +0 -0
  73. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/pattern_utils.py +0 -0
  74. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/rand_pb_testing.py +0 -0
  75. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/sandbox_fs_utils.py +0 -0
  76. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/shell_utils.py +0 -0
  77. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/task_command_router_client.py +0 -0
  78. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_utils/time_utils.py +0 -0
  79. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_vendor/__init__.py +0 -0
  80. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  81. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_vendor/cloudpickle.py +0 -0
  82. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_vendor/tblib.py +0 -0
  83. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_vendor/version.py +0 -0
  84. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/_watcher.py +0 -0
  85. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/app.py +0 -0
  86. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/app.pyi +0 -0
  87. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/billing.py +0 -0
  88. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/builder/2023.12.312.txt +0 -0
  89. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/builder/2023.12.txt +0 -0
  90. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/builder/2024.04.txt +0 -0
  91. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/builder/2024.10.txt +0 -0
  92. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/builder/2025.06.txt +0 -0
  93. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/builder/PREVIEW.txt +0 -0
  94. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/builder/README.md +0 -0
  95. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/builder/base-images.json +0 -0
  96. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/call_graph.py +0 -0
  97. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/__init__.py +0 -0
  98. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/_download.py +0 -0
  99. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/_help.py +0 -0
  100. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/_traceback.py +0 -0
  101. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/app.py +0 -0
  102. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/billing.py +0 -0
  103. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/bootstrap.py +0 -0
  104. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/changelog.py +0 -0
  105. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/cluster.py +0 -0
  106. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/config.py +0 -0
  107. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/container.py +0 -0
  108. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/dashboard.py +0 -0
  109. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/dict.py +0 -0
  110. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/entry_point.py +0 -0
  111. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/environment.py +0 -0
  112. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/import_refs.py +0 -0
  113. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/launch.py +0 -0
  114. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/logo.py +0 -0
  115. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/network_file_system.py +0 -0
  116. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/profile.py +0 -0
  117. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/programs/__init__.py +0 -0
  118. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/programs/run_jupyter.py +0 -0
  119. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/programs/vscode.py +0 -0
  120. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/queues.py +0 -0
  121. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/run.py +0 -0
  122. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/secret.py +0 -0
  123. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/selector.py +0 -0
  124. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/token.py +0 -0
  125. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/utils.py +0 -0
  126. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cli/volume.py +0 -0
  127. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/client.py +0 -0
  128. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cloud_bucket_mount.py +0 -0
  129. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cloud_bucket_mount.pyi +0 -0
  130. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cls.py +0 -0
  131. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/cls.pyi +0 -0
  132. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/config.py +0 -0
  133. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/container_process.py +0 -0
  134. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/container_process.pyi +0 -0
  135. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/dict.py +0 -0
  136. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/dict.pyi +0 -0
  137. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/environments.py +0 -0
  138. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/environments.pyi +0 -0
  139. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/exception.py +0 -0
  140. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/experimental/__init__.py +0 -0
  141. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/experimental/flash.py +0 -0
  142. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/experimental/flash.pyi +0 -0
  143. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/experimental/ipython.py +0 -0
  144. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/file_io.py +0 -0
  145. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/file_io.pyi +0 -0
  146. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/file_pattern_matcher.py +0 -0
  147. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/functions.py +0 -0
  148. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/functions.pyi +0 -0
  149. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/image.py +0 -0
  150. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/image.pyi +0 -0
  151. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/mount.py +0 -0
  152. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/mount.pyi +0 -0
  153. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/network_file_system.py +0 -0
  154. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/network_file_system.pyi +0 -0
  155. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/object.py +0 -0
  156. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/object.pyi +0 -0
  157. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/output.py +0 -0
  158. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/parallel_map.py +0 -0
  159. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/parallel_map.pyi +0 -0
  160. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/partial_function.py +0 -0
  161. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/partial_function.pyi +0 -0
  162. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/proxy.py +0 -0
  163. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/proxy.pyi +0 -0
  164. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/py.typed +0 -0
  165. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/queue.py +0 -0
  166. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/queue.pyi +0 -0
  167. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/retries.py +0 -0
  168. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/runner.py +0 -0
  169. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/runner.pyi +0 -0
  170. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/running_app.py +0 -0
  171. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/schedule.py +0 -0
  172. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/scheduler_placement.py +0 -0
  173. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/secret.py +0 -0
  174. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/secret.pyi +0 -0
  175. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/server.py +0 -0
  176. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/server.pyi +0 -0
  177. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/serving.py +0 -0
  178. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/serving.pyi +0 -0
  179. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/snapshot.py +0 -0
  180. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/snapshot.pyi +0 -0
  181. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/stream_type.py +0 -0
  182. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/token_flow.py +0 -0
  183. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/token_flow.pyi +0 -0
  184. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/volume.py +0 -0
  185. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal/volume.pyi +0 -0
  186. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal.egg-info/SOURCES.txt +0 -0
  187. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal.egg-info/dependency_links.txt +0 -0
  188. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal.egg-info/entry_points.txt +0 -0
  189. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal.egg-info/requires.txt +0 -0
  190. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal.egg-info/top_level.txt +0 -0
  191. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_docs/__init__.py +0 -0
  192. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_docs/gen_cli_docs.py +0 -0
  193. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_docs/gen_cli_docs_main.py +0 -0
  194. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_docs/gen_reference_docs.py +0 -0
  195. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_docs/gen_reference_docs_main.py +0 -0
  196. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_docs/mdmd/__init__.py +0 -0
  197. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_docs/mdmd/mdmd.py +0 -0
  198. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_docs/mdmd/signatures.py +0 -0
  199. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_proto/__init__.py +0 -0
  200. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_proto/api_grpc.py +0 -0
  201. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_proto/api_pb2.py +0 -0
  202. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_proto/api_pb2.pyi +0 -0
  203. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_proto/api_pb2_grpc.py +0 -0
  204. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_proto/api_pb2_grpc.pyi +0 -0
  205. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_proto/modal_api_grpc.py +0 -0
  206. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_proto/py.typed +0 -0
  207. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_proto/task_command_router_grpc.py +0 -0
  208. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_proto/task_command_router_pb2.py +0 -0
  209. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_proto/task_command_router_pb2.pyi +0 -0
  210. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  211. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  212. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/modal_version/__main__.py +0 -0
  213. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/pyproject.toml +0 -0
  214. {modal-1.4.4.dev6 → modal-1.4.4.dev8}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.4.4.dev6
3
+ Version: 1.4.4.dev8
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -285,7 +285,7 @@ def wait_for_web_server(host: str, port: int, *, timeout: float) -> None:
285
285
  start_time = time.monotonic()
286
286
  while True:
287
287
  try:
288
- with socket.create_connection((host, port), timeout=timeout):
288
+ with socket.create_connection((host, port), timeout=min(timeout, 1.0)):
289
289
  break
290
290
  except OSError as ex:
291
291
  time.sleep(0.01)
@@ -2,7 +2,7 @@
2
2
  import platform
3
3
  import shlex
4
4
  from pathlib import Path, PurePosixPath
5
- from typing import Any, Callable, Iterable, Optional
5
+ from typing import Any, Callable, Iterable, Optional, Union
6
6
 
7
7
  import click
8
8
  from click import ClickException
@@ -10,12 +10,13 @@ from click import ClickException
10
10
  from .._environments import ensure_env
11
11
  from .._functions import _FunctionSpec
12
12
  from ..app import App
13
+ from ..container_process import ContainerProcess
13
14
  from ..exception import InvalidError, NotFoundError
14
15
  from ..functions import Function
15
16
  from ..image import Image
16
17
  from ..mount import _Mount
17
18
  from ..runner import interactive_shell
18
- from ..sandbox import Sandbox
19
+ from ..sandbox import _MAIN_CONTAINER_NAME, Sandbox
19
20
  from ..secret import Secret
20
21
  from ..stream_type import StreamType
21
22
  from ..volume import Volume
@@ -105,8 +106,8 @@ def _is_running_container_ref(ref: Optional[str]) -> bool:
105
106
  return _is_valid_modal_id(sandbox_id, "sb-") or _is_valid_modal_id(ref, "ta-")
106
107
 
107
108
 
108
- def _start_shell_in_sandbox_container(sandbox_id: str, container_name: str, cmd: str, pty: bool) -> None:
109
- """Shell into a named container within a sandbox."""
109
+ def _start_shell_in_sidecar_container(sandbox_id: str, container_name: str, cmd: str, pty: bool) -> None:
110
+ """Shell into a sidecar container within a sandbox."""
110
111
  try:
111
112
  sandbox = Sandbox.from_id(sandbox_id)
112
113
  except NotFoundError:
@@ -115,18 +116,19 @@ def _start_shell_in_sandbox_container(sandbox_id: str, container_name: str, cmd:
115
116
  raise ClickException(f"Error connecting to Sandbox '{sandbox_id}': {str(e)}")
116
117
 
117
118
  try:
118
- sandbox_container = sandbox._experimental_containers.get(name=container_name)
119
+ sandbox_container = sandbox._experimental_sidecars.get(name=container_name)
120
+ process: Union[ContainerProcess[bytes], ContainerProcess[str]]
119
121
  if pty:
120
122
  # PTY output is raw terminal bytes, not text; strict UTF-8 decode
121
123
  # crashes on the first non-UTF-8 byte (e.g. vim drawing a Latin-1
122
124
  # file under LC_CTYPE=C). See the matching call in `_exec_impl`.
123
- process = sandbox_container.exec(*shlex.split(cmd), pty=pty, text=False)
125
+ process = sandbox_container.exec(*shlex.split(cmd), pty=True, text=False)
124
126
  process.attach()
125
127
  else:
126
128
  process = sandbox_container.exec(
127
- *shlex.split(cmd), pty=pty, stdout=StreamType.STDOUT, stderr=StreamType.STDOUT
129
+ *shlex.split(cmd), pty=False, text=False, stdout=StreamType.STDOUT, stderr=StreamType.STDOUT
128
130
  )
129
- process.wait()
131
+ _ = process.wait()
130
132
  except NotFoundError:
131
133
  raise ClickException(f"Container '{container_name}' not found in Sandbox '{sandbox_id}'.")
132
134
  except Exception as e:
@@ -136,8 +138,8 @@ def _start_shell_in_sandbox_container(sandbox_id: str, container_name: str, cmd:
136
138
  def _start_shell_in_running_container(ref: str, cmd: str, pty: bool) -> None:
137
139
  sandbox_id, container_name = _parse_sandbox_container_ref(ref)
138
140
 
139
- if container_name is not None:
140
- return _start_shell_in_sandbox_container(sandbox_id, container_name, cmd, pty)
141
+ if container_name is not None and container_name != _MAIN_CONTAINER_NAME:
142
+ return _start_shell_in_sidecar_container(sandbox_id, container_name, cmd, pty)
141
143
 
142
144
  if _is_valid_modal_id(sandbox_id, "sb-"):
143
145
  try:
@@ -35,7 +35,7 @@ class _Client:
35
35
  server_url: str,
36
36
  client_type: int,
37
37
  credentials: typing.Optional[tuple[str, str]],
38
- version: str = "1.4.4.dev6",
38
+ version: str = "1.4.4.dev8",
39
39
  ):
40
40
  """mdmd:hidden
41
41
  The Modal client object is not intended to be instantiated directly by users.
@@ -175,7 +175,7 @@ class Client:
175
175
  server_url: str,
176
176
  client_type: int,
177
177
  credentials: typing.Optional[tuple[str, str]],
178
- version: str = "1.4.4.dev6",
178
+ version: str = "1.4.4.dev8",
179
179
  ):
180
180
  """mdmd:hidden
181
181
  The Modal client object is not intended to be instantiated directly by users.
@@ -501,7 +501,7 @@ class _StreamReader(Generic[T]):
501
501
  MAX_BUFFER_SIZE = 2 * 1024 * 1024
502
502
  # Larger buffer limit for the exec path via the task command router.
503
503
  # This applies only to task_exec_stdin_write; sandbox stdin via the server keeps MAX_BUFFER_SIZE.
504
- TASK_COMMAND_ROUTER_MAX_BUFFER_SIZE = 16 * 1024 * 1024
504
+ TASK_COMMAND_ROUTER_MAX_BUFFER_SIZE: int = 16 * 1024 * 1024
505
505
 
506
506
 
507
507
  @dataclass(frozen=True)
@@ -589,3 +589,5 @@ class StreamWriter:
589
589
  ...
590
590
 
591
591
  drain: __drain_spec
592
+
593
+ TASK_COMMAND_ROUTER_MAX_BUFFER_SIZE: int
@@ -5,6 +5,7 @@ import enum
5
5
  import json
6
6
  import os
7
7
  import time
8
+ import typing
8
9
  import uuid
9
10
  from collections.abc import AsyncGenerator, Collection, Sequence
10
11
  from dataclasses import dataclass
@@ -1385,10 +1386,10 @@ class _Sandbox(_Object, type_prefix="sb"):
1385
1386
  return self._command_router_client
1386
1387
 
1387
1388
  @property
1388
- def _experimental_containers(self) -> "_SandboxContainerManager":
1389
- """Manage additional containers running in this Sandbox."""
1389
+ def _experimental_sidecars(self) -> "_SidecarManager":
1390
+ """Manage sidecar containers running in this Sandbox."""
1390
1391
  self._ensure_attached()
1391
- return _SandboxContainerManager(self)
1392
+ return _SidecarManager(self)
1392
1393
 
1393
1394
  @overload
1394
1395
  async def exec(
@@ -1853,10 +1854,11 @@ class _Sandbox(_Object, type_prefix="sb"):
1853
1854
  before_timestamp = resp.sandboxes[-1].created_at
1854
1855
 
1855
1856
 
1856
- class _SandboxContainer:
1857
+ class _SidecarContainer:
1857
1858
  """Handle to an additional container running in a Sandbox."""
1858
1859
 
1859
1860
  _result: Optional[api_pb2.GenericResult]
1861
+ _filesystem: Optional[_SandboxFilesystem]
1860
1862
 
1861
1863
  def __init__(
1862
1864
  self,
@@ -1869,6 +1871,7 @@ class _SandboxContainer:
1869
1871
  self._container_id = container_id
1870
1872
  self._container_name = container_name
1871
1873
  self._result = result
1874
+ self._filesystem = None
1872
1875
 
1873
1876
  @property
1874
1877
  def object_id(self) -> str:
@@ -1879,9 +1882,9 @@ class _SandboxContainer:
1879
1882
  return self._container_name
1880
1883
 
1881
1884
  @staticmethod
1882
- def _from_container_info(sandbox: "_Sandbox", container_info: sr_pb2.TaskContainerInfo) -> "_SandboxContainer":
1885
+ def _from_container_info(sandbox: "_Sandbox", container_info: sr_pb2.TaskContainerInfo) -> "_SidecarContainer":
1883
1886
  result = container_info.result if container_info.HasField("result") else None
1884
- return _SandboxContainer(sandbox, container_info.container_id, container_info.container_name, result)
1887
+ return _SidecarContainer(sandbox, container_info.container_id, container_info.container_name, result)
1885
1888
 
1886
1889
  async def _get_command_router(self) -> tuple[str, "TaskCommandRouterClient"]:
1887
1890
  """Get task ID and command router client."""
@@ -1889,6 +1892,40 @@ class _SandboxContainer:
1889
1892
  command_router_client = await self._sandbox._get_command_router_client(task_id)
1890
1893
  return task_id, command_router_client
1891
1894
 
1895
+ @typing.overload
1896
+ async def exec(
1897
+ self,
1898
+ *args: str,
1899
+ stdout: StreamType = StreamType.PIPE,
1900
+ stderr: StreamType = StreamType.PIPE,
1901
+ timeout: Optional[int] = None,
1902
+ workdir: Optional[str] = None,
1903
+ env: Optional[dict[str, Optional[str]]] = None,
1904
+ secrets: Optional[Collection[_Secret]] = None,
1905
+ text: Literal[True] = True,
1906
+ bufsize: Literal[-1, 1] = -1,
1907
+ # Enable a PTY for the command. When enabled, all output (stdout and stderr from the
1908
+ # process) is multiplexed into stdout, and the stderr stream is effectively empty.
1909
+ pty: bool = False,
1910
+ ) -> _ContainerProcess[str]: ...
1911
+
1912
+ @typing.overload
1913
+ async def exec(
1914
+ self,
1915
+ *args: str,
1916
+ stdout: StreamType = StreamType.PIPE,
1917
+ stderr: StreamType = StreamType.PIPE,
1918
+ timeout: Optional[int] = None,
1919
+ workdir: Optional[str] = None,
1920
+ env: Optional[dict[str, Optional[str]]] = None,
1921
+ secrets: Optional[Collection[_Secret]] = None,
1922
+ text: Literal[False],
1923
+ bufsize: Literal[-1, 1] = -1,
1924
+ # Enable a PTY for the command. When enabled, all output (stdout and stderr from the
1925
+ # process) is multiplexed into stdout, and the stderr stream is effectively empty.
1926
+ pty: bool = False,
1927
+ ) -> _ContainerProcess[bytes]: ...
1928
+
1892
1929
  async def exec(
1893
1930
  self,
1894
1931
  *args: str,
@@ -1919,6 +1956,13 @@ class _SandboxContainer:
1919
1956
  container_id=self._container_id,
1920
1957
  )
1921
1958
 
1959
+ @property
1960
+ def filesystem(self) -> _SandboxFilesystem:
1961
+ """Namespace for filesystem APIs."""
1962
+ if self._filesystem is None:
1963
+ self._filesystem = _SandboxFilesystem(self)
1964
+ return self._filesystem
1965
+
1922
1966
  async def wait(self, raise_on_termination: bool = True) -> None:
1923
1967
  if self._result is not None and self._result.status != api_pb2.GenericResult.GENERIC_STATUS_UNSPECIFIED:
1924
1968
  if self._result.status == api_pb2.GenericResult.GENERIC_STATUS_TERMINATED and raise_on_termination:
@@ -1987,8 +2031,11 @@ class _SandboxContainer:
1987
2031
  return _result_returncode(self._result)
1988
2032
 
1989
2033
 
1990
- class _SandboxContainerManager:
1991
- """Creates and manages additional containers in a Sandbox."""
2034
+ _MAIN_CONTAINER_NAME: str = "main"
2035
+
2036
+
2037
+ class _SidecarManager:
2038
+ """Creates and manages sidecar containers in a Sandbox."""
1992
2039
 
1993
2040
  def __init__(self, sandbox: _Sandbox) -> None:
1994
2041
  self._sandbox = sandbox
@@ -2007,22 +2054,24 @@ class _SandboxContainerManager:
2007
2054
  env: Optional[dict[str, str]] = None,
2008
2055
  secrets: Optional[Collection[_Secret]] = None,
2009
2056
  workdir: Optional[str] = None,
2010
- ) -> _SandboxContainer:
2057
+ ) -> _SidecarContainer:
2058
+ if name == _MAIN_CONTAINER_NAME:
2059
+ raise InvalidError(f"The name {_MAIN_CONTAINER_NAME!r} is reserved for the sandbox's main container.")
2011
2060
  if workdir is not None and not workdir.startswith("/"):
2012
2061
  raise InvalidError(f"workdir must be an absolute path, got: {workdir}")
2013
2062
  _validate_exec_args(args)
2014
2063
 
2015
2064
  if image._mount_layers:
2016
2065
  raise InvalidError(
2017
- "Sandbox._experimental_containers.create(image=...) only supports pre-built images. "
2066
+ "Sandbox._experimental_sidecars.create(image=...) only supports pre-built images. "
2018
2067
  "When using `add_local*` methods, specify `copy=True` and call `.build()` before passing "
2019
- "the image to `._experimental_containers.create()`:\n\nE.g.\n"
2068
+ "the image to `._experimental_sidecars.create()`:\n\nE.g.\n"
2020
2069
  'img = modal.Image.debian_slim().add_local_file("foo", "/foo", copy=True).build(app)\n'
2021
- 'sandbox._experimental_containers.create(name="worker", image=img)'
2070
+ 'sandbox._experimental_sidecars.create(name="worker", image=img)'
2022
2071
  )
2023
2072
  if not image._object_id:
2024
2073
  raise InvalidError(
2025
- "Sandbox._experimental_containers.create(image=...) currently only supports Images that are "
2074
+ "Sandbox._experimental_sidecars.create(image=...) currently only supports Images that are "
2026
2075
  "either:\n"
2027
2076
  "- prebuilt using `image.build()`\n"
2028
2077
  "- referenced by id, e.g. `Image.from_id()`\n"
@@ -2048,9 +2097,14 @@ class _SandboxContainerManager:
2048
2097
  create_resp = await command_router_client.container_create(create_req)
2049
2098
  container_id = create_resp.container_id
2050
2099
  container_name = create_resp.container_name or name
2051
- return _SandboxContainer(self._sandbox, container_id, container_name)
2100
+ return _SidecarContainer(self._sandbox, container_id, container_name)
2052
2101
 
2053
- async def get(self, *, name: str, include_terminated: bool = False) -> "_SandboxContainer":
2102
+ async def get(self, *, name: str, include_terminated: bool = False) -> "_SidecarContainer":
2103
+ if name == _MAIN_CONTAINER_NAME:
2104
+ raise InvalidError(
2105
+ "Cannot get the main sandbox container through the sidecars API. "
2106
+ "Use Sandbox methods directly to interact with the main container."
2107
+ )
2054
2108
  task_id, command_router_client = await self._get_command_router()
2055
2109
  resp = await command_router_client.container_get(
2056
2110
  sr_pb2.TaskContainerGetRequest(
@@ -2059,16 +2113,20 @@ class _SandboxContainerManager:
2059
2113
  include_terminated=include_terminated,
2060
2114
  )
2061
2115
  )
2062
- return _SandboxContainer._from_container_info(self._sandbox, resp.container)
2116
+ return _SidecarContainer._from_container_info(self._sandbox, resp.container)
2063
2117
 
2064
- async def list(self, include_terminated: bool = False) -> builtins.list[_SandboxContainer]:
2118
+ async def list(self, include_terminated: bool = False) -> builtins.list[_SidecarContainer]:
2065
2119
  task_id, command_router_client = await self._get_command_router()
2066
2120
  resp = await command_router_client.container_list(
2067
2121
  sr_pb2.TaskContainerListRequest(task_id=task_id, include_terminated=include_terminated)
2068
2122
  )
2069
- return [_SandboxContainer._from_container_info(self._sandbox, container) for container in resp.containers]
2123
+ return [
2124
+ _SidecarContainer._from_container_info(self._sandbox, container)
2125
+ for container in resp.containers
2126
+ if container.container_name != _MAIN_CONTAINER_NAME
2127
+ ]
2070
2128
 
2071
2129
 
2072
- SandboxContainer = synchronize_api(_SandboxContainer)
2073
- SandboxContainerManager = synchronize_api(_SandboxContainerManager)
2130
+ SidecarContainer = synchronize_api(_SidecarContainer)
2131
+ SidecarManager = synchronize_api(_SidecarManager)
2074
2132
  Sandbox = synchronize_api(_Sandbox)
@@ -533,8 +533,8 @@ class _Sandbox(modal._object._Object):
533
533
  self, task_id: str
534
534
  ) -> modal._utils.task_command_router_client.TaskCommandRouterClient: ...
535
535
  @property
536
- def _experimental_containers(self) -> _SandboxContainerManager:
537
- """Manage additional containers running in this Sandbox."""
536
+ def _experimental_sidecars(self) -> _SidecarManager:
537
+ """Manage sidecar containers running in this Sandbox."""
538
538
  ...
539
539
 
540
540
  @typing.overload
@@ -697,10 +697,11 @@ class _Sandbox(modal._object._Object):
697
697
  """
698
698
  ...
699
699
 
700
- class _SandboxContainer:
700
+ class _SidecarContainer:
701
701
  """Handle to an additional container running in a Sandbox."""
702
702
 
703
703
  _result: typing.Optional[modal_proto.api_pb2.GenericResult]
704
+ _filesystem: typing.Optional[modal.sandbox_fs._SandboxFilesystem]
704
705
 
705
706
  def __init__(
706
707
  self,
@@ -719,11 +720,12 @@ class _SandboxContainer:
719
720
  @staticmethod
720
721
  def _from_container_info(
721
722
  sandbox: _Sandbox, container_info: modal_proto.task_command_router_pb2.TaskContainerInfo
722
- ) -> _SandboxContainer: ...
723
+ ) -> _SidecarContainer: ...
723
724
  async def _get_command_router(self) -> tuple[str, modal._utils.task_command_router_client.TaskCommandRouterClient]:
724
725
  """Get task ID and command router client."""
725
726
  ...
726
727
 
728
+ @typing.overload
727
729
  async def exec(
728
730
  self,
729
731
  *args: str,
@@ -733,12 +735,29 @@ class _SandboxContainer:
733
735
  workdir: typing.Optional[str] = None,
734
736
  env: typing.Optional[dict[str, typing.Optional[str]]] = None,
735
737
  secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
736
- text: bool = True,
738
+ text: typing.Literal[True] = True,
739
+ bufsize: typing.Literal[-1, 1] = -1,
740
+ pty: bool = False,
741
+ ) -> modal.container_process._ContainerProcess[str]: ...
742
+ @typing.overload
743
+ async def exec(
744
+ self,
745
+ *args: str,
746
+ stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
747
+ stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
748
+ timeout: typing.Optional[int] = None,
749
+ workdir: typing.Optional[str] = None,
750
+ env: typing.Optional[dict[str, typing.Optional[str]]] = None,
751
+ secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
752
+ text: typing.Literal[False],
737
753
  bufsize: typing.Literal[-1, 1] = -1,
738
754
  pty: bool = False,
739
- ) -> typing.Union[
740
- modal.container_process._ContainerProcess[bytes], modal.container_process._ContainerProcess[str]
741
- ]: ...
755
+ ) -> modal.container_process._ContainerProcess[bytes]: ...
756
+ @property
757
+ def filesystem(self) -> modal.sandbox_fs._SandboxFilesystem:
758
+ """Namespace for filesystem APIs."""
759
+ ...
760
+
742
761
  async def wait(self, raise_on_termination: bool = True) -> None: ...
743
762
  async def poll(self) -> typing.Optional[int]: ...
744
763
  @typing.overload
@@ -746,8 +765,8 @@ class _SandboxContainer:
746
765
  @typing.overload
747
766
  async def terminate(self, *, wait: typing.Literal[False] = False) -> None: ...
748
767
 
749
- class _SandboxContainerManager:
750
- """Creates and manages additional containers in a Sandbox."""
768
+ class _SidecarManager:
769
+ """Creates and manages sidecar containers in a Sandbox."""
751
770
  def __init__(self, sandbox: _Sandbox) -> None:
752
771
  """Initialize self. See help(type(self)) for accurate signature."""
753
772
  ...
@@ -764,14 +783,15 @@ class _SandboxContainerManager:
764
783
  env: typing.Optional[dict[str, str]] = None,
765
784
  secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
766
785
  workdir: typing.Optional[str] = None,
767
- ) -> _SandboxContainer: ...
768
- async def get(self, *, name: str, include_terminated: bool = False) -> _SandboxContainer: ...
769
- async def list(self, include_terminated: bool = False) -> list[_SandboxContainer]: ...
786
+ ) -> _SidecarContainer: ...
787
+ async def get(self, *, name: str, include_terminated: bool = False) -> _SidecarContainer: ...
788
+ async def list(self, include_terminated: bool = False) -> list[_SidecarContainer]: ...
770
789
 
771
- class SandboxContainer:
790
+ class SidecarContainer:
772
791
  """Handle to an additional container running in a Sandbox."""
773
792
 
774
793
  _result: typing.Optional[modal_proto.api_pb2.GenericResult]
794
+ _filesystem: typing.Optional[modal.sandbox_fs.SandboxFilesystem]
775
795
 
776
796
  def __init__(
777
797
  self,
@@ -787,7 +807,7 @@ class SandboxContainer:
787
807
  @staticmethod
788
808
  def _from_container_info(
789
809
  sandbox: Sandbox, container_info: modal_proto.task_command_router_pb2.TaskContainerInfo
790
- ) -> SandboxContainer: ...
810
+ ) -> SidecarContainer: ...
791
811
 
792
812
  class ___get_command_router_spec(typing_extensions.Protocol):
793
813
  def __call__(self, /) -> tuple[str, modal._utils.task_command_router_client.TaskCommandRouterClient]:
@@ -801,6 +821,7 @@ class SandboxContainer:
801
821
  _get_command_router: ___get_command_router_spec
802
822
 
803
823
  class __exec_spec(typing_extensions.Protocol):
824
+ @typing.overload
804
825
  def __call__(
805
826
  self,
806
827
  /,
@@ -811,12 +832,26 @@ class SandboxContainer:
811
832
  workdir: typing.Optional[str] = None,
812
833
  env: typing.Optional[dict[str, typing.Optional[str]]] = None,
813
834
  secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
814
- text: bool = True,
835
+ text: typing.Literal[True] = True,
815
836
  bufsize: typing.Literal[-1, 1] = -1,
816
837
  pty: bool = False,
817
- ) -> typing.Union[
818
- modal.container_process.ContainerProcess[bytes], modal.container_process.ContainerProcess[str]
819
- ]: ...
838
+ ) -> modal.container_process.ContainerProcess[str]: ...
839
+ @typing.overload
840
+ def __call__(
841
+ self,
842
+ /,
843
+ *args: str,
844
+ stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
845
+ stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
846
+ timeout: typing.Optional[int] = None,
847
+ workdir: typing.Optional[str] = None,
848
+ env: typing.Optional[dict[str, typing.Optional[str]]] = None,
849
+ secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
850
+ text: typing.Literal[False],
851
+ bufsize: typing.Literal[-1, 1] = -1,
852
+ pty: bool = False,
853
+ ) -> modal.container_process.ContainerProcess[bytes]: ...
854
+ @typing.overload
820
855
  async def aio(
821
856
  self,
822
857
  /,
@@ -827,15 +862,33 @@ class SandboxContainer:
827
862
  workdir: typing.Optional[str] = None,
828
863
  env: typing.Optional[dict[str, typing.Optional[str]]] = None,
829
864
  secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
830
- text: bool = True,
865
+ text: typing.Literal[True] = True,
831
866
  bufsize: typing.Literal[-1, 1] = -1,
832
867
  pty: bool = False,
833
- ) -> typing.Union[
834
- modal.container_process.ContainerProcess[bytes], modal.container_process.ContainerProcess[str]
835
- ]: ...
868
+ ) -> modal.container_process.ContainerProcess[str]: ...
869
+ @typing.overload
870
+ async def aio(
871
+ self,
872
+ /,
873
+ *args: str,
874
+ stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
875
+ stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
876
+ timeout: typing.Optional[int] = None,
877
+ workdir: typing.Optional[str] = None,
878
+ env: typing.Optional[dict[str, typing.Optional[str]]] = None,
879
+ secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
880
+ text: typing.Literal[False],
881
+ bufsize: typing.Literal[-1, 1] = -1,
882
+ pty: bool = False,
883
+ ) -> modal.container_process.ContainerProcess[bytes]: ...
836
884
 
837
885
  exec: __exec_spec
838
886
 
887
+ @property
888
+ def filesystem(self) -> modal.sandbox_fs.SandboxFilesystem:
889
+ """Namespace for filesystem APIs."""
890
+ ...
891
+
839
892
  class __wait_spec(typing_extensions.Protocol):
840
893
  def __call__(self, /, raise_on_termination: bool = True) -> None: ...
841
894
  async def aio(self, /, raise_on_termination: bool = True) -> None: ...
@@ -860,8 +913,8 @@ class SandboxContainer:
860
913
 
861
914
  terminate: __terminate_spec
862
915
 
863
- class SandboxContainerManager:
864
- """Creates and manages additional containers in a Sandbox."""
916
+ class SidecarManager:
917
+ """Creates and manages sidecar containers in a Sandbox."""
865
918
  def __init__(self, sandbox: Sandbox) -> None: ...
866
919
 
867
920
  class ___get_command_router_spec(typing_extensions.Protocol):
@@ -885,7 +938,7 @@ class SandboxContainerManager:
885
938
  env: typing.Optional[dict[str, str]] = None,
886
939
  secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
887
940
  workdir: typing.Optional[str] = None,
888
- ) -> SandboxContainer: ...
941
+ ) -> SidecarContainer: ...
889
942
  async def aio(
890
943
  self,
891
944
  /,
@@ -895,19 +948,19 @@ class SandboxContainerManager:
895
948
  env: typing.Optional[dict[str, str]] = None,
896
949
  secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
897
950
  workdir: typing.Optional[str] = None,
898
- ) -> SandboxContainer: ...
951
+ ) -> SidecarContainer: ...
899
952
 
900
953
  create: __create_spec
901
954
 
902
955
  class __get_spec(typing_extensions.Protocol):
903
- def __call__(self, /, *, name: str, include_terminated: bool = False) -> SandboxContainer: ...
904
- async def aio(self, /, *, name: str, include_terminated: bool = False) -> SandboxContainer: ...
956
+ def __call__(self, /, *, name: str, include_terminated: bool = False) -> SidecarContainer: ...
957
+ async def aio(self, /, *, name: str, include_terminated: bool = False) -> SidecarContainer: ...
905
958
 
906
959
  get: __get_spec
907
960
 
908
961
  class __list_spec(typing_extensions.Protocol):
909
- def __call__(self, /, include_terminated: bool = False) -> list[SandboxContainer]: ...
910
- async def aio(self, /, include_terminated: bool = False) -> list[SandboxContainer]: ...
962
+ def __call__(self, /, include_terminated: bool = False) -> list[SidecarContainer]: ...
963
+ async def aio(self, /, include_terminated: bool = False) -> list[SidecarContainer]: ...
911
964
 
912
965
  list: __list_spec
913
966
 
@@ -1707,8 +1760,8 @@ class Sandbox(modal.object.Object):
1707
1760
  _get_command_router_client: ___get_command_router_client_spec
1708
1761
 
1709
1762
  @property
1710
- def _experimental_containers(self) -> SandboxContainerManager:
1711
- """Manage additional containers running in this Sandbox."""
1763
+ def _experimental_sidecars(self) -> SidecarManager:
1764
+ """Manage sidecar containers running in this Sandbox."""
1712
1765
  ...
1713
1766
 
1714
1767
  class __exec_spec(typing_extensions.Protocol):
@@ -2060,3 +2113,5 @@ class Sandbox(modal.object.Object):
2060
2113
  list: typing.ClassVar[__list_spec]
2061
2114
 
2062
2115
  _default_image: modal.image._Image
2116
+
2117
+ _MAIN_CONTAINER_NAME: str