modal 1.1.5.dev77__tar.gz → 1.1.5.dev81__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 (196) hide show
  1. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/PKG-INFO +1 -1
  2. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/name_utils.py +2 -3
  3. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/app.py +40 -2
  4. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/app.pyi +60 -0
  5. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/client.pyi +2 -2
  6. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal.egg-info/PKG-INFO +1 -1
  7. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/sandbox_router.proto +24 -2
  8. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/sandbox_router_grpc.py +16 -0
  9. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/sandbox_router_pb2.py +45 -25
  10. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/sandbox_router_pb2.pyi +44 -0
  11. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/sandbox_router_pb2_grpc.py +34 -0
  12. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/sandbox_router_pb2_grpc.pyi +12 -0
  13. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_version/__init__.py +1 -1
  14. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/LICENSE +0 -0
  15. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/README.md +0 -0
  16. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/__init__.py +0 -0
  17. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/__main__.py +0 -0
  18. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_clustered_functions.py +0 -0
  19. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_clustered_functions.pyi +0 -0
  20. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_container_entrypoint.py +0 -0
  21. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_functions.py +0 -0
  22. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_ipython.py +0 -0
  23. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_location.py +0 -0
  24. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_object.py +0 -0
  25. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_output.py +0 -0
  26. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_partial_function.py +0 -0
  27. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_pty.py +0 -0
  28. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_resolver.py +0 -0
  29. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_resources.py +0 -0
  30. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_runtime/__init__.py +0 -0
  31. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_runtime/asgi.py +0 -0
  32. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_runtime/container_io_manager.py +0 -0
  33. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_runtime/container_io_manager.pyi +0 -0
  34. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_runtime/execution_context.py +0 -0
  35. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_runtime/execution_context.pyi +0 -0
  36. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  37. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_runtime/telemetry.py +0 -0
  38. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_runtime/user_code_imports.py +0 -0
  39. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_serialization.py +0 -0
  40. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_traceback.py +0 -0
  41. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_tunnel.py +0 -0
  42. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_tunnel.pyi +0 -0
  43. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_type_manager.py +0 -0
  44. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/__init__.py +0 -0
  45. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/app_utils.py +0 -0
  46. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/async_utils.py +0 -0
  47. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/auth_token_manager.py +0 -0
  48. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/blob_utils.py +0 -0
  49. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/bytes_io_segment_payload.py +0 -0
  50. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/deprecation.py +0 -0
  51. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/docker_utils.py +0 -0
  52. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/function_utils.py +0 -0
  53. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/git_utils.py +0 -0
  54. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/grpc_testing.py +0 -0
  55. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/grpc_utils.py +0 -0
  56. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/hash_utils.py +0 -0
  57. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/http_utils.py +0 -0
  58. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/jwt_utils.py +0 -0
  59. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/logger.py +0 -0
  60. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/mount_utils.py +0 -0
  61. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/package_utils.py +0 -0
  62. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/pattern_utils.py +0 -0
  63. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/rand_pb_testing.py +0 -0
  64. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/shell_utils.py +0 -0
  65. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_utils/time_utils.py +0 -0
  66. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_vendor/__init__.py +0 -0
  67. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  68. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_vendor/cloudpickle.py +0 -0
  69. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_vendor/tblib.py +0 -0
  70. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/_watcher.py +0 -0
  71. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/builder/2023.12.312.txt +0 -0
  72. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/builder/2023.12.txt +0 -0
  73. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/builder/2024.04.txt +0 -0
  74. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/builder/2024.10.txt +0 -0
  75. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/builder/2025.06.txt +0 -0
  76. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/builder/PREVIEW.txt +0 -0
  77. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/builder/README.md +0 -0
  78. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/builder/base-images.json +0 -0
  79. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/call_graph.py +0 -0
  80. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/__init__.py +0 -0
  81. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/_download.py +0 -0
  82. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/_traceback.py +0 -0
  83. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/app.py +0 -0
  84. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/cluster.py +0 -0
  85. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/config.py +0 -0
  86. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/container.py +0 -0
  87. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/dict.py +0 -0
  88. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/entry_point.py +0 -0
  89. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/environment.py +0 -0
  90. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/import_refs.py +0 -0
  91. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/launch.py +0 -0
  92. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/network_file_system.py +0 -0
  93. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/profile.py +0 -0
  94. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/programs/__init__.py +0 -0
  95. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/programs/launch_instance_ssh.py +0 -0
  96. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/programs/run_jupyter.py +0 -0
  97. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/programs/run_marimo.py +0 -0
  98. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/programs/vscode.py +0 -0
  99. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/queues.py +0 -0
  100. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/run.py +0 -0
  101. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/secret.py +0 -0
  102. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/token.py +0 -0
  103. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/utils.py +0 -0
  104. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cli/volume.py +0 -0
  105. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/client.py +0 -0
  106. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cloud_bucket_mount.py +0 -0
  107. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cloud_bucket_mount.pyi +0 -0
  108. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cls.py +0 -0
  109. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/cls.pyi +0 -0
  110. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/config.py +0 -0
  111. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/container_process.py +0 -0
  112. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/container_process.pyi +0 -0
  113. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/dict.py +0 -0
  114. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/dict.pyi +0 -0
  115. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/environments.py +0 -0
  116. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/environments.pyi +0 -0
  117. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/exception.py +0 -0
  118. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/experimental/__init__.py +0 -0
  119. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/experimental/flash.py +0 -0
  120. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/experimental/flash.pyi +0 -0
  121. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/experimental/ipython.py +0 -0
  122. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/file_io.py +0 -0
  123. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/file_io.pyi +0 -0
  124. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/file_pattern_matcher.py +0 -0
  125. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/functions.py +0 -0
  126. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/functions.pyi +0 -0
  127. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/gpu.py +0 -0
  128. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/image.py +0 -0
  129. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/image.pyi +0 -0
  130. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/io_streams.py +0 -0
  131. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/io_streams.pyi +0 -0
  132. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/mount.py +0 -0
  133. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/mount.pyi +0 -0
  134. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/network_file_system.py +0 -0
  135. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/network_file_system.pyi +0 -0
  136. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/object.py +0 -0
  137. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/object.pyi +0 -0
  138. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/output.py +0 -0
  139. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/parallel_map.py +0 -0
  140. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/parallel_map.pyi +0 -0
  141. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/partial_function.py +0 -0
  142. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/partial_function.pyi +0 -0
  143. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/proxy.py +0 -0
  144. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/proxy.pyi +0 -0
  145. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/py.typed +0 -0
  146. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/queue.py +0 -0
  147. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/queue.pyi +0 -0
  148. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/retries.py +0 -0
  149. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/runner.py +0 -0
  150. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/runner.pyi +0 -0
  151. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/running_app.py +0 -0
  152. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/sandbox.py +0 -0
  153. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/sandbox.pyi +0 -0
  154. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/schedule.py +0 -0
  155. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/scheduler_placement.py +0 -0
  156. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/secret.py +0 -0
  157. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/secret.pyi +0 -0
  158. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/serving.py +0 -0
  159. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/serving.pyi +0 -0
  160. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/snapshot.py +0 -0
  161. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/snapshot.pyi +0 -0
  162. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/stream_type.py +0 -0
  163. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/token_flow.py +0 -0
  164. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/token_flow.pyi +0 -0
  165. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/volume.py +0 -0
  166. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal/volume.pyi +0 -0
  167. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal.egg-info/SOURCES.txt +0 -0
  168. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal.egg-info/dependency_links.txt +0 -0
  169. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal.egg-info/entry_points.txt +0 -0
  170. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal.egg-info/requires.txt +0 -0
  171. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal.egg-info/top_level.txt +0 -0
  172. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_docs/__init__.py +0 -0
  173. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_docs/gen_cli_docs.py +0 -0
  174. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_docs/gen_reference_docs.py +0 -0
  175. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_docs/mdmd/__init__.py +0 -0
  176. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_docs/mdmd/mdmd.py +0 -0
  177. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_docs/mdmd/signatures.py +0 -0
  178. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/__init__.py +0 -0
  179. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/api.proto +0 -0
  180. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/api_grpc.py +0 -0
  181. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/api_pb2.py +0 -0
  182. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/api_pb2.pyi +0 -0
  183. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/api_pb2_grpc.py +0 -0
  184. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/api_pb2_grpc.pyi +0 -0
  185. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/modal_api_grpc.py +0 -0
  186. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/modal_options_grpc.py +0 -0
  187. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/options.proto +0 -0
  188. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/options_grpc.py +0 -0
  189. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/options_pb2.py +0 -0
  190. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/options_pb2.pyi +0 -0
  191. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/options_pb2_grpc.py +0 -0
  192. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/options_pb2_grpc.pyi +0 -0
  193. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_proto/py.typed +0 -0
  194. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/modal_version/__main__.py +0 -0
  195. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/pyproject.toml +0 -0
  196. {modal-1.1.5.dev77 → modal-1.1.5.dev81}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.1.5.dev77
