modAL 1.2.4.dev2__tar.gz → 1.2.5.dev0__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 (201) hide show
  1. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/PKG-INFO +1 -1
  2. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/entry_point.py +2 -2
  3. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/run.py +3 -222
  4. modal-1.2.5.dev0/modal/cli/shell.py +237 -0
  5. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/client.pyi +2 -2
  6. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/functions.pyi +6 -6
  7. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal.egg-info/PKG-INFO +1 -1
  8. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal.egg-info/SOURCES.txt +1 -0
  9. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_version/__init__.py +1 -1
  10. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/LICENSE +0 -0
  11. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/README.md +0 -0
  12. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/__init__.py +0 -0
  13. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/__main__.py +0 -0
  14. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_billing.py +0 -0
  15. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_clustered_functions.py +0 -0
  16. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_clustered_functions.pyi +0 -0
  17. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_container_entrypoint.py +0 -0
  18. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_functions.py +0 -0
  19. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_grpc_client.py +0 -0
  20. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_ipython.py +0 -0
  21. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_load_context.py +0 -0
  22. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_location.py +0 -0
  23. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_object.py +0 -0
  24. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_output.py +0 -0
  25. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_partial_function.py +0 -0
  26. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_pty.py +0 -0
  27. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_resolver.py +0 -0
  28. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_resources.py +0 -0
  29. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_runtime/__init__.py +0 -0
  30. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_runtime/asgi.py +0 -0
  31. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_runtime/container_io_manager.py +0 -0
  32. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_runtime/container_io_manager.pyi +0 -0
  33. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_runtime/execution_context.py +0 -0
  34. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_runtime/execution_context.pyi +0 -0
  35. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  36. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_runtime/telemetry.py +0 -0
  37. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_runtime/user_code_imports.py +0 -0
  38. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_serialization.py +0 -0
  39. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_traceback.py +0 -0
  40. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_tunnel.py +0 -0
  41. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_tunnel.pyi +0 -0
  42. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_type_manager.py +0 -0
  43. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/__init__.py +0 -0
  44. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/app_utils.py +0 -0
  45. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/async_utils.py +0 -0
  46. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/auth_token_manager.py +0 -0
  47. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/blob_utils.py +0 -0
  48. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/bytes_io_segment_payload.py +0 -0
  49. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/deprecation.py +0 -0
  50. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/docker_utils.py +0 -0
  51. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/function_utils.py +0 -0
  52. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/git_utils.py +0 -0
  53. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/grpc_testing.py +0 -0
  54. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/grpc_utils.py +0 -0
  55. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/hash_utils.py +0 -0
  56. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/http_utils.py +0 -0
  57. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/jwt_utils.py +0 -0
  58. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/logger.py +0 -0
  59. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/mount_utils.py +0 -0
  60. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/name_utils.py +0 -0
  61. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/package_utils.py +0 -0
  62. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/pattern_utils.py +0 -0
  63. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/rand_pb_testing.py +0 -0
  64. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/shell_utils.py +0 -0
  65. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/task_command_router_client.py +0 -0
  66. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_utils/time_utils.py +0 -0
  67. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_vendor/__init__.py +0 -0
  68. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  69. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_vendor/cloudpickle.py +0 -0
  70. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_vendor/tblib.py +0 -0
  71. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/_watcher.py +0 -0
  72. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/app.py +0 -0
  73. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/app.pyi +0 -0
  74. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/billing.py +0 -0
  75. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/builder/2023.12.312.txt +0 -0
  76. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/builder/2023.12.txt +0 -0
  77. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/builder/2024.04.txt +0 -0
  78. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/builder/2024.10.txt +0 -0
  79. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/builder/2025.06.txt +0 -0
  80. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/builder/PREVIEW.txt +0 -0
  81. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/builder/README.md +0 -0
  82. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/builder/base-images.json +0 -0
  83. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/call_graph.py +0 -0
  84. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/__init__.py +0 -0
  85. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/_download.py +0 -0
  86. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/_traceback.py +0 -0
  87. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/app.py +0 -0
  88. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/cluster.py +0 -0
  89. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/config.py +0 -0
  90. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/container.py +0 -0
  91. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/dict.py +0 -0
  92. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/environment.py +0 -0
  93. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/import_refs.py +0 -0
  94. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/launch.py +0 -0
  95. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/network_file_system.py +0 -0
  96. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/profile.py +0 -0
  97. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/programs/__init__.py +0 -0
  98. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/programs/launch_instance_ssh.py +0 -0
  99. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/programs/run_jupyter.py +0 -0
  100. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/programs/run_marimo.py +0 -0
  101. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/programs/vscode.py +0 -0
  102. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/queues.py +0 -0
  103. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/secret.py +0 -0
  104. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/token.py +0 -0
  105. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/utils.py +0 -0
  106. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cli/volume.py +0 -0
  107. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/client.py +0 -0
  108. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cloud_bucket_mount.py +0 -0
  109. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cloud_bucket_mount.pyi +0 -0
  110. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cls.py +0 -0
  111. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/cls.pyi +0 -0
  112. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/config.py +0 -0
  113. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/container_process.py +0 -0
  114. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/container_process.pyi +0 -0
  115. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/dict.py +0 -0
  116. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/dict.pyi +0 -0
  117. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/environments.py +0 -0
  118. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/environments.pyi +0 -0
  119. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/exception.py +0 -0
  120. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/experimental/__init__.py +0 -0
  121. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/experimental/flash.py +0 -0
  122. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/experimental/flash.pyi +0 -0
  123. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/experimental/ipython.py +0 -0
  124. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/file_io.py +0 -0
  125. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/file_io.pyi +0 -0
  126. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/file_pattern_matcher.py +0 -0
  127. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/functions.py +0 -0
  128. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/gpu.py +0 -0
  129. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/image.py +0 -0
  130. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/image.pyi +0 -0
  131. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/io_streams.py +0 -0
  132. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/io_streams.pyi +0 -0
  133. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/mount.py +0 -0
  134. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/mount.pyi +0 -0
  135. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/network_file_system.py +0 -0
  136. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/network_file_system.pyi +0 -0
  137. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/object.py +0 -0
  138. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/object.pyi +0 -0
  139. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/output.py +0 -0
  140. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/parallel_map.py +0 -0
  141. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/parallel_map.pyi +0 -0
  142. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/partial_function.py +0 -0
  143. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/partial_function.pyi +0 -0
  144. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/proxy.py +0 -0
  145. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/proxy.pyi +0 -0
  146. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/py.typed +0 -0
  147. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/queue.py +0 -0
  148. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/queue.pyi +0 -0
  149. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/retries.py +0 -0
  150. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/runner.py +0 -0
  151. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/runner.pyi +0 -0
  152. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/running_app.py +0 -0
  153. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/sandbox.py +0 -0
  154. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/sandbox.pyi +0 -0
  155. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/schedule.py +0 -0
  156. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/scheduler_placement.py +0 -0
  157. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/secret.py +0 -0
  158. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/secret.pyi +0 -0
  159. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/serving.py +0 -0
  160. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/serving.pyi +0 -0
  161. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/snapshot.py +0 -0
  162. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/snapshot.pyi +0 -0
  163. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/stream_type.py +0 -0
  164. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/token_flow.py +0 -0
  165. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/token_flow.pyi +0 -0
  166. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/volume.py +0 -0
  167. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal/volume.pyi +0 -0
  168. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal.egg-info/dependency_links.txt +0 -0
  169. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal.egg-info/entry_points.txt +0 -0
  170. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal.egg-info/requires.txt +0 -0
  171. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal.egg-info/top_level.txt +0 -0
  172. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_docs/__init__.py +0 -0
  173. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_docs/gen_cli_docs.py +0 -0
  174. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_docs/gen_reference_docs.py +0 -0
  175. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_docs/mdmd/__init__.py +0 -0
  176. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_docs/mdmd/mdmd.py +0 -0
  177. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_docs/mdmd/signatures.py +0 -0
  178. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/__init__.py +0 -0
  179. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/api.proto +0 -0
  180. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/api_grpc.py +0 -0
  181. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/api_pb2.py +0 -0
  182. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/api_pb2.pyi +0 -0
  183. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/api_pb2_grpc.py +0 -0
  184. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/api_pb2_grpc.pyi +0 -0
  185. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/modal_api_grpc.py +0 -0
  186. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/py.typed +0 -0
  187. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/sandbox_router.proto +0 -0
  188. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/sandbox_router_grpc.py +0 -0
  189. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/sandbox_router_pb2.py +0 -0
  190. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/sandbox_router_pb2.pyi +0 -0
  191. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/sandbox_router_pb2_grpc.py +0 -0
  192. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/sandbox_router_pb2_grpc.pyi +0 -0
  193. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/task_command_router.proto +0 -0
  194. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/task_command_router_grpc.py +0 -0
  195. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/task_command_router_pb2.py +0 -0
  196. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/task_command_router_pb2.pyi +0 -0
  197. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  198. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  199. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/modal_version/__main__.py +0 -0
  200. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/pyproject.toml +0 -0
  201. {modal-1.2.4.dev2 → modal-1.2.5.dev0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.4.dev2
3
+ Version: 1.2.5.dev0
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -8,7 +8,7 @@ from rich.rule import Rule
8
8
  from modal._output import make_console
9
9
  from modal._utils.async_utils import synchronizer
10
10
 
11
- from . import run
11
+ from . import run, shell as shell_module
12
12
  from .app import app_cli
13
13
  from .cluster import cluster_cli
14
14
  from .config import config_cli
@@ -94,7 +94,7 @@ async def setup(profile: Optional[str] = None):
94
94
  # Commands
95
95
  entrypoint_cli_typer.command("deploy", no_args_is_help=True)(run.deploy)
96
96
  entrypoint_cli_typer.command("serve", no_args_is_help=True)(run.serve)
97
- entrypoint_cli_typer.command("shell")(run.shell)
97
+ entrypoint_cli_typer.command("shell")(shell_module.shell)
98
98
  entrypoint_cli_typer.add_typer(launch_cli)
99
99
 
100
100
  # Deployments
@@ -2,15 +2,11 @@
2
2
  import asyncio
3
3
  import functools
4
4
  import inspect
5
- import platform
6
5
  import re
7
- import shlex
8
6
  import sys
9
7
  import time
10
8
  import typing
11
9
  from dataclasses import dataclass
12
- from functools import partial
13
- from pathlib import Path, PurePosixPath
14
10
  from typing import Any, Callable, Optional
15
11
 
16
12
  import click
@@ -18,20 +14,15 @@ import typer
18
14
  from click import ClickException
19
15
  from typing_extensions import TypedDict
20
16
 
21
- from .._functions import _FunctionSpec
22
17
  from ..app import App, LocalEntrypoint
23
18
  from ..cls import _get_class_constructor_signature
24
19
  from ..config import config
25
20
  from ..environments import ensure_env
26
- from ..exception import ExecutionError, InvalidError, NotFoundError, _CliUserExecutionError
21
+ from ..exception import ExecutionError, InvalidError, _CliUserExecutionError
27
22
  from ..functions import Function
28
- from ..image import Image
29
- from ..mount import _Mount
30
23
  from ..output import enable_output
31
- from ..runner import deploy_app, interactive_shell, run_app
32
- from ..secret import Secret
24
+ from ..runner import deploy_app, run_app
33
25
  from ..serving import serve_app
34
- from ..volume import Volume
35
26
  from .import_refs import (
36
27
  CLICommand,
37
28
  MethodReference,
@@ -40,7 +31,7 @@ from .import_refs import (
40
31
  import_app_from_ref,
41
32
  parse_import_ref,
42
33
  )
43
- from .utils import ENV_OPTION, ENV_OPTION_HELP, is_tty, stream_app_logs
34
+ from .utils import ENV_OPTION, ENV_OPTION_HELP, stream_app_logs
44
35
 
45
36
 
46
37
  class ParameterMetadata(TypedDict):
@@ -521,213 +512,3 @@ def serve(
521
512
  t = min(timeout, 3600)
522
513
  time.sleep(t)
523
514
  timeout -= t
524
-
525
-
526
- def shell(
527
- ref: Optional[str] = typer.Argument(
528
- default=None,
529
- help=(
530
- "ID of running container or Sandbox, or path to a Python file containing an App."
531
- " Can also include a Function specifier, like `module.py::func`, if the file defines multiple Functions."
532
- ),
533
- ),
534
- cmd: str = typer.Option("/bin/bash", "-c", "--cmd", help="Command to run inside the Modal image."),
535
- env: str = ENV_OPTION,
536
- image: Optional[str] = typer.Option(
537
- default=None, help="Container image tag for inside the shell (if not using REF)."
538
- ),
539
- add_python: Optional[str] = typer.Option(default=None, help="Add Python to the image (if not using REF)."),
540
- volume: Optional[list[str]] = typer.Option(
541
- default=None,
542
- help=(
543
- "Name of a `modal.Volume` to mount inside the shell at `/mnt/{name}` (if not using REF)."
544
- " Can be used multiple times."
545
- ),
546
- ),
547
- add_local: Optional[list[str]] = typer.Option(
548
- default=None,
549
- help=(
550
- "Local file or directory to mount inside the shell at `/mnt/{basename}` (if not using REF)."
551
- " Can be used multiple times."
552
- ),
553
- ),
554
- secret: Optional[list[str]] = typer.Option(
555
- default=None,
556
- help=("Name of a `modal.Secret` to mount inside the shell (if not using REF). Can be used multiple times."),
557
- ),
558
- cpu: Optional[int] = typer.Option(default=None, help="Number of CPUs to allocate to the shell (if not using REF)."),
559
- memory: Optional[int] = typer.Option(
560
- default=None, help="Memory to allocate for the shell, in MiB (if not using REF)."
561
- ),
562
- gpu: Optional[str] = typer.Option(
563
- default=None,
564
- help="GPUs to request for the shell, if any. Examples are `any`, `a10g`, `a100:4` (if not using REF).",
565
- ),
566
- cloud: Optional[str] = typer.Option(
567
- default=None,
568
- help=(
569
- "Cloud provider to run the shell on. Possible values are `aws`, `gcp`, `oci`, `auto` (if not using REF)."
570
- ),
571
- ),
572
- region: Optional[str] = typer.Option(
573
- default=None,
574
- help=(
575
- "Region(s) to run the container on. "
576
- "Can be a single region or a comma-separated list to choose from (if not using REF)."
577
- ),
578
- ),
579
- pty: Optional[bool] = typer.Option(default=None, help="Run the command using a PTY."),
580
- use_module_mode: bool = typer.Option(
581
- False, "-m", help="Interpret argument as a Python module path instead of a file/script path"
582
- ),
583
- ):
584
- """Run a command or interactive shell inside a Modal container.
585
-
586
- **Examples:**
587
-
588
- Start an interactive shell inside the default Debian-based image:
589
-
590
- ```
591
- modal shell
592
- ```
593
-
594
- Start an interactive shell with the spec for `my_function` in your App
595
- (uses the same image, volumes, mounts, etc.):
596
-
597
- ```
598
- modal shell hello_world.py::my_function
599
- ```
600
-
601
- Or, if you're using a [modal.Cls](https://modal.com/docs/reference/modal.Cls)
602
- you can refer to a `@modal.method` directly:
603
-
604
- ```
605
- modal shell hello_world.py::MyClass.my_method
606
- ```
607
-
608
- Start a `python` shell:
609
-
610
- ```
611
- modal shell hello_world.py --cmd=python
612
- ```
613
-
614
- Run a command with your function's spec and pipe the output to a file:
615
-
616
- ```
617
- modal shell hello_world.py -c 'uv pip list' > env.txt
618
- ```
619
-
620
- Connect to a running Sandbox by ID:
621
-
622
- ```
623
- modal shell sb-abc123xyz
624
- ```
625
- """
626
- env = ensure_env(env)
627
-
628
- if pty is None:
629
- pty = is_tty()
630
-
631
- if platform.system() == "Windows":
632
- raise InvalidError("`modal shell` is currently not supported on Windows")
633
-
634
- app = App("modal shell")
635
-
636
- if ref is not None:
637
- # `modal shell` with a sandbox ID gets the task_id, that's then handled by the `ta-*` flow below.
638
- if ref.startswith("sb-") and len(ref[3:]) > 0 and ref[3:].isalnum():
639
- from ..sandbox import Sandbox
640
-
641
- try:
642
- sandbox = Sandbox.from_id(ref)
643
- task_id = sandbox._get_task_id()
644
- ref = task_id
645
- except NotFoundError as e:
646
- raise ClickException(f"Sandbox '{ref}' not found")
647
- except Exception as e:
648
- raise ClickException(f"Error connecting to sandbox '{ref}': {str(e)}")
649
-
650
- # `modal shell` with a container ID is a special case, alias for `modal container exec`.
651
- if ref.startswith("ta-") and len(ref[3:]) > 0 and ref[3:].isalnum():
652
- from .container import exec
653
-
654
- exec(container_id=ref, command=shlex.split(cmd), pty=pty)
655
- return
656
-
657
- import_ref = parse_import_ref(ref, use_module_mode=use_module_mode)
658
- runnable, all_usable_commands = import_and_filter(
659
- import_ref, base_cmd="modal shell", accept_local_entrypoint=False, accept_webhook=True
660
- )
661
- if not runnable:
662
- help_header = (
663
- "Specify a Modal function to start a shell session for. E.g.\n"
664
- f"> modal shell {import_ref.file_or_module}::my_function"
665
- )
666
-
667
- if all_usable_commands:
668
- help_footer = f"The selected module '{import_ref.file_or_module}' has the following choices:\n\n"
669
- help_footer += _get_runnable_list(all_usable_commands)
670
- else:
671
- help_footer = f"The selected module '{import_ref.file_or_module}' has no Modal functions or classes."
672
-
673
- raise ClickException(f"{help_header}\n\n{help_footer}")
674
-
675
- function_spec: _FunctionSpec
676
- if isinstance(runnable, MethodReference):
677
- # TODO: let users specify a class instead of a method, since they use the same environment
678
- class_service_function = runnable.cls._get_class_service_function()
679
- function_spec = class_service_function.spec
680
- elif isinstance(runnable, Function):
681
- function_spec = runnable.spec
682
- else:
683
- raise ValueError("Referenced entity is not a Modal function or class")
684
-
685
- start_shell = partial(
686
- interactive_shell,
687
- image=function_spec.image,
688
- mounts=function_spec.mounts,
689
- secrets=function_spec.secrets,
690
- network_file_systems=function_spec.network_file_systems,
691
- gpu=function_spec.gpus,
692
- cloud=function_spec.cloud,
693
- cpu=function_spec.cpu,
694
- memory=function_spec.memory,
695
- volumes=function_spec.volumes,
696
- region=function_spec.scheduler_placement.regions if function_spec.scheduler_placement else None,
697
- pty=pty,
698
- proxy=function_spec.proxy,
699
- )
700
- else:
701
- modal_image = Image.from_registry(image, add_python=add_python) if image else None
702
- volumes = {} if volume is None else {f"/mnt/{vol}": Volume.from_name(vol) for vol in volume}
703
- secrets = [] if secret is None else [Secret.from_name(s) for s in secret]
704
-
705
- mounts = []
706
- if add_local:
707
- for local_path_str in add_local:
708
- local_path = Path(local_path_str).expanduser().resolve()
709
- remote_path = PurePosixPath(f"/mnt/{local_path.name}")
710
-
711
- if local_path.is_dir():
712
- m = _Mount._from_local_dir(local_path, remote_path=remote_path)
713
- else:
714
- m = _Mount._from_local_file(local_path, remote_path=remote_path)
715
- mounts.append(m)
716
-
717
- start_shell = partial(
718
- interactive_shell,
719
- image=modal_image,
720
- mounts=mounts,
721
- cpu=cpu,
722
- memory=memory,
723
- gpu=gpu,
724
- cloud=cloud,
725
- volumes=volumes,
726
- secrets=secrets,
727
- region=region.split(",") if region else [],
728
- pty=pty,
729
- )
730
-
731
- # NB: invoking under bash makes --cmd a lot more flexible.
732
- cmds = shlex.split(f'/bin/bash -c "{cmd}"')
733
- start_shell(app, cmds=cmds, environment_name=env, timeout=3600)
@@ -0,0 +1,237 @@
1
+ # Copyright Modal Labs 2022
2
+ import platform
3
+ import shlex
4
+ from functools import partial
5
+ from pathlib import Path, PurePosixPath
6
+ from typing import Optional
7
+
8
+ import typer
9
+ from click import ClickException
10
+
11
+ from .._functions import _FunctionSpec
12
+ from ..app import App
13
+ from ..environments import ensure_env
14
+ from ..exception import InvalidError, NotFoundError
15
+ from ..functions import Function
16
+ from ..image import Image
17
+ from ..mount import _Mount
18
+ from ..runner import interactive_shell
19
+ from ..secret import Secret
20
+ from ..volume import Volume
21
+ from .import_refs import (
22
+ MethodReference,
23
+ import_and_filter,
24
+ parse_import_ref,
25
+ )
26
+ from .run import _get_runnable_list
27
+ from .utils import ENV_OPTION, is_tty
28
+
29
+
30
+ def shell(
31
+ ref: Optional[str] = typer.Argument(
32
+ default=None,
33
+ help=(
34
+ "ID of running container or Sandbox, or path to a Python file containing an App."
35
+ " Can also include a Function specifier, like `module.py::func`, if the file defines multiple Functions."
36
+ ),
37
+ ),
38
+ cmd: str = typer.Option("/bin/bash", "-c", "--cmd", help="Command to run inside the Modal image."),
39
+ env: str = ENV_OPTION,
40
+ image: Optional[str] = typer.Option(
41
+ default=None, help="Container image tag for inside the shell (if not using REF)."
42
+ ),
43
+ add_python: Optional[str] = typer.Option(default=None, help="Add Python to the image (if not using REF)."),
44
+ volume: Optional[list[str]] = typer.Option(
45
+ default=None,
46
+ help=(
47
+ "Name of a `modal.Volume` to mount inside the shell at `/mnt/{name}` (if not using REF)."
48
+ " Can be used multiple times."
49
+ ),
50
+ ),
51
+ add_local: Optional[list[str]] = typer.Option(
52
+ default=None,
53
+ help=(
54
+ "Local file or directory to mount inside the shell at `/mnt/{basename}` (if not using REF)."
55
+ " Can be used multiple times."
56
+ ),
57
+ ),
58
+ secret: Optional[list[str]] = typer.Option(
59
+ default=None,
60
+ help=("Name of a `modal.Secret` to mount inside the shell (if not using REF). Can be used multiple times."),
61
+ ),
62
+ cpu: Optional[int] = typer.Option(default=None, help="Number of CPUs to allocate to the shell (if not using REF)."),
63
+ memory: Optional[int] = typer.Option(
64
+ default=None, help="Memory to allocate for the shell, in MiB (if not using REF)."
65
+ ),
66
+ gpu: Optional[str] = typer.Option(
67
+ default=None,
68
+ help="GPUs to request for the shell, if any. Examples are `any`, `a10g`, `a100:4` (if not using REF).",
69
+ ),
70
+ cloud: Optional[str] = typer.Option(
71
+ default=None,
72
+ help=(
73
+ "Cloud provider to run the shell on. Possible values are `aws`, `gcp`, `oci`, `auto` (if not using REF)."
74
+ ),
75
+ ),
76
+ region: Optional[str] = typer.Option(
77
+ default=None,
78
+ help=(
79
+ "Region(s) to run the container on. "
80
+ "Can be a single region or a comma-separated list to choose from (if not using REF)."
81
+ ),
82
+ ),
83
+ pty: Optional[bool] = typer.Option(default=None, help="Run the command using a PTY."),
84
+ use_module_mode: bool = typer.Option(
85
+ False, "-m", help="Interpret argument as a Python module path instead of a file/script path"
86
+ ),
87
+ ):
88
+ """Run a command or interactive shell inside a Modal container.
89
+
90
+ **Examples:**
91
+
92
+ Start an interactive shell inside the default Debian-based image:
93
+
94
+ ```
95
+ modal shell
96
+ ```
97
+
98
+ Start an interactive shell with the spec for `my_function` in your App
99
+ (uses the same image, volumes, mounts, etc.):
100
+
101
+ ```
102
+ modal shell hello_world.py::my_function
103
+ ```
104
+
105
+ Or, if you're using a [modal.Cls](https://modal.com/docs/reference/modal.Cls)
106
+ you can refer to a `@modal.method` directly:
107
+
108
+ ```
109
+ modal shell hello_world.py::MyClass.my_method
110
+ ```
111
+
112
+ Start a `python` shell:
113
+
114
+ ```
115
+ modal shell hello_world.py --cmd=python
116
+ ```
117
+
118
+ Run a command with your function's spec and pipe the output to a file:
119
+
120
+ ```
121
+ modal shell hello_world.py -c 'uv pip list' > env.txt
122
+ ```
123
+
124
+ Connect to a running Sandbox by ID:
125
+
126
+ ```
127
+ modal shell sb-abc123xyz
128
+ ```
129
+ """
130
+ env = ensure_env(env)
131
+
132
+ if pty is None:
133
+ pty = is_tty()
134
+
135
+ if platform.system() == "Windows":
136
+ raise InvalidError("`modal shell` is currently not supported on Windows")
137
+
138
+ app = App("modal shell")
139
+
140
+ if ref is not None:
141
+ # `modal shell` with a sandbox ID gets the task_id, that's then handled by the `ta-*` flow below.
142
+ if ref.startswith("sb-") and len(ref[3:]) > 0 and ref[3:].isalnum():
143
+ from ..sandbox import Sandbox
144
+
145
+ try:
146
+ sandbox = Sandbox.from_id(ref)
147
+ task_id = sandbox._get_task_id()
148
+ ref = task_id
149
+ except NotFoundError as e:
150
+ raise ClickException(f"Sandbox '{ref}' not found")
151
+ except Exception as e:
152
+ raise ClickException(f"Error connecting to sandbox '{ref}': {str(e)}")
153
+
154
+ # `modal shell` with a container ID is a special case, alias for `modal container exec`.
155
+ if ref.startswith("ta-") and len(ref[3:]) > 0 and ref[3:].isalnum():
156
+ from .container import exec
157
+
158
+ exec(container_id=ref, command=shlex.split(cmd), pty=pty)
159
+ return
160
+
161
+ import_ref = parse_import_ref(ref, use_module_mode=use_module_mode)
162
+ runnable, all_usable_commands = import_and_filter(
163
+ import_ref, base_cmd="modal shell", accept_local_entrypoint=False, accept_webhook=True
164
+ )
165
+ if not runnable:
166
+ help_header = (
167
+ "Specify a Modal function to start a shell session for. E.g.\n"
168
+ f"> modal shell {import_ref.file_or_module}::my_function"
169
+ )
170
+
171
+ if all_usable_commands:
172
+ help_footer = f"The selected module '{import_ref.file_or_module}' has the following choices:\n\n"
173
+ help_footer += _get_runnable_list(all_usable_commands)
174
+ else:
175
+ help_footer = f"The selected module '{import_ref.file_or_module}' has no Modal functions or classes."
176
+
177
+ raise ClickException(f"{help_header}\n\n{help_footer}")
178
+
179
+ function_spec: _FunctionSpec
180
+ if isinstance(runnable, MethodReference):
181
+ # TODO: let users specify a class instead of a method, since they use the same environment
182
+ class_service_function = runnable.cls._get_class_service_function()
183
+ function_spec = class_service_function.spec
184
+ elif isinstance(runnable, Function):
185
+ function_spec = runnable.spec
186
+ else:
187
+ raise ValueError("Referenced entity is not a Modal function or class")
188
+
189
+ start_shell = partial(
190
+ interactive_shell,
191
+ image=function_spec.image,
192
+ mounts=function_spec.mounts,
193
+ secrets=function_spec.secrets,
194
+ network_file_systems=function_spec.network_file_systems,
195
+ gpu=function_spec.gpus,
196
+ cloud=function_spec.cloud,
197
+ cpu=function_spec.cpu,
198
+ memory=function_spec.memory,
199
+ volumes=function_spec.volumes,
200
+ region=function_spec.scheduler_placement.regions if function_spec.scheduler_placement else None,
201
+ pty=pty,
202
+ proxy=function_spec.proxy,
203
+ )
204
+ else:
205
+ modal_image = Image.from_registry(image, add_python=add_python) if image else None
206
+ volumes = {} if volume is None else {f"/mnt/{vol}": Volume.from_name(vol) for vol in volume}
207
+ secrets = [] if secret is None else [Secret.from_name(s) for s in secret]
208
+
209
+ mounts = []
210
+ if add_local:
211
+ for local_path_str in add_local:
212
+ local_path = Path(local_path_str).expanduser().resolve()
213
+ remote_path = PurePosixPath(f"/mnt/{local_path.name}")
214
+
215
+ if local_path.is_dir():
216
+ m = _Mount._from_local_dir(local_path, remote_path=remote_path)
217
+ else:
218
+ m = _Mount._from_local_file(local_path, remote_path=remote_path)
219
+ mounts.append(m)
220
+
221
+ start_shell = partial(
222
+ interactive_shell,
223
+ image=modal_image,
224
+ mounts=mounts,
225
+ cpu=cpu,
226
+ memory=memory,
227
+ gpu=gpu,
228
+ cloud=cloud,
229
+ volumes=volumes,
230
+ secrets=secrets,
231
+ region=region.split(",") if region else [],
232
+ pty=pty,
233
+ )
234
+
235
+ # NB: invoking under bash makes --cmd a lot more flexible.
236
+ cmds = shlex.split(f'/bin/bash -c "{cmd}"')
237
+ start_shell(app, cmds=cmds, environment_name=env, timeout=3600)
@@ -32,7 +32,7 @@ class _Client:
32
32
  server_url: str,
33
33
  client_type: int,
34
34
  credentials: typing.Optional[tuple[str, str]],
35
- version: str = "1.2.4.dev2",
35
+ version: str = "1.2.5.dev0",
36
36
  ):
37
37
  """mdmd:hidden
38
38
  The Modal client object is not intended to be instantiated directly by users.
@@ -163,7 +163,7 @@ class Client:
163
163
  server_url: str,
164
164
  client_type: int,
165
165
  credentials: typing.Optional[tuple[str, str]],
166
- version: str = "1.2.4.dev2",
166
+ version: str = "1.2.5.dev0",
167
167
  ):
168
168
  """mdmd:hidden
169
169
  The Modal client object is not intended to be instantiated directly by users.
@@ -408,7 +408,7 @@ class Function(
408
408
 
409
409
  _call_generator: ___call_generator_spec[typing_extensions.Self]
410
410
 
411
- class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
411
+ class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
412
412
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
413
413
  """Calls the function remotely, executing it with the given arguments and returning the execution's result."""
414
414
  ...
@@ -417,7 +417,7 @@ class Function(
417
417
  """Calls the function remotely, executing it with the given arguments and returning the execution's result."""
418
418
  ...
419
419
 
420
- remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
420
+ remote: __remote_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
421
421
 
422
422
  class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
423
423
  def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
@@ -444,7 +444,7 @@ class Function(
444
444
  """
445
445
  ...
446
446
 
447
- class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
447
+ class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
448
448
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
449
449
  """[Experimental] Calls the function with the given arguments, without waiting for the results.
450
450
 
@@ -468,7 +468,7 @@ class Function(
468
468
  ...
469
469
 
470
470
  _experimental_spawn: ___experimental_spawn_spec[
471
- modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
471
+ modal._functions.ReturnType, modal._functions.P, typing_extensions.Self
472
472
  ]
473
473
 
474
474
  class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER, SUPERSELF]):
@@ -477,7 +477,7 @@ class Function(
477
477
 
478
478
  _spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P, typing_extensions.Self]
479
479
 
480
- class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
480
+ class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
481
481
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
482
482
  """Calls the function with the given arguments, without waiting for the results.
483
483
 
@@ -498,7 +498,7 @@ class Function(
498
498
  """
499
499
  ...
500
500
 
501
- spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
501
+ spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
502
502
 
503
503
  def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
504
504
  """Return the inner Python object wrapped by this Modal Function."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.4.dev2
3
+ Version: 1.2.5.dev0
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -155,6 +155,7 @@ modal/cli/profile.py
155
155
  modal/cli/queues.py
156
156
  modal/cli/run.py
157
157
  modal/cli/secret.py
158
+ modal/cli/shell.py
158
159
  modal/cli/token.py
159
160
  modal/cli/utils.py
160
161
  modal/cli/volume.py
@@ -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.4.dev2"
4
+ __version__ = "1.2.5.dev0"
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