modal 1.2.3.dev15__tar.gz → 1.2.3.dev16__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 (200) hide show
  1. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/PKG-INFO +1 -1
  2. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/grpc_utils.py +20 -15
  3. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/client.pyi +2 -2
  4. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/config.py +1 -8
  5. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal.egg-info/PKG-INFO +1 -1
  6. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_version/__init__.py +1 -1
  7. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/LICENSE +0 -0
  8. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/README.md +0 -0
  9. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/__init__.py +0 -0
  10. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/__main__.py +0 -0
  11. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_billing.py +0 -0
  12. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_clustered_functions.py +0 -0
  13. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_clustered_functions.pyi +0 -0
  14. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_container_entrypoint.py +0 -0
  15. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_functions.py +0 -0
  16. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_grpc_client.py +0 -0
  17. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_ipython.py +0 -0
  18. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_load_context.py +0 -0
  19. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_location.py +0 -0
  20. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_object.py +0 -0
  21. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_output.py +0 -0
  22. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_partial_function.py +0 -0
  23. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_pty.py +0 -0
  24. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_resolver.py +0 -0
  25. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_resources.py +0 -0
  26. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_runtime/__init__.py +0 -0
  27. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_runtime/asgi.py +0 -0
  28. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_runtime/container_io_manager.py +0 -0
  29. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_runtime/container_io_manager.pyi +0 -0
  30. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_runtime/execution_context.py +0 -0
  31. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_runtime/execution_context.pyi +0 -0
  32. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  33. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_runtime/telemetry.py +0 -0
  34. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_runtime/user_code_imports.py +0 -0
  35. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_serialization.py +0 -0
  36. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_traceback.py +0 -0
  37. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_tunnel.py +0 -0
  38. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_tunnel.pyi +0 -0
  39. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_type_manager.py +0 -0
  40. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/__init__.py +0 -0
  41. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/app_utils.py +0 -0
  42. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/async_utils.py +0 -0
  43. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/auth_token_manager.py +0 -0
  44. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/blob_utils.py +0 -0
  45. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/bytes_io_segment_payload.py +0 -0
  46. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/deprecation.py +0 -0
  47. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/docker_utils.py +0 -0
  48. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/function_utils.py +0 -0
  49. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/git_utils.py +0 -0
  50. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/grpc_testing.py +0 -0
  51. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/hash_utils.py +0 -0
  52. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/http_utils.py +0 -0
  53. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/jwt_utils.py +0 -0
  54. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/logger.py +0 -0
  55. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/mount_utils.py +0 -0
  56. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/name_utils.py +0 -0
  57. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/package_utils.py +0 -0
  58. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/pattern_utils.py +0 -0
  59. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/rand_pb_testing.py +0 -0
  60. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/shell_utils.py +0 -0
  61. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/task_command_router_client.py +0 -0
  62. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_utils/time_utils.py +0 -0
  63. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_vendor/__init__.py +0 -0
  64. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  65. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_vendor/cloudpickle.py +0 -0
  66. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_vendor/tblib.py +0 -0
  67. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/_watcher.py +0 -0
  68. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/app.py +0 -0
  69. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/app.pyi +0 -0
  70. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/billing.py +0 -0
  71. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/builder/2023.12.312.txt +0 -0
  72. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/builder/2023.12.txt +0 -0
  73. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/builder/2024.04.txt +0 -0
  74. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/builder/2024.10.txt +0 -0
  75. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/builder/2025.06.txt +0 -0
  76. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/builder/PREVIEW.txt +0 -0
  77. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/builder/README.md +0 -0
  78. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/builder/base-images.json +0 -0
  79. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/call_graph.py +0 -0
  80. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/__init__.py +0 -0
  81. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/_download.py +0 -0
  82. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/_traceback.py +0 -0
  83. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/app.py +0 -0
  84. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/cluster.py +0 -0
  85. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/config.py +0 -0
  86. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/container.py +0 -0
  87. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/dict.py +0 -0
  88. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/entry_point.py +0 -0
  89. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/environment.py +0 -0
  90. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/import_refs.py +0 -0
  91. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/launch.py +0 -0
  92. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/network_file_system.py +0 -0
  93. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/profile.py +0 -0
  94. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/programs/__init__.py +0 -0
  95. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/programs/launch_instance_ssh.py +0 -0
  96. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/programs/run_jupyter.py +0 -0
  97. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/programs/run_marimo.py +0 -0
  98. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/programs/vscode.py +0 -0
  99. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/queues.py +0 -0
  100. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/run.py +0 -0
  101. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/secret.py +0 -0
  102. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/token.py +0 -0
  103. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/utils.py +0 -0
  104. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cli/volume.py +0 -0
  105. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/client.py +0 -0
  106. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cloud_bucket_mount.py +0 -0
  107. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cloud_bucket_mount.pyi +0 -0
  108. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cls.py +0 -0
  109. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/cls.pyi +0 -0
  110. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/container_process.py +0 -0
  111. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/container_process.pyi +0 -0
  112. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/dict.py +0 -0
  113. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/dict.pyi +0 -0
  114. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/environments.py +0 -0
  115. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/environments.pyi +0 -0
  116. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/exception.py +0 -0
  117. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/experimental/__init__.py +0 -0
  118. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/experimental/flash.py +0 -0
  119. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/experimental/flash.pyi +0 -0
  120. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/experimental/ipython.py +0 -0
  121. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/file_io.py +0 -0
  122. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/file_io.pyi +0 -0
  123. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/file_pattern_matcher.py +0 -0
  124. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/functions.py +0 -0
  125. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/functions.pyi +0 -0
  126. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/gpu.py +0 -0
  127. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/image.py +0 -0
  128. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/image.pyi +0 -0
  129. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/io_streams.py +0 -0
  130. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/io_streams.pyi +0 -0
  131. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/mount.py +0 -0
  132. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/mount.pyi +0 -0
  133. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/network_file_system.py +0 -0
  134. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/network_file_system.pyi +0 -0
  135. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/object.py +0 -0
  136. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/object.pyi +0 -0
  137. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/output.py +0 -0
  138. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/parallel_map.py +0 -0
  139. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/parallel_map.pyi +0 -0
  140. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/partial_function.py +0 -0
  141. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/partial_function.pyi +0 -0
  142. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/proxy.py +0 -0
  143. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/proxy.pyi +0 -0
  144. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/py.typed +0 -0
  145. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/queue.py +0 -0
  146. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/queue.pyi +0 -0
  147. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/retries.py +0 -0
  148. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/runner.py +0 -0
  149. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/runner.pyi +0 -0
  150. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/running_app.py +0 -0
  151. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/sandbox.py +0 -0
  152. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/sandbox.pyi +0 -0
  153. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/schedule.py +0 -0
  154. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/scheduler_placement.py +0 -0
  155. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/secret.py +0 -0
  156. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/secret.pyi +0 -0
  157. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/serving.py +0 -0
  158. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/serving.pyi +0 -0
  159. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/snapshot.py +0 -0
  160. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/snapshot.pyi +0 -0
  161. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/stream_type.py +0 -0
  162. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/token_flow.py +0 -0
  163. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/token_flow.pyi +0 -0
  164. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/volume.py +0 -0
  165. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal/volume.pyi +0 -0
  166. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal.egg-info/SOURCES.txt +0 -0
  167. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal.egg-info/dependency_links.txt +0 -0
  168. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal.egg-info/entry_points.txt +0 -0
  169. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal.egg-info/requires.txt +0 -0
  170. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal.egg-info/top_level.txt +0 -0
  171. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_docs/__init__.py +0 -0
  172. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_docs/gen_cli_docs.py +0 -0
  173. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_docs/gen_reference_docs.py +0 -0
  174. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_docs/mdmd/__init__.py +0 -0
  175. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_docs/mdmd/mdmd.py +0 -0
  176. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_docs/mdmd/signatures.py +0 -0
  177. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/__init__.py +0 -0
  178. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/api.proto +0 -0
  179. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/api_grpc.py +0 -0
  180. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/api_pb2.py +0 -0
  181. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/api_pb2.pyi +0 -0
  182. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/api_pb2_grpc.py +0 -0
  183. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/api_pb2_grpc.pyi +0 -0
  184. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/modal_api_grpc.py +0 -0
  185. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/py.typed +0 -0
  186. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/sandbox_router.proto +0 -0
  187. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/sandbox_router_grpc.py +0 -0
  188. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/sandbox_router_pb2.py +0 -0
  189. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/sandbox_router_pb2.pyi +0 -0
  190. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/sandbox_router_pb2_grpc.py +0 -0
  191. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/sandbox_router_pb2_grpc.pyi +0 -0
  192. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/task_command_router.proto +0 -0
  193. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/task_command_router_grpc.py +0 -0
  194. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/task_command_router_pb2.py +0 -0
  195. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/task_command_router_pb2.pyi +0 -0
  196. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  197. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  198. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/modal_version/__main__.py +0 -0
  199. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/pyproject.toml +0 -0
  200. {modal-1.2.3.dev15 → modal-1.2.3.dev16}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.3.dev15