3
+ Version: 1.1.5.dev81
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -1,5 +1,6 @@
1
1
  # Copyright Modal Labs 2022
2
2
  import re
3
+ from collections.abc import Mapping
3
4
 
4
5
  from ..exception import InvalidError
5
6
 
@@ -37,7 +38,7 @@ def is_valid_tag(tag: str, max_length: int = 50) -> bool:
37
38
  return bool(re.match(pattern, tag))
38
39
 
39
40
 
40
- def check_tag_dict(tags: dict[str, str]) -> dict[str, str]:
41
+ def check_tag_dict(tags: Mapping[str, str]) -> None:
41
42
  rules = (
42
43
  "\n\nTags may contain only alphanumeric characters, dashes, periods, or underscores, "
43
44
  "and must be 63 characters or less."
@@ -49,8 +50,6 @@ def check_tag_dict(tags: dict[str, str]) -> dict[str, str]:
49
50
  if not is_valid_tag(value, max_length):
50
51
  raise InvalidError(f"Invalid tag value: {value!r}.{rules}")
51
52
 
52
- return tags
53
-
54
53
 
55
54
  def check_object_name(name: str, object_type: str) -> None:
56
55
  message = (
@@ -1,7 +1,7 @@
1
1
  # Copyright Modal Labs 2022
2
2
  import inspect
3
3
  import typing
4
- from collections.abc import AsyncGenerator, Collection, Coroutine, Sequence
4
+ from collections.abc import AsyncGenerator, Collection, Coroutine, Mapping, Sequence
5
5
  from pathlib import PurePosixPath
6
6
  from textwrap import dedent
7
7
  from typing import (
@@ -191,9 +191,12 @@ class _App:
191
191
  if name is not None and not isinstance(name, str):
192
192
  raise InvalidError("Invalid value for `name`: Must be string.")
193
193
 
194
+ if tags is not None:
195
+ check_tag_dict(tags)
196
+
194
197
  self._name = name
195
198
  self._description = name
196
- self._tags = check_tag_dict(tags or {})
199
+ self._tags = tags or {}
197
200
  self._include_source_default = include_source
198
201
 
199
202
  check_sequence(secrets, _Secret, "`secrets=` has to be a list or tuple of `modal.Secret` objects")
@@ -1088,6 +1091,41 @@ class _App:
1088
1091
 
1089
1092
  return self
1090
1093
 
1094
+ async def set_tags(self, tags: Mapping[str, str], *, client: Optional[_Client] = None) -> None:
1095
+ """Attach key-value metadata to the App.
1096
+
1097
+ Tag metadata can be used to add organization-specific context to the App and can be
1098
+ included in billing reports and other informational APIs. Tags can also be set in
1099
+ the App constructor.
1100
+
1101
+ Any tags set on the App before calling this method will be removed if they are not
1102
+ included in the argument (i.e., this method does not have `.update()` semantics).
1103
+
1104
+ """
1105
+ # Note that we are requiring the App to be "running" before we set the tags.
1106
+ # Alternatively, we could hold onto the tags (i.e. in `self._tags`) and then pass
1107
+ # then up when AppPublish gets called. I'm not certain we want to support it, though.
1108
+ # It might not be obvious to users that `.set_tags()` is eager and has immediate effect
1109
+ # when the App is running, but lazy (and potentially ignored) otherwise. There would be
1110
+ # other complications, like what do you do with any tags set in the constructor, and
1111
+ # what should `.get_tags()` do when it's called before the App is running?
1112
+ if self._app_id is None:
1113
+ raise InvalidError("`App.set_tags` cannot be called before the App is running.")
1114
+ check_tag_dict(tags)
1115
+ req = api_pb2.AppSetTagsRequest(app_id=self._app_id, tags=tags)
1116
+
1117
+ client = client or self._client or await _Client.from_env()
1118
+ await retry_transient_errors(client.stub.AppSetTags, req)
1119
+
1120
+ async def get_tags(self, *, client: Optional[_Client] = None) -> dict[str, str]:
1121
+ """Get the tags that are currently attached to the App."""
1122
+ if self._app_id is None:
1123
+ raise InvalidError("`App.get_tags` cannot be called before the App is running.")
1124
+ req = api_pb2.AppGetTagsRequest(app_id=self._app_id)
1125
+ client = client or self._client or await _Client.from_env()
1126
+ resp = await retry_transient_errors(client.stub.AppGetTags, req)
1127
+ return dict(resp.tags)
1128
+
1091
1129
  async def _logs(self, client: Optional[_Client] = None) -> AsyncGenerator[str, None]:
1092
1130
  """Stream logs from the app.
1093
1131
 
@@ -521,6 +521,24 @@ class _App:
521
521
  """
522
522
  ...
523
523
 
524
+ async def set_tags(
525
+ self, tags: collections.abc.Mapping[str, str], *, client: typing.Optional[modal.client._Client] = None
526
+ ) -> None:
527
+ """Attach key-value metadata to the App.
528
+
529
+ Tag metadata can be used to add organization-specific context to the App and can be
530
+ included in billing reports and other informational APIs. Tags can also be set in
531
+ the App constructor.
532
+
533
+ Any tags set on the App before calling this method will be removed if they are not
534
+ included in the argument (i.e., this method does not have `.update()` semantics).
535
+ """
536
+ ...
537
+
538
+ async def get_tags(self, *, client: typing.Optional[modal.client._Client] = None) -> dict[str, str]:
539
+ """Get the tags that are currently attached to the App."""
540
+ ...
541
+
524
542
  def _logs(self, client: typing.Optional[modal.client._Client] = None) -> collections.abc.AsyncGenerator[str, None]:
525
543
  """Stream logs from the app.
526
544
 
@@ -1133,6 +1151,48 @@ class App:
1133
1151
  """
1134
1152
  ...
1135
1153
 
1154
+ class __set_tags_spec(typing_extensions.Protocol[SUPERSELF]):
1155
+ def __call__(
1156
+ self, /, tags: collections.abc.Mapping[str, str], *, client: typing.Optional[modal.client.Client] = None
1157
+ ) -> None:
1158
+ """Attach key-value metadata to the App.
1159
+
1160
+ Tag metadata can be used to add organization-specific context to the App and can be
1161
+ included in billing reports and other informational APIs. Tags can also be set in
1162
+ the App constructor.
1163
+
1164
+ Any tags set on the App before calling this method will be removed if they are not
1165
+ included in the argument (i.e., this method does not have `.update()` semantics).
1166
+ """
1167
+ ...
1168
+
1169
+ async def aio(
1170
+ self, /, tags: collections.abc.Mapping[str, str], *, client: typing.Optional[modal.client.Client] = None
1171
+ ) -> None:
1172
+ """Attach key-value metadata to the App.
1173
+
1174
+ Tag metadata can be used to add organization-specific context to the App and can be
1175
+ included in billing reports and other informational APIs. Tags can also be set in
1176
+ the App constructor.
1177
+
1178
+ Any tags set on the App before calling this method will be removed if they are not
1179
+ included in the argument (i.e., this method does not have `.update()` semantics).
1180
+ """
1181
+ ...
1182
+
1183
+ set_tags: __set_tags_spec[typing_extensions.Self]
1184
+
1185
+ class __get_tags_spec(typing_extensions.Protocol[SUPERSELF]):
1186
+ def __call__(self, /, *, client: typing.Optional[modal.client.Client] = None) -> dict[str, str]:
1187
+ """Get the tags that are currently attached to the App."""
1188
+ ...
1189
+
1190
+ async def aio(self, /, *, client: typing.Optional[modal.client.Client] = None) -> dict[str, str]:
1191
+ """Get the tags that are currently attached to the App."""
1192
+ ...
1193
+
1194
+ get_tags: __get_tags_spec[typing_extensions.Self]
1195
+
1136
1196
  class ___logs_spec(typing_extensions.Protocol[SUPERSELF]):
1137
1197
  def __call__(self, /, client: typing.Optional[modal.client.Client] = None) -> typing.Generator[str, None, None]:
1138
1198
  """Stream logs from the app.
@@ -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.1.5.dev77",
36
+ version: str = "1.1.5.dev81",
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.1.5.dev77",
167
+ version: str = "1.1.5.dev81",
168
168
  ):
169
169
  """mdmd:hidden
170
170
  The Modal client object is not intended to be instantiated directly by users.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.1.5.dev77
3
+ Version: 1.1.5.dev81
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -28,6 +28,26 @@ enum SandboxExecStdoutConfig {
28
28
  SANDBOX_EXEC_STDOUT_CONFIG_PIPE = 1;
29
29
  }
30
30
 
31
+ message SandboxExecPollRequest {
32
+ // The task ID of the sandbox running the exec'd command.
33
+ string task_id = 1;
34
+ // The execution ID of the command to wait on.
35
+ string exec_id = 2;
36
+ }
37
+
38
+ // The response to a SandboxExecPollRequest. If the exec'd command has not
39
+ // completed, exit_status will be unset.
40
+ message SandboxExecPollResponse {
41
+ oneof exit_status {
42
+ // The exit code of the command.
43
+ int32 code = 1;
44
+ // The signal that terminated the command.
45
+ int32 signal = 2;
46
+ }
47
+ // TODO(saltzm): Give a way for the user to distinguish between normal exit
48
+ // and termination by Modal (due to sandbox timeout, exec exceeded deadline, etc.)
49
+ }
50
+
31
51
  message SandboxExecStartRequest {
32
52
  // The task ID of the sandbox to execute the command in.
33
53
  string task_id = 1;
@@ -105,15 +125,17 @@ message SandboxExecWaitRequest {
105
125
  message SandboxExecWaitResponse {
106
126
  oneof exit_status {
107
127
  // The exit code of the command.
108
- int32 code = 3;
128
+ int32 code = 1;
109
129
  // The signal that terminated the command.
110
- int32 signal = 4;
130
+ int32 signal = 2;
111
131
  }
112
132
  // TODO(saltzm): Give a way for the user to distinguish between normal exit
113
133
  // and termination by Modal (due to sandbox timeout, exec exceeded deadline, etc.)
114
134
  }
115
135
 
116
136
  service SandboxRouter {
137
+ // Poll for the exit status of an exec'd command.
138
+ rpc SandboxExecPoll(SandboxExecPollRequest) returns (SandboxExecPollResponse);
117
139
  // Execute a command in the sandbox.
118
140
  rpc SandboxExecStart(SandboxExecStartRequest) returns (SandboxExecStartResponse);
119
141
  // Write to the stdin stream of an exec'd command.
@@ -15,6 +15,10 @@ import modal_proto.sandbox_router_pb2
15
15
 
16
16
  class SandboxRouterBase(abc.ABC):
17
17
 
18
+ @abc.abstractmethod
19
+ async def SandboxExecPoll(self, stream: 'grpclib.server.Stream[modal_proto.sandbox_router_pb2.SandboxExecPollRequest, modal_proto.sandbox_router_pb2.SandboxExecPollResponse]') -> None:
20
+ pass
21
+
18
22
  @abc.abstractmethod
19
23
  async def SandboxExecStart(self, stream: 'grpclib.server.Stream[modal_proto.sandbox_router_pb2.SandboxExecStartRequest, modal_proto.sandbox_router_pb2.SandboxExecStartResponse]') -> None:
20
24
  pass
@@ -33,6 +37,12 @@ class SandboxRouterBase(abc.ABC):
33
37
 
34
38
  def __mapping__(self) -> typing.Dict[str, grpclib.const.Handler]:
35
39
  return {
40
+ '/modal.sandbox_router.SandboxRouter/SandboxExecPoll': grpclib.const.Handler(
41
+ self.SandboxExecPoll,
42
+ grpclib.const.Cardinality.UNARY_UNARY,
43
+ modal_proto.sandbox_router_pb2.SandboxExecPollRequest,
44
+ modal_proto.sandbox_router_pb2.SandboxExecPollResponse,
45
+ ),
36
46
  '/modal.sandbox_router.SandboxRouter/SandboxExecStart': grpclib.const.Handler(
37
47
  self.SandboxExecStart,
38
48
  grpclib.const.Cardinality.UNARY_UNARY,
@@ -63,6 +73,12 @@ class SandboxRouterBase(abc.ABC):
63
73
  class SandboxRouterStub:
64
74
 
65
75
  def __init__(self, channel: grpclib.client.Channel) -> None:
76
+ self.SandboxExecPoll = grpclib.client.UnaryUnaryMethod(
77
+ channel,
78
+ '/modal.sandbox_router.SandboxRouter/SandboxExecPoll',
79
+ modal_proto.sandbox_router_pb2.SandboxExecPollRequest,
80
+ modal_proto.sandbox_router_pb2.SandboxExecPollResponse,
81
+ )
66
82
  self.SandboxExecStart = grpclib.client.UnaryUnaryMethod(
67
83
  channel,
68
84
  '/modal.sandbox_router.SandboxRouter/SandboxExecStart',
@@ -16,7 +16,7 @@ _sym_db = _symbol_database.Default()
16
16
  from modal_proto import api_pb2 as modal__proto_dot_api__pb2
17
17
 
18
18
 
19
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n modal_proto/sandbox_router.proto\x12\x14modal.sandbox_router\x1a\x15modal_proto/api.proto\"\x91\x03\n\x17SandboxExecStartRequest\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x0f\n\x07\x65xec_id\x18\x02 \x01(\t\x12\x14\n\x0c\x63ommand_args\x18\x03 \x03(\t\x12\x44\n\rstdout_config\x18\x04 \x01(\x0e\x32-.modal.sandbox_router.SandboxExecStdoutConfig\x12\x44\n\rstderr_config\x18\x05 \x01(\x0e\x32-.modal.sandbox_router.SandboxExecStderrConfig\x12\x19\n\x0ctimeout_secs\x18\x06 \x01(\rH\x00\x88\x01\x01\x12\x14\n\x07workdir\x18\x07 \x01(\tH\x01\x88\x01\x01\x12\x12\n\nsecret_ids\x18\x08 \x03(\t\x12,\n\x08pty_info\x18\t \x01(\x0b\x32\x15.modal.client.PTYInfoH\x02\x88\x01\x01\x12\x15\n\rruntime_debug\x18\n \x01(\x08\x42\x0f\n\r_timeout_secsB\n\n\x08_workdirB\x0b\n\t_pty_info\"\x1a\n\x18SandboxExecStartResponse\"k\n\x1cSandboxExecStdinWriteRequest\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x0f\n\x07\x65xec_id\x18\x02 \x01(\t\x12\x0e\n\x06offset\x18\x03 \x01(\x04\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x12\x0b\n\x03\x65of\x18\x05 \x01(\x08\"\x1f\n\x1dSandboxExecStdinWriteResponse\"\x9e\x01\n\x1bSandboxExecStdioReadRequest\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x0f\n\x07\x65xec_id\x18\x02 \x01(\t\x12\x0e\n\x06offset\x18\x03 \x01(\x04\x12M\n\x0f\x66ile_descriptor\x18\x04 \x01(\x0e\x32\x34.modal.sandbox_router.SandboxExecStdioFileDescriptor\",\n\x1cSandboxExecStdioReadResponse\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\":\n\x16SandboxExecWaitRequest\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x0f\n\x07\x65xec_id\x18\x02 \x01(\t\"J\n\x17SandboxExecWaitResponse\x12\x0e\n\x04\x63ode\x18\x03 \x01(\x05H\x00\x12\x10\n\x06signal\x18\x04 \x01(\x05H\x00\x42\r\n\x0b\x65xit_status*\x8d\x01\n\x17SandboxExecStderrConfig\x12&\n\"SANDBOX_EXEC_STDERR_CONFIG_DEVNULL\x10\x00\x12#\n\x1fSANDBOX_EXEC_STDERR_CONFIG_PIPE\x10\x01\x12%\n!SANDBOX_EXEC_STDERR_CONFIG_STDOUT\x10\x02*~\n\x1eSandboxExecStdioFileDescriptor\x12-\n)SANDBOX_EXEC_STDIO_FILE_DESCRIPTOR_STDOUT\x10\x00\x12-\n)SANDBOX_EXEC_STDIO_FILE_DESCRIPTOR_STDERR\x10\x01*f\n\x17SandboxExecStdoutConfig\x12&\n\"SANDBOX_EXEC_STDOUT_CONFIG_DEVNULL\x10\x00\x12#\n\x1fSANDBOX_EXEC_STDOUT_CONFIG_PIPE\x10\x01\x32\xf6\x03\n\rSandboxRouter\x12q\n\x10SandboxExecStart\x12-.modal.sandbox_router.SandboxExecStartRequest\x1a..modal.sandbox_router.SandboxExecStartResponse\x12\x80\x01\n\x15SandboxExecStdinWrite\x12\x32.modal.sandbox_router.SandboxExecStdinWriteRequest\x1a\x33.modal.sandbox_router.SandboxExecStdinWriteResponse\x12\x7f\n\x14SandboxExecStdioRead\x12\x31.modal.sandbox_router.SandboxExecStdioReadRequest\x1a\x32.modal.sandbox_router.SandboxExecStdioReadResponse0\x01\x12n\n\x0fSandboxExecWait\x12,.modal.sandbox_router.SandboxExecWaitRequest\x1a-.modal.sandbox_router.SandboxExecWaitResponseb\x06proto3')
19
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n modal_proto/sandbox_router.proto\x12\x14modal.sandbox_router\x1a\x15modal_proto/api.proto\":\n\x16SandboxExecPollRequest\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x0f\n\x07\x65xec_id\x18\x02 \x01(\t\"J\n\x17SandboxExecPollResponse\x12\x0e\n\x04\x63ode\x18\x01 \x01(\x05H\x00\x12\x10\n\x06signal\x18\x02 \x01(\x05H\x00\x42\r\n\x0b\x65xit_status\"\x91\x03\n\x17SandboxExecStartRequest\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x0f\n\x07\x65xec_id\x18\x02 \x01(\t\x12\x14\n\x0c\x63ommand_args\x18\x03 \x03(\t\x12\x44\n\rstdout_config\x18\x04 \x01(\x0e\x32-.modal.sandbox_router.SandboxExecStdoutConfig\x12\x44\n\rstderr_config\x18\x05 \x01(\x0e\x32-.modal.sandbox_router.SandboxExecStderrConfig\x12\x19\n\x0ctimeout_secs\x18\x06 \x01(\rH\x00\x88\x01\x01\x12\x14\n\x07workdir\x18\x07 \x01(\tH\x01\x88\x01\x01\x12\x12\n\nsecret_ids\x18\x08 \x03(\t\x12,\n\x08pty_info\x18\t \x01(\x0b\x32\x15.modal.client.PTYInfoH\x02\x88\x01\x01\x12\x15\n\rruntime_debug\x18\n \x01(\x08\x42\x0f\n\r_timeout_secsB\n\n\x08_workdirB\x0b\n\t_pty_info\"\x1a\n\x18SandboxExecStartResponse\"k\n\x1cSandboxExecStdinWriteRequest\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x0f\n\x07\x65xec_id\x18\x02 \x01(\t\x12\x0e\n\x06offset\x18\x03 \x01(\x04\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x12\x0b\n\x03\x65of\x18\x05 \x01(\x08\"\x1f\n\x1dSandboxExecStdinWriteResponse\"\x9e\x01\n\x1bSandboxExecStdioReadRequest\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x0f\n\x07\x65xec_id\x18\x02 \x01(\t\x12\x0e\n\x06offset\x18\x03 \x01(\x04\x12M\n\x0f\x66ile_descriptor\x18\x04 \x01(\x0e\x32\x34.modal.sandbox_router.SandboxExecStdioFileDescriptor\",\n\x1cSandboxExecStdioReadResponse\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\":\n\x16SandboxExecWaitRequest\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x0f\n\x07\x65xec_id\x18\x02 \x01(\t\"J\n\x17SandboxExecWaitResponse\x12\x0e\n\x04\x63ode\x18\x01 \x01(\x05H\x00\x12\x10\n\x06signal\x18\x02 \x01(\x05H\x00\x42\r\n\x0b\x65xit_status*\x8d\x01\n\x17SandboxExecStderrConfig\x12&\n\"SANDBOX_EXEC_STDERR_CONFIG_DEVNULL\x10\x00\x12#\n\x1fSANDBOX_EXEC_STDERR_CONFIG_PIPE\x10\x01\x12%\n!SANDBOX_EXEC_STDERR_CONFIG_STDOUT\x10\x02*~\n\x1eSandboxExecStdioFileDescriptor\x12-\n)SANDBOX_EXEC_STDIO_FILE_DESCRIPTOR_STDOUT\x10\x00\x12-\n)SANDBOX_EXEC_STDIO_FILE_DESCRIPTOR_STDERR\x10\x01*f\n\x17SandboxExecStdoutConfig\x12&\n\"SANDBOX_EXEC_STDOUT_CONFIG_DEVNULL\x10\x00\x12#\n\x1fSANDBOX_EXEC_STDOUT_CONFIG_PIPE\x10\x01\x32\xe6\x04\n\rSandboxRouter\x12n\n\x0fSandboxExecPoll\x12,.modal.sandbox_router.SandboxExecPollRequest\x1a-.modal.sandbox_router.SandboxExecPollResponse\x12q\n\x10SandboxExecStart\x12-.modal.sandbox_router.SandboxExecStartRequest\x1a..modal.sandbox_router.SandboxExecStartResponse\x12\x80\x01\n\x15SandboxExecStdinWrite\x12\x32.modal.sandbox_router.SandboxExecStdinWriteRequest\x1a\x33.modal.sandbox_router.SandboxExecStdinWriteResponse\x12\x7f\n\x14SandboxExecStdioRead\x12\x31.modal.sandbox_router.SandboxExecStdioReadRequest\x1a\x32.modal.sandbox_router.SandboxExecStdioReadResponse0\x01\x12n\n\x0fSandboxExecWait\x12,.modal.sandbox_router.SandboxExecWaitRequest\x1a-.modal.sandbox_router.SandboxExecWaitResponseb\x06proto3')
20
20
 
21
21
  _SANDBOXEXECSTDERRCONFIG = DESCRIPTOR.enum_types_by_name['SandboxExecStderrConfig']
22
22
  SandboxExecStderrConfig = enum_type_wrapper.EnumTypeWrapper(_SANDBOXEXECSTDERRCONFIG)
@@ -33,6 +33,8 @@ SANDBOX_EXEC_STDOUT_CONFIG_DEVNULL = 0
33
33
  SANDBOX_EXEC_STDOUT_CONFIG_PIPE = 1
34
34
 
35
35
 
36
+ _SANDBOXEXECPOLLREQUEST = DESCRIPTOR.message_types_by_name['SandboxExecPollRequest']
37
+ _SANDBOXEXECPOLLRESPONSE = DESCRIPTOR.message_types_by_name['SandboxExecPollResponse']
36
38
  _SANDBOXEXECSTARTREQUEST = DESCRIPTOR.message_types_by_name['SandboxExecStartRequest']
37
39
  _SANDBOXEXECSTARTRESPONSE = DESCRIPTOR.message_types_by_name['SandboxExecStartResponse']
38
40
  _SANDBOXEXECSTDINWRITEREQUEST = DESCRIPTOR.message_types_by_name['SandboxExecStdinWriteRequest']
@@ -41,6 +43,20 @@ _SANDBOXEXECSTDIOREADREQUEST = DESCRIPTOR.message_types_by_name['SandboxExecStdi
41
43
  _SANDBOXEXECSTDIOREADRESPONSE = DESCRIPTOR.message_types_by_name['SandboxExecStdioReadResponse']
42
44
  _SANDBOXEXECWAITREQUEST = DESCRIPTOR.message_types_by_name['SandboxExecWaitRequest']
43
45
  _SANDBOXEXECWAITRESPONSE = DESCRIPTOR.message_types_by_name['SandboxExecWaitResponse']
46
+ SandboxExecPollRequest = _reflection.GeneratedProtocolMessageType('SandboxExecPollRequest', (_message.Message,), {
47
+ 'DESCRIPTOR' : _SANDBOXEXECPOLLREQUEST,
48
+ '__module__' : 'modal_proto.sandbox_router_pb2'
49
+ # @@protoc_insertion_point(class_scope:modal.sandbox_router.SandboxExecPollRequest)
50
+ })
51
+ _sym_db.RegisterMessage(SandboxExecPollRequest)
52
+
53
+ SandboxExecPollResponse = _reflection.GeneratedProtocolMessageType('SandboxExecPollResponse', (_message.Message,), {
54
+ 'DESCRIPTOR' : _SANDBOXEXECPOLLRESPONSE,
55
+ '__module__' : 'modal_proto.sandbox_router_pb2'
56
+ # @@protoc_insertion_point(class_scope:modal.sandbox_router.SandboxExecPollResponse)
57
+ })
58
+ _sym_db.RegisterMessage(SandboxExecPollResponse)
59
+
44
60
  SandboxExecStartRequest = _reflection.GeneratedProtocolMessageType('SandboxExecStartRequest', (_message.Message,), {
45
61
  'DESCRIPTOR' : _SANDBOXEXECSTARTREQUEST,
46
62
  '__module__' : 'modal_proto.sandbox_router_pb2'
@@ -101,28 +117,32 @@ _SANDBOXROUTER = DESCRIPTOR.services_by_name['SandboxRouter']
101
117
  if _descriptor._USE_C_DESCRIPTORS == False:
102
118
 
103
119
  DESCRIPTOR._options = None
104
- _SANDBOXEXECSTDERRCONFIG._serialized_start=999
105
- _SANDBOXEXECSTDERRCONFIG._serialized_end=1140
106
- _SANDBOXEXECSTDIOFILEDESCRIPTOR._serialized_start=1142
107
- _SANDBOXEXECSTDIOFILEDESCRIPTOR._serialized_end=1268
108
- _SANDBOXEXECSTDOUTCONFIG._serialized_start=1270
109
- _SANDBOXEXECSTDOUTCONFIG._serialized_end=1372
110
- _SANDBOXEXECSTARTREQUEST._serialized_start=82
111
- _SANDBOXEXECSTARTREQUEST._serialized_end=483
112
- _SANDBOXEXECSTARTRESPONSE._serialized_start=485
113
- _SANDBOXEXECSTARTRESPONSE._serialized_end=511
114
- _SANDBOXEXECSTDINWRITEREQUEST._serialized_start=513
115
- _SANDBOXEXECSTDINWRITEREQUEST._serialized_end=620
116
- _SANDBOXEXECSTDINWRITERESPONSE._serialized_start=622
117
- _SANDBOXEXECSTDINWRITERESPONSE._serialized_end=653
118
- _SANDBOXEXECSTDIOREADREQUEST._serialized_start=656
119
- _SANDBOXEXECSTDIOREADREQUEST._serialized_end=814
120
- _SANDBOXEXECSTDIOREADRESPONSE._serialized_start=816
121
- _SANDBOXEXECSTDIOREADRESPONSE._serialized_end=860
122
- _SANDBOXEXECWAITREQUEST._serialized_start=862
123
- _SANDBOXEXECWAITREQUEST._serialized_end=920
124
- _SANDBOXEXECWAITRESPONSE._serialized_start=922
125
- _SANDBOXEXECWAITRESPONSE._serialized_end=996
126
- _SANDBOXROUTER._serialized_start=1375
127
- _SANDBOXROUTER._serialized_end=1877
120
+ _SANDBOXEXECSTDERRCONFIG._serialized_start=1135
121
+ _SANDBOXEXECSTDERRCONFIG._serialized_end=1276
122
+ _SANDBOXEXECSTDIOFILEDESCRIPTOR._serialized_start=1278
123
+ _SANDBOXEXECSTDIOFILEDESCRIPTOR._serialized_end=1404
124
+ _SANDBOXEXECSTDOUTCONFIG._serialized_start=1406
125
+ _SANDBOXEXECSTDOUTCONFIG._serialized_end=1508
126
+ _SANDBOXEXECPOLLREQUEST._serialized_start=81
127
+ _SANDBOXEXECPOLLREQUEST._serialized_end=139
128
+ _SANDBOXEXECPOLLRESPONSE._serialized_start=141
129
+ _SANDBOXEXECPOLLRESPONSE._serialized_end=215
130
+ _SANDBOXEXECSTARTREQUEST._serialized_start=218
131
+ _SANDBOXEXECSTARTREQUEST._serialized_end=619
132
+ _SANDBOXEXECSTARTRESPONSE._serialized_start=621
133
+ _SANDBOXEXECSTARTRESPONSE._serialized_end=647
134
+ _SANDBOXEXECSTDINWRITEREQUEST._serialized_start=649
135
+ _SANDBOXEXECSTDINWRITEREQUEST._serialized_end=756
136
+ _SANDBOXEXECSTDINWRITERESPONSE._serialized_start=758
137
+ _SANDBOXEXECSTDINWRITERESPONSE._serialized_end=789
138
+ _SANDBOXEXECSTDIOREADREQUEST._serialized_start=792
139
+ _SANDBOXEXECSTDIOREADREQUEST._serialized_end=950
140
+ _SANDBOXEXECSTDIOREADRESPONSE._serialized_start=952
141
+ _SANDBOXEXECSTDIOREADRESPONSE._serialized_end=996
142
+ _SANDBOXEXECWAITREQUEST._serialized_start=998
143
+ _SANDBOXEXECWAITREQUEST._serialized_end=1056
144
+ _SANDBOXEXECWAITRESPONSE._serialized_start=1058
145
+ _SANDBOXEXECWAITRESPONSE._serialized_end=1132
146
+ _SANDBOXROUTER._serialized_start=1511
147
+ _SANDBOXROUTER._serialized_end=2125
128
148
  # @@protoc_insertion_point(module_scope)
@@ -84,6 +84,50 @@ SANDBOX_EXEC_STDOUT_CONFIG_PIPE: SandboxExecStdoutConfig.ValueType # 1
84
84
  """The output will be streamed to the client."""
85
85
  global___SandboxExecStdoutConfig = SandboxExecStdoutConfig
86
86
 
87
+ class SandboxExecPollRequest(google.protobuf.message.Message):
88
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
89
+
90
+ TASK_ID_FIELD_NUMBER: builtins.int
91
+ EXEC_ID_FIELD_NUMBER: builtins.int
92
+ task_id: builtins.str
93
+ """The task ID of the sandbox running the exec'd command."""
94
+ exec_id: builtins.str
95
+ """The execution ID of the command to wait on."""
96
+ def __init__(
97
+ self,
98
+ *,
99
+ task_id: builtins.str = ...,
100
+ exec_id: builtins.str = ...,
101
+ ) -> None: ...
102
+ def ClearField(self, field_name: typing_extensions.Literal["exec_id", b"exec_id", "task_id", b"task_id"]) -> None: ...
103
+
104
+ global___SandboxExecPollRequest = SandboxExecPollRequest
105
+
106
+ class SandboxExecPollResponse(google.protobuf.message.Message):
107
+ """The response to a SandboxExecPollRequest. If the exec'd command has not
108
+ completed, exit_status will be unset.
109
+ """
110
+
111
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
112
+
113
+ CODE_FIELD_NUMBER: builtins.int
114
+ SIGNAL_FIELD_NUMBER: builtins.int
115
+ code: builtins.int
116
+ """The exit code of the command."""
117
+ signal: builtins.int
118
+ """The signal that terminated the command."""
119
+ def __init__(
120
+ self,
121
+ *,
122
+ code: builtins.int = ...,
123
+ signal: builtins.int = ...,
124
+ ) -> None: ...
125
+ def HasField(self, field_name: typing_extensions.Literal["code", b"code", "exit_status", b"exit_status", "signal", b"signal"]) -> builtins.bool: ...
126
+ def ClearField(self, field_name: typing_extensions.Literal["code", b"code", "exit_status", b"exit_status", "signal", b"signal"]) -> None: ...
127
+ def WhichOneof(self, oneof_group: typing_extensions.Literal["exit_status", b"exit_status"]) -> typing_extensions.Literal["code", "signal"] | None: ...
128
+
129
+ global___SandboxExecPollResponse = SandboxExecPollResponse
130
+
87
131
  class SandboxExecStartRequest(google.protobuf.message.Message):
88
132
  DESCRIPTOR: google.protobuf.descriptor.Descriptor
89
133
 
@@ -14,6 +14,11 @@ class SandboxRouterStub(object):
14
14
  Args:
15
15
  channel: A grpc.Channel.
16
16
  """
17
+ self.SandboxExecPoll = channel.unary_unary(
18
+ '/modal.sandbox_router.SandboxRouter/SandboxExecPoll',
19
+ request_serializer=modal__proto_dot_sandbox__router__pb2.SandboxExecPollRequest.SerializeToString,
20
+ response_deserializer=modal__proto_dot_sandbox__router__pb2.SandboxExecPollResponse.FromString,
21
+ )
17
22
  self.SandboxExecStart = channel.unary_unary(
18
23
  '/modal.sandbox_router.SandboxRouter/SandboxExecStart',
19
24
  request_serializer=modal__proto_dot_sandbox__router__pb2.SandboxExecStartRequest.SerializeToString,
@@ -39,6 +44,13 @@ class SandboxRouterStub(object):
39
44
  class SandboxRouterServicer(object):
40
45
  """Missing associated documentation comment in .proto file."""
41
46
 
47
+ def SandboxExecPoll(self, request, context):
48
+ """Poll for the exit status of an exec'd command.
49
+ """
50
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
51
+ context.set_details('Method not implemented!')
52
+ raise NotImplementedError('Method not implemented!')
53
+
42
54
  def SandboxExecStart(self, request, context):
43
55
  """Execute a command in the sandbox.
44
56
  """
@@ -70,6 +82,11 @@ class SandboxRouterServicer(object):
70
82
 
71
83
  def add_SandboxRouterServicer_to_server(servicer, server):
72
84
  rpc_method_handlers = {
85
+ 'SandboxExecPoll': grpc.unary_unary_rpc_method_handler(
86
+ servicer.SandboxExecPoll,
87
+ request_deserializer=modal__proto_dot_sandbox__router__pb2.SandboxExecPollRequest.FromString,
88
+ response_serializer=modal__proto_dot_sandbox__router__pb2.SandboxExecPollResponse.SerializeToString,
89
+ ),
73
90
  'SandboxExecStart': grpc.unary_unary_rpc_method_handler(
74
91
  servicer.SandboxExecStart,
75
92
  request_deserializer=modal__proto_dot_sandbox__router__pb2.SandboxExecStartRequest.FromString,
@@ -100,6 +117,23 @@ def add_SandboxRouterServicer_to_server(servicer, server):
100
117
  class SandboxRouter(object):
101
118
  """Missing associated documentation comment in .proto file."""
102
119
 
120
+ @staticmethod
121
+ def SandboxExecPoll(request,
122
+ target,
123
+ options=(),
124
+ channel_credentials=None,
125
+ call_credentials=None,
126
+ insecure=False,
127
+ compression=None,
128
+ wait_for_ready=None,
129
+ timeout=None,
130
+ metadata=None):
131
+ return grpc.experimental.unary_unary(request, target, '/modal.sandbox_router.SandboxRouter/SandboxExecPoll',
132
+ modal__proto_dot_sandbox__router__pb2.SandboxExecPollRequest.SerializeToString,
133
+ modal__proto_dot_sandbox__router__pb2.SandboxExecPollResponse.FromString,
134
+ options, channel_credentials,
135
+ insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
136
+
103
137
  @staticmethod
104
138
  def SandboxExecStart(request,
105
139
  target,
@@ -9,6 +9,11 @@ import modal_proto.sandbox_router_pb2
9
9
 
10
10
  class SandboxRouterStub:
11
11
  def __init__(self, channel: grpc.Channel) -> None: ...
12
+ SandboxExecPoll: grpc.UnaryUnaryMultiCallable[
13
+ modal_proto.sandbox_router_pb2.SandboxExecPollRequest,
14
+ modal_proto.sandbox_router_pb2.SandboxExecPollResponse,
15
+ ]
16
+ """Poll for the exit status of an exec'd command."""
12
17
  SandboxExecStart: grpc.UnaryUnaryMultiCallable[
13
18
  modal_proto.sandbox_router_pb2.SandboxExecStartRequest,
14
19
  modal_proto.sandbox_router_pb2.SandboxExecStartResponse,
@@ -32,6 +37,13 @@ class SandboxRouterStub:
32
37
 
33
38
  class SandboxRouterServicer(metaclass=abc.ABCMeta):
34
39
  @abc.abstractmethod
40
+ def SandboxExecPoll(
41
+ self,
42
+ request: modal_proto.sandbox_router_pb2.SandboxExecPollRequest,
43
+ context: grpc.ServicerContext,
44
+ ) -> modal_proto.sandbox_router_pb2.SandboxExecPollResponse:
45
+ """Poll for the exit status of an exec'd command."""
46
+ @abc.abstractmethod
35
47
  def SandboxExecStart(
36
48
  self,
37
49
  request: modal_proto.sandbox_router_pb2.SandboxExecStartRequest,
@@ -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.1.5.dev77"
4
+ __version__ = "1.1.5.dev81"
File without changes
File without changes
File without changes