modAL 1.3.2.dev0__tar.gz → 1.3.3__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 (207) hide show
  1. {modal-1.3.2.dev0 → modal-1.3.3}/PKG-INFO +1 -1
  2. {modal-1.3.2.dev0 → modal-1.3.3}/modal/__init__.py +2 -2
  3. modal-1.3.3/modal/__main__.py +49 -0
  4. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_billing.py +8 -2
  5. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_functions.py +5 -8
  6. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_object.py +40 -35
  7. modal-1.3.3/modal/_output/__init__.py +1 -0
  8. modal-1.3.3/modal/_output/manager.py +542 -0
  9. modal-1.3.3/modal/_output/pty.py +200 -0
  10. modal-1.3.2.dev0/modal/_output.py → modal-1.3.3/modal/_output/rich.py +326 -265
  11. modal-1.3.3/modal/_output/status.py +101 -0
  12. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_resolver.py +1 -62
  13. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_runtime/asgi.py +2 -2
  14. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_server.py +3 -0
  15. modal-1.3.3/modal/_utils/browser_utils.py +29 -0
  16. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/function_utils.py +0 -87
  17. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/shell_utils.py +48 -2
  18. modal-1.3.3/modal/_utils/time_utils.py +204 -0
  19. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_watcher.py +2 -3
  20. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/_download.py +2 -0
  21. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/_traceback.py +3 -36
  22. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/app.py +31 -0
  23. modal-1.3.3/modal/cli/billing.py +153 -0
  24. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/cluster.py +4 -5
  25. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/config.py +2 -3
  26. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/container.py +17 -3
  27. modal-1.3.3/modal/cli/dashboard.py +27 -0
  28. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/dict.py +2 -3
  29. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/entry_point.py +17 -10
  30. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/import_refs.py +15 -10
  31. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/launch.py +12 -15
  32. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/network_file_system.py +21 -29
  33. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/profile.py +6 -6
  34. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/queues.py +4 -5
  35. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/run.py +46 -45
  36. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/secret.py +7 -6
  37. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/token.py +11 -12
  38. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/utils.py +30 -9
  39. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/volume.py +44 -21
  40. {modal-1.3.2.dev0 → modal-1.3.3}/modal/client.pyi +2 -10
  41. {modal-1.3.2.dev0 → modal-1.3.3}/modal/config.py +1 -1
  42. {modal-1.3.2.dev0 → modal-1.3.3}/modal/container_process.py +6 -8
  43. {modal-1.3.2.dev0 → modal-1.3.3}/modal/dict.py +42 -0
  44. {modal-1.3.2.dev0 → modal-1.3.3}/modal/dict.pyi +52 -0
  45. {modal-1.3.2.dev0 → modal-1.3.3}/modal/experimental/flash.py +10 -1
  46. {modal-1.3.2.dev0 → modal-1.3.3}/modal/experimental/flash.pyi +3 -0
  47. {modal-1.3.2.dev0 → modal-1.3.3}/modal/functions.pyi +6 -6
  48. {modal-1.3.2.dev0 → modal-1.3.3}/modal/image.py +6 -8
  49. {modal-1.3.2.dev0 → modal-1.3.3}/modal/mount.py +4 -1
  50. {modal-1.3.2.dev0 → modal-1.3.3}/modal/object.pyi +11 -0
  51. modal-1.3.3/modal/output.py +47 -0
  52. {modal-1.3.2.dev0 → modal-1.3.3}/modal/queue.py +42 -0
  53. {modal-1.3.2.dev0 → modal-1.3.3}/modal/queue.pyi +52 -0
  54. {modal-1.3.2.dev0 → modal-1.3.3}/modal/retries.py +0 -3
  55. {modal-1.3.2.dev0 → modal-1.3.3}/modal/runner.py +50 -61
  56. {modal-1.3.2.dev0 → modal-1.3.3}/modal/sandbox.py +1 -1
  57. {modal-1.3.2.dev0 → modal-1.3.3}/modal/serving.py +10 -13
  58. {modal-1.3.2.dev0 → modal-1.3.3}/modal/token_flow.py +20 -36
  59. {modal-1.3.2.dev0 → modal-1.3.3}/modal/token_flow.pyi +0 -3
  60. {modal-1.3.2.dev0 → modal-1.3.3}/modal/volume.py +38 -5
  61. {modal-1.3.2.dev0 → modal-1.3.3}/modal/volume.pyi +7 -0
  62. {modal-1.3.2.dev0 → modal-1.3.3}/modal.egg-info/PKG-INFO +1 -1
  63. {modal-1.3.2.dev0 → modal-1.3.3}/modal.egg-info/SOURCES.txt +8 -2
  64. {modal-1.3.2.dev0 → modal-1.3.3}/modal_docs/gen_reference_docs.py +1 -1
  65. {modal-1.3.2.dev0 → modal-1.3.3}/modal_proto/api.proto +30 -0
  66. {modal-1.3.2.dev0 → modal-1.3.3}/modal_proto/api_grpc.py +48 -0
  67. {modal-1.3.2.dev0 → modal-1.3.3}/modal_proto/api_pb2.py +815 -755
  68. {modal-1.3.2.dev0 → modal-1.3.3}/modal_proto/api_pb2.pyi +94 -0
  69. {modal-1.3.2.dev0 → modal-1.3.3}/modal_proto/api_pb2_grpc.py +99 -0
  70. {modal-1.3.2.dev0 → modal-1.3.3}/modal_proto/api_pb2_grpc.pyi +30 -0
  71. {modal-1.3.2.dev0 → modal-1.3.3}/modal_proto/modal_api_grpc.py +3 -0
  72. {modal-1.3.2.dev0 → modal-1.3.3}/modal_version/__init__.py +1 -1
  73. modal-1.3.2.dev0/modal/__main__.py +0 -53
  74. modal-1.3.2.dev0/modal/_pty.py +0 -57
  75. modal-1.3.2.dev0/modal/_utils/time_utils.py +0 -43
  76. modal-1.3.2.dev0/modal/output.py +0 -64
  77. {modal-1.3.2.dev0 → modal-1.3.3}/LICENSE +0 -0
  78. {modal-1.3.2.dev0 → modal-1.3.3}/README.md +0 -0
  79. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_clustered_functions.py +0 -0
  80. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_clustered_functions.pyi +0 -0
  81. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_container_entrypoint.py +0 -0
  82. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_grpc_client.py +0 -0
  83. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_ipython.py +0 -0
  84. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_load_context.py +0 -0
  85. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_location.py +0 -0
  86. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_partial_function.py +0 -0
  87. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_resources.py +0 -0
  88. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_runtime/__init__.py +0 -0
  89. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_runtime/container_io_manager.py +0 -0
  90. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_runtime/container_io_manager.pyi +0 -0
  91. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_runtime/execution_context.py +0 -0
  92. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_runtime/execution_context.pyi +0 -0
  93. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  94. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_runtime/telemetry.py +0 -0
  95. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_runtime/user_code_event_loop.py +0 -0
  96. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_runtime/user_code_imports.py +0 -0
  97. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_serialization.py +0 -0
  98. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_traceback.py +0 -0
  99. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_tunnel.py +0 -0
  100. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_tunnel.pyi +0 -0
  101. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_type_manager.py +0 -0
  102. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/__init__.py +0 -0
  103. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/app_utils.py +0 -0
  104. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/async_utils.py +0 -0
  105. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/auth_token_manager.py +0 -0
  106. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/blob_utils.py +0 -0
  107. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/bytes_io_segment_payload.py +0 -0
  108. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/deprecation.py +0 -0
  109. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/docker_utils.py +0 -0
  110. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/git_utils.py +0 -0
  111. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/grpc_testing.py +0 -0
  112. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/grpc_utils.py +0 -0
  113. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/hash_utils.py +0 -0
  114. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/http_utils.py +0 -0
  115. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/jwt_utils.py +0 -0
  116. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/logger.py +0 -0
  117. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/mount_utils.py +0 -0
  118. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/name_utils.py +0 -0
  119. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/package_utils.py +0 -0
  120. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/pattern_utils.py +0 -0
  121. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/rand_pb_testing.py +0 -0
  122. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_utils/task_command_router_client.py +0 -0
  123. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_vendor/__init__.py +0 -0
  124. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  125. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_vendor/cloudpickle.py +0 -0
  126. {modal-1.3.2.dev0 → modal-1.3.3}/modal/_vendor/tblib.py +0 -0
  127. {modal-1.3.2.dev0 → modal-1.3.3}/modal/app.py +0 -0
  128. {modal-1.3.2.dev0 → modal-1.3.3}/modal/app.pyi +0 -0
  129. {modal-1.3.2.dev0 → modal-1.3.3}/modal/billing.py +0 -0
  130. {modal-1.3.2.dev0 → modal-1.3.3}/modal/builder/2023.12.312.txt +0 -0
  131. {modal-1.3.2.dev0 → modal-1.3.3}/modal/builder/2023.12.txt +0 -0
  132. {modal-1.3.2.dev0 → modal-1.3.3}/modal/builder/2024.04.txt +0 -0
  133. {modal-1.3.2.dev0 → modal-1.3.3}/modal/builder/2024.10.txt +0 -0
  134. {modal-1.3.2.dev0 → modal-1.3.3}/modal/builder/2025.06.txt +0 -0
  135. {modal-1.3.2.dev0 → modal-1.3.3}/modal/builder/PREVIEW.txt +0 -0
  136. {modal-1.3.2.dev0 → modal-1.3.3}/modal/builder/README.md +0 -0
  137. {modal-1.3.2.dev0 → modal-1.3.3}/modal/builder/base-images.json +0 -0
  138. {modal-1.3.2.dev0 → modal-1.3.3}/modal/call_graph.py +0 -0
  139. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/__init__.py +0 -0
  140. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/environment.py +0 -0
  141. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/programs/__init__.py +0 -0
  142. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/programs/run_jupyter.py +0 -0
  143. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/programs/vscode.py +0 -0
  144. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cli/shell.py +0 -0
  145. {modal-1.3.2.dev0 → modal-1.3.3}/modal/client.py +0 -0
  146. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cloud_bucket_mount.py +0 -0
  147. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cloud_bucket_mount.pyi +0 -0
  148. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cls.py +0 -0
  149. {modal-1.3.2.dev0 → modal-1.3.3}/modal/cls.pyi +0 -0
  150. {modal-1.3.2.dev0 → modal-1.3.3}/modal/container_process.pyi +0 -0
  151. {modal-1.3.2.dev0 → modal-1.3.3}/modal/environments.py +0 -0
  152. {modal-1.3.2.dev0 → modal-1.3.3}/modal/environments.pyi +0 -0
  153. {modal-1.3.2.dev0 → modal-1.3.3}/modal/exception.py +0 -0
  154. {modal-1.3.2.dev0 → modal-1.3.3}/modal/experimental/__init__.py +0 -0
  155. {modal-1.3.2.dev0 → modal-1.3.3}/modal/experimental/ipython.py +0 -0
  156. {modal-1.3.2.dev0 → modal-1.3.3}/modal/file_io.py +0 -0
  157. {modal-1.3.2.dev0 → modal-1.3.3}/modal/file_io.pyi +0 -0
  158. {modal-1.3.2.dev0 → modal-1.3.3}/modal/file_pattern_matcher.py +0 -0
  159. {modal-1.3.2.dev0 → modal-1.3.3}/modal/functions.py +0 -0
  160. {modal-1.3.2.dev0 → modal-1.3.3}/modal/gpu.py +0 -0
  161. {modal-1.3.2.dev0 → modal-1.3.3}/modal/image.pyi +0 -0
  162. {modal-1.3.2.dev0 → modal-1.3.3}/modal/io_streams.py +0 -0
  163. {modal-1.3.2.dev0 → modal-1.3.3}/modal/io_streams.pyi +0 -0
  164. {modal-1.3.2.dev0 → modal-1.3.3}/modal/mount.pyi +0 -0
  165. {modal-1.3.2.dev0 → modal-1.3.3}/modal/network_file_system.py +0 -0
  166. {modal-1.3.2.dev0 → modal-1.3.3}/modal/network_file_system.pyi +0 -0
  167. {modal-1.3.2.dev0 → modal-1.3.3}/modal/object.py +0 -0
  168. {modal-1.3.2.dev0 → modal-1.3.3}/modal/parallel_map.py +0 -0
  169. {modal-1.3.2.dev0 → modal-1.3.3}/modal/parallel_map.pyi +0 -0
  170. {modal-1.3.2.dev0 → modal-1.3.3}/modal/partial_function.py +0 -0
  171. {modal-1.3.2.dev0 → modal-1.3.3}/modal/partial_function.pyi +0 -0
  172. {modal-1.3.2.dev0 → modal-1.3.3}/modal/proxy.py +0 -0
  173. {modal-1.3.2.dev0 → modal-1.3.3}/modal/proxy.pyi +0 -0
  174. {modal-1.3.2.dev0 → modal-1.3.3}/modal/py.typed +0 -0
  175. {modal-1.3.2.dev0 → modal-1.3.3}/modal/runner.pyi +0 -0
  176. {modal-1.3.2.dev0 → modal-1.3.3}/modal/running_app.py +0 -0
  177. {modal-1.3.2.dev0 → modal-1.3.3}/modal/sandbox.pyi +0 -0
  178. {modal-1.3.2.dev0 → modal-1.3.3}/modal/schedule.py +0 -0
  179. {modal-1.3.2.dev0 → modal-1.3.3}/modal/scheduler_placement.py +0 -0
  180. {modal-1.3.2.dev0 → modal-1.3.3}/modal/secret.py +0 -0
  181. {modal-1.3.2.dev0 → modal-1.3.3}/modal/secret.pyi +0 -0
  182. {modal-1.3.2.dev0 → modal-1.3.3}/modal/server.py +0 -0
  183. {modal-1.3.2.dev0 → modal-1.3.3}/modal/server.pyi +0 -0
  184. {modal-1.3.2.dev0 → modal-1.3.3}/modal/serving.pyi +0 -0
  185. {modal-1.3.2.dev0 → modal-1.3.3}/modal/snapshot.py +0 -0
  186. {modal-1.3.2.dev0 → modal-1.3.3}/modal/snapshot.pyi +0 -0
  187. {modal-1.3.2.dev0 → modal-1.3.3}/modal/stream_type.py +0 -0
  188. {modal-1.3.2.dev0 → modal-1.3.3}/modal.egg-info/dependency_links.txt +0 -0
  189. {modal-1.3.2.dev0 → modal-1.3.3}/modal.egg-info/entry_points.txt +0 -0
  190. {modal-1.3.2.dev0 → modal-1.3.3}/modal.egg-info/requires.txt +0 -0
  191. {modal-1.3.2.dev0 → modal-1.3.3}/modal.egg-info/top_level.txt +0 -0
  192. {modal-1.3.2.dev0 → modal-1.3.3}/modal_docs/__init__.py +0 -0
  193. {modal-1.3.2.dev0 → modal-1.3.3}/modal_docs/gen_cli_docs.py +0 -0
  194. {modal-1.3.2.dev0 → modal-1.3.3}/modal_docs/mdmd/__init__.py +0 -0
  195. {modal-1.3.2.dev0 → modal-1.3.3}/modal_docs/mdmd/mdmd.py +0 -0
  196. {modal-1.3.2.dev0 → modal-1.3.3}/modal_docs/mdmd/signatures.py +0 -0
  197. {modal-1.3.2.dev0 → modal-1.3.3}/modal_proto/__init__.py +0 -0
  198. {modal-1.3.2.dev0 → modal-1.3.3}/modal_proto/py.typed +0 -0
  199. {modal-1.3.2.dev0 → modal-1.3.3}/modal_proto/task_command_router.proto +0 -0
  200. {modal-1.3.2.dev0 → modal-1.3.3}/modal_proto/task_command_router_grpc.py +0 -0
  201. {modal-1.3.2.dev0 → modal-1.3.3}/modal_proto/task_command_router_pb2.py +0 -0
  202. {modal-1.3.2.dev0 → modal-1.3.3}/modal_proto/task_command_router_pb2.pyi +0 -0
  203. {modal-1.3.2.dev0 → modal-1.3.3}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  204. {modal-1.3.2.dev0 → modal-1.3.3}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  205. {modal-1.3.2.dev0 → modal-1.3.3}/modal_version/__main__.py +0 -0
  206. {modal-1.3.2.dev0 → modal-1.3.3}/pyproject.toml +0 -0
  207. {modal-1.3.2.dev0 → modal-1.3.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.3.2.dev0
3
+ Version: 1.3.3
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -9,6 +9,7 @@ if sys.version_info[:2] >= (3, 15):
9
9
  from modal_version import __version__
10
10
 
11
11
  try:
12
+ from . import billing
12
13
  from ._runtime.execution_context import current_function_call_id, current_input_id, interact, is_local
13
14
  from ._tunnel import Tunnel, forward
14
15
  from .app import App
@@ -41,7 +42,6 @@ try:
41
42
  from .schedule import Cron, Period
42
43
  from .scheduler_placement import SchedulerPlacement
43
44
  from .secret import Secret
44
- from .server import Server
45
45
  from .snapshot import SandboxSnapshot
46
46
  from .volume import Volume
47
47
  except Exception:
@@ -76,11 +76,11 @@ __all__ = [
76
76
  "SandboxSnapshot",
77
77
  "SchedulerPlacement",
78
78
  "Secret",
79
- "Server",
80
79
  "Tunnel",
81
80
  "Volume",
82
81
  "asgi_app",
83
82
  "batched",
83
+ "billing",
84
84
  "concurrent",
85
85
  "current_function_call_id",
86
86
  "current_input_id",
@@ -0,0 +1,49 @@
1
+ # Copyright Modal Labs 2022
2
+ import sys
3
+
4
+ from ._traceback import reduce_traceback_to_user_code
5
+ from .cli._traceback import highlight_modal_warnings, setup_rich_traceback
6
+ from .cli.entry_point import entrypoint_cli
7
+ from .cli.import_refs import _CliUserExecutionError
8
+ from .config import config
9
+ from .output import OutputManager, enable_output
10
+
11
+
12
+ def main():
13
+ # Setup rich tracebacks, but only on user's end, when using the Modal CLI.
14
+ setup_rich_traceback()
15
+ highlight_modal_warnings()
16
+
17
+ # Enable rich output for the entire CLI session
18
+ with enable_output():
19
+ try:
20
+ entrypoint_cli()
21
+
22
+ except _CliUserExecutionError as exc:
23
+ if config.get("traceback"):
24
+ raise
25
+
26
+ assert exc.__cause__ # We should always raise this class from another error
27
+ tb = reduce_traceback_to_user_code(exc.__cause__.__traceback__, exc.user_source)
28
+ sys.excepthook(type(exc.__cause__), exc.__cause__, tb)
29
+ sys.exit(1)
30
+
31
+ except Exception as exc:
32
+ if (
33
+ # User has asked to alway see full tracebacks
34
+ config.get("traceback")
35
+ # The exception message is empty, so we need to provide _some_ actionable information
36
+ or not str(exc)
37
+ ):
38
+ raise
39
+
40
+ content = str(exc)
41
+ if notes := getattr(exc, "__notes__", []):
42
+ content = f"{content}\n\nNote: {' '.join(notes)}"
43
+
44
+ OutputManager.get().print_error(content)
45
+ sys.exit(1)
46
+
47
+
48
+ if __name__ == "__main__":
49
+ main()
@@ -40,8 +40,14 @@ async def _workspace_billing_report(
40
40
  partial `end` intervals will be excluded.
41
41
 
42
42
  Additional user-provided metadata can be included in the report if the objects have tags
43
- and `tag_names` (i.e., keys) are specified in the request. Note that tags will be attributed
44
- to the entire interval even if they were added or removed at some point within it.
43
+ and `tag_names` (i.e., keys) are specified in the request. Alternatively, pass `tag_names=["*"]`
44
+ to include all tags in the report. Note that tags will be attributed to the entire interval even
45
+ if they were added or removed at some point within it. If the tag name was not in use during an
46
+ interval, it will be absent from the tags dictionary in that output row.
47
+
48
+ In most cases, billing data will be available in the database that this API queries within
49
+ minutes, although there may be collection delays. If completeness is important for your use
50
+ case, we recommend leaving a buffer after the end of the query interval.
45
51
 
46
52
  """
47
53
  if client is None:
@@ -21,7 +21,8 @@ from modal_proto.modal_api_grpc import ModalClientModal
21
21
 
22
22
  from ._load_context import LoadContext
23
23
  from ._object import _Object, live_method, live_method_gen
24
- from ._pty import get_pty_info
24
+ from ._output.pty import get_pty_info
25
+ from ._output.status import FunctionCreationStatus
25
26
  from ._resolver import Resolver
26
27
  from ._resources import convert_fn_config_to_resources_config
27
28
  from ._runtime.execution_context import current_input_id, is_local
@@ -47,7 +48,6 @@ from ._utils.deprecation import deprecation_warning, warn_if_passing_namespace
47
48
  from ._utils.function_utils import (
48
49
  ATTEMPT_TIMEOUT_GRACE_PERIOD,
49
50
  OUTPUTS_TIMEOUT,
50
- FunctionCreationStatus,
51
51
  FunctionInfo,
52
52
  _create_input,
53
53
  _process_result,
@@ -71,7 +71,7 @@ from .gpu import GPU_T, parse_gpu_config
71
71
  from .image import _Image
72
72
  from .mount import _get_client_mount, _Mount
73
73
  from .network_file_system import _NetworkFileSystem, network_file_system_mount_protos
74
- from .output import _get_output_manager
74
+ from .output import OutputManager
75
75
  from .parallel_map import (
76
76
  _experimental_spawn_map_async,
77
77
  _experimental_spawn_map_sync,
@@ -922,7 +922,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
922
922
  async def _load(
923
923
  self: _Function, resolver: Resolver, load_context: LoadContext, existing_object_id: Optional[str]
924
924
  ):
925
- with FunctionCreationStatus(resolver, tag) as function_creation_status:
925
+ with FunctionCreationStatus(tag) as function_creation_status:
926
926
  timeout_secs = timeout
927
927
 
928
928
  if app and app.is_interactive and not is_builder_function:
@@ -1639,10 +1639,7 @@ Use the `Function.get_web_url()` method instead.
1639
1639
  raise InvalidError("A generator function cannot be called with `.map(...)`.")
1640
1640
 
1641
1641
  assert self._function_name
1642
- if output_mgr := _get_output_manager():
1643
- count_update_callback = output_mgr.function_progress_callback(self._function_name, total=None)
1644
- else:
1645
- count_update_callback = None
1642
+ count_update_callback = OutputManager.get().function_progress_callback(self._function_name, total=None)
1646
1643
 
1647
1644
  if self._input_plane_url:
1648
1645
  async with aclosing(
@@ -39,6 +39,41 @@ def _get_environment_name(
39
39
  return config.get("environment")
40
40
 
41
41
 
42
+ def live_method(method):
43
+ @wraps(method)
44
+ async def wrapped(self, *args, **kwargs):
45
+ await self.hydrate()
46
+ return await method(self, *args, **kwargs)
47
+
48
+ return wrapped
49
+
50
+
51
+ def live_method_gen(method):
52
+ @wraps(method)
53
+ async def wrapped(self, *args, **kwargs):
54
+ await self.hydrate()
55
+ async with aclosing(method(self, *args, **kwargs)) as stream:
56
+ async for item in stream:
57
+ yield item
58
+
59
+ return wrapped
60
+
61
+
62
+ def live_method_contextmanager(method):
63
+ # make sure a wrapped function returning an async context manager
64
+ # will not require both an `await func.aio()` and `async with`
65
+ # which would have been the case if it was wrapped in live_method
66
+
67
+ @wraps(method)
68
+ @contextlib.asynccontextmanager
69
+ async def wrapped(self, *args, **kwargs):
70
+ await self.hydrate()
71
+ async with method(self, *args, **kwargs) as ctx:
72
+ yield ctx
73
+
74
+ return wrapped
75
+
76
+
42
77
  class _Object:
43
78
  _type_prefix: ClassVar[Optional[str]] = None
44
79
  _prefix_to_type: ClassVar[dict[str, type]] = {}
@@ -275,6 +310,11 @@ class _Object:
275
310
  raise AttributeError(f"Attempting to get object_id of unhydrated {self}")
276
311
  return self._object_id
277
312
 
313
+ @live_method
314
+ async def get_dashboard_url(self) -> str:
315
+ """mdmd:hidden"""
316
+ return f"https://modal.com/id/{self.object_id}"
317
+
278
318
  @property
279
319
  def client(self) -> _Client:
280
320
  """mdmd:hidden"""
@@ -336,38 +376,3 @@ class _Object:
336
376
  with suppress_tb_frame(): # skip this frame by default
337
377
  await resolver.load(self, root_load_context)
338
378
  return self
339
-
340
-
341
- def live_method(method):
342
- @wraps(method)
343
- async def wrapped(self, *args, **kwargs):
344
- await self.hydrate()
345
- return await method(self, *args, **kwargs)
346
-
347
- return wrapped
348
-
349
-
350
- def live_method_gen(method):
351
- @wraps(method)
352
- async def wrapped(self, *args, **kwargs):
353
- await self.hydrate()
354
- async with aclosing(method(self, *args, **kwargs)) as stream:
355
- async for item in stream:
356
- yield item
357
-
358
- return wrapped
359
-
360
-
361
- def live_method_contextmanager(method):
362
- # make sure a wrapped function returning an async context manager
363
- # will not require both an `await func.aio()` and `async with`
364
- # which would have been the case if it was wrapped in live_method
365
-
366
- @wraps(method)
367
- @contextlib.asynccontextmanager
368
- async def wrapped(self, *args, **kwargs):
369
- await self.hydrate()
370
- async with method(self, *args, **kwargs) as ctx:
371
- yield ctx
372
-
373
- return wrapped
@@ -0,0 +1 @@
1
+ # Copyright Modal Labs 2025