modAL 1.2.6.dev3__tar.gz → 1.2.6.dev4__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 (196) hide show
  1. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/PKG-INFO +1 -1
  2. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/task_command_router_client.py +21 -13
  3. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/client.pyi +2 -2
  4. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal.egg-info/PKG-INFO +1 -1
  5. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_version/__init__.py +1 -1
  6. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/LICENSE +0 -0
  7. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/README.md +0 -0
  8. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/__init__.py +0 -0
  9. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/__main__.py +0 -0
  10. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_billing.py +0 -0
  11. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_clustered_functions.py +0 -0
  12. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_clustered_functions.pyi +0 -0
  13. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_container_entrypoint.py +0 -0
  14. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_functions.py +0 -0
  15. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_grpc_client.py +0 -0
  16. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_ipython.py +0 -0
  17. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_load_context.py +0 -0
  18. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_location.py +0 -0
  19. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_object.py +0 -0
  20. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_output.py +0 -0
  21. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_partial_function.py +0 -0
  22. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_pty.py +0 -0
  23. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_resolver.py +0 -0
  24. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_resources.py +0 -0
  25. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_runtime/__init__.py +0 -0
  26. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_runtime/asgi.py +0 -0
  27. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_runtime/container_io_manager.py +0 -0
  28. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_runtime/container_io_manager.pyi +0 -0
  29. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_runtime/execution_context.py +0 -0
  30. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_runtime/execution_context.pyi +0 -0
  31. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  32. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_runtime/telemetry.py +0 -0
  33. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_runtime/user_code_event_loop.py +0 -0
  34. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_runtime/user_code_imports.py +0 -0
  35. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_serialization.py +0 -0
  36. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_traceback.py +0 -0
  37. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_tunnel.py +0 -0
  38. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_tunnel.pyi +0 -0
  39. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_type_manager.py +0 -0
  40. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/__init__.py +0 -0
  41. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/app_utils.py +0 -0
  42. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/async_utils.py +0 -0
  43. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/auth_token_manager.py +0 -0
  44. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/blob_utils.py +0 -0
  45. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/bytes_io_segment_payload.py +0 -0
  46. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/deprecation.py +0 -0
  47. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/docker_utils.py +0 -0
  48. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/function_utils.py +0 -0
  49. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/git_utils.py +0 -0
  50. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/grpc_testing.py +0 -0
  51. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/grpc_utils.py +0 -0
  52. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/hash_utils.py +0 -0
  53. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/http_utils.py +0 -0
  54. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/jwt_utils.py +0 -0
  55. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/logger.py +0 -0
  56. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/mount_utils.py +0 -0
  57. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/name_utils.py +0 -0
  58. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/package_utils.py +0 -0
  59. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/pattern_utils.py +0 -0
  60. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/rand_pb_testing.py +0 -0
  61. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/shell_utils.py +0 -0
  62. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_utils/time_utils.py +0 -0
  63. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_vendor/__init__.py +0 -0
  64. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  65. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_vendor/cloudpickle.py +0 -0
  66. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_vendor/tblib.py +0 -0
  67. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/_watcher.py +0 -0
  68. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/app.py +0 -0
  69. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/app.pyi +0 -0
  70. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/billing.py +0 -0
  71. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/builder/2023.12.312.txt +0 -0
  72. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/builder/2023.12.txt +0 -0
  73. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/builder/2024.04.txt +0 -0
  74. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/builder/2024.10.txt +0 -0
  75. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/builder/2025.06.txt +0 -0
  76. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/builder/PREVIEW.txt +0 -0
  77. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/builder/README.md +0 -0
  78. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/builder/base-images.json +0 -0
  79. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/call_graph.py +0 -0
  80. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/__init__.py +0 -0
  81. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/_download.py +0 -0
  82. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/_traceback.py +0 -0
  83. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/app.py +0 -0
  84. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/cluster.py +0 -0
  85. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/config.py +0 -0
  86. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/container.py +0 -0
  87. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/dict.py +0 -0
  88. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/entry_point.py +0 -0
  89. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/environment.py +0 -0
  90. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/import_refs.py +0 -0
  91. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/launch.py +0 -0
  92. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/network_file_system.py +0 -0
  93. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/profile.py +0 -0
  94. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/programs/__init__.py +0 -0
  95. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/programs/launch_instance_ssh.py +0 -0
  96. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/programs/run_jupyter.py +0 -0
  97. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/programs/run_marimo.py +0 -0
  98. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/programs/vscode.py +0 -0
  99. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/queues.py +0 -0
  100. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/run.py +0 -0
  101. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/secret.py +0 -0
  102. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/shell.py +0 -0
  103. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/token.py +0 -0
  104. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/utils.py +0 -0
  105. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cli/volume.py +0 -0
  106. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/client.py +0 -0
  107. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cloud_bucket_mount.py +0 -0
  108. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cloud_bucket_mount.pyi +0 -0
  109. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cls.py +0 -0
  110. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/cls.pyi +0 -0
  111. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/config.py +0 -0
  112. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/container_process.py +0 -0
  113. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/container_process.pyi +0 -0
  114. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/dict.py +0 -0
  115. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/dict.pyi +0 -0
  116. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/environments.py +0 -0
  117. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/environments.pyi +0 -0
  118. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/exception.py +0 -0
  119. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/experimental/__init__.py +0 -0
  120. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/experimental/flash.py +0 -0
  121. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/experimental/flash.pyi +0 -0
  122. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/experimental/ipython.py +0 -0
  123. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/file_io.py +0 -0
  124. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/file_io.pyi +0 -0
  125. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/file_pattern_matcher.py +0 -0
  126. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/functions.py +0 -0
  127. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/functions.pyi +0 -0
  128. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/gpu.py +0 -0
  129. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/image.py +0 -0
  130. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/image.pyi +0 -0
  131. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/io_streams.py +0 -0
  132. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/io_streams.pyi +0 -0
  133. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/mount.py +0 -0
  134. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/mount.pyi +0 -0
  135. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/network_file_system.py +0 -0
  136. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/network_file_system.pyi +0 -0
  137. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/object.py +0 -0
  138. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/object.pyi +0 -0
  139. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/output.py +0 -0
  140. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/parallel_map.py +0 -0
  141. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/parallel_map.pyi +0 -0
  142. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/partial_function.py +0 -0
  143. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/partial_function.pyi +0 -0
  144. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/proxy.py +0 -0
  145. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/proxy.pyi +0 -0
  146. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/py.typed +0 -0
  147. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/queue.py +0 -0
  148. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/queue.pyi +0 -0
  149. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/retries.py +0 -0
  150. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/runner.py +0 -0
  151. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/runner.pyi +0 -0
  152. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/running_app.py +0 -0
  153. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/sandbox.py +0 -0
  154. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/sandbox.pyi +0 -0
  155. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/schedule.py +0 -0
  156. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/scheduler_placement.py +0 -0
  157. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/secret.py +0 -0
  158. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/secret.pyi +0 -0
  159. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/serving.py +0 -0
  160. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/serving.pyi +0 -0
  161. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/snapshot.py +0 -0
  162. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/snapshot.pyi +0 -0
  163. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/stream_type.py +0 -0
  164. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/token_flow.py +0 -0
  165. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/token_flow.pyi +0 -0
  166. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/volume.py +0 -0
  167. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal/volume.pyi +0 -0
  168. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal.egg-info/SOURCES.txt +0 -0
  169. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal.egg-info/dependency_links.txt +0 -0
  170. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal.egg-info/entry_points.txt +0 -0
  171. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal.egg-info/requires.txt +0 -0
  172. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal.egg-info/top_level.txt +0 -0
  173. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_docs/__init__.py +0 -0
  174. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_docs/gen_cli_docs.py +0 -0
  175. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_docs/gen_reference_docs.py +0 -0
  176. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_docs/mdmd/__init__.py +0 -0
  177. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_docs/mdmd/mdmd.py +0 -0
  178. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_docs/mdmd/signatures.py +0 -0
  179. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_proto/__init__.py +0 -0
  180. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_proto/api.proto +0 -0
  181. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_proto/api_grpc.py +0 -0
  182. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_proto/api_pb2.py +0 -0
  183. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_proto/api_pb2.pyi +0 -0
  184. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_proto/api_pb2_grpc.py +0 -0
  185. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_proto/api_pb2_grpc.pyi +0 -0
  186. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_proto/modal_api_grpc.py +0 -0
  187. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_proto/py.typed +0 -0
  188. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_proto/task_command_router.proto +0 -0
  189. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_proto/task_command_router_grpc.py +0 -0
  190. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_proto/task_command_router_pb2.py +0 -0
  191. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_proto/task_command_router_pb2.pyi +0 -0
  192. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  193. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  194. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/modal_version/__main__.py +0 -0
  195. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/pyproject.toml +0 -0
  196. {modal-1.2.6.dev3 → modal-1.2.6.dev4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.6.dev3
3
+ Version: 1.2.6.dev4
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -403,7 +403,10 @@ class TaskCommandRouterClient:
403
403
  )
404
404
  return
405
405
 
406
+ logger.debug(f"Refreshing JWT for exec with task ID {self._task_id}")
406
407
  resp = await fetch_command_router_access(self._server_client, self._task_id)
408
+ logger.debug(f"Finished refreshing JWT for exec with task ID {self._task_id}")
409
+
407
410
  # Ensure the server URL remains stable for the lifetime of this client.
408
411
  assert resp.url == self._server_url, "Task router URL changed during session"
409
412
  self._jwt = resp.jwt
@@ -434,7 +437,9 @@ class TaskCommandRouterClient:
434
437
  delay_secs = self.stream_stdio_retry_delay_secs
435
438
  delay_factor = self.stream_stdio_retry_delay_factor
436
439
  num_retries_remaining = self.stream_stdio_max_retries
437
- num_auth_retries = 0
440
+ # Flag to prevent infinite auth retries in the event that the JWT
441
+ # refresh yields an invalid JWT somehow or that the JWT is otherwise invalid.
442
+ did_auth_retry = False
438
443
 
439
444
  async def sleep_and_update_delay_and_num_retries_remaining(e: Exception):
440
445
  nonlocal delay_secs, num_retries_remaining
@@ -458,25 +463,28 @@ class TaskCommandRouterClient:
458
463
  file_descriptor=file_descriptor,
459
464
  )
460
465
 
461
- # Scope auth retry strictly to the initial send (where headers/auth are sent).
466
+ # Auth retry is scoped to a single refresh per streaming attempt. While auth metadata is
467
+ # sent on request start, UNAUTHENTICATED may sometimes surface during iteration,
468
+ # so we handle it at both send and receive boundaries.
462
469
  try:
463
470
  await s.send_message(req, end=True)
471
+ async for item in s:
472
+ # We successfully authenticated after a JWT refresh, reset the auth retry flag.
473
+ if did_auth_retry:
474
+ did_auth_retry = False
475
+ # Reset retry backoff after any successful chunk.
476
+ delay_secs = self.stream_stdio_retry_delay_secs
477
+ offset += len(item.data)
478
+ yield item
464
479
  except GRPCError as exc:
465
- if exc.status == Status.UNAUTHENTICATED and num_auth_retries < 1:
480
+ if exc.status == Status.UNAUTHENTICATED and not did_auth_retry:
466
481
  await self._refresh_jwt()
467
- num_auth_retries += 1
482
+ # Mark that we've retried authentication for this streaming attempt, to
483
+ # prevent subsequent retries.
484
+ did_auth_retry = True
468
485
  continue
469
486
  raise
470
487
 
471
- # We successfully authenticated, reset the auth retry count.
472
- num_auth_retries = 0
473
-
474
- async for item in s:
475
- # Reset retry backoff after any successful chunk.
476
- delay_secs = self.stream_stdio_retry_delay_secs
477
- offset += len(item.data)
478
- yield item
479
-
480
488
  # We successfully streamed all output.
481
489
  return
482
490
  except GRPCError as e:
@@ -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.6.dev3",
35
+ version: str = "1.2.6.dev4",
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.6.dev3",
166
+ version: str = "1.2.6.dev4",
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.2.6.dev3
3
+ Version: 1.2.6.dev4
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.6.dev3"
4
+ __version__ = "1.2.6.dev4"
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
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