modAL 1.2.6.dev2__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.dev2 → modal-1.2.6.dev4}/PKG-INFO +1 -1
  2. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/task_command_router_client.py +21 -13
  3. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/client.pyi +2 -2
  4. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/functions.pyi +6 -6
  5. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal.egg-info/PKG-INFO +1 -1
  6. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_version/__init__.py +1 -1
  7. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/pyproject.toml +1 -0
  8. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/LICENSE +0 -0
  9. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/README.md +0 -0
  10. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/__init__.py +0 -0
  11. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/__main__.py +0 -0
  12. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_billing.py +0 -0
  13. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_clustered_functions.py +0 -0
  14. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_clustered_functions.pyi +0 -0
  15. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_container_entrypoint.py +0 -0
  16. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_functions.py +0 -0
  17. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_grpc_client.py +0 -0
  18. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_ipython.py +0 -0
  19. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_load_context.py +0 -0
  20. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_location.py +0 -0
  21. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_object.py +0 -0
  22. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_output.py +0 -0
  23. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_partial_function.py +0 -0
  24. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_pty.py +0 -0
  25. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_resolver.py +0 -0
  26. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_resources.py +0 -0
  27. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_runtime/__init__.py +0 -0
  28. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_runtime/asgi.py +0 -0
  29. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_runtime/container_io_manager.py +0 -0
  30. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_runtime/container_io_manager.pyi +0 -0
  31. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_runtime/execution_context.py +0 -0
  32. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_runtime/execution_context.pyi +0 -0
  33. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  34. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_runtime/telemetry.py +0 -0
  35. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_runtime/user_code_event_loop.py +0 -0
  36. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_runtime/user_code_imports.py +0 -0
  37. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_serialization.py +0 -0
  38. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_traceback.py +0 -0
  39. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_tunnel.py +0 -0
  40. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_tunnel.pyi +0 -0
  41. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_type_manager.py +0 -0
  42. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/__init__.py +0 -0
  43. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/app_utils.py +0 -0
  44. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/async_utils.py +0 -0
  45. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/auth_token_manager.py +0 -0
  46. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/blob_utils.py +0 -0
  47. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/bytes_io_segment_payload.py +0 -0
  48. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/deprecation.py +0 -0
  49. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/docker_utils.py +0 -0
  50. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/function_utils.py +0 -0
  51. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/git_utils.py +0 -0
  52. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/grpc_testing.py +0 -0
  53. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/grpc_utils.py +0 -0
  54. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/hash_utils.py +0 -0
  55. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/http_utils.py +0 -0
  56. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/jwt_utils.py +0 -0
  57. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/logger.py +0 -0
  58. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/mount_utils.py +0 -0
  59. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/name_utils.py +0 -0
  60. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/package_utils.py +0 -0
  61. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/pattern_utils.py +0 -0
  62. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/rand_pb_testing.py +0 -0
  63. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/shell_utils.py +0 -0
  64. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_utils/time_utils.py +0 -0
  65. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_vendor/__init__.py +0 -0
  66. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  67. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_vendor/cloudpickle.py +0 -0
  68. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_vendor/tblib.py +0 -0
  69. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/_watcher.py +0 -0
  70. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/app.py +0 -0
  71. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/app.pyi +0 -0
  72. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/billing.py +0 -0
  73. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/builder/2023.12.312.txt +0 -0
  74. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/builder/2023.12.txt +0 -0
  75. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/builder/2024.04.txt +0 -0
  76. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/builder/2024.10.txt +0 -0
  77. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/builder/2025.06.txt +0 -0
  78. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/builder/PREVIEW.txt +0 -0
  79. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/builder/README.md +0 -0
  80. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/builder/base-images.json +0 -0
  81. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/call_graph.py +0 -0
  82. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/__init__.py +0 -0
  83. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/_download.py +0 -0
  84. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/_traceback.py +0 -0
  85. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/app.py +0 -0
  86. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/cluster.py +0 -0
  87. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/config.py +0 -0
  88. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/container.py +0 -0
  89. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/dict.py +0 -0
  90. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/entry_point.py +0 -0
  91. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/environment.py +0 -0
  92. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/import_refs.py +0 -0
  93. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/launch.py +0 -0
  94. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/network_file_system.py +0 -0
  95. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/profile.py +0 -0
  96. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/programs/__init__.py +0 -0
  97. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/programs/launch_instance_ssh.py +0 -0
  98. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/programs/run_jupyter.py +0 -0
  99. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/programs/run_marimo.py +0 -0
  100. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/programs/vscode.py +0 -0
  101. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/queues.py +0 -0
  102. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/run.py +0 -0
  103. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/secret.py +0 -0
  104. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/shell.py +0 -0
  105. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/token.py +0 -0
  106. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/utils.py +0 -0
  107. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cli/volume.py +0 -0
  108. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/client.py +0 -0
  109. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cloud_bucket_mount.py +0 -0
  110. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cloud_bucket_mount.pyi +0 -0
  111. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cls.py +0 -0
  112. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/cls.pyi +0 -0
  113. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/config.py +0 -0
  114. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/container_process.py +0 -0
  115. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/container_process.pyi +0 -0
  116. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/dict.py +0 -0
  117. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/dict.pyi +0 -0
  118. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/environments.py +0 -0
  119. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/environments.pyi +0 -0
  120. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/exception.py +0 -0
  121. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/experimental/__init__.py +0 -0
  122. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/experimental/flash.py +0 -0
  123. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/experimental/flash.pyi +0 -0
  124. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/experimental/ipython.py +0 -0
  125. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/file_io.py +0 -0
  126. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/file_io.pyi +0 -0
  127. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/file_pattern_matcher.py +0 -0
  128. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/functions.py +0 -0
  129. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/gpu.py +0 -0
  130. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/image.py +0 -0
  131. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/image.pyi +0 -0
  132. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/io_streams.py +0 -0
  133. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/io_streams.pyi +0 -0
  134. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/mount.py +0 -0
  135. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/mount.pyi +0 -0
  136. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/network_file_system.py +0 -0
  137. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/network_file_system.pyi +0 -0
  138. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/object.py +0 -0
  139. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/object.pyi +0 -0
  140. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/output.py +0 -0
  141. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/parallel_map.py +0 -0
  142. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/parallel_map.pyi +0 -0
  143. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/partial_function.py +0 -0
  144. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/partial_function.pyi +0 -0
  145. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/proxy.py +0 -0
  146. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/proxy.pyi +0 -0
  147. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/py.typed +0 -0
  148. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/queue.py +0 -0
  149. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/queue.pyi +0 -0
  150. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/retries.py +0 -0
  151. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/runner.py +0 -0
  152. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/runner.pyi +0 -0
  153. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/running_app.py +0 -0
  154. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/sandbox.py +0 -0
  155. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/sandbox.pyi +0 -0
  156. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/schedule.py +0 -0
  157. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/scheduler_placement.py +0 -0
  158. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/secret.py +0 -0
  159. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/secret.pyi +0 -0
  160. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/serving.py +0 -0
  161. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/serving.pyi +0 -0
  162. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/snapshot.py +0 -0
  163. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/snapshot.pyi +0 -0
  164. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/stream_type.py +0 -0
  165. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/token_flow.py +0 -0
  166. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/token_flow.pyi +0 -0
  167. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/volume.py +0 -0
  168. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal/volume.pyi +0 -0
  169. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal.egg-info/SOURCES.txt +0 -0
  170. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal.egg-info/dependency_links.txt +0 -0
  171. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal.egg-info/entry_points.txt +0 -0
  172. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal.egg-info/requires.txt +0 -0
  173. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal.egg-info/top_level.txt +0 -0
  174. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_docs/__init__.py +0 -0
  175. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_docs/gen_cli_docs.py +0 -0
  176. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_docs/gen_reference_docs.py +0 -0
  177. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_docs/mdmd/__init__.py +0 -0
  178. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_docs/mdmd/mdmd.py +0 -0
  179. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_docs/mdmd/signatures.py +0 -0
  180. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_proto/__init__.py +0 -0
  181. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_proto/api.proto +0 -0
  182. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_proto/api_grpc.py +0 -0
  183. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_proto/api_pb2.py +0 -0
  184. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_proto/api_pb2.pyi +0 -0
  185. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_proto/api_pb2_grpc.py +0 -0
  186. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_proto/api_pb2_grpc.pyi +0 -0
  187. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_proto/modal_api_grpc.py +0 -0
  188. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_proto/py.typed +0 -0
  189. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_proto/task_command_router.proto +0 -0
  190. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_proto/task_command_router_grpc.py +0 -0
  191. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_proto/task_command_router_pb2.py +0 -0
  192. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_proto/task_command_router_pb2.pyi +0 -0
  193. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  194. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  195. {modal-1.2.6.dev2 → modal-1.2.6.dev4}/modal_version/__main__.py +0 -0
  196. {modal-1.2.6.dev2 → 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.dev2
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.dev2",
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.dev2",
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.
@@ -409,7 +409,7 @@ class Function(
409
409
 
410
410
  _call_generator: ___call_generator_spec[typing_extensions.Self]
411
411
 
412
- class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
412
+ class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
413
413
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
414
414
  """Calls the function remotely, executing it with the given arguments and returning the execution's result."""
415
415
  ...
@@ -418,7 +418,7 @@ class Function(
418
418
  """Calls the function remotely, executing it with the given arguments and returning the execution's result."""
419
419
  ...
420
420
 
421
- remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
421
+ remote: __remote_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
422
422
 
423
423
  class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
424
424
  def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
@@ -445,7 +445,7 @@ class Function(
445
445
  """
446
446
  ...
447
447
 
448
- class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
448
+ class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
449
449
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
450
450
  """[Experimental] Calls the function with the given arguments, without waiting for the results.
451
451
 
@@ -469,7 +469,7 @@ class Function(
469
469
  ...
470
470
 
471
471
  _experimental_spawn: ___experimental_spawn_spec[
472
- modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
472
+ modal._functions.ReturnType, modal._functions.P, typing_extensions.Self
473
473
  ]
474
474
 
475
475
  class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER, SUPERSELF]):
@@ -478,7 +478,7 @@ class Function(
478
478
 
479
479
  _spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P, typing_extensions.Self]
480
480
 
481
- class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
481
+ class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
482
482
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
483
483
  """Calls the function with the given arguments, without waiting for the results.
484
484
 
@@ -499,7 +499,7 @@ class Function(
499
499
  """
500
500
  ...
501
501
 
502
- spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
502
+ spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
503
503
 
504
504
  def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
505
505
  """Return the inner Python object wrapped by this Modal Function."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.6.dev2
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.dev2"
4
+ __version__ = "1.2.6.dev4"
@@ -81,6 +81,7 @@ filterwarnings = [
81
81
  "ignore:Type google._upb.*MapContainer uses PyType_Spec.*Python 3.14:DeprecationWarning",
82
82
  "error::modal.exception.DeprecationError",
83
83
  "ignore:There is no current event loop:DeprecationWarning", # pytest-asyncio internals
84
+ "ignore:distutils Version classes are deprecated:DeprecationWarning", # pytest-freezegun internals
84
85
  ]
85
86
 
86
87
  [tool.ruff]
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