3
+ Version: 1.2.3.dev16
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -271,15 +271,13 @@ def process_exception_before_retry(
271
271
  fn_name: str,
272
272
  n_retries: int,
273
273
  delay: float,
274
- total_deadline: Optional[float],
275
274
  idempotency_key: str,
276
275
  ):
277
276
  """Process exception before retry, used by `_retry_transient_errors`."""
278
277
  with suppress_tb_frames(1):
279
278
  if final_attempt:
280
279
  logger.debug(
281
- f"Final attempt failed with {repr(exc)} {n_retries=} {delay=} "
282
- f"{total_deadline=} for {fn_name} ({idempotency_key[:8]})"
280
+ f"Final attempt failed with {repr(exc)} {n_retries=} {delay=} for {fn_name} ({idempotency_key[:8]})"
283
281
  )
284
282
  if isinstance(exc, OSError):
285
283
  raise ConnectionError(str(exc))
@@ -358,6 +356,7 @@ async def _retry_transient_errors(
358
356
  timeout = min(timeouts) # In case the function provided both types of timeouts
359
357
  else:
360
358
  timeout = None
359
+
361
360
  try:
362
361
  with suppress_tb_frames(1):
363
362
  return await fn_callable(req, metadata=attempt_metadata, timeout=timeout)
@@ -366,21 +365,29 @@ async def _retry_transient_errors(
366
365
  # in grpclib<=0.4.7. See above (search for `write_appdata`).
367
366
 
368
367
  # Server side instruction for retries
369
- if isinstance(exc, GRPCError) and (server_retry_policy := get_server_retry_policy(exc)):
368
+ max_throttle_wait: Optional[int] = config.get("max_throttle_wait")
369
+ if (
370
+ max_throttle_wait != 0
371
+ and isinstance(exc, GRPCError)
372
+ and (server_retry_policy := get_server_retry_policy(exc))
373
+ ):
370
374
  server_delay = server_retry_policy.retry_after_secs
371
375
 
372
- # When `total_deadline` is not defined and server gives instruction for retries, then use
373
- # `max_throttle_wait`.
374
- if total_deadline is None and (max_throttle_wait := config.get("max_throttle_wait")):
375
- total_deadline = t0 + max_throttle_wait
376
+ now = time.time()
376
377
 
377
- final_attempt = (
378
- total_deadline is not None
379
- and time.time() + server_delay + retry.attempt_timeout_floor >= total_deadline
378
+ # We check if the timeout will be reached **after** the sleep, so we can raise an error early
379
+ # without needing to actually sleep.
380
+ total_timeout_will_be_reached = (
381
+ retry.total_timeout is not None and (now + server_delay - t0) >= retry.total_timeout
382
+ )
383
+ max_throttle_will_be_reached = (
384
+ max_throttle_wait is not None and (now + server_delay - t0) >= max_throttle_wait
380
385
  )
386
+ final_attempt = total_timeout_will_be_reached or max_throttle_will_be_reached
387
+
381
388
  with suppress_tb_frames(1):
382
389
  process_exception_before_retry(
383
- exc, final_attempt, fn.name, n_retries, server_delay, total_deadline, idempotency_key
390
+ exc, final_attempt, fn.name, n_retries, server_delay, idempotency_key
384
391
  )
385
392
 
386
393
  now = time.time()
@@ -411,9 +418,7 @@ async def _retry_transient_errors(
411
418
  final_attempt = False
412
419
 
413
420
  with suppress_tb_frames(1):
414
- process_exception_before_retry(
415
- exc, final_attempt, fn.name, n_retries, delay, total_deadline, idempotency_key
416
- )
421
+ process_exception_before_retry(exc, final_attempt, fn.name, n_retries, delay, idempotency_key)
417
422
 
418
423
  n_retries += 1
419
424
 
@@ -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.3.dev15",
35
+ version: str = "1.2.3.dev16",
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.3.dev15",
166
+ version: str = "1.2.3.dev16",
167
167
  ):
168
168
  """mdmd:hidden
169
169
  The Modal client object is not intended to be instantiated directly by users.
@@ -221,13 +221,6 @@ def _enforce_suffix_rules(x: str) -> str:
221
221
  return x
222
222
 
223
223
 
224
- def _int_or_none(x: str) -> Optional[int]:
225
- if not x:
226
- return None
227
- x_int = int(x)
228
- return x_int if x_int > 0 else None
229
-
230
-
231
224
  class _Setting(typing.NamedTuple):
232
225
  default: typing.Any = None
233
226
  transform: typing.Callable[[str], typing.Any] = lambda x: x # noqa: E731
@@ -269,7 +262,7 @@ _SETTINGS = {
269
262
  transform=lambda s: _check_value(["pickle", "cbor"])(s.lower()),
270
263
  ),
271
264
  "dev_suffix": _Setting("", transform=_enforce_suffix_rules),
272
- "max_throttle_wait": _Setting(None, transform=_int_or_none),
265
+ "max_throttle_wait": _Setting(None, transform=lambda x: int(x) if x else None),
273
266
  }
274
267
 
275
268
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.3.dev15
3
+ Version: 1.2.3.dev16
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2025
2
2
  """Supplies the current version of the modal client library."""
3
3
 
4
- __version__ = "1.2.3.dev15"
4
+ __version__ = "1.2.3.dev16"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes