modal 1.5.1.dev14__tar.gz → 1.5.2.dev0__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 (232) hide show
  1. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/PKG-INFO +1 -1
  2. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_billing.py +2 -23
  3. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_environments.py +27 -20
  4. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_functions.py +5 -5
  5. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_image.py +3 -4
  6. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/gpu_memory_snapshot.py +5 -0
  7. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/task_lifecycle_manager.py +9 -4
  8. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_server.py +31 -4
  9. modal-1.5.2.dev0/modal/_utils/curl_utils.py +115 -0
  10. modal-1.5.2.dev0/modal/_workspace.py +342 -0
  11. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/app.py +15 -13
  12. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/app.pyi +30 -26
  13. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/billing.pyi +0 -8
  14. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/app.py +24 -3
  15. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/billing.py +9 -9
  16. modal-1.5.2.dev0/modal/cli/curl.py +137 -0
  17. modal-1.5.2.dev0/modal/cli/endpoint.py +352 -0
  18. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/entry_point.py +8 -2
  19. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/environment.py +10 -11
  20. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/profile.py +20 -5
  21. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/utils.py +8 -3
  22. modal-1.5.2.dev0/modal/cli/workspace.py +129 -0
  23. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/client.pyi +2 -2
  24. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/config.py +3 -1
  25. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/environments.pyi +57 -2
  26. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/functions.pyi +16 -16
  27. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/sandbox.py +16 -21
  28. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/sandbox.pyi +18 -12
  29. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/secret.py +39 -9
  30. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/secret.pyi +19 -0
  31. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/server.pyi +65 -12
  32. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/workspace.py +13 -1
  33. modal-1.5.2.dev0/modal/workspace.pyi +450 -0
  34. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal.egg-info/PKG-INFO +1 -1
  35. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal.egg-info/SOURCES.txt +4 -0
  36. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/mdmd/mdmd.py +10 -1
  37. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/mdmd/types.py +1 -0
  38. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/api_grpc.py +16 -0
  39. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/api_pb2.py +969 -949
  40. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/api_pb2.pyi +36 -2
  41. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/api_pb2_grpc.py +34 -0
  42. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/api_pb2_grpc.pyi +12 -0
  43. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/modal_api_grpc.py +1 -0
  44. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_version/__init__.py +1 -1
  45. modal-1.5.1.dev14/modal/_workspace.py +0 -191
  46. modal-1.5.1.dev14/modal/workspace.pyi +0 -139
  47. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/LICENSE +0 -0
  48. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/README.md +0 -0
  49. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/__init__.py +0 -0
  50. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/__main__.py +0 -0
  51. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_clustered_functions.py +0 -0
  52. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_clustered_functions.pyi +0 -0
  53. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_container_entrypoint.py +0 -0
  54. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_function_variants.py +0 -0
  55. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_grpc_client.py +0 -0
  56. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_ipython.py +0 -0
  57. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_load_context.py +0 -0
  58. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_location.py +0 -0
  59. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_logs.py +0 -0
  60. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_object.py +0 -0
  61. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_output/__init__.py +0 -0
  62. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_output/manager.py +0 -0
  63. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_output/pty.py +0 -0
  64. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_output/rich.py +0 -0
  65. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_output/status.py +0 -0
  66. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_partial_function.py +0 -0
  67. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_resolver.py +0 -0
  68. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_resources.py +0 -0
  69. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/__init__.py +0 -0
  70. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/asgi.py +0 -0
  71. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/container_io_manager.py +0 -0
  72. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/container_io_manager.pyi +0 -0
  73. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/execution_context.py +0 -0
  74. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/execution_context.pyi +0 -0
  75. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/task_lifecycle_manager.pyi +0 -0
  76. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/telemetry.py +0 -0
  77. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/user_code_event_loop.py +0 -0
  78. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/user_code_imports.py +0 -0
  79. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_serialization.py +0 -0
  80. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_traceback.py +0 -0
  81. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_tunnel.py +0 -0
  82. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_tunnel.pyi +0 -0
  83. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_type_manager.py +0 -0
  84. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/__init__.py +0 -0
  85. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/app_utils.py +0 -0
  86. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/async_utils.py +0 -0
  87. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/auth_token_manager.py +0 -0
  88. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/blob_utils.py +0 -0
  89. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/browser_utils.py +0 -0
  90. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/bytes_io_segment_payload.py +0 -0
  91. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/deprecation.py +0 -0
  92. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/docker_utils.py +0 -0
  93. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/function_utils.py +0 -0
  94. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/git_utils.py +0 -0
  95. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/grpc_testing.py +0 -0
  96. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/grpc_utils.py +0 -0
  97. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/hash_utils.py +0 -0
  98. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/http_utils.py +0 -0
  99. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/jwt_utils.py +0 -0
  100. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/logger.py +0 -0
  101. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/mount_utils.py +0 -0
  102. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/name_utils.py +0 -0
  103. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/package_utils.py +0 -0
  104. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/pattern_utils.py +0 -0
  105. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/proxy_support.py +0 -0
  106. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/rand_pb_testing.py +0 -0
  107. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/sandbox_fs_utils.py +0 -0
  108. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/shell_utils.py +0 -0
  109. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/task_command_router_client.py +0 -0
  110. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/time_utils.py +0 -0
  111. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_vendor/__init__.py +0 -0
  112. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  113. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_vendor/cloudpickle.py +0 -0
  114. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_vendor/tblib.py +0 -0
  115. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_vendor/version.py +0 -0
  116. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_watcher.py +0 -0
  117. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/billing.py +0 -0
  118. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/builder/2023.12.312.txt +0 -0
  119. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/builder/2023.12.txt +0 -0
  120. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/builder/2024.04.txt +0 -0
  121. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/builder/2024.10.txt +0 -0
  122. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/builder/2025.06.txt +0 -0
  123. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/builder/PREVIEW.txt +0 -0
  124. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/builder/README.md +0 -0
  125. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/builder/base-images.json +0 -0
  126. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/call_graph.py +0 -0
  127. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/__init__.py +0 -0
  128. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/_download.py +0 -0
  129. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/_help.py +0 -0
  130. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/_traceback.py +0 -0
  131. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/bootstrap.py +0 -0
  132. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/changelog.py +0 -0
  133. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/cluster.py +0 -0
  134. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/config.py +0 -0
  135. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/container.py +0 -0
  136. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/dashboard.py +0 -0
  137. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/dict.py +0 -0
  138. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/image.py +0 -0
  139. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/import_refs.py +0 -0
  140. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/launch.py +0 -0
  141. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/logo.py +0 -0
  142. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/network_file_system.py +0 -0
  143. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/programs/__init__.py +0 -0
  144. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/programs/run_jupyter.py +0 -0
  145. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/programs/vscode.py +0 -0
  146. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/queues.py +0 -0
  147. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/run.py +0 -0
  148. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/secret.py +0 -0
  149. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/selector.py +0 -0
  150. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/shell.py +0 -0
  151. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/skills.py +0 -0
  152. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/token.py +0 -0
  153. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/volume.py +0 -0
  154. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/client.py +0 -0
  155. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cloud_bucket_mount.py +0 -0
  156. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cloud_bucket_mount.pyi +0 -0
  157. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cls.py +0 -0
  158. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cls.pyi +0 -0
  159. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/container_process.py +0 -0
  160. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/container_process.pyi +0 -0
  161. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/dict.py +0 -0
  162. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/dict.pyi +0 -0
  163. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/environments.py +0 -0
  164. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/exception.py +0 -0
  165. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/experimental/__init__.py +0 -0
  166. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/experimental/flash.py +0 -0
  167. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/experimental/flash.pyi +0 -0
  168. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/experimental/ipython.py +0 -0
  169. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/file_io.py +0 -0
  170. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/file_io.pyi +0 -0
  171. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/file_pattern_matcher.py +0 -0
  172. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/functions.py +0 -0
  173. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/image.py +0 -0
  174. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/image.pyi +0 -0
  175. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/io_streams.py +0 -0
  176. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/io_streams.pyi +0 -0
  177. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/mount.py +0 -0
  178. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/mount.pyi +0 -0
  179. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/network_file_system.py +0 -0
  180. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/network_file_system.pyi +0 -0
  181. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/object.py +0 -0
  182. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/object.pyi +0 -0
  183. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/output.py +0 -0
  184. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/parallel_map.py +0 -0
  185. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/parallel_map.pyi +0 -0
  186. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/partial_function.py +0 -0
  187. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/partial_function.pyi +0 -0
  188. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/proxy.py +0 -0
  189. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/proxy.pyi +0 -0
  190. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/py.typed +0 -0
  191. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/queue.py +0 -0
  192. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/queue.pyi +0 -0
  193. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/retries.py +0 -0
  194. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/runner.py +0 -0
  195. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/runner.pyi +0 -0
  196. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/running_app.py +0 -0
  197. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/sandbox_fs.py +0 -0
  198. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/sandbox_fs.pyi +0 -0
  199. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/schedule.py +0 -0
  200. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/scheduler_placement.py +0 -0
  201. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/server.py +0 -0
  202. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/serving.py +0 -0
  203. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/serving.pyi +0 -0
  204. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/skills/modal/SKILL.md +0 -0
  205. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/snapshot.py +0 -0
  206. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/snapshot.pyi +0 -0
  207. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/stream_type.py +0 -0
  208. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/token_flow.py +0 -0
  209. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/token_flow.pyi +0 -0
  210. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/volume.py +0 -0
  211. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/volume.pyi +0 -0
  212. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal.egg-info/dependency_links.txt +0 -0
  213. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal.egg-info/entry_points.txt +0 -0
  214. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal.egg-info/requires.txt +0 -0
  215. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal.egg-info/top_level.txt +0 -0
  216. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/__init__.py +0 -0
  217. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/gen_cli_docs.py +0 -0
  218. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/gen_cli_docs_main.py +0 -0
  219. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/gen_reference_docs.py +0 -0
  220. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/gen_reference_docs_main.py +0 -0
  221. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/mdmd/__init__.py +0 -0
  222. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/mdmd/signatures.py +0 -0
  223. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/__init__.py +0 -0
  224. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/py.typed +0 -0
  225. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/task_command_router_grpc.py +0 -0
  226. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/task_command_router_pb2.py +0 -0
  227. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/task_command_router_pb2.pyi +0 -0
  228. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  229. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  230. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_version/__main__.py +0 -0
  231. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/pyproject.toml +0 -0
  232. {modal-1.5.1.dev14 → modal-1.5.2.dev0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.5.1.dev14
3
+ Version: 1.5.2.dev0
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -9,24 +9,6 @@ from modal_proto import api_pb2
9
9
  from ._utils.deprecation import deprecation_warning
10
10
  from .client import _Client
11
11
 
12
- BILLING_DOCSTRING = """
13
- The `start` and `end` parameters are required to either have a UTC timezone or to be
14
- timezone-naive (which will be interpreted as UTC times). The timestamps in the result will
15
- be in UTC. Cost will be reported for full intervals, even if the provided `start` or `end`
16
- parameters are partial: `start` will be rounded to the beginning of its interval, while
17
- partial `end` intervals will be excluded.
18
-
19
- Additional user-provided metadata can be included in the report if the objects have tags
20
- and `tag_names` (i.e., keys) are specified in the request. Alternatively, pass `tag_names=["*"]`
21
- to include all tags in the report. Note that tags will be attributed to the entire interval even
22
- if they were added or removed at some point within it. If the tag name was not in use during an
23
- interval, it will be absent from the tags dictionary in that output row.
24
-
25
- In most cases, billing data will be available in the database that this API queries within
26
- minutes, although there may be collection delays. If completeness is important for your use
27
- case, we recommend leaving a buffer after the end of the query interval.
28
- """
29
-
30
12
 
31
13
  class WorkspaceBillingReportItem(TypedDict):
32
14
  object_id: str
@@ -115,10 +97,6 @@ async def _workspace_billing_report(
115
97
  if they were added or removed at some point within it. If the tag name was not in use during an
116
98
  interval, it will be absent from the tags dictionary in that output row.
117
99
 
118
- In most cases, billing data will be available in the database that this API queries within
119
- minutes, although there may be collection delays. If completeness is important for your use
120
- case, we recommend leaving a buffer after the end of the query interval.
121
-
122
100
  It's also possible to generate reports using the
123
101
  [`modal billing report`](https://modal.com/docs/cli/latest/billing) CLI command. The CLI
124
102
  has a few convenience features for generating reports across relative time ranges.
@@ -127,7 +105,8 @@ async def _workspace_billing_report(
127
105
 
128
106
  deprecation_warning(
129
107
  (2026, 6, 18),
130
- "`workspace_billing_report()` is deprecated. Use `Workspace.billing.report()` instead.",
108
+ "The `modal.billing.workspace_billing_report()` function is deprecated. "
109
+ "Use the `workspace.billing.report()` method on the `modal.Workspace` object instead.",
131
110
  )
132
111
 
133
112
  from ._workspace import _Workspace
@@ -13,7 +13,7 @@ from synchronicity import classproperty
13
13
 
14
14
  from modal_proto import api_pb2
15
15
 
16
- from ._billing import BILLING_DOCSTRING, BillingReportItem
16
+ from ._billing import BillingReportItem
17
17
  from ._load_context import LoadContext
18
18
  from ._object import _Object
19
19
  from ._resolver import Resolver
@@ -416,26 +416,33 @@ class _EnvironmentBillingManager:
416
416
  resolution: str = "d", # Resolution, e.g. "d" for daily or "h" for hourly
417
417
  tag_names: list[str] | None = None, # Optional additional metadata to include
418
418
  ) -> list[BillingReportItem]:
419
- (
420
- """Return a report of workspace usage by object and time, scoped to the calling Environment.
421
-
422
- The result will be a list of dataclasses for each interval (determined by `resolution`)
423
- between the `start` and `end` limits. Each item represents a single (Modal object, time interval)
424
- pair that billing can be attributed to (e.g., an App) along with metadata (including user-defined
425
- tags) to identify that object. The dataclass also contains a breakdown of the cost value
426
- attributed to individual resources (for an App, this can be CPU, Memory, specific GPU types,
427
- etc.). The specific resource types included in the breakdown are subject to change as
428
- Modal's billing model evolves.
429
-
430
- It's also possible to generate reports using the
431
- [`modal environment billing report`](https://modal.com/docs/cli/latest/environment#modal-environment-billing-report)
432
- CLI command. The CLI has a few convenience features for generating
433
- reports across relative time ranges.
434
-
435
- """
436
- + BILLING_DOCSTRING
437
- )
419
+ """Return a cost report for Environment usage, broken down by object and time.
420
+
421
+ Args:
422
+ start: Start of the report, inclusive and rounded to the beginning of the interval.
423
+ Must be in UTC or timezone-naive (interpreted as UTC).
424
+ end: End of the report, exclusive. Must be in UTC or timezone-naive. Partial final
425
+ intervals will be excluded from the report.
426
+ resolution: Resolution, e.g. "d" for daily or "h" for hourly.
427
+ tag_names: List of tag names; each row will include the tag name and value in use
428
+ for that object during the relevant time interval. Pass `["*"]` to include all
429
+ tags in the report.
430
+
431
+ Returns:
432
+ A list of `BillingReportItem` dataclasses. Each item reports the cost attributed to
433
+ a specific Modal object during a given time interval. Cost is further broken down by
434
+ the resource type that generated it (e.g. CPU, Memory, specific GPU usage).
435
+ Note that the specific resource types included in the breakdown are subject to change
436
+ as Modal's billing model evolves.
437
+
438
+ See also:
439
+ - [`modal environment billing report`](https://modal.com/docs/cli/latest/environment#modal-environment-billing-report):
440
+ An environment report CLI that has convenience features around relative time range queries
441
+ and JSON/CSV output.
442
+ - [`Workspace.billing.report()`](https://modal.com/docs/sdk/py/latest/modal.Workspace#billingreport):
443
+ An analogous report API for the entire Workspace.
438
444
 
445
+ """
439
446
  if tag_names is None:
440
447
  tag_names = []
441
448
 
@@ -1195,10 +1195,10 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1195
1195
  its static configuration.
1196
1196
 
1197
1197
  Args:
1198
- min_containers: Minimum number of containers to keep running, or `None` to leave unchanged.
1199
- max_containers: Maximum concurrent containers, or `None` to leave unchanged.
1200
- buffer_containers: Extra containers to keep warm beyond demand, or `None` to leave unchanged.
1201
- scaledown_window: Seconds idle containers wait before scaling down, or `None` to leave unchanged.
1198
+ min_containers: Minimum number of containers to keep running.
1199
+ max_containers: Maximum concurrent containers.
1200
+ buffer_containers: Extra containers to keep warm beyond current demand.
1201
+ scaledown_window: Maximum duration (in seconds) idle containers wait before scaling down.
1202
1202
 
1203
1203
  Examples:
1204
1204
  ```python notest
@@ -1212,7 +1212,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1212
1212
 
1213
1213
  # Extend the scaledown window to increase the amount of time that idle containers stay alive
1214
1214
  f.update_autoscaler(scaledown_window=300)
1215
- ```
1215
+ ```
1216
1216
 
1217
1217
  """
1218
1218
  # Assert .update_autoscaler() is not called on a method as opposed to the Object. Applicable for Cls only.
@@ -2965,17 +2965,16 @@ class _Image(_Object, type_prefix="im"):
2965
2965
  """
2966
2966
  tag = _parse_named_image_ref(name)
2967
2967
 
2968
- if not self.is_hydrated:
2968
+ if self._object_id is None:
2969
2969
  raise InvalidError("Cannot publish an image that has not been created yet. Call `.build()` first.")
2970
2970
 
2971
- _client = client or self._client
2972
- assert _client is not None
2971
+ _client = client or await _Client.from_env()
2973
2972
 
2974
2973
  resolved_env = environment_name or config.get("environment") or ""
2975
2974
 
2976
2975
  await _client.stub.ImagePublish(
2977
2976
  api_pb2.ImagePublishRequest(
2978
- image_id=self.object_id,
2977
+ image_id=self._object_id,
2979
2978
  environment_name=resolved_env,
2980
2979
  is_public=False,
2981
2980
  tag=tag,
@@ -17,6 +17,11 @@ from modal.config import config, logger
17
17
 
18
18
  CUDA_CHECKPOINT_PATH: str = config.get("cuda_checkpoint_path")
19
19
 
20
+ # Exit code used to signal to modal-runtime that a GPU memory snapshot restore failed
21
+ # and the task should be retried without a snapshot. This is a sentinel value that must
22
+ # stay in sync with `GPU_SNAPSHOT_RESTORE_FAILED_EXIT_CODE` in runner.rs.
23
+ SNAPSHOT_RESTORE_FAILED_EXIT_CODE: int = 222
24
+
20
25
  # Maximum total duration for each individual `cuda-checkpoint` invocation.
21
26
  CUDA_CHECKPOINT_TIMEOUT: float = 3 * 60.0
22
27
 
@@ -180,10 +180,15 @@ class _TaskLifecycleManager:
180
180
  if self.function_def._experimental_enable_gpu_snapshot and self.function_def.resources.gpu_config.gpu_type:
181
181
  logger.debug("GPU memory snapshot enabled. Attempting to restore GPU memory.")
182
182
 
183
- assert self._cuda_checkpoint_session, (
184
- "CudaCheckpointSession not found when attempting to restore GPU memory"
185
- )
186
- self._cuda_checkpoint_session.restore()
183
+ try:
184
+ if self._cuda_checkpoint_session is None:
185
+ raise gpu_memory_snapshot.CudaCheckpointException("CudaCheckpointSession not found")
186
+ self._cuda_checkpoint_session.restore()
187
+ except gpu_memory_snapshot.CudaCheckpointException as exc:
188
+ logger.warning(f"GPU memory snapshot restore failed; retrying task without snapshot. Error: {exc}")
189
+ sys.stderr.flush()
190
+ # Exit with a sentinel code that the runtime will use to retry the task without a snapshot.
191
+ os._exit(gpu_memory_snapshot.SNAPSHOT_RESTORE_FAILED_EXIT_CODE)
187
192
 
188
193
  self._client = await _Client.from_env()
189
194
 
@@ -46,7 +46,7 @@ def validate_http_server_config(
46
46
  class _Server:
47
47
  """Server runs an HTTP server started in an `@modal.enter` method.
48
48
 
49
- See [lifecycle hooks](https://modal.com/docs/guide/lifecycle-functions) for more information.
49
+ See the [guide](https://modal.com/docs/guide/servers) for more information.
50
50
 
51
51
  Generally, you will not construct a Server directly.
52
52
  Instead, use the [`@app.server()`](https://modal.com/docs/sdk/py/latest/modal.App#server) decorator.
@@ -77,6 +77,7 @@ class _Server:
77
77
 
78
78
  @property
79
79
  def object_id(self) -> str:
80
+ """Modal's internal ID for this Server instance."""
80
81
  return self._service_function.object_id
81
82
 
82
83
  @staticmethod
@@ -91,6 +92,7 @@ class _Server:
91
92
 
92
93
  @live_method
93
94
  async def get_url(self) -> str | None:
95
+ """The URL for making requests to this Server."""
94
96
  urls = await self._get_service_function()._experimental_get_flash_urls()
95
97
  # Return the first URL if it exists. Servers should only have one URL
96
98
  # since they only have one region.
@@ -101,16 +103,28 @@ class _Server:
101
103
  async def update_autoscaler(
102
104
  self,
103
105
  *,
106
+ target_concurrency: int | None = None,
104
107
  min_containers: int | None = None,
105
108
  max_containers: int | None = None,
106
109
  buffer_containers: int | None = None,
107
110
  scaleup_window: int | None = None,
108
111
  scaledown_window: int | None = None,
109
- target_concurrency: int | None = None,
110
112
  ) -> None:
111
113
  """Override the current autoscaler behavior for this Server.
112
114
 
113
- Unspecified parameters will retain their current value.
115
+ Unspecified parameters will retain their current value, i.e. either the static value
116
+ from the `@app.server()` decorator, or an override value from a previous call to this method.
117
+
118
+ Subsequent deployments of the App containing this Server will reset the autoscaler back to
119
+ its static configuration.
120
+
121
+ Args:
122
+ target_concurrency: Target number of concurrent requests per container.
123
+ min_containers: Minimum number of containers to keep running regardless of demand.
124
+ max_containers: Limit on the number of containers that can be concurrently running.
125
+ buffer_containers: Extra containers to scale up beyond current demand.
126
+ scaleup_window: Seconds of sustained demand required before scaling up new containers.
127
+ scaledown_window: Maximum duration (in seconds) idle containers wait before scaling down.
114
128
 
115
129
  Examples:
116
130
  ```python notest
@@ -130,7 +144,7 @@ class _Server:
130
144
 
131
145
  # Disable the Server autoscaling by setting target_concurrency to 0
132
146
  server.update_autoscaler(target_concurrency=0)
133
- ```
147
+ ```
134
148
 
135
149
  """
136
150
  return await self._get_service_function()._update_autoscaler(
@@ -144,6 +158,13 @@ class _Server:
144
158
 
145
159
  # ============ Hydration ============
146
160
  async def hydrate(self, client: _Client | None = None) -> "_Server":
161
+ """Synchronize the local object with its identity on the Modal server.
162
+
163
+ It is rarely necessary to call this method explicitly, as most operations will
164
+ lazily hydrate when needed. The main use case is when you need to access object
165
+ metadata, such as its ID.
166
+
167
+ """
147
168
  # This is required since we want to support @livemethod() decorated methods
148
169
  service_function = self._get_service_function()
149
170
  await service_function.hydrate(client)
@@ -183,6 +204,12 @@ class _Server:
183
204
  object with metadata from Modal servers until the first
184
205
  time it is actually used.
185
206
 
207
+ Args:
208
+ app_name: Name of the App containing the Server.
209
+ name: Name of the Server within the App.
210
+ environment_name: Name of the Environment where the App is deployed.
211
+ client: Modal client instance for this session.
212
+
186
213
  ```python notest
187
214
  server = modal.Server.from_name("other-app", "Server")
188
215
  ```
@@ -0,0 +1,115 @@
1
+ # Copyright Modal Labs 2026
2
+ from urllib.parse import urlparse
3
+
4
+ # Short curl flags (single dash, single letter) that consume the following argument.
5
+ _CURL_SHORT_VALUE_FLAGS = frozenset("AbCcDdEeFHhKmoQrTtUuwXxYyz")
6
+
7
+ # Long curl flags that consume the following argument (when given as `--flag value`).
8
+ # Flags given as `--flag=value` are self-contained and handled generically.
9
+ _CURL_LONG_VALUE_FLAGS = frozenset(
10
+ {
11
+ "--cacert",
12
+ "--capath",
13
+ "--cert",
14
+ "--cert-type",
15
+ "--config",
16
+ "--connect-timeout",
17
+ "--connect-to",
18
+ "--continue-at",
19
+ "--cookie",
20
+ "--cookie-jar",
21
+ "--data",
22
+ "--data-ascii",
23
+ "--data-binary",
24
+ "--data-raw",
25
+ "--data-urlencode",
26
+ "--dump-header",
27
+ "--form",
28
+ "--form-string",
29
+ "--header",
30
+ "--interface",
31
+ "--key",
32
+ "--key-type",
33
+ "--limit-rate",
34
+ "--max-filesize",
35
+ "--max-redirs",
36
+ "--max-time",
37
+ "--oauth2-bearer",
38
+ "--output",
39
+ "--pass",
40
+ "--proxy",
41
+ "--proxy-user",
42
+ "--range",
43
+ "--referer",
44
+ "--request",
45
+ "--resolve",
46
+ "--retry",
47
+ "--retry-delay",
48
+ "--retry-max-time",
49
+ "--unix-socket",
50
+ "--upload-file",
51
+ "--url",
52
+ "--user",
53
+ "--user-agent",
54
+ "--write-out",
55
+ }
56
+ )
57
+
58
+
59
+ def endpoint_cache_host(url: str) -> str:
60
+ parsed = urlparse(url if "://" in url else f"https://{url}")
61
+ return (parsed.hostname or url).lower().rstrip(".")
62
+
63
+
64
+ def is_modal_direct_url(url: str) -> bool:
65
+ # Only fetch token for app.server() functions
66
+ host = endpoint_cache_host(url)
67
+ return host.endswith("modal.direct") or host.endswith("modal-dev.direct")
68
+
69
+
70
+ def _is_modal_direct_candidate(arg: str) -> bool:
71
+ try:
72
+ return is_modal_direct_url(arg)
73
+ except ValueError:
74
+ return False
75
+
76
+
77
+ def find_url(curl_args: tuple[str, ...]) -> str | None:
78
+ """Find the Modal direct URL operand within a curl argument list.
79
+
80
+ Parses the args the way curl does well enough to skip over flag values, so that
81
+ a `modal.direct` host appearing as e.g. a header or data value is not mistaken
82
+ for the request URL.
83
+ """
84
+ i = 0
85
+ n = len(curl_args)
86
+ while i < n:
87
+ arg = curl_args[i]
88
+
89
+ if arg.startswith("--"):
90
+ flag, sep, value = arg.partition("=")
91
+ if sep:
92
+ # `--flag=value`: the value is self-contained.
93
+ if flag == "--url" and _is_modal_direct_candidate(value):
94
+ return value
95
+ elif flag in _CURL_LONG_VALUE_FLAGS:
96
+ # `--flag value`: the next argument is this flag's value.
97
+ value = curl_args[i + 1] if i + 1 < n else ""
98
+ if flag == "--url" and _is_modal_direct_candidate(value):
99
+ return value
100
+ i += 2
101
+ continue
102
+ elif arg.startswith("-") and len(arg) >= 2:
103
+ last = arg[-1]
104
+ if len(arg) == 2 and last in _CURL_SHORT_VALUE_FLAGS:
105
+ # `-X value`: the next argument is this flag's value.
106
+ i += 2
107
+ continue
108
+ # `-Xvalue` (attached value) or a cluster of boolean flags: nothing to skip.
109
+ elif _is_modal_direct_candidate(arg):
110
+ # A bare (positional) URL operand.
111
+ return arg
112
+
113
+ i += 1
114
+
115
+ return None