modal 1.3.1.dev7__tar.gz → 1.3.1.dev9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/PKG-INFO +3 -2
  2. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_grpc_client.py +3 -3
  3. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_object.py +2 -2
  4. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_resolver.py +23 -22
  5. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_traceback.py +3 -14
  6. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/grpc_utils.py +5 -5
  7. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/client.pyi +2 -2
  8. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal.egg-info/PKG-INFO +3 -2
  9. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal.egg-info/requires.txt +6 -1
  10. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_proto/api.proto +16 -0
  11. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_proto/api_pb2.py +370 -349
  12. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_proto/api_pb2.pyi +62 -2
  13. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_version/__init__.py +1 -1
  14. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/pyproject.toml +2 -1
  15. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/LICENSE +0 -0
  16. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/README.md +0 -0
  17. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/__init__.py +0 -0
  18. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/__main__.py +0 -0
  19. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_billing.py +0 -0
  20. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_clustered_functions.py +0 -0
  21. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_clustered_functions.pyi +0 -0
  22. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_container_entrypoint.py +0 -0
  23. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_functions.py +0 -0
  24. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_ipython.py +0 -0
  25. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_load_context.py +0 -0
  26. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_location.py +0 -0
  27. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_output.py +0 -0
  28. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_partial_function.py +0 -0
  29. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_pty.py +0 -0
  30. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_resources.py +0 -0
  31. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_runtime/__init__.py +0 -0
  32. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_runtime/asgi.py +0 -0
  33. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_runtime/container_io_manager.py +0 -0
  34. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_runtime/container_io_manager.pyi +0 -0
  35. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_runtime/execution_context.py +0 -0
  36. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_runtime/execution_context.pyi +0 -0
  37. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  38. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_runtime/telemetry.py +0 -0
  39. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_runtime/user_code_event_loop.py +0 -0
  40. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_runtime/user_code_imports.py +0 -0
  41. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_serialization.py +0 -0
  42. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_tunnel.py +0 -0
  43. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_tunnel.pyi +0 -0
  44. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_type_manager.py +0 -0
  45. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/__init__.py +0 -0
  46. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/app_utils.py +0 -0
  47. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/async_utils.py +0 -0
  48. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/auth_token_manager.py +0 -0
  49. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/blob_utils.py +0 -0
  50. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/bytes_io_segment_payload.py +0 -0
  51. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/deprecation.py +0 -0
  52. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/docker_utils.py +0 -0
  53. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/function_utils.py +0 -0
  54. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/git_utils.py +0 -0
  55. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/grpc_testing.py +0 -0
  56. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/hash_utils.py +0 -0
  57. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/http_utils.py +0 -0
  58. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/jwt_utils.py +0 -0
  59. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/logger.py +0 -0
  60. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/mount_utils.py +0 -0
  61. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/name_utils.py +0 -0
  62. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/package_utils.py +0 -0
  63. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/pattern_utils.py +0 -0
  64. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/rand_pb_testing.py +0 -0
  65. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/shell_utils.py +0 -0
  66. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/task_command_router_client.py +0 -0
  67. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_utils/time_utils.py +0 -0
  68. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_vendor/__init__.py +0 -0
  69. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  70. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_vendor/cloudpickle.py +0 -0
  71. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_vendor/tblib.py +0 -0
  72. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/_watcher.py +0 -0
  73. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/app.py +0 -0
  74. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/app.pyi +0 -0
  75. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/billing.py +0 -0
  76. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/builder/2023.12.312.txt +0 -0
  77. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/builder/2023.12.txt +0 -0
  78. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/builder/2024.04.txt +0 -0
  79. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/builder/2024.10.txt +0 -0
  80. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/builder/2025.06.txt +0 -0
  81. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/builder/PREVIEW.txt +0 -0
  82. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/builder/README.md +0 -0
  83. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/builder/base-images.json +0 -0
  84. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/call_graph.py +0 -0
  85. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/__init__.py +0 -0
  86. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/_download.py +0 -0
  87. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/_traceback.py +0 -0
  88. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/app.py +0 -0
  89. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/cluster.py +0 -0
  90. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/config.py +0 -0
  91. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/container.py +0 -0
  92. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/dict.py +0 -0
  93. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/entry_point.py +0 -0
  94. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/environment.py +0 -0
  95. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/import_refs.py +0 -0
  96. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/launch.py +0 -0
  97. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/network_file_system.py +0 -0
  98. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/profile.py +0 -0
  99. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/programs/__init__.py +0 -0
  100. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/programs/run_jupyter.py +0 -0
  101. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/programs/vscode.py +0 -0
  102. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/queues.py +0 -0
  103. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/run.py +0 -0
  104. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/secret.py +0 -0
  105. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/shell.py +0 -0
  106. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/token.py +0 -0
  107. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/utils.py +0 -0
  108. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cli/volume.py +0 -0
  109. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/client.py +0 -0
  110. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cloud_bucket_mount.py +0 -0
  111. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cloud_bucket_mount.pyi +0 -0
  112. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cls.py +0 -0
  113. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/cls.pyi +0 -0
  114. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/config.py +0 -0
  115. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/container_process.py +0 -0
  116. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/container_process.pyi +0 -0
  117. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/dict.py +0 -0
  118. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/dict.pyi +0 -0
  119. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/environments.py +0 -0
  120. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/environments.pyi +0 -0
  121. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/exception.py +0 -0
  122. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/experimental/__init__.py +0 -0
  123. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/experimental/flash.py +0 -0
  124. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/experimental/flash.pyi +0 -0
  125. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/experimental/ipython.py +0 -0
  126. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/file_io.py +0 -0
  127. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/file_io.pyi +0 -0
  128. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/file_pattern_matcher.py +0 -0
  129. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/functions.py +0 -0
  130. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/functions.pyi +0 -0
  131. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/gpu.py +0 -0
  132. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/image.py +0 -0
  133. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/image.pyi +0 -0
  134. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/io_streams.py +0 -0
  135. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/io_streams.pyi +0 -0
  136. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/mount.py +0 -0
  137. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/mount.pyi +0 -0
  138. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/network_file_system.py +0 -0
  139. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/network_file_system.pyi +0 -0
  140. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/object.py +0 -0
  141. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/object.pyi +0 -0
  142. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/output.py +0 -0
  143. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/parallel_map.py +0 -0
  144. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/parallel_map.pyi +0 -0
  145. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/partial_function.py +0 -0
  146. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/partial_function.pyi +0 -0
  147. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/proxy.py +0 -0
  148. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/proxy.pyi +0 -0
  149. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/py.typed +0 -0
  150. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/queue.py +0 -0
  151. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/queue.pyi +0 -0
  152. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/retries.py +0 -0
  153. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/runner.py +0 -0
  154. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/runner.pyi +0 -0
  155. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/running_app.py +0 -0
  156. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/sandbox.py +0 -0
  157. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/sandbox.pyi +0 -0
  158. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/schedule.py +0 -0
  159. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/scheduler_placement.py +0 -0
  160. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/secret.py +0 -0
  161. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/secret.pyi +0 -0
  162. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/serving.py +0 -0
  163. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/serving.pyi +0 -0
  164. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/snapshot.py +0 -0
  165. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/snapshot.pyi +0 -0
  166. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/stream_type.py +0 -0
  167. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/token_flow.py +0 -0
  168. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/token_flow.pyi +0 -0
  169. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/volume.py +0 -0
  170. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal/volume.pyi +0 -0
  171. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal.egg-info/SOURCES.txt +0 -0
  172. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal.egg-info/dependency_links.txt +0 -0
  173. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal.egg-info/entry_points.txt +0 -0
  174. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal.egg-info/top_level.txt +0 -0
  175. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_docs/__init__.py +0 -0
  176. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_docs/gen_cli_docs.py +0 -0
  177. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_docs/gen_reference_docs.py +0 -0
  178. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_docs/mdmd/__init__.py +0 -0
  179. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_docs/mdmd/mdmd.py +0 -0
  180. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_docs/mdmd/signatures.py +0 -0
  181. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_proto/__init__.py +0 -0
  182. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_proto/api_grpc.py +0 -0
  183. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_proto/api_pb2_grpc.py +0 -0
  184. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_proto/api_pb2_grpc.pyi +0 -0
  185. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_proto/modal_api_grpc.py +0 -0
  186. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_proto/py.typed +0 -0
  187. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_proto/task_command_router.proto +0 -0
  188. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_proto/task_command_router_grpc.py +0 -0
  189. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_proto/task_command_router_pb2.py +0 -0
  190. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_proto/task_command_router_pb2.pyi +0 -0
  191. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  192. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  193. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/modal_version/__main__.py +0 -0
  194. {modal-1.3.1.dev7 → modal-1.3.1.dev9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.3.1.dev7
3
+ Version: 1.3.1.dev9
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -20,7 +20,8 @@ Requires-Dist: aiohttp
20
20
  Requires-Dist: cbor2
21
21
  Requires-Dist: certifi
22
22
  Requires-Dist: click~=8.1
23
- Requires-Dist: grpclib<0.4.10,>=0.4.7
23
+ Requires-Dist: grpclib<0.4.10,>=0.4.7; python_version < "3.14"
24
+ Requires-Dist: grpclib<0.4.10,>=0.4.9; python_version >= "3.14"
24
25
  Requires-Dist: protobuf!=4.24.0,<7.0,>=3.19
25
26
  Requires-Dist: rich>=12.0.0
26
27
  Requires-Dist: synchronicity~=0.11.1
@@ -6,7 +6,7 @@ from google.protobuf.message import Message
6
6
  from grpclib import GRPCError, Status
7
7
 
8
8
  from . import exception
9
- from ._traceback import suppress_tb_frames
9
+ from ._traceback import suppress_tb_frame
10
10
  from ._utils.grpc_utils import Retry, _retry_transient_errors
11
11
  from .config import config, logger
12
12
 
@@ -50,7 +50,7 @@ class grpc_error_converter:
50
50
  def __exit__(self, exc_type, exc, traceback) -> Literal[False]:
51
51
  # skip all internal frames from grpclib
52
52
  use_full_traceback = config.get("traceback")
53
- with suppress_tb_frames(1):
53
+ with suppress_tb_frame():
54
54
  if isinstance(exc, GRPCError):
55
55
  modal_exc = _STATUS_TO_EXCEPTION[exc.status](exc.message)
56
56
  modal_exc._grpc_message = exc.message
@@ -115,7 +115,7 @@ class UnaryUnaryWrapper(Generic[RequestType, ResponseType]):
115
115
  timeout: Optional[float] = None,
116
116
  metadata: Optional[list[tuple[str, str]]] = None,
117
117
  ) -> ResponseType:
118
- with suppress_tb_frames(1):
118
+ with suppress_tb_frame():
119
119
  if timeout is not None and retry is not None:
120
120
  raise exception.InvalidError("Retry must be None when timeout is set")
121
121
 
@@ -9,7 +9,7 @@ from typing import Callable, ClassVar, Optional
9
9
  from google.protobuf.message import Message
10
10
  from typing_extensions import Self
11
11
 
12
- from modal._traceback import suppress_tb_frames
12
+ from modal._traceback import suppress_tb_frame
13
13
 
14
14
  from ._load_context import LoadContext
15
15
  from ._resolver import Resolver
@@ -328,7 +328,7 @@ class _Object:
328
328
  # Set the client on LoadContext before loading
329
329
  root_load_context = LoadContext(client=client)
330
330
  resolver = Resolver()
331
- with suppress_tb_frames(1): # skip this frame by default
331
+ with suppress_tb_frame(): # skip this frame by default
332
332
  await resolver.load(self, root_load_context)
333
333
  return self
334
334
 
@@ -9,7 +9,7 @@ from collections.abc import Hashable
9
9
  from typing import TYPE_CHECKING, Optional
10
10
 
11
11
  import modal._object
12
- from modal._traceback import suppress_tb_frames
12
+ from modal._traceback import suppress_tb_frame
13
13
  from modal_proto import api_pb2
14
14
 
15
15
  from ._load_context import LoadContext
@@ -120,37 +120,38 @@ class Resolver:
120
120
  if not cached_future:
121
121
  # don't run any awaits within this if-block to prevent race conditions
122
122
  async def loader():
123
- load_context = await obj._load_context_overrides.merged_with(parent_load_context).apply_defaults()
123
+ with suppress_tb_frame():
124
+ load_context = await obj._load_context_overrides.merged_with(parent_load_context).apply_defaults()
124
125
 
125
- # TODO(erikbern): do we need existing_object_id for those?
126
- await TaskContext.gather(*[self.load(dep, load_context) for dep in obj.deps()])
126
+ # TODO(erikbern): do we need existing_object_id for those?
127
+ await TaskContext.gather(*[self.load(dep, load_context) for dep in obj.deps()])
127
128
 
128
- # Load the object itself
129
- if not obj._load:
130
- raise Exception(f"Object {obj} has no loader function")
129
+ # Load the object itself
130
+ if not obj._load:
131
+ raise Exception(f"Object {obj} has no loader function")
131
132
 
132
- await obj._load(obj, self, load_context, existing_object_id)
133
+ await obj._load(obj, self, load_context, existing_object_id)
133
134
 
134
- # Check that the id of functions didn't change
135
- # Persisted refs are ignored because their life cycle is managed independently.
136
- if (
137
- not obj._is_another_app
138
- and existing_object_id is not None
139
- and existing_object_id.startswith("fu-")
140
- and obj.object_id != existing_object_id
141
- ):
142
- raise Exception(
143
- f"Tried creating an object using existing id {existing_object_id} but it has id {obj.object_id}"
144
- )
135
+ # Check that the id of functions didn't change
136
+ # Persisted refs are ignored because their life cycle is managed independently.
137
+ if (
138
+ not obj._is_another_app
139
+ and existing_object_id is not None
140
+ and existing_object_id.startswith("fu-")
141
+ and obj.object_id != existing_object_id
142
+ ):
143
+ raise Exception(
144
+ f"Tried creating an object using existing id {existing_object_id} "
145
+ f"but it has id {obj.object_id}"
146
+ )
145
147
 
146
- return obj
148
+ return obj
147
149
 
148
150
  cached_future = asyncio.create_task(loader())
149
151
  self._local_uuid_to_future[obj.local_uuid] = cached_future
150
152
  if deduplication_key is not None:
151
153
  self._deduplication_cache[deduplication_key] = cached_future
152
- with suppress_tb_frames(2):
153
- # skip current frame + `loader()` closure frame from above
154
+ with suppress_tb_frame():
154
155
  return await cached_future
155
156
 
156
157
  def objects(self) -> list["modal._object._Object"]:
@@ -13,7 +13,7 @@ import warnings
13
13
  from types import TracebackType
14
14
  from typing import Any, Iterable, Optional
15
15
 
16
- from modal.config import config, logger
16
+ from modal.config import config
17
17
  from modal_proto import api_pb2
18
18
 
19
19
  from ._vendor.tblib import Traceback as TBLibTraceback
@@ -137,10 +137,7 @@ traceback_suppression_note = (
137
137
  )
138
138
 
139
139
 
140
- class suppress_tb_frames:
141
- def __init__(self, n: int):
142
- self.n = n
143
-
140
+ class suppress_tb_frame:
144
141
  def __enter__(self):
145
142
  pass
146
143
 
@@ -154,15 +151,7 @@ class suppress_tb_frames:
154
151
  return False
155
152
 
156
153
  # modify traceback on exception object
157
- try:
158
- removed = 0
159
- final_tb = tb
160
- while final_tb is not None and removed < self.n:
161
- final_tb = final_tb.tb_next
162
- removed += 1
163
- except AttributeError:
164
- logger.debug(f"Failed to suppress {self.n} traceback frames from {str(exc_type)} {str(exc)}")
165
- raise
154
+ final_tb = tb.tb_next if tb is not None else tb
166
155
 
167
156
  exc.with_traceback(final_tb)
168
157
  notes = getattr(exc, "__notes__", [])
@@ -27,7 +27,7 @@ from modal.exception import ConnectionError
27
27
  from modal_proto import api_pb2
28
28
  from modal_version import __version__
29
29
 
30
- from .._traceback import suppress_tb_frames
30
+ from .._traceback import suppress_tb_frame
31
31
  from ..config import config
32
32
  from .async_utils import retry
33
33
  from .logger import logger
@@ -273,7 +273,7 @@ def process_exception_before_retry(
273
273
  idempotency_key: str,
274
274
  ):
275
275
  """Process exception before retry, used by `_retry_transient_errors`."""
276
- with suppress_tb_frames(1):
276
+ with suppress_tb_frame():
277
277
  if final_attempt:
278
278
  logger.debug(
279
279
  f"Final attempt failed with {repr(exc)} {n_retries=} {delay=} for {fn_name} ({idempotency_key[:8]})"
@@ -357,7 +357,7 @@ async def _retry_transient_errors(
357
357
  timeout = None
358
358
 
359
359
  try:
360
- with suppress_tb_frames(1):
360
+ with suppress_tb_frame():
361
361
  return await fn_callable(req, metadata=attempt_metadata, timeout=timeout)
362
362
  except (StreamTerminatedError, GRPCError, OSError, asyncio.TimeoutError, AttributeError) as exc:
363
363
  # Note that we only catch AttributeError to handle a specific case that works around a bug
@@ -384,7 +384,7 @@ async def _retry_transient_errors(
384
384
  )
385
385
  final_attempt = total_timeout_will_be_reached or max_throttle_will_be_reached
386
386
 
387
- with suppress_tb_frames(1):
387
+ with suppress_tb_frame():
388
388
  process_exception_before_retry(
389
389
  exc, final_attempt, fn.name, n_retries, server_delay, idempotency_key
390
390
  )
@@ -414,7 +414,7 @@ async def _retry_transient_errors(
414
414
  else:
415
415
  final_attempt = False
416
416
 
417
- with suppress_tb_frames(1):
417
+ with suppress_tb_frame():
418
418
  process_exception_before_retry(exc, final_attempt, fn.name, n_retries, delay, idempotency_key)
419
419
 
420
420
  n_retries += 1
@@ -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.3.1.dev7",
36
+ version: str = "1.3.1.dev9",
37
37
  ):
38
38
  """mdmd:hidden
39
39
  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.3.1.dev7",
166
+ version: str = "1.3.1.dev9",
167
167
  ):
168
168
  """mdmd:hidden
169
169
  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.3.1.dev7
3
+ Version: 1.3.1.dev9
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -20,7 +20,8 @@ Requires-Dist: aiohttp
20
20
  Requires-Dist: cbor2
21
21
  Requires-Dist: certifi
22
22
  Requires-Dist: click~=8.1
23
- Requires-Dist: grpclib<0.4.10,>=0.4.7
23
+ Requires-Dist: grpclib<0.4.10,>=0.4.7; python_version < "3.14"
24
+ Requires-Dist: grpclib<0.4.10,>=0.4.9; python_version >= "3.14"
24
25
  Requires-Dist: protobuf!=4.24.0,<7.0,>=3.19
25
26
  Requires-Dist: rich>=12.0.0
26
27
  Requires-Dist: synchronicity~=0.11.1
@@ -2,7 +2,6 @@ aiohttp
2
2
  cbor2
3
3
  certifi
4
4
  click~=8.1
5
- grpclib<0.4.10,>=0.4.7
6
5
  protobuf!=4.24.0,<7.0,>=3.19
7
6
  rich>=12.0.0
8
7
  synchronicity~=0.11.1
@@ -12,3 +11,9 @@ types-certifi
12
11
  types-toml
13
12
  watchfiles
14
13
  typing_extensions~=4.6
14
+
15
+ [:python_version < "3.14"]
16
+ grpclib<0.4.10,>=0.4.7
17
+
18
+ [:python_version >= "3.14"]
19
+ grpclib<0.4.10,>=0.4.9
@@ -2679,6 +2679,19 @@ message RateLimit {
2679
2679
  RateLimitInterval interval = 2;
2680
2680
  }
2681
2681
 
2682
+ message ResourceInfo {
2683
+ message ResourceValue {
2684
+ uint32 value = 1;
2685
+ bool is_default = 2;
2686
+ }
2687
+ ResourceValue memory_mb = 1; // MiB
2688
+ ResourceValue milli_cpu = 2; // milli CPU cores
2689
+ string gpu_type = 3;
2690
+ uint32 memory_mb_max = 4 ; // MiB
2691
+ uint32 ephemeral_disk_mb = 5; // MiB
2692
+ uint32 milli_cpu_max = 6; // milli CPU cores
2693
+ }
2694
+
2682
2695
  message Resources {
2683
2696
  uint32 memory_mb = 2; // MiB
2684
2697
  uint32 milli_cpu = 3; // milli CPU cores
@@ -2887,9 +2900,12 @@ message SandboxInfo {
2887
2900
  repeated SandboxTag tags = 6; // TODO: Not yet exposed in client library.
2888
2901
  string name = 7;
2889
2902
  string image_id = 8;
2903
+ ResourceInfo resource_info = 9;
2904
+ repeated string regions = 10;
2890
2905
  reserved 2; // modal.client.Sandbox definition
2891
2906
  }
2892
2907
 
2908
+
2893
2909
  message SandboxListRequest {
2894
2910
  string app_id = 1;
2895
2911
  double before_timestamp = 2;