modal 1.6.2.dev10__tar.gz → 1.6.2.dev11__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 (246) hide show
  1. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/PKG-INFO +4 -3
  2. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/README.md +1 -1
  3. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/__init__.py +2 -2
  4. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_functions.py +140 -0
  5. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_image.py +2 -2
  6. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_server.py +179 -0
  7. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_server.pyi +83 -0
  8. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/async_utils.py +6 -2
  9. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/builder/2025.06.txt +8 -4
  10. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/builder/PREVIEW.txt +4 -2
  11. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/builder/base-images.json +4 -2
  12. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/function.py +1 -1
  13. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/server.py +2 -2
  14. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/workspace.py +18 -10
  15. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/client.pyi +2 -2
  16. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cls.py +1 -1
  17. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cls.pyi +1 -1
  18. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/functions.py +2 -1
  19. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/functions.pyi +149 -0
  20. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/mount.py +2 -0
  21. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/mount.pyi +3 -3
  22. modal-1.6.2.dev11/modal/server.py +6 -0
  23. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/server.pyi +164 -0
  24. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal.egg-info/PKG-INFO +4 -3
  25. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal.egg-info/requires.txt +3 -0
  26. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_proto/api_grpc.py +16 -0
  27. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_proto/api_pb2.py +809 -799
  28. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_proto/api_pb2.pyi +15 -0
  29. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_proto/api_pb2_grpc.py +33 -0
  30. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_proto/api_pb2_grpc.pyi +10 -0
  31. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_proto/modal_api_grpc.py +1 -0
  32. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_version/__init__.py +1 -1
  33. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/pyproject.toml +3 -1
  34. modal-1.6.2.dev10/modal/server.py +0 -5
  35. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/LICENSE +0 -0
  36. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/__main__.py +0 -0
  37. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_billing.py +0 -0
  38. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_cluster.py +0 -0
  39. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_cluster.pyi +0 -0
  40. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_container_entrypoint.py +0 -0
  41. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_environments.py +0 -0
  42. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_function_variants.py +0 -0
  43. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_grpc_client.py +0 -0
  44. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_ipython.py +0 -0
  45. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_load_context.py +0 -0
  46. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_location.py +0 -0
  47. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_logs.py +0 -0
  48. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_logs_manager.py +0 -0
  49. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_logs_manager.pyi +0 -0
  50. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_metrics.py +0 -0
  51. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_metrics.pyi +0 -0
  52. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_object.py +0 -0
  53. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_outbound_policy.py +0 -0
  54. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_outbound_policy.pyi +0 -0
  55. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_output/__init__.py +0 -0
  56. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_output/manager.py +0 -0
  57. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_output/pty.py +0 -0
  58. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_output/rich.py +0 -0
  59. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_output/status.py +0 -0
  60. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_partial_function.py +0 -0
  61. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_resolver.py +0 -0
  62. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_resources.py +0 -0
  63. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_runtime/__init__.py +0 -0
  64. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_runtime/asgi.py +0 -0
  65. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_runtime/container_io_manager.py +0 -0
  66. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_runtime/container_io_manager.pyi +0 -0
  67. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_runtime/execution_context.py +0 -0
  68. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_runtime/execution_context.pyi +0 -0
  69. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  70. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_runtime/task_lifecycle_manager.py +0 -0
  71. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_runtime/task_lifecycle_manager.pyi +0 -0
  72. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_runtime/telemetry.py +0 -0
  73. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_runtime/user_code_event_loop.py +0 -0
  74. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_runtime/user_code_imports.py +0 -0
  75. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_serialization.py +0 -0
  76. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_supports_logs.py +0 -0
  77. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_traceback.py +0 -0
  78. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_tunnel.py +0 -0
  79. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_tunnel.pyi +0 -0
  80. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_type_manager.py +0 -0
  81. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/__init__.py +0 -0
  82. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/app_utils.py +0 -0
  83. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/auth_token_manager.py +0 -0
  84. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/blob_utils.py +0 -0
  85. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/browser_utils.py +0 -0
  86. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/bytes_io_segment_payload.py +0 -0
  87. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/curl_utils.py +0 -0
  88. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/deprecation.py +0 -0
  89. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/display_utils.py +0 -0
  90. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/docker_utils.py +0 -0
  91. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/function_utils.py +0 -0
  92. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/git_utils.py +0 -0
  93. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/grpc_testing.py +0 -0
  94. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/grpc_utils.py +0 -0
  95. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/hash_utils.py +0 -0
  96. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/http_utils.py +0 -0
  97. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/idle_countdown.py +0 -0
  98. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/jwt_utils.py +0 -0
  99. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/logger.py +0 -0
  100. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/mount_utils.py +0 -0
  101. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/name_utils.py +0 -0
  102. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/package_utils.py +0 -0
  103. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/pattern_utils.py +0 -0
  104. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/proxy_support.py +0 -0
  105. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/rand_pb_testing.py +0 -0
  106. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/sandbox_fs_utils.py +0 -0
  107. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/shell_utils.py +0 -0
  108. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_utils/time_utils.py +0 -0
  109. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_vendor/__init__.py +0 -0
  110. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  111. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_vendor/cloudpickle.py +0 -0
  112. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_vendor/tblib.py +0 -0
  113. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_vendor/version.py +0 -0
  114. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_watcher.py +0 -0
  115. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/_workspace.py +0 -0
  116. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/app.py +0 -0
  117. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/app.pyi +0 -0
  118. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/billing.py +0 -0
  119. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/billing.pyi +0 -0
  120. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/builder/2023.12.312.txt +0 -0
  121. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/builder/2023.12.txt +0 -0
  122. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/builder/2024.04.txt +0 -0
  123. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/builder/2024.10.txt +0 -0
  124. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/builder/README.md +0 -0
  125. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/call_graph.py +0 -0
  126. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/__init__.py +0 -0
  127. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/_download.py +0 -0
  128. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/_help.py +0 -0
  129. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/_logs.py +0 -0
  130. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/_stats.py +0 -0
  131. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/_traceback.py +0 -0
  132. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/app.py +0 -0
  133. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/billing.py +0 -0
  134. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/changelog.py +0 -0
  135. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/config.py +0 -0
  136. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/container.py +0 -0
  137. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/curl.py +0 -0
  138. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/dashboard.py +0 -0
  139. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/dict.py +0 -0
  140. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/endpoint.py +0 -0
  141. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/entry_point.py +0 -0
  142. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/environment.py +0 -0
  143. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/image.py +0 -0
  144. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/import_refs.py +0 -0
  145. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/logo.py +0 -0
  146. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/network_file_system.py +0 -0
  147. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/profile.py +0 -0
  148. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/queues.py +0 -0
  149. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/run.py +0 -0
  150. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/secret.py +0 -0
  151. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/selector.py +0 -0
  152. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/shell.py +0 -0
  153. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/skills.py +0 -0
  154. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/token.py +0 -0
  155. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/utils.py +0 -0
  156. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cli/volume.py +0 -0
  157. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/client.py +0 -0
  158. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cloud_bucket_mount.py +0 -0
  159. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cloud_bucket_mount.pyi +0 -0
  160. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cluster.py +0 -0
  161. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/cluster.pyi +0 -0
  162. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/config.py +0 -0
  163. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/container_process.py +0 -0
  164. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/container_process.pyi +0 -0
  165. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/dict.py +0 -0
  166. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/dict.pyi +0 -0
  167. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/environments.py +0 -0
  168. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/environments.pyi +0 -0
  169. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/exception.py +0 -0
  170. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/experimental/__init__.py +0 -0
  171. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/experimental/_flash_container_entry.py +0 -0
  172. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/experimental/flash.py +0 -0
  173. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/experimental/flash.pyi +0 -0
  174. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/experimental/flash_server.py +0 -0
  175. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/experimental/flash_server.pyi +0 -0
  176. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/experimental/ipython.py +0 -0
  177. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/file_pattern_matcher.py +0 -0
  178. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/image.py +0 -0
  179. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/image.pyi +0 -0
  180. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/io_streams.py +0 -0
  181. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/io_streams.pyi +0 -0
  182. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/network_file_system.py +0 -0
  183. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/network_file_system.pyi +0 -0
  184. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/object.py +0 -0
  185. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/object.pyi +0 -0
  186. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/output.py +0 -0
  187. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/parallel_map.py +0 -0
  188. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/parallel_map.pyi +0 -0
  189. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/partial_function.py +0 -0
  190. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/partial_function.pyi +0 -0
  191. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/proxy.py +0 -0
  192. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/proxy.pyi +0 -0
  193. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/py.typed +0 -0
  194. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/queue.py +0 -0
  195. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/queue.pyi +0 -0
  196. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/retries.py +0 -0
  197. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/runner.py +0 -0
  198. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/runner.pyi +0 -0
  199. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/running_app.py +0 -0
  200. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/sandbox/__init__.py +0 -0
  201. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/sandbox/_common.py +0 -0
  202. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/sandbox/_filesystem.py +0 -0
  203. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/sandbox/_sandbox.py +0 -0
  204. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/sandbox/_sidecar.py +0 -0
  205. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/sandbox/_snapshot.py +0 -0
  206. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/sandbox/_task_command_router_client.py +0 -0
  207. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/sandbox/sandbox.py +0 -0
  208. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/sandbox/sandbox.pyi +0 -0
  209. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/schedule.py +0 -0
  210. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/scheduler_placement.py +0 -0
  211. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/secret.py +0 -0
  212. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/secret.pyi +0 -0
  213. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/serving.py +0 -0
  214. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/serving.pyi +0 -0
  215. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/skills/modal/SKILL.md +0 -0
  216. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/stream_type.py +0 -0
  217. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/token_flow.py +0 -0
  218. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/token_flow.pyi +0 -0
  219. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/types.py +0 -0
  220. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/volume.py +0 -0
  221. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/volume.pyi +0 -0
  222. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/workspace.py +0 -0
  223. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal/workspace.pyi +0 -0
  224. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal.egg-info/SOURCES.txt +0 -0
  225. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal.egg-info/dependency_links.txt +0 -0
  226. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal.egg-info/entry_points.txt +0 -0
  227. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal.egg-info/top_level.txt +0 -0
  228. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_docs/__init__.py +0 -0
  229. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_docs/gen_cli_docs.py +0 -0
  230. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_docs/gen_cli_docs_main.py +0 -0
  231. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_docs/gen_reference_docs.py +0 -0
  232. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_docs/gen_reference_docs_main.py +0 -0
  233. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_docs/mdmd/__init__.py +0 -0
  234. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_docs/mdmd/mdmd.py +0 -0
  235. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_docs/mdmd/signatures.py +0 -0
  236. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_docs/mdmd/types.py +0 -0
  237. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_docs/reference_intro.md +0 -0
  238. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_proto/__init__.py +0 -0
  239. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_proto/py.typed +0 -0
  240. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_proto/task_command_router_grpc.py +0 -0
  241. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_proto/task_command_router_pb2.py +0 -0
  242. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_proto/task_command_router_pb2.pyi +0 -0
  243. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  244. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  245. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/modal_version/__main__.py +0 -0
  246. {modal-1.6.2.dev10 → modal-1.6.2.dev11}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.6.2.dev10
3
+ Version: 1.6.2.dev11
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -12,7 +12,7 @@ Keywords: modal,client,cloud,serverless,infrastructure
12
12
  Classifier: Topic :: System :: Distributed Computing
13
13
  Classifier: Operating System :: OS Independent
14
14
  Classifier: Programming Language :: Python :: 3
15
- Requires-Python: <3.15,>=3.10
15
+ Requires-Python: <3.16,>=3.10
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
18
  Requires-Dist: aiohttp
@@ -29,6 +29,7 @@ Requires-Dist: types-certifi
29
29
  Requires-Dist: types-toml
30
30
  Requires-Dist: watchfiles
31
31
  Requires-Dist: typing_extensions~=4.6
32
+ Requires-Dist: typing_extensions>=4.14; python_version >= "3.15"
32
33
  Provides-Extra: api-proxy-support
33
34
  Requires-Dist: python-socks[asyncio]>=2.5; extra == "api-proxy-support"
34
35
  Requires-Dist: aiohttp-socks>=0.8; extra == "api-proxy-support"
@@ -52,7 +53,7 @@ a [user guide](https://modal.com/docs/guide), and the detailed
52
53
 
53
54
  ## Installation
54
55
 
55
- **This library requires Python 3.10 – 3.14.**
56
+ **This library requires Python 3.10 – 3.15.**
56
57
 
57
58
  Install the package with `uv` or `pip`:
58
59
 
@@ -16,7 +16,7 @@ a [user guide](https://modal.com/docs/guide), and the detailed
16
16
 
17
17
  ## Installation
18
18
 
19
- **This library requires Python 3.10 – 3.14.**
19
+ **This library requires Python 3.10 – 3.15.**
20
20
 
21
21
  Install the package with `uv` or `pip`:
22
22
 
@@ -3,8 +3,8 @@ import sys
3
3
 
4
4
  if sys.version_info[:2] < (3, 10):
5
5
  raise RuntimeError("This version of Modal requires at least Python 3.10")
6
- if sys.version_info[:2] >= (3, 15):
7
- raise RuntimeError("This version of Modal does not support Python 3.15+")
6
+ if sys.version_info[:2] >= (3, 16):
7
+ raise RuntimeError("This version of Modal does not support Python 3.16+")
8
8
 
9
9
  from modal_version import __version__
10
10
 
@@ -51,6 +51,7 @@ from ._utils.async_utils import (
51
51
  )
52
52
  from ._utils.auth_token_manager import _AuthTokenManager
53
53
  from ._utils.blob_utils import MAX_ASYNC_OBJECT_SIZE_BYTES, MAX_OBJECT_SIZE_BYTES
54
+ from ._utils.deprecation import deprecation_warning
54
55
  from ._utils.function_utils import (
55
56
  ATTEMPT_TIMEOUT_GRACE_PERIOD,
56
57
  OUTPUTS_TIMEOUT,
@@ -1396,6 +1397,13 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1396
1397
  ```
1397
1398
 
1398
1399
  """
1400
+
1401
+ deprecation_warning(
1402
+ (2026, 10, 16),
1403
+ "`Function.update_autoscaler()` is deprecated and will be removed in a future version "
1404
+ "of `modal`. Use `Function.autoscaler.update()` instead.",
1405
+ )
1406
+
1399
1407
  # Assert .update_autoscaler() is not called on a method as opposed to the Object. Applicable for Cls only.
1400
1408
  if self._is_method:
1401
1409
  raise InvalidError("Cannot call .update_autoscaler() on a method. Call it on the class instance instead.")
@@ -2312,6 +2320,11 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
2312
2320
  assert self._metadata
2313
2321
  return self._metadata.function_schema
2314
2322
 
2323
+ @property
2324
+ def autoscaler(self) -> "_FunctionAutoscalerManager":
2325
+ """Namespace for Function autoscaler APIs."""
2326
+ return _FunctionAutoscalerManager(self)
2327
+
2315
2328
  # A bit hacky - but the map-style functions need to not be synchronicity-wrapped
2316
2329
  # in order to not execute their input iterators on the synchronicity event loop.
2317
2330
  # We still need to wrap them using MethodWithAio to maintain a synchronicity-like
@@ -2565,3 +2578,130 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
2565
2578
  except Exception as exc:
2566
2579
  # TODO: kill all running function calls
2567
2580
  raise exc
2581
+
2582
+
2583
+ UNSET_PARAMETER = -1
2584
+
2585
+
2586
+ class _FunctionAutoscalerManager:
2587
+ """mdmd:namespace"""
2588
+
2589
+ def __init__(self, function: _Function):
2590
+ """mdmd:hidden"""
2591
+ self._function = function
2592
+
2593
+ async def settings(self) -> FunctionAutoscalerSettings:
2594
+ """View the current Autoscaler settings for this Function.
2595
+
2596
+ Returns:
2597
+ A `FunctionAutoscalerSettings` dataclass.
2598
+
2599
+ Examples:
2600
+
2601
+ ```python notest
2602
+ fn = modal.Function.from_name("my-app", "my_function")
2603
+ settings = fn.autoscaler.settings()
2604
+ ```
2605
+ """
2606
+
2607
+ if not self._function._is_hydrated:
2608
+ await self._function.hydrate()
2609
+
2610
+ response = await self._function.client._stub.FunctionGetSchedulingParams(
2611
+ api_pb2.FunctionGetSchedulingParamsRequest(function_id=self._function.object_id)
2612
+ )
2613
+
2614
+ ret = FunctionAutoscalerSettings._from_proto(response.autoscaler_configuration.settings)
2615
+ if ret.max_containers == 0:
2616
+ ret = dataclasses.replace(ret, max_containers=None)
2617
+
2618
+ return ret
2619
+
2620
+ async def update(
2621
+ self,
2622
+ *,
2623
+ min_containers: int | None = UNSET_PARAMETER,
2624
+ max_containers: int | None = UNSET_PARAMETER,
2625
+ buffer_containers: int | None = UNSET_PARAMETER,
2626
+ scaledown_window: int = UNSET_PARAMETER,
2627
+ ) -> FunctionAutoscalerSettings:
2628
+ """Override the current Autoscaler settings for this Function.
2629
+
2630
+ All parameters to this function are optional; not passing an argument for a given parameter
2631
+ will not update its value.
2632
+
2633
+ Note that re-deploying the App containing this Function will wipe any overrides and revert
2634
+ its Autoscaler settings back to those defined on the Function at creation time.
2635
+
2636
+ Args:
2637
+ min_containers: Minimum number of containers to keep running. Must be a nonnegative
2638
+ integer, or `None`. Passing `None` is equivalent to setting the minimum to 0.
2639
+ max_containers: Maximum concurrent containers. Must be a positive integer, or `None`.
2640
+ Passing `None` is equivalent to disabling the upper bound on container concurrency at
2641
+ the Function level (note that Environment and Workspace level container upper limits
2642
+ still apply.)
2643
+ buffer_containers: Extra containers to keep warm beyond current demand. Must be a
2644
+ nonnegative integer, or `None`. Passing `None` is equivalent to setting the buffer to
2645
+ 0.
2646
+ scaledown_window: Maximum duration (in seconds) idle containers wait before scaling down.
2647
+ Must be a positive integer between 2 and 3600, inclusive.
2648
+
2649
+ Returns:
2650
+ A `FunctionAutoscalerSettings` dataclass.
2651
+
2652
+ Examples:
2653
+
2654
+ Update `my_function` so that 2 containers are always active.
2655
+
2656
+ ```python notest
2657
+ fn = modal.Function.from_name("my-app", "my_function")
2658
+ fn.autoscaler.update(min_containers=2)
2659
+ ```
2660
+
2661
+ Update `my_function` so that there is no Function-level limit on `max_containers`:
2662
+
2663
+ ```python notest
2664
+ fn = modal.Function.from_name("my-app", "my_function")
2665
+ fn.autoscaler.update(max_containers=None)
2666
+ ```
2667
+ """
2668
+
2669
+ if not self._function._is_hydrated:
2670
+ await self._function.hydrate()
2671
+
2672
+ settings: api_pb2.AutoscalerSettings = api_pb2.AutoscalerSettings()
2673
+
2674
+ if min_containers != UNSET_PARAMETER:
2675
+ min_containers = min_containers if min_containers is not None else 0
2676
+ if min_containers < 0:
2677
+ raise InvalidError("Invalid argument: `min_containers` must be a nonnegative integer or `None`.")
2678
+
2679
+ settings.min_containers = min_containers
2680
+
2681
+ if buffer_containers != UNSET_PARAMETER:
2682
+ buffer_containers = buffer_containers if buffer_containers is not None else 0
2683
+ if buffer_containers < 0:
2684
+ raise InvalidError("Invalid argument: `buffer_containers` must be a nonnegative integer or `None`.")
2685
+
2686
+ settings.buffer_containers = buffer_containers
2687
+
2688
+ if max_containers != UNSET_PARAMETER:
2689
+ if max_containers is not None and max_containers <= 0:
2690
+ raise InvalidError("Invalid argument: `max_containers` must be a postive integer or `None`.")
2691
+
2692
+ settings.max_containers = max_containers if max_containers is not None else 0
2693
+
2694
+ if scaledown_window != UNSET_PARAMETER:
2695
+ if not (2 <= scaledown_window <= 3600):
2696
+ raise InvalidError("Invalid argument: `scaledown_window` must be between 2 and 3600 (inclusive)")
2697
+
2698
+ settings.scaledown_window = scaledown_window
2699
+
2700
+ request = api_pb2.FunctionUpdateSchedulingParamsRequest(function_id=self._function.object_id, settings=settings)
2701
+ response = await self._function.client._stub.FunctionUpdateSchedulingParams(request)
2702
+
2703
+ ret = FunctionAutoscalerSettings._from_proto(response.current_settings)
2704
+ if ret.max_containers == 0:
2705
+ ret = dataclasses.replace(ret, max_containers=None)
2706
+
2707
+ return ret
@@ -76,8 +76,8 @@ ImageBuilderVersion = Literal["2023.12", "2024.04", "2024.10", "2025.06", "PREVI
76
76
  # Python versions in mount.py where we specify the "standalone Python versions" we create mounts for.
77
77
  # Consider consolidating these multiple sources of truth?
78
78
  SUPPORTED_PYTHON_SERIES: dict[ImageBuilderVersion, list[str]] = {
79
- "PREVIEW": ["3.10", "3.11", "3.12", "3.13", "3.14", "3.14t"],
80
- "2025.06": ["3.10", "3.11", "3.12", "3.13", "3.14", "3.14t"],
79
+ "PREVIEW": ["3.10", "3.11", "3.12", "3.13", "3.14", "3.14t", "3.15", "3.15t"],
80
+ "2025.06": ["3.10", "3.11", "3.12", "3.13", "3.14", "3.14t", "3.15", "3.15t"],
81
81
  "2024.10": ["3.10", "3.11", "3.12", "3.13"],
82
82
  "2024.04": ["3.10", "3.11", "3.12"],
83
83
  "2023.12": ["3.10", "3.11", "3.12"],
@@ -1,5 +1,6 @@
1
1
  # Copyright Modal Labs 2025
2
2
  import asyncio
3
+ import dataclasses
3
4
  import inspect
4
5
  import json
5
6
  import time
@@ -23,6 +24,8 @@ from ._partial_function import (
23
24
  )
24
25
  from ._supports_logs import _LogQueryData
25
26
  from ._utils.async_utils import retry, synchronize_api
27
+ from ._utils.deprecation import deprecation_warning
28
+ from ._utils.function_utils import normalize_fractional_target_concurrency, validate_target_concurrency
26
29
  from ._utils.http_utils import ClientSessionRegistry
27
30
  from .client import _Client
28
31
  from .cls import is_parameter
@@ -125,6 +128,11 @@ class _Server:
125
128
  """Start and terminate sticky sessions on a Server decorated with `@modal.sessioned()`."""
126
129
  return _ServerSessionsManager(self)
127
130
 
131
+ @property
132
+ def autoscaler(self) -> "_ServerAutoscalerManager":
133
+ """View and update Autoscaler settings on a Server."""
134
+ return _ServerAutoscalerManager(self)
135
+
128
136
  async def info(self, *, refresh: bool = False) -> ServerInfo:
129
137
  """Get an overview of a Server's resource requests, associated mounts, http config, etc.
130
138
 
@@ -238,6 +246,13 @@ class _Server:
238
246
  ```
239
247
 
240
248
  """
249
+
250
+ deprecation_warning(
251
+ (2026, 10, 16),
252
+ "`Server.update_autoscaler()` is deprecated and will be removed in a future version "
253
+ "of `modal`. Use `Server.autoscaler.update()` instead.",
254
+ )
255
+
241
256
  return await self._get_service_function()._update_autoscaler_server(
242
257
  min_containers=min_containers,
243
258
  max_containers=max_containers,
@@ -618,3 +633,167 @@ class _ServerSessionsManager:
618
633
 
619
634
 
620
635
  ServerSessionsManager = synchronize_api(_ServerSessionsManager, target_module=__name__)
636
+
637
+
638
+ UNSET_PARAMETER = -1
639
+
640
+
641
+ class _ServerAutoscalerManager:
642
+ def __init__(self, server: _Server):
643
+ """mdmd:hidden"""
644
+ self._server = server
645
+
646
+ async def settings(self) -> ServerAutoscalerSettings:
647
+ """View the current Autoscaler settings for this Server.
648
+
649
+ Returns:
650
+ A `ServerAutoscalerSettings` dataclass.
651
+
652
+ Examples:
653
+
654
+ ```python notest
655
+ server = modal.Server.from_name("my-app", "MyServer")
656
+ settings = server.autoscaler.settings()
657
+ ```
658
+ """
659
+
660
+ await self._server.hydrate()
661
+
662
+ service_fn = self._server._get_service_function()
663
+ response = await service_fn.client._stub.FunctionGetSchedulingParams(
664
+ api_pb2.FunctionGetSchedulingParamsRequest(function_id=service_fn.object_id)
665
+ )
666
+
667
+ ret = ServerAutoscalerSettings._from_proto(response.autoscaler_configuration.settings)
668
+
669
+ updates = {}
670
+ if ret.target_concurrency == 0.0:
671
+ updates["target_concurrency"] = None
672
+ if ret.max_containers == 0:
673
+ updates["max_containers"] = None
674
+
675
+ if updates:
676
+ ret = dataclasses.replace(ret, **updates)
677
+
678
+ return ret
679
+
680
+ async def update(
681
+ self,
682
+ *,
683
+ target_concurrency: float | None = UNSET_PARAMETER,
684
+ min_containers: int | None = UNSET_PARAMETER,
685
+ max_containers: int | None = UNSET_PARAMETER,
686
+ buffer_containers: int | None = UNSET_PARAMETER,
687
+ scaledown_window: int = UNSET_PARAMETER,
688
+ scaleup_window: int = UNSET_PARAMETER,
689
+ ) -> ServerAutoscalerSettings:
690
+ """Override the current Autoscaler settings for this Server.
691
+
692
+ All parameters to this function are optional; not passing an argument for a given parameter
693
+ will not update its value.
694
+
695
+ Note that re-deploying the App containing this Server will wipe any overrides and revert
696
+ its Autoscaler settings back to those defined on the Server at creation time.
697
+
698
+ Args:
699
+ target_concurrency: Target number of concurrent requests per container. Must either be a
700
+ positive float (e.g. 1.5 to target 3 requests for every 2 containers), or `None`.
701
+ Passing `None` will disable autoscaling of this Server (effectively setting target
702
+ concurrency to infinity).
703
+ min_containers: Minimum number of containers to keep running. Must be a nonnegative
704
+ integer, or `None`. Passing `None` is equivalent to setting the minimum to 0.
705
+ max_containers: Maximum concurrent containers. Must be a positive integer, or `None`.
706
+ Passing `None` is equivalent to disabling the upper bound on container concurrency at
707
+ the Server level (note that Environment and Workspace level container upper limits
708
+ still apply.)
709
+ buffer_containers: Extra containers to keep warm beyond current demand. Must be a
710
+ nonnegative integer, or `None`. Passing `None` is equivalent to setting the buffer to
711
+ 0.
712
+ scaledown_window: Maximum duration (in seconds) idle containers wait before scaling down.
713
+ Must be a positive integer between 2 and 3600, inclusive.
714
+ scaleup_window: Seconds of sustained demand required before scaling up new containers.
715
+ Must be a positive integer.
716
+
717
+ Returns:
718
+ A `ServerAutoscalerSettings` dataclass.
719
+
720
+ Examples:
721
+
722
+ Update `MyServer` so that 2 containers are always active.
723
+
724
+ ```python notest
725
+ MyServer = modal.Server.from_name("my-app", "MyServer")
726
+ MyServer.autoscaler.update(min_containers=2)
727
+ ```
728
+
729
+ Update `MyServer` so that there is no Server-level limit on `max_containers`:
730
+
731
+ ```python notest
732
+ MyServer = modal.Server.from_name("my-app", "MyServer")
733
+ MyServer.autoscaler.update(max_containers=None)
734
+ ```
735
+ """
736
+ await self._server.hydrate()
737
+
738
+ service_fn = self._server._get_service_function()
739
+
740
+ settings: api_pb2.AutoscalerSettings = api_pb2.AutoscalerSettings()
741
+
742
+ if min_containers != UNSET_PARAMETER:
743
+ min_containers = min_containers if min_containers is not None else 0
744
+ if min_containers < 0:
745
+ raise InvalidError("Invalid argument: `min_containers` must be a nonnegative integer or `None`.")
746
+
747
+ settings.min_containers = min_containers
748
+
749
+ if buffer_containers != UNSET_PARAMETER:
750
+ buffer_containers = buffer_containers if buffer_containers is not None else 0
751
+ if buffer_containers < 0:
752
+ raise InvalidError("Invalid argument: `buffer_containers` must be a nonnegative integer or `None`.")
753
+
754
+ settings.buffer_containers = buffer_containers
755
+
756
+ if max_containers != UNSET_PARAMETER:
757
+ if max_containers is not None and max_containers <= 0:
758
+ raise InvalidError("Invalid argument: `max_containers` must be a postive integer or `None`.")
759
+
760
+ settings.max_containers = max_containers if max_containers is not None else 0
761
+
762
+ if scaledown_window != UNSET_PARAMETER:
763
+ if not (2 <= scaledown_window <= 3600):
764
+ raise InvalidError("Invalid argument: `scaledown_window` must be between 2 and 3600 (inclusive)")
765
+
766
+ settings.scaledown_window = scaledown_window
767
+
768
+ if scaleup_window != UNSET_PARAMETER:
769
+ if scaleup_window <= 0:
770
+ raise InvalidError("Invalid argument: `scaleup_window` must be a postive integer.")
771
+
772
+ settings.scaleup_window = scaleup_window
773
+
774
+ if target_concurrency != UNSET_PARAMETER:
775
+ if target_concurrency is not None:
776
+ if target_concurrency <= 0:
777
+ raise InvalidError("Invalid argument: `target_concurrency` must be a postive float or `None`.")
778
+
779
+ validate_target_concurrency(target_concurrency, "target_concurrency", allow_fractional=True)
780
+
781
+ settings.target_concurrency_float = (
782
+ normalize_fractional_target_concurrency(target_concurrency) if target_concurrency is not None else 0.0
783
+ )
784
+
785
+ request = api_pb2.FunctionUpdateSchedulingParamsRequest(function_id=service_fn.object_id, settings=settings)
786
+ response = await service_fn.client._stub.FunctionUpdateSchedulingParams(request)
787
+
788
+ ret = ServerAutoscalerSettings._from_proto(response.current_settings)
789
+
790
+ updates = {}
791
+ if ret.target_concurrency == 0.0:
792
+ updates["target_concurrency"] = None
793
+ if ret.max_containers == 0:
794
+ updates["max_containers"] = None
795
+
796
+ if updates:
797
+ ret = dataclasses.replace(ret, **updates)
798
+
799
+ return ret
@@ -76,6 +76,11 @@ class _Server:
76
76
  """Start and terminate sticky sessions on a Server decorated with `@modal.sessioned()`."""
77
77
  ...
78
78
 
79
+ @property
80
+ def autoscaler(self) -> _ServerAutoscalerManager:
81
+ """View and update Autoscaler settings on a Server."""
82
+ ...
83
+
79
84
  async def info(self, *, refresh: bool = False) -> modal.types.ServerInfo:
80
85
  """Get an overview of a Server's resource requests, associated mounts, http config, etc.
81
86
 
@@ -450,3 +455,81 @@ class ServerSessionsManager:
450
455
  ...
451
456
 
452
457
  terminate: __terminate_spec
458
+
459
+ class _ServerAutoscalerManager:
460
+ def __init__(self, server: _Server):
461
+ """mdmd:hidden"""
462
+ ...
463
+
464
+ async def settings(self) -> modal.types.ServerAutoscalerSettings:
465
+ """View the current Autoscaler settings for this Server.
466
+
467
+ Returns:
468
+ A `ServerAutoscalerSettings` dataclass.
469
+
470
+ Examples:
471
+
472
+ ```python notest
473
+ server = modal.Server.from_name("my-app", "MyServer")
474
+ settings = server.autoscaler.settings()
475
+ ```
476
+ """
477
+ ...
478
+
479
+ async def update(
480
+ self,
481
+ *,
482
+ target_concurrency: typing.Optional[float] = -1,
483
+ min_containers: typing.Optional[int] = -1,
484
+ max_containers: typing.Optional[int] = -1,
485
+ buffer_containers: typing.Optional[int] = -1,
486
+ scaledown_window: int = -1,
487
+ scaleup_window: int = -1,
488
+ ) -> modal.types.ServerAutoscalerSettings:
489
+ """Override the current Autoscaler settings for this Server.
490
+
491
+ All parameters to this function are optional; not passing an argument for a given parameter
492
+ will not update its value.
493
+
494
+ Note that re-deploying the App containing this Server will wipe any overrides and revert
495
+ its Autoscaler settings back to those defined on the Server at creation time.
496
+
497
+ Args:
498
+ target_concurrency: Target number of concurrent requests per container. Must either be a
499
+ positive float (e.g. 1.5 to target 3 requests for every 2 containers), or `None`.
500
+ Passing `None` will disable autoscaling of this Server (effectively setting target
501
+ concurrency to infinity).
502
+ min_containers: Minimum number of containers to keep running. Must be a nonnegative
503
+ integer, or `None`. Passing `None` is equivalent to setting the minimum to 0.
504
+ max_containers: Maximum concurrent containers. Must be a positive integer, or `None`.
505
+ Passing `None` is equivalent to disabling the upper bound on container concurrency at
506
+ the Server level (note that Environment and Workspace level container upper limits
507
+ still apply.)
508
+ buffer_containers: Extra containers to keep warm beyond current demand. Must be a
509
+ nonnegative integer, or `None`. Passing `None` is equivalent to setting the buffer to
510
+ 0.
511
+ scaledown_window: Maximum duration (in seconds) idle containers wait before scaling down.
512
+ Must be a positive integer between 2 and 3600, inclusive.
513
+ scaleup_window: Seconds of sustained demand required before scaling up new containers.
514
+ Must be a positive integer.
515
+
516
+ Returns:
517
+ A `ServerAutoscalerSettings` dataclass.
518
+
519
+ Examples:
520
+
521
+ Update `MyServer` so that 2 containers are always active.
522
+
523
+ ```python notest
524
+ MyServer = modal.Server.from_name("my-app", "MyServer")
525
+ MyServer.autoscaler.update(min_containers=2)
526
+ ```
527
+
528
+ Update `MyServer` so that there is no Server-level limit on `max_containers`:
529
+
530
+ ```python notest
531
+ MyServer = modal.Server.from_name("my-app", "MyServer")
532
+ MyServer.autoscaler.update(max_containers=None)
533
+ ```
534
+ """
535
+ ...
@@ -378,7 +378,9 @@ def retry(
378
378
 
379
379
  Usage:
380
380
 
381
- ```python notest
381
+ ```python
382
+ from modal._utils.async_utils import retry
383
+
382
384
  @retry
383
385
  async def may_fail_default():
384
386
  # ...
@@ -907,7 +909,9 @@ async def asyncnullcontext(*args, **kwargs):
907
909
  Note that for Python 3.10+ you can use contextlib.nullcontext() instead.
908
910
 
909
911
  Usage:
910
- ```python notest
912
+ ```python
913
+ from modal._utils.async_utils import asyncnullcontext
914
+
911
915
  async with asyncnullcontext():
912
916
  pass
913
917
  ```
@@ -1,6 +1,7 @@
1
1
  aiohappyeyeballs==2.6.1
2
2
  aiohttp==3.12.7 ; python_version < "3.14"
3
- aiohttp==3.13.2 ; python_version >= "3.14"
3
+ aiohttp==3.13.2 ; python_version == "3.14"
4
+ aiohttp==3.14.4 ; python_version >= "3.15"
4
5
  aiosignal==1.3.2 ; python_version < "3.14"
5
6
  aiosignal==1.4.0 ; python_version >= "3.14"
6
7
  async-timeout==5.0.1 ; python_version < "3.11"
@@ -16,6 +17,9 @@ hyperframe==6.1.0
16
17
  idna==3.10
17
18
  multidict==6.4.4
18
19
  propcache==0.3.1
19
- protobuf==6.31.1
20
- typing_extensions==4.13.2
21
- yarl==1.20.0
20
+ protobuf==6.31.1 ; python_version < "3.15"
21
+ protobuf==7.35.1 ; python_version >= "3.15"
22
+ typing_extensions==4.13.2 ; python_version < "3.15"
23
+ typing_extensions==4.16.0 ; python_version >= "3.15"
24
+ yarl==1.20.0 ; python_version < "3.15"
25
+ yarl==1.25.1 ; python_version >= "3.15"
@@ -14,6 +14,8 @@ hyperframe==6.1.0
14
14
  idna==3.10
15
15
  multidict==6.4.4
16
16
  propcache==0.3.1
17
- protobuf==6.31.1
18
- typing_extensions==4.13.2
17
+ protobuf==6.31.1 ; python_version <= "3.14"
18
+ protobuf==7.35.1 ; python_version >= "3.15"
19
+ typing_extensions==4.13.2 ; python_version <= "3.14"
20
+ typing_extensions==4.16.0 ; python_version >= "3.15"
19
21
  yarl==1.20.0
@@ -13,7 +13,8 @@
13
13
  "3.11.12",
14
14
  "3.12.10",
15
15
  "3.13.3",
16
- "3.14.2"
16
+ "3.14.2",
17
+ "3.15.0"
17
18
  ],
18
19
  "2025.06": [
19
20
  "3.9.22",
@@ -21,7 +22,8 @@
21
22
  "3.11.12",
22
23
  "3.12.10",
23
24
  "3.13.3",
24
- "3.14.2"
25
+ "3.14.2",
26
+ "3.15.0"
25
27
  ],
26
28
  "2024.10": [
27
29
  "3.9.20",
@@ -1521,7 +1521,7 @@ async def autoscaler_update(
1521
1521
  )
1522
1522
 
1523
1523
  f: _Function = _Function._new_hydrated(function_id, client, handle_metadata)
1524
- await f.update_autoscaler(**updates)
1524
+ await f.autoscaler.update(**updates)
1525
1525
 
1526
1526
  output_manager.print(f"[green]✓[/green] Updated autoscaler settings for Function {handle_metadata.function_name}")
1527
1527
 
@@ -1321,7 +1321,7 @@ async def autoscaler_update(
1321
1321
  )
1322
1322
 
1323
1323
  if v == "none":
1324
- updates[k] = 0
1324
+ updates[k] = None # type: ignore
1325
1325
  continue
1326
1326
 
1327
1327
  try:
@@ -1358,7 +1358,7 @@ async def autoscaler_update(
1358
1358
  )
1359
1359
 
1360
1360
  s = _Server._new_from_function(function_id, client, handle_metadata)
1361
- await s.update_autoscaler(**updates) # type: ignore
1361
+ await s.autoscaler.update(**updates) # type: ignore
1362
1362
 
1363
1363
  output_manager.print(f"[green]✓[/green] Updated autoscaler settings for Server {handle_metadata.function_name}")
1364
1364