modal 1.3.6.dev8__tar.gz → 1.3.6.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 (210) hide show
  1. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/PKG-INFO +1 -2
  2. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/README.md +0 -1
  3. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/async_utils.py +17 -2
  4. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/blob_utils.py +2 -2
  5. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/grpc_utils.py +15 -5
  6. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/client.pyi +2 -2
  7. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/functions.pyi +6 -6
  8. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/volume.py +3 -3
  9. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal.egg-info/PKG-INFO +1 -2
  10. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_version/__init__.py +1 -1
  11. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/pyproject.toml +47 -1
  12. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/LICENSE +0 -0
  13. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/__init__.py +0 -0
  14. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/__main__.py +0 -0
  15. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_billing.py +0 -0
  16. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_clustered_functions.py +0 -0
  17. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_clustered_functions.pyi +0 -0
  18. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_container_entrypoint.py +0 -0
  19. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_functions.py +0 -0
  20. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_grpc_client.py +0 -0
  21. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_ipython.py +0 -0
  22. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_load_context.py +0 -0
  23. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_location.py +0 -0
  24. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_logs.py +0 -0
  25. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_object.py +0 -0
  26. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_output/__init__.py +0 -0
  27. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_output/manager.py +0 -0
  28. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_output/pty.py +0 -0
  29. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_output/rich.py +0 -0
  30. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_output/status.py +0 -0
  31. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_partial_function.py +0 -0
  32. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_resolver.py +0 -0
  33. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_resources.py +0 -0
  34. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_runtime/__init__.py +0 -0
  35. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_runtime/asgi.py +0 -0
  36. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_runtime/container_io_manager.py +0 -0
  37. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_runtime/container_io_manager.pyi +0 -0
  38. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_runtime/execution_context.py +0 -0
  39. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_runtime/execution_context.pyi +0 -0
  40. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  41. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_runtime/telemetry.py +0 -0
  42. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_runtime/user_code_event_loop.py +0 -0
  43. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_runtime/user_code_imports.py +0 -0
  44. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_serialization.py +0 -0
  45. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_server.py +0 -0
  46. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_traceback.py +0 -0
  47. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_tunnel.py +0 -0
  48. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_tunnel.pyi +0 -0
  49. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_type_manager.py +0 -0
  50. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/__init__.py +0 -0
  51. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/app_utils.py +0 -0
  52. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/auth_token_manager.py +0 -0
  53. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/browser_utils.py +0 -0
  54. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/bytes_io_segment_payload.py +0 -0
  55. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/deprecation.py +0 -0
  56. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/docker_utils.py +0 -0
  57. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/function_utils.py +0 -0
  58. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/git_utils.py +0 -0
  59. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/grpc_testing.py +0 -0
  60. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/hash_utils.py +0 -0
  61. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/http_utils.py +0 -0
  62. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/jwt_utils.py +0 -0
  63. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/logger.py +0 -0
  64. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/mount_utils.py +0 -0
  65. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/name_utils.py +0 -0
  66. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/package_utils.py +0 -0
  67. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/pattern_utils.py +0 -0
  68. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/rand_pb_testing.py +0 -0
  69. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/sandbox_fs_utils.py +0 -0
  70. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/shell_utils.py +0 -0
  71. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/task_command_router_client.py +0 -0
  72. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_utils/time_utils.py +0 -0
  73. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_vendor/__init__.py +0 -0
  74. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  75. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_vendor/cloudpickle.py +0 -0
  76. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_vendor/tblib.py +0 -0
  77. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_vendor/version.py +0 -0
  78. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/_watcher.py +0 -0
  79. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/app.py +0 -0
  80. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/app.pyi +0 -0
  81. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/billing.py +0 -0
  82. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/builder/2023.12.312.txt +0 -0
  83. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/builder/2023.12.txt +0 -0
  84. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/builder/2024.04.txt +0 -0
  85. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/builder/2024.10.txt +0 -0
  86. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/builder/2025.06.txt +0 -0
  87. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/builder/PREVIEW.txt +0 -0
  88. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/builder/README.md +0 -0
  89. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/builder/base-images.json +0 -0
  90. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/call_graph.py +0 -0
  91. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/__init__.py +0 -0
  92. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/_download.py +0 -0
  93. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/_traceback.py +0 -0
  94. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/app.py +0 -0
  95. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/billing.py +0 -0
  96. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/changelog.py +0 -0
  97. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/cluster.py +0 -0
  98. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/config.py +0 -0
  99. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/container.py +0 -0
  100. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/dashboard.py +0 -0
  101. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/dict.py +0 -0
  102. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/entry_point.py +0 -0
  103. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/environment.py +0 -0
  104. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/import_refs.py +0 -0
  105. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/launch.py +0 -0
  106. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/network_file_system.py +0 -0
  107. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/profile.py +0 -0
  108. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/programs/__init__.py +0 -0
  109. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/programs/run_jupyter.py +0 -0
  110. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/programs/vscode.py +0 -0
  111. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/queues.py +0 -0
  112. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/run.py +0 -0
  113. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/secret.py +0 -0
  114. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/selector.py +0 -0
  115. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/shell.py +0 -0
  116. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/token.py +0 -0
  117. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/utils.py +0 -0
  118. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cli/volume.py +0 -0
  119. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/client.py +0 -0
  120. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cloud_bucket_mount.py +0 -0
  121. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cloud_bucket_mount.pyi +0 -0
  122. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cls.py +0 -0
  123. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/cls.pyi +0 -0
  124. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/config.py +0 -0
  125. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/container_process.py +0 -0
  126. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/container_process.pyi +0 -0
  127. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/dict.py +0 -0
  128. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/dict.pyi +0 -0
  129. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/environments.py +0 -0
  130. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/environments.pyi +0 -0
  131. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/exception.py +0 -0
  132. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/experimental/__init__.py +0 -0
  133. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/experimental/flash.py +0 -0
  134. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/experimental/flash.pyi +0 -0
  135. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/experimental/ipython.py +0 -0
  136. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/file_io.py +0 -0
  137. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/file_io.pyi +0 -0
  138. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/file_pattern_matcher.py +0 -0
  139. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/functions.py +0 -0
  140. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/gpu.py +0 -0
  141. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/image.py +0 -0
  142. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/image.pyi +0 -0
  143. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/io_streams.py +0 -0
  144. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/io_streams.pyi +0 -0
  145. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/mount.py +0 -0
  146. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/mount.pyi +0 -0
  147. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/network_file_system.py +0 -0
  148. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/network_file_system.pyi +0 -0
  149. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/object.py +0 -0
  150. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/object.pyi +0 -0
  151. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/output.py +0 -0
  152. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/parallel_map.py +0 -0
  153. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/parallel_map.pyi +0 -0
  154. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/partial_function.py +0 -0
  155. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/partial_function.pyi +0 -0
  156. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/proxy.py +0 -0
  157. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/proxy.pyi +0 -0
  158. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/py.typed +0 -0
  159. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/queue.py +0 -0
  160. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/queue.pyi +0 -0
  161. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/retries.py +0 -0
  162. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/runner.py +0 -0
  163. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/runner.pyi +0 -0
  164. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/running_app.py +0 -0
  165. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/sandbox.py +0 -0
  166. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/sandbox.pyi +0 -0
  167. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/sandbox_fs.py +0 -0
  168. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/sandbox_fs.pyi +0 -0
  169. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/schedule.py +0 -0
  170. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/scheduler_placement.py +0 -0
  171. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/secret.py +0 -0
  172. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/secret.pyi +0 -0
  173. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/server.py +0 -0
  174. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/server.pyi +0 -0
  175. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/serving.py +0 -0
  176. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/serving.pyi +0 -0
  177. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/snapshot.py +0 -0
  178. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/snapshot.pyi +0 -0
  179. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/stream_type.py +0 -0
  180. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/token_flow.py +0 -0
  181. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/token_flow.pyi +0 -0
  182. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal/volume.pyi +0 -0
  183. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal.egg-info/SOURCES.txt +0 -0
  184. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal.egg-info/dependency_links.txt +0 -0
  185. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal.egg-info/entry_points.txt +0 -0
  186. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal.egg-info/requires.txt +0 -0
  187. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal.egg-info/top_level.txt +0 -0
  188. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_docs/__init__.py +0 -0
  189. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_docs/gen_cli_docs.py +0 -0
  190. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_docs/gen_cli_docs_main.py +0 -0
  191. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_docs/gen_reference_docs.py +0 -0
  192. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_docs/gen_reference_docs_main.py +0 -0
  193. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_docs/mdmd/__init__.py +0 -0
  194. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_docs/mdmd/mdmd.py +0 -0
  195. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_docs/mdmd/signatures.py +0 -0
  196. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_proto/__init__.py +0 -0
  197. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_proto/api_grpc.py +0 -0
  198. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_proto/api_pb2.py +0 -0
  199. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_proto/api_pb2.pyi +0 -0
  200. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_proto/api_pb2_grpc.py +0 -0
  201. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_proto/api_pb2_grpc.pyi +0 -0
  202. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_proto/modal_api_grpc.py +0 -0
  203. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_proto/py.typed +0 -0
  204. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_proto/task_command_router_grpc.py +0 -0
  205. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_proto/task_command_router_pb2.py +0 -0
  206. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_proto/task_command_router_pb2.pyi +0 -0
  207. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  208. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  209. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/modal_version/__main__.py +0 -0
  210. {modal-1.3.6.dev8 → modal-1.3.6.dev9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.3.6.dev8
3
+ Version: 1.3.6.dev9
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -36,7 +36,6 @@ Dynamic: license-file
36
36
 
37
37
  [![PyPI Version](https://img.shields.io/pypi/v/modal.svg)](https://pypi.org/project/modal/)
38
38
  [![License](https://img.shields.io/badge/license-apache_2.0-darkviolet.svg)](https://github.com/modal-labs/modal-client/blob/master/LICENSE)
39
- [![Tests](https://github.com/modal-labs/modal-client/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/modal-labs/modal-client/actions/workflows/ci-cd.yml)
40
39
  [![Slack](https://img.shields.io/badge/slack-join-blue.svg?logo=slack)](https://modal.com/slack)
41
40
 
42
41
  The [Modal](https://modal.com/) Python SDK provides convenient, on-demand
@@ -2,7 +2,6 @@
2
2
 
3
3
  [![PyPI Version](https://img.shields.io/pypi/v/modal.svg)](https://pypi.org/project/modal/)
4
4
  [![License](https://img.shields.io/badge/license-apache_2.0-darkviolet.svg)](https://github.com/modal-labs/modal-client/blob/master/LICENSE)
5
- [![Tests](https://github.com/modal-labs/modal-client/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/modal-labs/modal-client/actions/workflows/ci-cd.yml)
6
5
  [![Slack](https://img.shields.io/badge/slack-join-blue.svg?logo=slack)](https://modal.com/slack)
7
6
 
8
7
  The [Modal](https://modal.com/) Python SDK provides convenient, on-demand
@@ -345,12 +345,24 @@ def synchronize_api(obj, target_module=None):
345
345
  RETRY_N_ATTEMPTS_OVERRIDE: Optional[int] = None
346
346
 
347
347
 
348
- def retry(direct_fn=None, *, n_attempts=3, base_delay=0, delay_factor=2, timeout=90):
348
+ def retry(
349
+ direct_fn=None,
350
+ *,
351
+ n_attempts=3,
352
+ base_delay=0,
353
+ delay_factor=2,
354
+ attempt_timeout: Optional[float] = 90,
355
+ attempt_timeout_factor=1,
356
+ ):
349
357
  """Decorator that calls an async function multiple times, with a given timeout.
350
358
 
351
359
  If a `base_delay` is provided, the function is given an exponentially
352
360
  increasing delay on each run, up until the maximum number of attempts.
353
361
 
362
+ If `attempt_timeout_factor` is set to a value > 1, the per-attempt timeout
363
+ increases exponentially (starting from `attempt_timeout`, multiplied by
364
+ `attempt_timeout_factor` after each failed attempt).
365
+
354
366
  Usage:
355
367
 
356
368
  ```
@@ -375,10 +387,11 @@ def retry(direct_fn=None, *, n_attempts=3, base_delay=0, delay_factor=2, timeout
375
387
  local_n_attempts = n_attempts
376
388
 
377
389
  delay = base_delay
390
+ current_attempt_timeout = attempt_timeout
378
391
  for i in range(local_n_attempts):
379
392
  t0 = time.time()
380
393
  try:
381
- return await asyncio.wait_for(fn(*args, **kwargs), timeout=timeout)
394
+ return await asyncio.wait_for(fn(*args, **kwargs), timeout=current_attempt_timeout)
382
395
  except asyncio.CancelledError:
383
396
  logger.debug(f"Function {fn} was cancelled")
384
397
  raise
@@ -392,6 +405,8 @@ def retry(direct_fn=None, *, n_attempts=3, base_delay=0, delay_factor=2, timeout
392
405
  )
393
406
  await asyncio.sleep(delay)
394
407
  delay *= delay_factor
408
+ if current_attempt_timeout is not None:
409
+ current_attempt_timeout *= attempt_timeout_factor
395
410
 
396
411
  return f_wrapped
397
412
 
@@ -58,7 +58,7 @@ MULTIPART_UPLOAD_THRESHOLD = 1024**3
58
58
  BLOCK_SIZE: int = 8 * 1024 * 1024
59
59
 
60
60
 
61
- @retry(n_attempts=3, base_delay=0.3, timeout=None)
61
+ @retry(n_attempts=3, base_delay=0.3, attempt_timeout=None)
62
62
  async def _upload_to_s3_url(
63
63
  upload_url,
64
64
  payload: "BytesIOSegmentPayload",
@@ -310,7 +310,7 @@ async def blob_upload_file(
310
310
  return blob_id
311
311
 
312
312
 
313
- @retry(n_attempts=5, base_delay=0.1, timeout=None)
313
+ @retry(n_attempts=5, base_delay=0.1, attempt_timeout=None)
314
314
  async def _download_from_url(download_url: str) -> bytes:
315
315
  async with ClientSessionRegistry.get_session().get(download_url) as s3_resp:
316
316
  # S3 signal to slow down request rate.
@@ -89,6 +89,10 @@ RETRYABLE_GRPC_STATUS_CODES = [
89
89
  Status.UNKNOWN,
90
90
  ]
91
91
  SERVER_RETRY_WARNING_TIME_INTERVAL = 30.0
92
+ # Initial per-attempt timeout for TCP/TLS handshake in connect_channel.
93
+ # Doubles each attempt (attempt_timeout_factor=2): 0.5 + 1 + 2 + 4 + 8 = 15.5s + ~1.5s inter-attempt delays.
94
+ CONNECT_TIMEOUT = 0.5
95
+ DEFAULT_MAX_RETRIES = 3
92
96
 
93
97
 
94
98
  @dataclass
@@ -117,7 +121,7 @@ class ConnectionManager:
117
121
  self._channels[server_url] = create_channel(server_url, self._metadata)
118
122
  try:
119
123
  await connect_channel(self._channels[server_url])
120
- except OSError as exc:
124
+ except (OSError, asyncio.TimeoutError) as exc:
121
125
  raise ConnectionError("Could not connect to the Modal server.") from exc
122
126
  return self._channels[server_url]
123
127
 
@@ -221,7 +225,7 @@ def create_channel(
221
225
  return channel
222
226
 
223
227
 
224
- @retry(n_attempts=5, base_delay=0.1)
228
+ @retry(n_attempts=5, base_delay=0.1, attempt_timeout=CONNECT_TIMEOUT, attempt_timeout_factor=2)
225
229
  async def connect_channel(channel: grpclib.client.Channel):
226
230
  """Connect to socket and raise exceptions when there is a connection issue."""
227
231
  await channel.__connect__()
@@ -246,7 +250,7 @@ class Retry:
246
250
  base_delay: float = 0.1
247
251
  max_delay: float = 1
248
252
  delay_factor: float = 2
249
- max_retries: Optional[int] = 3
253
+ max_retries: Optional[int] = DEFAULT_MAX_RETRIES
250
254
  additional_status_codes: list = field(default_factory=list)
251
255
  attempt_timeout: Optional[float] = None # timeout for each attempt
252
256
  total_timeout: Optional[float] = None # timeout for the entire function call
@@ -257,7 +261,7 @@ class Retry:
257
261
  async def retry_transient_errors(
258
262
  fn: "grpclib.client.UnaryUnaryMethod[RequestType, ResponseType]",
259
263
  req: RequestType,
260
- max_retries: Optional[int] = 3,
264
+ max_retries: Optional[int] = DEFAULT_MAX_RETRIES,
261
265
  ) -> ResponseType:
262
266
  """Minimum API version of _retry_transient_errors that works with grpclib.client.UnaryUnaryMethod.
263
267
 
@@ -373,7 +377,13 @@ async def _retry_transient_errors(
373
377
  try:
374
378
  with suppress_tb_frame():
375
379
  return await fn_callable(req, metadata=attempt_metadata, timeout=timeout)
376
- except (StreamTerminatedError, GRPCError, OSError, asyncio.TimeoutError, AttributeError) as exc:
380
+ except (
381
+ StreamTerminatedError,
382
+ GRPCError,
383
+ OSError,
384
+ asyncio.TimeoutError,
385
+ AttributeError,
386
+ ) as exc:
377
387
  # Note that we only catch AttributeError to handle a specific case that works around a bug
378
388
  # in grpclib<=0.4.7. See above (search for `write_appdata`).
379
389
 
@@ -35,7 +35,7 @@ class _Client:
35
35
  server_url: str,
36
36
  client_type: int,
37
37
  credentials: typing.Optional[tuple[str, str]],
38
- version: str = "1.3.6.dev8",
38
+ version: str = "1.3.6.dev9",
39
39
  ):
40
40
  """mdmd:hidden
41
41
  The Modal client object is not intended to be instantiated directly by users.
@@ -171,7 +171,7 @@ class Client:
171
171
  server_url: str,
172
172
  client_type: int,
173
173
  credentials: typing.Optional[tuple[str, str]],
174
- version: str = "1.3.6.dev8",
174
+ version: str = "1.3.6.dev9",
175
175
  ):
176
176
  """mdmd:hidden
177
177
  The Modal client object is not intended to be instantiated directly by users.
@@ -408,7 +408,7 @@ class Function(
408
408
 
409
409
  _call_generator: ___call_generator_spec
410
410
 
411
- class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
411
+ class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
412
412
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
413
413
  """Calls the function remotely, executing it with the given arguments and returning the execution's result."""
414
414
  ...
@@ -417,7 +417,7 @@ class Function(
417
417
  """Calls the function remotely, executing it with the given arguments and returning the execution's result."""
418
418
  ...
419
419
 
420
- remote: __remote_spec[modal._functions.P, modal._functions.ReturnType]
420
+ remote: __remote_spec[modal._functions.ReturnType, modal._functions.P]
421
421
 
422
422
  class __remote_gen_spec(typing_extensions.Protocol):
423
423
  def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
@@ -444,7 +444,7 @@ class Function(
444
444
  """
445
445
  ...
446
446
 
447
- class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
447
+ class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
448
448
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
449
449
  """[Experimental] Calls the function with the given arguments, without waiting for the results.
450
450
 
@@ -467,7 +467,7 @@ class Function(
467
467
  """
468
468
  ...
469
469
 
470
- _experimental_spawn: ___experimental_spawn_spec[modal._functions.P, modal._functions.ReturnType]
470
+ _experimental_spawn: ___experimental_spawn_spec[modal._functions.ReturnType, modal._functions.P]
471
471
 
472
472
  class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER]):
473
473
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> None: ...
@@ -475,7 +475,7 @@ class Function(
475
475
 
476
476
  _spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P]
477
477
 
478
- class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
478
+ class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
479
479
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
480
480
  """Calls the function with the given arguments, without waiting for the results.
481
481
 
@@ -496,7 +496,7 @@ class Function(
496
496
  """
497
497
  ...
498
498
 
499
- spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType]
499
+ spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P]
500
500
 
501
501
  def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
502
502
  """Return the inner Python object wrapped by this Modal Function."""
@@ -740,7 +740,7 @@ class _Volume(_Object, type_prefix="vo"):
740
740
  except modal.exception.NotFoundError as exc:
741
741
  raise FileNotFoundError(exc.args[0])
742
742
 
743
- @retry(n_attempts=5, base_delay=0.1, timeout=None)
743
+ @retry(n_attempts=5, base_delay=0.1, attempt_timeout=None)
744
744
  async def read_block(block_url: str) -> bytes:
745
745
  async with ClientSessionRegistry.get_session().get(block_url) as get_response:
746
746
  get_response.raise_for_status()
@@ -806,7 +806,7 @@ class _Volume(_Object, type_prefix="vo"):
806
806
  write_lock = asyncio.Lock()
807
807
  start_pos = fileobj.tell()
808
808
 
809
- @retry(n_attempts=5, base_delay=0.1, timeout=None)
809
+ @retry(n_attempts=5, base_delay=0.1, attempt_timeout=None)
810
810
  async def download_block(idx, url) -> int:
811
811
  block_start_pos = start_pos + idx * BLOCK_SIZE
812
812
  num_bytes_written = 0
@@ -1369,7 +1369,7 @@ async def _put_missing_blocks(
1369
1369
  file_progress.pending_blocks.add(missing_block.block_index)
1370
1370
  task_progress_cb = functools.partial(progress_cb, task_id=file_progress.task_id)
1371
1371
 
1372
- @retry(n_attempts=11, base_delay=0.5, timeout=None)
1372
+ @retry(n_attempts=11, base_delay=0.5, attempt_timeout=None)
1373
1373
  async def put_missing_block_attempt(payload: BytesIOSegmentPayload) -> bytes:
1374
1374
  with payload.reset_on_error(subtract_progress=True):
1375
1375
  async with ClientSessionRegistry.get_session().put(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.3.6.dev8
3
+ Version: 1.3.6.dev9
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -36,7 +36,6 @@ Dynamic: license-file
36
36
 
37
37
  [![PyPI Version](https://img.shields.io/pypi/v/modal.svg)](https://pypi.org/project/modal/)
38
38
  [![License](https://img.shields.io/badge/license-apache_2.0-darkviolet.svg)](https://github.com/modal-labs/modal-client/blob/master/LICENSE)
39
- [![Tests](https://github.com/modal-labs/modal-client/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/modal-labs/modal-client/actions/workflows/ci-cd.yml)
40
39
  [![Slack](https://img.shields.io/badge/slack-join-blue.svg?logo=slack)](https://modal.com/slack)
41
40
 
42
41
  The [Modal](https://modal.com/) Python SDK provides convenient, on-demand
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2026
2
2
  """Supplies the current version of the modal client library."""
3
3
 
4
- __version__ = "1.3.6.dev8"
4
+ __version__ = "1.3.6.dev9"
@@ -28,7 +28,7 @@ dependencies = [
28
28
  "types-certifi",
29
29
  "types-toml",
30
30
  "watchfiles",
31
- "typing_extensions~=4.6"
31
+ "typing_extensions~=4.6",
32
32
  ]
33
33
  keywords = ["modal", "client", "cloud", "serverless", "infrastructure"]
34
34
  classifiers = [
@@ -37,6 +37,51 @@ classifiers = [
37
37
  "Programming Language :: Python :: 3"
38
38
  ]
39
39
 
40
+ [dependency-groups]
41
+ dev = [
42
+ "cbor2==5.7.0",
43
+ "fastapi~=0.125",
44
+ "flaky~=3.8",
45
+ "grpclib==0.4.9",
46
+ "invoke~=2.2",
47
+ "httpx~=0.27.2",
48
+ "pyjwt~=2.10.1",
49
+ "pre-commit>=2.21,<4",
50
+ "mypy~=1.18.2",
51
+ "packaging>=23.1",
52
+ "pytest~=8.4.0",
53
+ "pytest-asyncio @ git+https://github.com/modal-labs/pytest-asyncio.git@af3f2d721b842309749cd26e5bbdd210e17d80c8",
54
+ "pytest-env~=1.1.5",
55
+ "pytest-markdown-docs==0.9.1",
56
+ "pytest-timeout~=2.4.0",
57
+ "python-dotenv~=1.0.0",
58
+ "requests~=2.32.4",
59
+ "ruff~=0.9.6",
60
+ "setuptools<82", # Required by grpcio-tools for pkg_resources (v82+ removed pkg_resources)"
61
+ "types-croniter~=1.0.8",
62
+ "types-python-dateutil~=2.8.10",
63
+ "types-requests~=2.31.0",
64
+ "types-setuptools~=57.4.11",
65
+ "types-six~=1.16.21",
66
+ "types-toml~=0.10.4",
67
+ "wheel~=0.38.1",
68
+ "nbclient~=0.10.2",
69
+ "notebook~=7.5.4",
70
+ "jupytext~=1.19.1",
71
+ "pyright~=1.1.351",
72
+ "console-ctrl~=0.1.0",
73
+ "zstandard~=0.25.0",
74
+ "synchronicity[compile]==0.11.1",
75
+ "python-json-logger==2.0.7",
76
+ "build~=1.3.0",
77
+
78
+ "mypy-protobuf",
79
+ "grpcio-tools",
80
+ ]
81
+
82
+ [tool.uv.extra-build-dependencies]
83
+ grpcio-tools = ["setuptools<82"]
84
+
40
85
  [project.urls]
41
86
  Homepage = "https://modal.com"
42
87
  Source = "https://github.com/modal-labs/modal-client"
@@ -122,6 +167,7 @@ extend-select = ['PLR1702']
122
167
  "modal_docs/**" = ['T201']
123
168
  "modal_global_objects/**" = ['T201']
124
169
  "tasks.py" = ['T201']
170
+ "compile_protos.py" = ['T201']
125
171
  "modal/__init__.py" = ['T201']
126
172
  "modal/experimental/ipython.py" = ['T201']
127
173
 
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