modAL 1.4.3__tar.gz → 1.4.3.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 (220) hide show
  1. {modal-1.4.3 → modal-1.4.3.dev0}/PKG-INFO +2 -1
  2. {modal-1.4.3 → modal-1.4.3.dev0}/modal/__init__.py +0 -2
  3. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_container_entrypoint.py +1 -21
  4. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_functions.py +161 -161
  5. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_object.py +13 -13
  6. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_output/rich.py +4 -4
  7. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_output/status.py +1 -1
  8. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_partial_function.py +16 -14
  9. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_resolver.py +5 -3
  10. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_resources.py +1 -1
  11. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_runtime/container_io_manager.py +3 -1
  12. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_runtime/container_io_manager.pyi +9 -3
  13. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_runtime/execution_context.py +3 -6
  14. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_runtime/execution_context.pyi +3 -5
  15. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_runtime/user_code_imports.py +4 -4
  16. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_serialization.py +2 -4
  17. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/async_utils.py +1 -1
  18. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/blob_utils.py +8 -82
  19. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/deprecation.py +8 -5
  20. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/docker_utils.py +1 -10
  21. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/function_utils.py +2 -23
  22. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/grpc_utils.py +6 -10
  23. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/mount_utils.py +1 -1
  24. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/name_utils.py +1 -1
  25. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/sandbox_fs_utils.py +30 -90
  26. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/task_command_router_client.py +35 -99
  27. {modal-1.4.3 → modal-1.4.3.dev0}/modal/app.py +9 -12
  28. {modal-1.4.3 → modal-1.4.3.dev0}/modal/app.pyi +10 -17
  29. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/_traceback.py +2 -1
  30. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/app.py +59 -75
  31. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/billing.py +21 -27
  32. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/bootstrap.py +11 -15
  33. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/changelog.py +18 -21
  34. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/cluster.py +19 -47
  35. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/config.py +8 -13
  36. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/container.py +51 -90
  37. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/dashboard.py +2 -6
  38. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/dict.py +25 -60
  39. modal-1.4.3.dev0/modal/cli/entry_point.py +145 -0
  40. modal-1.4.3.dev0/modal/cli/environment.py +110 -0
  41. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/import_refs.py +1 -1
  42. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/launch.py +15 -39
  43. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/network_file_system.py +46 -57
  44. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/profile.py +8 -12
  45. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/queues.py +42 -64
  46. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/run.py +37 -81
  47. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/secret.py +18 -40
  48. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/shell.py +100 -137
  49. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/token.py +31 -27
  50. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/utils.py +9 -15
  51. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/volume.py +81 -90
  52. {modal-1.4.3 → modal-1.4.3.dev0}/modal/client.pyi +10 -2
  53. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cls.py +172 -118
  54. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cls.pyi +77 -44
  55. {modal-1.4.3 → modal-1.4.3.dev0}/modal/config.py +1 -1
  56. modal-1.4.3.dev0/modal/container_process.py +470 -0
  57. {modal-1.4.3 → modal-1.4.3.dev0}/modal/container_process.pyi +120 -11
  58. {modal-1.4.3 → modal-1.4.3.dev0}/modal/dict.py +4 -4
  59. modal-1.4.3.dev0/modal/environments.py +164 -0
  60. modal-1.4.3.dev0/modal/environments.pyi +120 -0
  61. {modal-1.4.3 → modal-1.4.3.dev0}/modal/exception.py +9 -8
  62. {modal-1.4.3 → modal-1.4.3.dev0}/modal/experimental/flash.py +6 -6
  63. {modal-1.4.3 → modal-1.4.3.dev0}/modal/experimental/flash.pyi +2 -2
  64. {modal-1.4.3 → modal-1.4.3.dev0}/modal/file_io.py +11 -1
  65. {modal-1.4.3 → modal-1.4.3.dev0}/modal/functions.pyi +21 -95
  66. {modal-1.4.3 → modal-1.4.3.dev0}/modal/image.py +12 -32
  67. {modal-1.4.3 → modal-1.4.3.dev0}/modal/image.pyi +0 -54
  68. {modal-1.4.3 → modal-1.4.3.dev0}/modal/io_streams.py +199 -69
  69. {modal-1.4.3 → modal-1.4.3.dev0}/modal/io_streams.pyi +64 -125
  70. {modal-1.4.3 → modal-1.4.3.dev0}/modal/mount.py +28 -38
  71. {modal-1.4.3 → modal-1.4.3.dev0}/modal/network_file_system.py +2 -2
  72. {modal-1.4.3 → modal-1.4.3.dev0}/modal/object.pyi +6 -6
  73. {modal-1.4.3 → modal-1.4.3.dev0}/modal/partial_function.pyi +16 -14
  74. {modal-1.4.3 → modal-1.4.3.dev0}/modal/proxy.py +1 -1
  75. {modal-1.4.3 → modal-1.4.3.dev0}/modal/queue.py +4 -4
  76. {modal-1.4.3 → modal-1.4.3.dev0}/modal/runner.py +2 -5
  77. {modal-1.4.3 → modal-1.4.3.dev0}/modal/runner.pyi +0 -3
  78. {modal-1.4.3 → modal-1.4.3.dev0}/modal/sandbox.py +158 -166
  79. {modal-1.4.3 → modal-1.4.3.dev0}/modal/sandbox.pyi +105 -79
  80. {modal-1.4.3 → modal-1.4.3.dev0}/modal/sandbox_fs.py +147 -307
  81. {modal-1.4.3 → modal-1.4.3.dev0}/modal/sandbox_fs.pyi +240 -454
  82. {modal-1.4.3 → modal-1.4.3.dev0}/modal/secret.py +2 -2
  83. {modal-1.4.3 → modal-1.4.3.dev0}/modal/serving.py +1 -4
  84. {modal-1.4.3 → modal-1.4.3.dev0}/modal/serving.pyi +0 -3
  85. {modal-1.4.3 → modal-1.4.3.dev0}/modal/volume.py +20 -149
  86. {modal-1.4.3 → modal-1.4.3.dev0}/modal/volume.pyi +18 -109
  87. {modal-1.4.3 → modal-1.4.3.dev0}/modal.egg-info/PKG-INFO +2 -1
  88. {modal-1.4.3 → modal-1.4.3.dev0}/modal.egg-info/SOURCES.txt +0 -3
  89. {modal-1.4.3 → modal-1.4.3.dev0}/modal.egg-info/requires.txt +1 -0
  90. {modal-1.4.3 → modal-1.4.3.dev0}/modal_docs/gen_cli_docs.py +1 -1
  91. {modal-1.4.3 → modal-1.4.3.dev0}/modal_proto/api_grpc.py +0 -16
  92. {modal-1.4.3 → modal-1.4.3.dev0}/modal_proto/api_pb2.py +777 -876
  93. {modal-1.4.3 → modal-1.4.3.dev0}/modal_proto/api_pb2.pyi +18 -272
  94. {modal-1.4.3 → modal-1.4.3.dev0}/modal_proto/api_pb2_grpc.py +0 -34
  95. {modal-1.4.3 → modal-1.4.3.dev0}/modal_proto/api_pb2_grpc.pyi +0 -12
  96. {modal-1.4.3 → modal-1.4.3.dev0}/modal_proto/modal_api_grpc.py +0 -1
  97. {modal-1.4.3 → modal-1.4.3.dev0}/modal_proto/task_command_router_grpc.py +0 -80
  98. modal-1.4.3.dev0/modal_proto/task_command_router_pb2.py +326 -0
  99. {modal-1.4.3 → modal-1.4.3.dev0}/modal_proto/task_command_router_pb2.pyi +1 -243
  100. {modal-1.4.3 → modal-1.4.3.dev0}/modal_proto/task_command_router_pb2_grpc.py +0 -170
  101. {modal-1.4.3 → modal-1.4.3.dev0}/modal_proto/task_command_router_pb2_grpc.pyi +0 -64
  102. {modal-1.4.3 → modal-1.4.3.dev0}/modal_version/__init__.py +1 -1
  103. {modal-1.4.3 → modal-1.4.3.dev0}/pyproject.toml +3 -6
  104. modal-1.4.3/modal/_environments.py +0 -470
  105. modal-1.4.3/modal/_function_variants.py +0 -249
  106. modal-1.4.3/modal/cli/_help.py +0 -295
  107. modal-1.4.3/modal/cli/entry_point.py +0 -132
  108. modal-1.4.3/modal/cli/environment.py +0 -180
  109. modal-1.4.3/modal/container_process.py +0 -224
  110. modal-1.4.3/modal/environments.py +0 -31
  111. modal-1.4.3/modal/environments.pyi +0 -343
  112. modal-1.4.3/modal_proto/task_command_router_pb2.py +0 -442
  113. {modal-1.4.3 → modal-1.4.3.dev0}/LICENSE +0 -0
  114. {modal-1.4.3 → modal-1.4.3.dev0}/README.md +0 -0
  115. {modal-1.4.3 → modal-1.4.3.dev0}/modal/__main__.py +0 -0
  116. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_billing.py +0 -0
  117. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_clustered_functions.py +0 -0
  118. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_clustered_functions.pyi +0 -0
  119. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_grpc_client.py +0 -0
  120. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_ipython.py +0 -0
  121. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_load_context.py +0 -0
  122. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_location.py +0 -0
  123. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_logs.py +0 -0
  124. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_output/__init__.py +0 -0
  125. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_output/manager.py +0 -0
  126. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_output/pty.py +0 -0
  127. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_runtime/__init__.py +0 -0
  128. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_runtime/asgi.py +0 -0
  129. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  130. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_runtime/telemetry.py +0 -0
  131. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_runtime/user_code_event_loop.py +0 -0
  132. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_server.py +0 -0
  133. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_traceback.py +0 -0
  134. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_tunnel.py +0 -0
  135. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_tunnel.pyi +0 -0
  136. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_type_manager.py +0 -0
  137. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/__init__.py +0 -0
  138. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/app_utils.py +0 -0
  139. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/auth_token_manager.py +0 -0
  140. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/browser_utils.py +0 -0
  141. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/bytes_io_segment_payload.py +0 -0
  142. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/git_utils.py +0 -0
  143. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/grpc_testing.py +0 -0
  144. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/hash_utils.py +0 -0
  145. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/http_utils.py +0 -0
  146. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/jwt_utils.py +0 -0
  147. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/logger.py +0 -0
  148. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/package_utils.py +0 -0
  149. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/pattern_utils.py +0 -0
  150. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/rand_pb_testing.py +0 -0
  151. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/shell_utils.py +0 -0
  152. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_utils/time_utils.py +0 -0
  153. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_vendor/__init__.py +0 -0
  154. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  155. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_vendor/cloudpickle.py +0 -0
  156. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_vendor/tblib.py +0 -0
  157. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_vendor/version.py +0 -0
  158. {modal-1.4.3 → modal-1.4.3.dev0}/modal/_watcher.py +0 -0
  159. {modal-1.4.3 → modal-1.4.3.dev0}/modal/billing.py +0 -0
  160. {modal-1.4.3 → modal-1.4.3.dev0}/modal/builder/2023.12.312.txt +0 -0
  161. {modal-1.4.3 → modal-1.4.3.dev0}/modal/builder/2023.12.txt +0 -0
  162. {modal-1.4.3 → modal-1.4.3.dev0}/modal/builder/2024.04.txt +0 -0
  163. {modal-1.4.3 → modal-1.4.3.dev0}/modal/builder/2024.10.txt +0 -0
  164. {modal-1.4.3 → modal-1.4.3.dev0}/modal/builder/2025.06.txt +0 -0
  165. {modal-1.4.3 → modal-1.4.3.dev0}/modal/builder/PREVIEW.txt +0 -0
  166. {modal-1.4.3 → modal-1.4.3.dev0}/modal/builder/README.md +0 -0
  167. {modal-1.4.3 → modal-1.4.3.dev0}/modal/builder/base-images.json +0 -0
  168. {modal-1.4.3 → modal-1.4.3.dev0}/modal/call_graph.py +0 -0
  169. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/__init__.py +0 -0
  170. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/_download.py +0 -0
  171. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/logo.py +0 -0
  172. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/programs/__init__.py +0 -0
  173. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/programs/run_jupyter.py +0 -0
  174. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/programs/vscode.py +0 -0
  175. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cli/selector.py +0 -0
  176. {modal-1.4.3 → modal-1.4.3.dev0}/modal/client.py +0 -0
  177. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cloud_bucket_mount.py +0 -0
  178. {modal-1.4.3 → modal-1.4.3.dev0}/modal/cloud_bucket_mount.pyi +0 -0
  179. {modal-1.4.3 → modal-1.4.3.dev0}/modal/dict.pyi +0 -0
  180. {modal-1.4.3 → modal-1.4.3.dev0}/modal/experimental/__init__.py +0 -0
  181. {modal-1.4.3 → modal-1.4.3.dev0}/modal/experimental/ipython.py +0 -0
  182. {modal-1.4.3 → modal-1.4.3.dev0}/modal/file_io.pyi +0 -0
  183. {modal-1.4.3 → modal-1.4.3.dev0}/modal/file_pattern_matcher.py +0 -0
  184. {modal-1.4.3 → modal-1.4.3.dev0}/modal/functions.py +0 -0
  185. {modal-1.4.3 → modal-1.4.3.dev0}/modal/mount.pyi +0 -0
  186. {modal-1.4.3 → modal-1.4.3.dev0}/modal/network_file_system.pyi +0 -0
  187. {modal-1.4.3 → modal-1.4.3.dev0}/modal/object.py +0 -0
  188. {modal-1.4.3 → modal-1.4.3.dev0}/modal/output.py +0 -0
  189. {modal-1.4.3 → modal-1.4.3.dev0}/modal/parallel_map.py +0 -0
  190. {modal-1.4.3 → modal-1.4.3.dev0}/modal/parallel_map.pyi +0 -0
  191. {modal-1.4.3 → modal-1.4.3.dev0}/modal/partial_function.py +0 -0
  192. {modal-1.4.3 → modal-1.4.3.dev0}/modal/proxy.pyi +0 -0
  193. {modal-1.4.3 → modal-1.4.3.dev0}/modal/py.typed +0 -0
  194. {modal-1.4.3 → modal-1.4.3.dev0}/modal/queue.pyi +0 -0
  195. {modal-1.4.3 → modal-1.4.3.dev0}/modal/retries.py +0 -0
  196. {modal-1.4.3 → modal-1.4.3.dev0}/modal/running_app.py +0 -0
  197. {modal-1.4.3 → modal-1.4.3.dev0}/modal/schedule.py +0 -0
  198. {modal-1.4.3 → modal-1.4.3.dev0}/modal/scheduler_placement.py +0 -0
  199. {modal-1.4.3 → modal-1.4.3.dev0}/modal/secret.pyi +0 -0
  200. {modal-1.4.3 → modal-1.4.3.dev0}/modal/server.py +0 -0
  201. {modal-1.4.3 → modal-1.4.3.dev0}/modal/server.pyi +0 -0
  202. {modal-1.4.3 → modal-1.4.3.dev0}/modal/snapshot.py +0 -0
  203. {modal-1.4.3 → modal-1.4.3.dev0}/modal/snapshot.pyi +0 -0
  204. {modal-1.4.3 → modal-1.4.3.dev0}/modal/stream_type.py +0 -0
  205. {modal-1.4.3 → modal-1.4.3.dev0}/modal/token_flow.py +0 -0
  206. {modal-1.4.3 → modal-1.4.3.dev0}/modal/token_flow.pyi +0 -0
  207. {modal-1.4.3 → modal-1.4.3.dev0}/modal.egg-info/dependency_links.txt +0 -0
  208. {modal-1.4.3 → modal-1.4.3.dev0}/modal.egg-info/entry_points.txt +0 -0
  209. {modal-1.4.3 → modal-1.4.3.dev0}/modal.egg-info/top_level.txt +0 -0
  210. {modal-1.4.3 → modal-1.4.3.dev0}/modal_docs/__init__.py +0 -0
  211. {modal-1.4.3 → modal-1.4.3.dev0}/modal_docs/gen_cli_docs_main.py +0 -0
  212. {modal-1.4.3 → modal-1.4.3.dev0}/modal_docs/gen_reference_docs.py +0 -0
  213. {modal-1.4.3 → modal-1.4.3.dev0}/modal_docs/gen_reference_docs_main.py +0 -0
  214. {modal-1.4.3 → modal-1.4.3.dev0}/modal_docs/mdmd/__init__.py +0 -0
  215. {modal-1.4.3 → modal-1.4.3.dev0}/modal_docs/mdmd/mdmd.py +0 -0
  216. {modal-1.4.3 → modal-1.4.3.dev0}/modal_docs/mdmd/signatures.py +0 -0
  217. {modal-1.4.3 → modal-1.4.3.dev0}/modal_proto/__init__.py +0 -0
  218. {modal-1.4.3 → modal-1.4.3.dev0}/modal_proto/py.typed +0 -0
  219. {modal-1.4.3 → modal-1.4.3.dev0}/modal_version/__main__.py +0 -0
  220. {modal-1.4.3 → modal-1.4.3.dev0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.4.3
3
+ Version: 1.4.3.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
@@ -25,6 +25,7 @@ Requires-Dist: protobuf!=4.24.0,<7.0,>=3.19
25
25
  Requires-Dist: rich>=12.0.0
26
26
  Requires-Dist: synchronicity~=0.12.1
27
27
  Requires-Dist: toml
28
+ Requires-Dist: typer>=0.9
28
29
  Requires-Dist: types-certifi
29
30
  Requires-Dist: types-toml
30
31
  Requires-Dist: watchfiles
@@ -17,7 +17,6 @@ try:
17
17
  from .cloud_bucket_mount import CloudBucketMount
18
18
  from .cls import Cls, parameter
19
19
  from .dict import Dict
20
- from .environments import Environment
21
20
  from .exception import Error
22
21
  from .file_pattern_matcher import FilePatternMatcher
23
22
  from .functions import Function, FunctionCall
@@ -62,7 +61,6 @@ __all__ = [
62
61
  "Cls",
63
62
  "Cron",
64
63
  "Dict",
65
- "Environment",
66
64
  "Error",
67
65
  "FilePatternMatcher",
68
66
  "Function",
@@ -94,23 +94,6 @@ class DaemonizedThreadPool:
94
94
  self.inputs.put((func, args))
95
95
 
96
96
 
97
- def call_server(user_code_event_loop: UserCodeEventLoop):
98
- async def run():
99
- exit_event = asyncio.Event()
100
-
101
- def _on_sigterm():
102
- logger.info("server_received_sigterm")
103
- exit_event.set()
104
-
105
- user_code_event_loop.loop.add_signal_handler(signal.SIGTERM, _on_sigterm)
106
- try:
107
- await exit_event.wait()
108
- finally:
109
- user_code_event_loop.loop.remove_signal_handler(signal.SIGTERM)
110
-
111
- user_code_event_loop.run(run())
112
-
113
-
114
97
  def call_function(
115
98
  user_code_event_loop: UserCodeEventLoop,
116
99
  container_io_manager: "modal._runtime.container_io_manager.ContainerIOManager",
@@ -402,10 +385,7 @@ def main(container_args: api_pb2.ContainerArguments, client: Client):
402
385
  )
403
386
 
404
387
  with service.execution_context(event_loop, container_io_manager) as finalized_functions:
405
- if function_def.is_server:
406
- call_server(event_loop)
407
- else:
408
- call_function(event_loop, container_io_manager, finalized_functions, batch_max_size, batch_wait_ms)
388
+ call_function(event_loop, container_io_manager, finalized_functions, batch_max_size, batch_wait_ms)
409
389
 
410
390
 
411
391
  if __name__ == "__main__":
@@ -5,7 +5,7 @@ import inspect
5
5
  import time
6
6
  import typing
7
7
  import warnings
8
- from collections.abc import AsyncGenerator, Collection, Sequence
8
+ from collections.abc import AsyncGenerator, Collection, Sequence, Sized
9
9
  from dataclasses import dataclass
10
10
  from pathlib import PurePosixPath
11
11
  from typing import TYPE_CHECKING, Any, AsyncIterator, Callable, Optional, Union
@@ -18,7 +18,6 @@ from synchronicity.combined_types import MethodWithAio
18
18
  from modal_proto import api_pb2
19
19
  from modal_proto.modal_api_grpc import ModalClientModal
20
20
 
21
- from ._function_variants import _FunctionOptions, _make_function_variant
22
21
  from ._load_context import LoadContext
23
22
  from ._object import _Object, live_method, live_method_gen
24
23
  from ._output.pty import get_pty_info
@@ -27,8 +26,11 @@ from ._resolver import Resolver
27
26
  from ._resources import convert_fn_config_to_resources_config
28
27
  from ._runtime.execution_context import current_input_id, is_local
29
28
  from ._serialization import (
29
+ apply_defaults,
30
30
  get_callable_schema,
31
31
  serialize,
32
+ serialize_proto_params,
33
+ validate_parameter_values,
32
34
  )
33
35
  from ._traceback import print_server_warnings
34
36
  from ._utils.async_utils import (
@@ -46,7 +48,6 @@ from ._utils.function_utils import (
46
48
  OUTPUTS_TIMEOUT,
47
49
  FunctionInfo,
48
50
  _create_input,
49
- _parse_retries,
50
51
  _process_result,
51
52
  _stream_function_call_data,
52
53
  get_function_type,
@@ -89,7 +90,7 @@ from .proxy import _Proxy
89
90
  from .retries import Retries, RetryManager
90
91
  from .schedule import Schedule
91
92
  from .secret import _Secret
92
- from .volume import _Volume, _volume_to_mount_proto
93
+ from .volume import _Volume
93
94
 
94
95
  if TYPE_CHECKING:
95
96
  import modal.app
@@ -548,7 +549,26 @@ class FunctionStats:
548
549
  backlog: int
549
550
  num_total_runners: int
550
551
  num_running_inputs: int
551
- input_headroom: int
552
+
553
+
554
+ def _parse_retries(
555
+ retries: Optional[Union[int, Retries]],
556
+ source: str = "",
557
+ ) -> Optional[api_pb2.FunctionRetryPolicy]:
558
+ if isinstance(retries, int):
559
+ return Retries(
560
+ max_retries=retries,
561
+ initial_delay=1.0,
562
+ backoff_coefficient=1.0,
563
+ )._to_proto()
564
+ elif isinstance(retries, Retries):
565
+ return retries._to_proto()
566
+ elif retries is None:
567
+ return None
568
+ else:
569
+ extra = f" on {source}" if source else ""
570
+ msg = f"Retries parameter must be an integer or instance of modal.Retries. Found: {type(retries)}{extra}."
571
+ raise InvalidError(msg)
552
572
 
553
573
 
554
574
  @dataclass
@@ -634,8 +654,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
634
654
  None # set for 0.67+ class service functions
635
655
  )
636
656
  _metadata: Optional[api_pb2.FunctionHandleMetadata] = None
637
- _options: _FunctionOptions
638
- _base_function: Optional["_Function"] = None
639
657
 
640
658
  @staticmethod
641
659
  def from_local(
@@ -667,7 +685,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
667
685
  batch_wait_ms: Optional[int] = None,
668
686
  cloud: Optional[str] = None,
669
687
  region: Optional[Union[str, Sequence[str]]] = None,
670
- routing_region: Optional[str] = None,
671
688
  nonpreemptible: bool = False,
672
689
  is_builder_function: bool = False,
673
690
  is_auto_snapshot: bool = False,
@@ -720,9 +737,9 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
720
737
 
721
738
  if retry_policy is not None:
722
739
  if webhook_config is not None:
723
- raise InvalidError("Web Functions do not support retries.")
740
+ raise InvalidError("Web endpoints do not support retries.")
724
741
  if is_generator:
725
- raise InvalidError("Generator Functions do not support retries.")
742
+ raise InvalidError("Generator functions do not support retries.")
726
743
 
727
744
  if timeout is None: # type: ignore[unreachable] # Help users who aren't using type checkers
728
745
  raise InvalidError("The `timeout` parameter cannot be set to None: https://modal.com/docs/guide/timeouts")
@@ -947,7 +964,13 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
947
964
 
948
965
  # Relies on dicts being ordered (true as of Python 3.6).
949
966
  volume_mounts = [
950
- _volume_to_mount_proto(path, volume) for path, volume in validated_volumes_no_cloud_buckets
967
+ api_pb2.VolumeMount(
968
+ mount_path=path,
969
+ volume_id=volume.object_id,
970
+ allow_background_commits=True,
971
+ read_only=volume._read_only,
972
+ )
973
+ for path, volume in validated_volumes_no_cloud_buckets
951
974
  ]
952
975
  loaded_mount_ids = {m.object_id for m in all_mounts} | {m.object_id for m in image._mount_layers}
953
976
 
@@ -1028,7 +1051,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1028
1051
  supported_output_formats=supported_output_formats,
1029
1052
  http_config=http_config,
1030
1053
  is_server=is_server,
1031
- routing_region=routing_region or "",
1032
1054
  )
1033
1055
 
1034
1056
  if isinstance(gpu, list):
@@ -1068,7 +1090,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1068
1090
  supported_output_formats=supported_output_formats,
1069
1091
  http_config=http_config,
1070
1092
  is_server=function_definition.is_server,
1071
- routing_region=function_definition.routing_region,
1072
1093
  )
1073
1094
 
1074
1095
  ranked_functions = []
@@ -1150,6 +1171,130 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1150
1171
 
1151
1172
  return obj
1152
1173
 
1174
+ def _bind_parameters(
1175
+ self,
1176
+ obj: "modal.cls._Obj",
1177
+ options: Optional["modal.cls._ServiceOptions"],
1178
+ args: Sized,
1179
+ kwargs: dict[str, Any],
1180
+ ) -> "_Function":
1181
+ """mdmd:hidden
1182
+
1183
+ Binds a class-function to a specific instance of (init params, options) or a new workspace
1184
+ """
1185
+
1186
+ parent = self
1187
+
1188
+ async def _load(
1189
+ param_bound_func: _Function,
1190
+ resolver: Resolver,
1191
+ load_context: LoadContext,
1192
+ existing_object_id: Optional[str],
1193
+ ):
1194
+ if not parent.is_hydrated:
1195
+ # While the base Object.hydrate() method appears to be idempotent, it's not always safe
1196
+ await parent.hydrate()
1197
+
1198
+ assert parent._client and parent._client.stub
1199
+
1200
+ if (
1201
+ parent._class_parameter_info
1202
+ and parent._class_parameter_info.format == api_pb2.ClassParameterInfo.PARAM_SERIALIZATION_FORMAT_PROTO
1203
+ ):
1204
+ if args:
1205
+ # TODO(elias) - We could potentially support positional args as well, if we want to?
1206
+ raise InvalidError(
1207
+ "Can't use positional arguments with modal.parameter-based synthetic constructors.\n"
1208
+ "Use (<parameter_name>=value) keyword arguments when constructing classes instead."
1209
+ )
1210
+ schema = parent._class_parameter_info.schema
1211
+ kwargs_with_defaults = apply_defaults(kwargs, schema)
1212
+ validate_parameter_values(kwargs_with_defaults, schema)
1213
+ serialized_params = serialize_proto_params(kwargs_with_defaults)
1214
+ can_use_parent = len(parent._class_parameter_info.schema) == 0 # no parameters
1215
+ else:
1216
+ from modal.cls import _ServiceOptions # Should probably define this dataclass here?
1217
+
1218
+ can_use_parent = len(args) + len(kwargs) == 0 and (options == _ServiceOptions())
1219
+ serialized_params = serialize((args, kwargs))
1220
+
1221
+ if can_use_parent:
1222
+ # We can end up here if parent wasn't hydrated when class was instantiated, but has been since.
1223
+ param_bound_func._hydrate_from_other(parent)
1224
+ return
1225
+
1226
+ assert parent is not None and parent.is_hydrated
1227
+
1228
+ if options:
1229
+ # Validate that the same volume (by object_id) isn't mounted at multiple paths
1230
+ validate_volumes_by_object_id(options.validated_volumes)
1231
+
1232
+ volume_mounts = [
1233
+ api_pb2.VolumeMount(
1234
+ mount_path=path,
1235
+ volume_id=volume.object_id,
1236
+ allow_background_commits=True,
1237
+ read_only=volume._read_only,
1238
+ )
1239
+ for path, volume in options.validated_volumes
1240
+ ]
1241
+ options_pb = api_pb2.FunctionOptions(
1242
+ secret_ids=[s.object_id for s in options.secrets],
1243
+ replace_secret_ids=bool(options.secrets),
1244
+ replace_volume_mounts=len(volume_mounts) > 0,
1245
+ volume_mounts=volume_mounts,
1246
+ cloud_bucket_mounts=cloud_bucket_mounts_to_proto(options.cloud_bucket_mounts),
1247
+ replace_cloud_bucket_mounts=bool(options.cloud_bucket_mounts),
1248
+ resources=options.resources,
1249
+ retry_policy=options.retry_policy,
1250
+ concurrency_limit=options.max_containers,
1251
+ buffer_containers=options.buffer_containers,
1252
+ task_idle_timeout_secs=options.scaledown_window,
1253
+ timeout_secs=options.timeout_secs,
1254
+ max_concurrent_inputs=options.max_concurrent_inputs,
1255
+ target_concurrent_inputs=options.target_concurrent_inputs,
1256
+ batch_max_size=options.batch_max_size,
1257
+ batch_linger_ms=options.batch_wait_ms,
1258
+ scheduler_placement=options.scheduler_placement,
1259
+ cloud_provider_str=options.cloud,
1260
+ )
1261
+ else:
1262
+ options_pb = None
1263
+
1264
+ req = api_pb2.FunctionBindParamsRequest(
1265
+ function_id=parent.object_id,
1266
+ serialized_params=serialized_params,
1267
+ function_options=options_pb,
1268
+ environment_name=load_context.environment_name
1269
+ or "", # TODO: investigate shouldn't environment name always be specified here?
1270
+ )
1271
+
1272
+ response = await parent._client.stub.FunctionBindParams(req)
1273
+ param_bound_func._hydrate(response.bound_function_id, parent._client, response.handle_metadata)
1274
+
1275
+ def _deps():
1276
+ if options:
1277
+ all_deps = (
1278
+ [v for _, v in options.validated_volumes]
1279
+ + list(options.secrets)
1280
+ + [mount.secret for _, mount in options.cloud_bucket_mounts if mount.secret]
1281
+ )
1282
+ return [dep for dep in all_deps if not dep.is_hydrated]
1283
+ return []
1284
+
1285
+ fun: _Function = _Function._from_loader(
1286
+ _load,
1287
+ "Function(parametrized)",
1288
+ hydrate_lazily=True,
1289
+ deps=_deps,
1290
+ load_context_overrides=self._load_context_overrides,
1291
+ )
1292
+
1293
+ fun._info = self._info
1294
+ fun._obj = obj
1295
+ fun._spec = self._spec # TODO (elias): fix - this is incorrect when using with_options
1296
+ return fun
1297
+
1153
1298
  @live_method
1154
1299
  async def update_autoscaler(
1155
1300
  self,
@@ -1239,7 +1384,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1239
1384
  )
1240
1385
  rep = f"modal.Function.from_name('{app_name}', '{name}'{environment_rep})"
1241
1386
  return cls._from_loader(
1242
- _load_remote, rep, skip_reload=True, hydrate_lazily=True, load_context_overrides=load_context_overrides
1387
+ _load_remote, rep, is_another_app=True, hydrate_lazily=True, load_context_overrides=load_context_overrides
1243
1388
  )
1244
1389
 
1245
1390
  @classmethod
@@ -1326,8 +1471,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1326
1471
  self._serve_mounts = frozenset()
1327
1472
  self._metadata = None
1328
1473
  self._experimental_flash_urls = None
1329
- self._options = _FunctionOptions()
1330
- self._base_function = None
1331
1474
 
1332
1475
  def _hydrate_metadata(self, metadata: Optional[Message]):
1333
1476
  # Overridden concrete implementation of base class method
@@ -1388,10 +1531,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1388
1531
 
1389
1532
  @live_method
1390
1533
  async def get_web_url(self) -> Optional[str]:
1391
- """URL for addressing a Web Function via HTTP.
1392
-
1393
- Returns None when this is not a Web Function.
1394
- """
1534
+ """URL of a Function running as a web endpoint."""
1395
1535
  return self._web_url
1396
1536
 
1397
1537
  @live_method
@@ -1399,143 +1539,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1399
1539
  """URL of the flash service for the function."""
1400
1540
  return list(self._experimental_flash_urls) if self._experimental_flash_urls else None
1401
1541
 
1402
- def _apply_dynamic_config(
1403
- self,
1404
- new_options: _FunctionOptions,
1405
- config_method_name: str,
1406
- ) -> "_Function[P, ReturnType, OriginalReturnType]":
1407
- base_function = self._base_function or self
1408
- combined_options = self._options.merge_options(new_options)
1409
-
1410
- # For "True Functions" (i.e. not the Function inside a Cls), we will use
1411
- # `parameter_schema=[]` when the Function is un-parameterized. Note that
1412
- # `parameter_schema=Null` has different semantics that preserve Cls backwards compatibility.
1413
- parameter_schema: Sequence[api_pb2.ClassParameterSpec] = []
1414
- args = ()
1415
- kwargs: dict[str, Any] = {}
1416
-
1417
- # The main reason to have two layers here (_apply_dynamic_config -> _make_function_variant)
1418
- # is because the _make_function_variant logic is shared between a true Function and a
1419
- # "class service function", but we need to propagate different instance metadata to the
1420
- # new object in each case. There's likely a cleaner way to do this, and then we could just
1421
- # collapse the dynamic configuration into a single layer.
1422
- new_function = _make_function_variant(base_function, combined_options, parameter_schema, args, kwargs)
1423
-
1424
- new_function._options = combined_options
1425
- new_function._base_function = base_function
1426
- new_function._rep = f"{self._rep}.{config_method_name}(...)"
1427
-
1428
- new_function._app = self._app
1429
- new_function._obj = self._obj
1430
-
1431
- new_function._is_generator = self._is_generator
1432
- new_function._webhook_config = self._webhook_config
1433
-
1434
- # Other fields not necessarily initialized
1435
- if self._info is not None:
1436
- new_function._build_args = self._build_args
1437
- new_function._is_method = self._is_method
1438
- new_function._raw_f = self._raw_f
1439
- new_function._tag = self._tag
1440
-
1441
- return new_function
1442
-
1443
- def with_options(
1444
- self,
1445
- *,
1446
- cpu: Optional[Union[float, tuple[float, float]]] = None,
1447
- memory: Optional[Union[int, tuple[int, int]]] = None,
1448
- gpu: Optional[str] = None,
1449
- env: Optional[dict[str, Optional[str]]] = None,
1450
- secrets: Optional[Collection[_Secret]] = None,
1451
- volumes: dict[Union[str, PurePosixPath], Union[_Volume, _CloudBucketMount]] = {},
1452
- retries: Optional[Union[int, Retries]] = None,
1453
- max_containers: Optional[int] = None,
1454
- buffer_containers: Optional[int] = None,
1455
- scaledown_window: Optional[int] = None,
1456
- timeout: Optional[int] = None,
1457
- region: Optional[Union[str, Sequence[str]]] = None,
1458
- cloud: Optional[str] = None,
1459
- ) -> "_Function[P, ReturnType, OriginalReturnType]":
1460
- """Dynamically override the static Function configuration with invocation-specific values.
1461
-
1462
- This method returns a new Function instance with the dynamic configuration. Invocations of
1463
- the new Function will run in a distinct container pool and autoscale independently from the
1464
- base Function (and from other dynamic configurations).
1465
-
1466
- Note that options cannot be "unset" with this method (i.e., if a GPU is configured in the
1467
- `@app.cls()` decorator, passing `gpu=None` here will not create a CPU-only instance).
1468
- Additionally, container arguments like `volumes` and `secrets` will _replace_ the base
1469
- configuration or any previous use of this method rather than extending it.
1470
-
1471
- **Usage:**
1472
-
1473
- You can use this method after looking up a deployed Function:
1474
-
1475
- ```python notest
1476
- fn = modal.Function.from_name("my_app", "fn").with_options(gpu="H100")
1477
- fn.remote() # will run on a H100 GPU
1478
- ```
1479
-
1480
- Or by referencing another Function defined in the same App:
1481
-
1482
- ```python notest
1483
- @app.function()
1484
- def fn():
1485
- ...
1486
-
1487
- # From a local entrypoint or another Function
1488
- fn.with_options(gpu="H100").remote() # Uses an H100 GPU
1489
- fn.remote() # Uses the static configuration with no GPU
1490
- ```
1491
-
1492
- """
1493
- options = _FunctionOptions.new(
1494
- cpu=cpu,
1495
- memory=memory,
1496
- gpu=gpu,
1497
- env=env,
1498
- secrets=secrets,
1499
- volumes=volumes,
1500
- retries=retries,
1501
- max_containers=max_containers,
1502
- buffer_containers=buffer_containers,
1503
- scaledown_window=scaledown_window,
1504
- timeout=timeout,
1505
- region=region,
1506
- cloud=cloud,
1507
- )
1508
-
1509
- return self._apply_dynamic_config(options, "with_options")
1510
-
1511
- def with_concurrency(
1512
- self,
1513
- *,
1514
- max_inputs: int,
1515
- target_inputs: Optional[int] = None,
1516
- ) -> "_Function[P, ReturnType, OriginalReturnType]":
1517
- """Override the static Function configuration with invocation-specific input concurrency.
1518
-
1519
- Returns a new Function instance that is dynamically configured to behave like a Function using
1520
- the `@modal.concurrent` decorator. This instance will autoscale independently from the base Function.
1521
- """
1522
- options = _FunctionOptions.new(max_concurrent_inputs=max_inputs, target_concurrent_inputs=target_inputs)
1523
- return self._apply_dynamic_config(options, "with_concurrency")
1524
-
1525
- def with_batching(
1526
- self,
1527
- *,
1528
- max_batch_size: int,
1529
- wait_ms: int,
1530
- ) -> "_Function[P, ReturnType, OriginalReturnType]":
1531
- """Override the static Function configuration with invocation-specific dynamic batching.
1532
-
1533
- Returns a new Function instance that is dynamically configured to behave like a Function using
1534
- the `@modal.batched` decorator. This instance will autoscale independently from the base Function.
1535
- """
1536
- options = _FunctionOptions.new(batch_max_size=max_batch_size, batch_wait_ms=wait_ms)
1537
- return self._apply_dynamic_config(options, "with_batching")
1538
-
1539
1542
  @property
1540
1543
  async def is_generator(self) -> bool:
1541
1544
  """mdmd:hidden"""
@@ -1848,10 +1851,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1848
1851
  retry=Retry(total_timeout=10.0),
1849
1852
  )
1850
1853
  return FunctionStats(
1851
- backlog=resp.backlog,
1852
- num_total_runners=resp.num_total_tasks,
1853
- num_running_inputs=resp.num_running_inputs,
1854
- input_headroom=resp.input_headroom,
1854
+ backlog=resp.backlog, num_total_runners=resp.num_total_tasks, num_running_inputs=resp.num_running_inputs
1855
1855
  )
1856
1856
 
1857
1857
  @live_method
@@ -82,7 +82,7 @@ class _Object:
82
82
  _load: Optional[Callable[[Self, Resolver, LoadContext, Optional[str]], Awaitable[None]]] = None
83
83
  _preload: Optional[Callable[[Self, Resolver, LoadContext, Optional[str]], Awaitable[None]]]
84
84
  _rep: str
85
- _skip_reload: bool
85
+ _is_another_app: bool
86
86
  _hydrate_lazily: bool
87
87
  _deps: Optional[Callable[..., Sequence["_Object"]]]
88
88
  _deduplication_key: Optional[Callable[[], Awaitable[Hashable]]] = None
@@ -113,9 +113,9 @@ class _Object:
113
113
  self,
114
114
  rep: str,
115
115
  load: Optional[Callable[[Self, Resolver, LoadContext, Optional[str]], Awaitable[None]]] = None,
116
+ is_another_app: bool = False,
116
117
  preload: Optional[Callable[[Self, Resolver, LoadContext, Optional[str]], Awaitable[None]]] = None,
117
118
  hydrate_lazily: bool = False,
118
- skip_reload: bool = False,
119
119
  deps: Optional[Callable[..., Sequence["_Object"]]] = None,
120
120
  deduplication_key: Optional[Callable[[], Awaitable[Hashable]]] = None,
121
121
  name: Optional[str] = None,
@@ -123,10 +123,10 @@ class _Object:
123
123
  load_context_overrides: Optional[LoadContext] = None,
124
124
  ):
125
125
  self._local_uuid = str(uuid.uuid4())
126
- self._rep = rep
127
126
  self._load = load
128
127
  self._preload = preload
129
- self._skip_reload = skip_reload
128
+ self._rep = rep
129
+ self._is_another_app = is_another_app
130
130
  self._hydrate_lazily = hydrate_lazily
131
131
  self._deps = deps
132
132
  self._deduplication_key = deduplication_key
@@ -218,7 +218,7 @@ class _Object:
218
218
  cls,
219
219
  load: Callable[[Self, Resolver, LoadContext, Optional[str]], Awaitable[None]],
220
220
  rep: str,
221
- skip_reload: bool = False,
221
+ is_another_app: bool = False,
222
222
  preload: Optional[Callable[[Self, Resolver, LoadContext, Optional[str]], Awaitable[None]]] = None,
223
223
  hydrate_lazily: bool = False,
224
224
  deps: Optional[Callable[..., Sequence["_Object"]]] = None,
@@ -232,12 +232,12 @@ class _Object:
232
232
  obj._init(
233
233
  rep,
234
234
  load,
235
- skip_reload=skip_reload,
236
- preload=preload,
237
- hydrate_lazily=hydrate_lazily,
238
- deps=deps,
239
- deduplication_key=deduplication_key,
240
- name=name,
235
+ is_another_app,
236
+ preload,
237
+ hydrate_lazily,
238
+ deps,
239
+ deduplication_key,
240
+ name,
241
241
  load_context_overrides=load_context_overrides,
242
242
  )
243
243
  return obj
@@ -268,7 +268,7 @@ class _Object:
268
268
  object_id: str,
269
269
  client: _Client,
270
270
  handle_metadata: Optional[Message],
271
- skip_reload: bool = False,
271
+ is_another_app: bool = False,
272
272
  rep: Optional[str] = None,
273
273
  ) -> Self:
274
274
  obj_cls: type[Self]
@@ -287,7 +287,7 @@ class _Object:
287
287
  # Instantiate provider
288
288
  obj = _Object.__new__(obj_cls)
289
289
  rep = rep or f"modal.{obj_cls.__name__.strip('_')}.from_id({object_id!r})"
290
- obj._init(rep, skip_reload=skip_reload)
290
+ obj._init(rep, is_another_app=is_another_app)
291
291
  obj._hydrate(object_id, client, handle_metadata)
292
292
 
293
293
  return obj
@@ -49,7 +49,7 @@ from modal._output.manager import (
49
49
  )
50
50
  from modal._utils.time_utils import timestamp_to_localized_str
51
51
  from modal.config import logger
52
- from modal.exception import DeprecationError, ServerWarning
52
+ from modal.exception import DeprecationError, PendingDeprecationError, ServerWarning
53
53
  from modal_proto import api_pb2
54
54
 
55
55
  if platform.system() == "Windows":
@@ -359,14 +359,14 @@ class RichOutputManager(OutputManager):
359
359
  ) -> None:
360
360
  """Display a warning, using rich formatting for Modal-specific warnings.
361
361
 
362
- Modal warnings (DeprecationError, ServerWarning) are shown
362
+ Modal warnings (DeprecationError, PendingDeprecationError, ServerWarning) are shown
363
363
  in a yellow-bordered panel with source context. Other warnings fall back to the
364
364
  default Python warning display.
365
365
  """
366
366
  # For non-Modal warnings, fall back to the default display
367
367
  import modal
368
368
 
369
- is_modal_warning = issubclass(category, (DeprecationError, ServerWarning))
369
+ is_modal_warning = issubclass(category, (DeprecationError, PendingDeprecationError, ServerWarning))
370
370
  filename_in_modal = modal.__path__ and Path(filename).is_relative_to(modal.__path__[0])
371
371
  if not is_modal_warning and not filename_in_modal:
372
372
  base_showwarning(warning, category, filename, lineno, file=None, line=None)
@@ -392,7 +392,7 @@ class RichOutputManager(OutputManager):
392
392
  pass
393
393
 
394
394
  # Build title
395
- if issubclass(category, DeprecationError):
395
+ if issubclass(category, (DeprecationError, PendingDeprecationError)):
396
396
  title = "Modal Deprecation Warning"
397
397
  else:
398
398
  title = "Modal Warning"
@@ -90,7 +90,7 @@ class FunctionCreationStatus:
90
90
  suffix = _get_suffix_from_web_url_info(url_info)
91
91
  class_web_endpoint_method_status_row = self._output_mgr.add_status_row()
92
92
  class_web_endpoint_method_status_row.finish(
93
- f"Created Web Function URL for {method_definition.function_name} => [magenta underline]"
93
+ f"Created web endpoint for {method_definition.function_name} => [magenta underline]"
94
94
  f"{method_definition.web_url}[/magenta underline]{suffix}"
95
95
  )
96
96
  for custom_domain in method_definition.custom_domain_info: