modAL 1.3.3.dev0__tar.gz → 1.3.5__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 (212) hide show
  1. {modal-1.3.3.dev0 → modal-1.3.5}/PKG-INFO +1 -3
  2. {modal-1.3.3.dev0 → modal-1.3.5}/modal/__init__.py +2 -2
  3. modal-1.3.5/modal/__main__.py +49 -0
  4. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_billing.py +15 -5
  5. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_functions.py +9 -9
  6. modal-1.3.5/modal/_output/__init__.py +1 -0
  7. modal-1.3.5/modal/_output/manager.py +542 -0
  8. modal-1.3.5/modal/_output/pty.py +200 -0
  9. modal-1.3.3.dev0/modal/_output.py → modal-1.3.5/modal/_output/rich.py +326 -266
  10. modal-1.3.5/modal/_output/status.py +101 -0
  11. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_resolver.py +1 -62
  12. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_runtime/asgi.py +2 -2
  13. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_server.py +3 -0
  14. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/async_utils.py +71 -67
  15. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/browser_utils.py +8 -7
  16. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/function_utils.py +0 -87
  17. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/grpc_utils.py +17 -1
  18. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/shell_utils.py +48 -2
  19. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/task_command_router_client.py +3 -1
  20. modal-1.3.5/modal/_utils/time_utils.py +204 -0
  21. modal-1.3.5/modal/_vendor/version.py +844 -0
  22. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_watcher.py +2 -3
  23. {modal-1.3.3.dev0 → modal-1.3.5}/modal/app.py +5 -0
  24. {modal-1.3.3.dev0 → modal-1.3.5}/modal/app.pyi +10 -3
  25. {modal-1.3.3.dev0 → modal-1.3.5}/modal/billing.py +2 -1
  26. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/_traceback.py +3 -36
  27. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/app.py +1 -4
  28. modal-1.3.5/modal/cli/billing.py +158 -0
  29. modal-1.3.5/modal/cli/changelog.py +157 -0
  30. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/cluster.py +4 -5
  31. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/config.py +2 -3
  32. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/container.py +8 -2
  33. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/dashboard.py +1 -4
  34. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/dict.py +2 -3
  35. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/entry_point.py +17 -10
  36. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/import_refs.py +15 -10
  37. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/launch.py +12 -15
  38. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/network_file_system.py +21 -29
  39. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/profile.py +6 -6
  40. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/queues.py +4 -5
  41. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/run.py +46 -45
  42. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/secret.py +7 -6
  43. modal-1.3.5/modal/cli/selector.py +124 -0
  44. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/token.py +11 -12
  45. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/utils.py +28 -9
  46. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/volume.py +19 -24
  47. {modal-1.3.3.dev0 → modal-1.3.5}/modal/client.pyi +2 -10
  48. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cloud_bucket_mount.py +3 -1
  49. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cloud_bucket_mount.pyi +3 -1
  50. {modal-1.3.3.dev0 → modal-1.3.5}/modal/container_process.py +6 -8
  51. {modal-1.3.3.dev0 → modal-1.3.5}/modal/dict.py +42 -0
  52. {modal-1.3.3.dev0 → modal-1.3.5}/modal/dict.pyi +52 -0
  53. {modal-1.3.3.dev0 → modal-1.3.5}/modal/experimental/flash.py +10 -1
  54. {modal-1.3.3.dev0 → modal-1.3.5}/modal/experimental/flash.pyi +3 -0
  55. {modal-1.3.3.dev0 → modal-1.3.5}/modal/functions.pyi +6 -6
  56. {modal-1.3.3.dev0 → modal-1.3.5}/modal/gpu.py +3 -0
  57. {modal-1.3.3.dev0 → modal-1.3.5}/modal/image.py +15 -8
  58. {modal-1.3.3.dev0 → modal-1.3.5}/modal/image.pyi +7 -1
  59. {modal-1.3.3.dev0 → modal-1.3.5}/modal/io_streams.py +4 -1
  60. {modal-1.3.3.dev0 → modal-1.3.5}/modal/mount.py +4 -1
  61. {modal-1.3.3.dev0 → modal-1.3.5}/modal/network_file_system.py +1 -0
  62. {modal-1.3.3.dev0 → modal-1.3.5}/modal/network_file_system.pyi +3 -1
  63. {modal-1.3.3.dev0 → modal-1.3.5}/modal/object.pyi +57 -13
  64. modal-1.3.5/modal/output.py +47 -0
  65. {modal-1.3.3.dev0 → modal-1.3.5}/modal/partial_function.pyi +2 -1
  66. {modal-1.3.3.dev0 → modal-1.3.5}/modal/queue.py +45 -3
  67. {modal-1.3.3.dev0 → modal-1.3.5}/modal/queue.pyi +59 -7
  68. {modal-1.3.3.dev0 → modal-1.3.5}/modal/retries.py +0 -3
  69. {modal-1.3.3.dev0 → modal-1.3.5}/modal/runner.py +49 -56
  70. {modal-1.3.3.dev0 → modal-1.3.5}/modal/sandbox.py +149 -19
  71. {modal-1.3.3.dev0 → modal-1.3.5}/modal/sandbox.pyi +203 -29
  72. {modal-1.3.3.dev0 → modal-1.3.5}/modal/secret.py +18 -0
  73. {modal-1.3.3.dev0 → modal-1.3.5}/modal/secret.pyi +27 -0
  74. {modal-1.3.3.dev0 → modal-1.3.5}/modal/serving.py +10 -13
  75. {modal-1.3.3.dev0 → modal-1.3.5}/modal/token_flow.py +18 -19
  76. {modal-1.3.3.dev0 → modal-1.3.5}/modal/volume.py +71 -1
  77. {modal-1.3.3.dev0 → modal-1.3.5}/modal/volume.pyi +56 -0
  78. {modal-1.3.3.dev0 → modal-1.3.5}/modal.egg-info/PKG-INFO +1 -3
  79. {modal-1.3.3.dev0 → modal-1.3.5}/modal.egg-info/SOURCES.txt +9 -5
  80. {modal-1.3.3.dev0 → modal-1.3.5}/modal_docs/gen_reference_docs.py +1 -0
  81. {modal-1.3.3.dev0 → modal-1.3.5}/modal_docs/mdmd/mdmd.py +51 -2
  82. {modal-1.3.3.dev0 → modal-1.3.5}/modal_proto/api_grpc.py +64 -0
  83. modal-1.3.5/modal_proto/api_pb2.py +5331 -0
  84. {modal-1.3.3.dev0 → modal-1.3.5}/modal_proto/api_pb2.pyi +147 -2
  85. {modal-1.3.3.dev0 → modal-1.3.5}/modal_proto/api_pb2_grpc.py +132 -0
  86. {modal-1.3.3.dev0 → modal-1.3.5}/modal_proto/api_pb2_grpc.pyi +40 -0
  87. {modal-1.3.3.dev0 → modal-1.3.5}/modal_proto/modal_api_grpc.py +4 -0
  88. modal-1.3.5/modal_proto/task_command_router_pb2.py +180 -0
  89. {modal-1.3.3.dev0 → modal-1.3.5}/modal_version/__init__.py +1 -1
  90. modal-1.3.3.dev0/LICENSE +0 -176
  91. modal-1.3.3.dev0/modal/__main__.py +0 -53
  92. modal-1.3.3.dev0/modal/_pty.py +0 -57
  93. modal-1.3.3.dev0/modal/_utils/time_utils.py +0 -43
  94. modal-1.3.3.dev0/modal/output.py +0 -64
  95. modal-1.3.3.dev0/modal_proto/api.proto +0 -3938
  96. modal-1.3.3.dev0/modal_proto/api_pb2.py +0 -1139
  97. modal-1.3.3.dev0/modal_proto/task_command_router.proto +0 -164
  98. modal-1.3.3.dev0/modal_proto/task_command_router_pb2.py +0 -60
  99. {modal-1.3.3.dev0 → modal-1.3.5}/README.md +0 -0
  100. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_clustered_functions.py +0 -0
  101. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_clustered_functions.pyi +0 -0
  102. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_container_entrypoint.py +0 -0
  103. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_grpc_client.py +0 -0
  104. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_ipython.py +0 -0
  105. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_load_context.py +0 -0
  106. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_location.py +0 -0
  107. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_object.py +0 -0
  108. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_partial_function.py +0 -0
  109. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_resources.py +0 -0
  110. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_runtime/__init__.py +0 -0
  111. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_runtime/container_io_manager.py +0 -0
  112. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_runtime/container_io_manager.pyi +0 -0
  113. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_runtime/execution_context.py +0 -0
  114. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_runtime/execution_context.pyi +0 -0
  115. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  116. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_runtime/telemetry.py +0 -0
  117. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_runtime/user_code_event_loop.py +0 -0
  118. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_runtime/user_code_imports.py +0 -0
  119. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_serialization.py +0 -0
  120. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_traceback.py +0 -0
  121. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_tunnel.py +0 -0
  122. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_tunnel.pyi +0 -0
  123. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_type_manager.py +0 -0
  124. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/__init__.py +0 -0
  125. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/app_utils.py +0 -0
  126. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/auth_token_manager.py +0 -0
  127. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/blob_utils.py +0 -0
  128. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/bytes_io_segment_payload.py +0 -0
  129. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/deprecation.py +0 -0
  130. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/docker_utils.py +0 -0
  131. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/git_utils.py +0 -0
  132. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/grpc_testing.py +0 -0
  133. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/hash_utils.py +0 -0
  134. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/http_utils.py +0 -0
  135. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/jwt_utils.py +0 -0
  136. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/logger.py +0 -0
  137. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/mount_utils.py +0 -0
  138. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/name_utils.py +0 -0
  139. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/package_utils.py +0 -0
  140. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/pattern_utils.py +0 -0
  141. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_utils/rand_pb_testing.py +0 -0
  142. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_vendor/__init__.py +0 -0
  143. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  144. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_vendor/cloudpickle.py +0 -0
  145. {modal-1.3.3.dev0 → modal-1.3.5}/modal/_vendor/tblib.py +0 -0
  146. {modal-1.3.3.dev0 → modal-1.3.5}/modal/builder/2023.12.312.txt +0 -0
  147. {modal-1.3.3.dev0 → modal-1.3.5}/modal/builder/2023.12.txt +0 -0
  148. {modal-1.3.3.dev0 → modal-1.3.5}/modal/builder/2024.04.txt +0 -0
  149. {modal-1.3.3.dev0 → modal-1.3.5}/modal/builder/2024.10.txt +0 -0
  150. {modal-1.3.3.dev0 → modal-1.3.5}/modal/builder/2025.06.txt +0 -0
  151. {modal-1.3.3.dev0 → modal-1.3.5}/modal/builder/PREVIEW.txt +0 -0
  152. {modal-1.3.3.dev0 → modal-1.3.5}/modal/builder/README.md +0 -0
  153. {modal-1.3.3.dev0 → modal-1.3.5}/modal/builder/base-images.json +0 -0
  154. {modal-1.3.3.dev0 → modal-1.3.5}/modal/call_graph.py +0 -0
  155. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/__init__.py +0 -0
  156. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/_download.py +0 -0
  157. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/environment.py +0 -0
  158. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/programs/__init__.py +0 -0
  159. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/programs/run_jupyter.py +0 -0
  160. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/programs/vscode.py +0 -0
  161. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cli/shell.py +0 -0
  162. {modal-1.3.3.dev0 → modal-1.3.5}/modal/client.py +0 -0
  163. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cls.py +0 -0
  164. {modal-1.3.3.dev0 → modal-1.3.5}/modal/cls.pyi +0 -0
  165. {modal-1.3.3.dev0 → modal-1.3.5}/modal/config.py +0 -0
  166. {modal-1.3.3.dev0 → modal-1.3.5}/modal/container_process.pyi +0 -0
  167. {modal-1.3.3.dev0 → modal-1.3.5}/modal/environments.py +0 -0
  168. {modal-1.3.3.dev0 → modal-1.3.5}/modal/environments.pyi +0 -0
  169. {modal-1.3.3.dev0 → modal-1.3.5}/modal/exception.py +0 -0
  170. {modal-1.3.3.dev0 → modal-1.3.5}/modal/experimental/__init__.py +0 -0
  171. {modal-1.3.3.dev0 → modal-1.3.5}/modal/experimental/ipython.py +0 -0
  172. {modal-1.3.3.dev0 → modal-1.3.5}/modal/file_io.py +0 -0
  173. {modal-1.3.3.dev0 → modal-1.3.5}/modal/file_io.pyi +0 -0
  174. {modal-1.3.3.dev0 → modal-1.3.5}/modal/file_pattern_matcher.py +0 -0
  175. {modal-1.3.3.dev0 → modal-1.3.5}/modal/functions.py +0 -0
  176. {modal-1.3.3.dev0 → modal-1.3.5}/modal/io_streams.pyi +0 -0
  177. {modal-1.3.3.dev0 → modal-1.3.5}/modal/mount.pyi +0 -0
  178. {modal-1.3.3.dev0 → modal-1.3.5}/modal/object.py +0 -0
  179. {modal-1.3.3.dev0 → modal-1.3.5}/modal/parallel_map.py +0 -0
  180. {modal-1.3.3.dev0 → modal-1.3.5}/modal/parallel_map.pyi +0 -0
  181. {modal-1.3.3.dev0 → modal-1.3.5}/modal/partial_function.py +0 -0
  182. {modal-1.3.3.dev0 → modal-1.3.5}/modal/proxy.py +0 -0
  183. {modal-1.3.3.dev0 → modal-1.3.5}/modal/proxy.pyi +0 -0
  184. {modal-1.3.3.dev0 → modal-1.3.5}/modal/py.typed +0 -0
  185. {modal-1.3.3.dev0 → modal-1.3.5}/modal/runner.pyi +0 -0
  186. {modal-1.3.3.dev0 → modal-1.3.5}/modal/running_app.py +0 -0
  187. {modal-1.3.3.dev0 → modal-1.3.5}/modal/schedule.py +0 -0
  188. {modal-1.3.3.dev0 → modal-1.3.5}/modal/scheduler_placement.py +0 -0
  189. {modal-1.3.3.dev0 → modal-1.3.5}/modal/server.py +0 -0
  190. {modal-1.3.3.dev0 → modal-1.3.5}/modal/server.pyi +0 -0
  191. {modal-1.3.3.dev0 → modal-1.3.5}/modal/serving.pyi +0 -0
  192. {modal-1.3.3.dev0 → modal-1.3.5}/modal/snapshot.py +0 -0
  193. {modal-1.3.3.dev0 → modal-1.3.5}/modal/snapshot.pyi +0 -0
  194. {modal-1.3.3.dev0 → modal-1.3.5}/modal/stream_type.py +0 -0
  195. {modal-1.3.3.dev0 → modal-1.3.5}/modal/token_flow.pyi +0 -0
  196. {modal-1.3.3.dev0 → modal-1.3.5}/modal.egg-info/dependency_links.txt +0 -0
  197. {modal-1.3.3.dev0 → modal-1.3.5}/modal.egg-info/entry_points.txt +0 -0
  198. {modal-1.3.3.dev0 → modal-1.3.5}/modal.egg-info/requires.txt +0 -0
  199. {modal-1.3.3.dev0 → modal-1.3.5}/modal.egg-info/top_level.txt +0 -0
  200. {modal-1.3.3.dev0 → modal-1.3.5}/modal_docs/__init__.py +0 -0
  201. {modal-1.3.3.dev0 → modal-1.3.5}/modal_docs/gen_cli_docs.py +0 -0
  202. {modal-1.3.3.dev0 → modal-1.3.5}/modal_docs/mdmd/__init__.py +0 -0
  203. {modal-1.3.3.dev0 → modal-1.3.5}/modal_docs/mdmd/signatures.py +0 -0
  204. {modal-1.3.3.dev0 → modal-1.3.5}/modal_proto/__init__.py +0 -0
  205. {modal-1.3.3.dev0 → modal-1.3.5}/modal_proto/py.typed +0 -0
  206. {modal-1.3.3.dev0 → modal-1.3.5}/modal_proto/task_command_router_grpc.py +0 -0
  207. {modal-1.3.3.dev0 → modal-1.3.5}/modal_proto/task_command_router_pb2.pyi +0 -0
  208. {modal-1.3.3.dev0 → modal-1.3.5}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  209. {modal-1.3.3.dev0 → modal-1.3.5}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  210. {modal-1.3.3.dev0 → modal-1.3.5}/modal_version/__main__.py +0 -0
  211. {modal-1.3.3.dev0 → modal-1.3.5}/pyproject.toml +0 -0
  212. {modal-1.3.3.dev0 → modal-1.3.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.3.3.dev0
3
+ Version: 1.3.5
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -15,7 +15,6 @@ Classifier: License :: OSI Approved :: Apache Software License
15
15
  Classifier: Programming Language :: Python :: 3
16
16
  Requires-Python: <3.15,>=3.10
17
17
  Description-Content-Type: text/markdown
18
- License-File: LICENSE
19
18
  Requires-Dist: aiohttp
20
19
  Requires-Dist: cbor2
21
20
  Requires-Dist: certifi
@@ -31,7 +30,6 @@ Requires-Dist: types-certifi
31
30
  Requires-Dist: types-toml
32
31
  Requires-Dist: watchfiles
33
32
  Requires-Dist: typing_extensions~=4.6
34
- Dynamic: license-file
35
33
 
36
34
  # Modal Python SDK
37
35
 
@@ -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()
@@ -1,7 +1,7 @@
1
1
  # Copyright Modal Labs 2025
2
2
  from datetime import datetime, timezone
3
3
  from decimal import Decimal
4
- from typing import Any, Optional, TypedDict
4
+ from typing import Optional, TypedDict
5
5
 
6
6
  from modal_proto import api_pb2
7
7
 
@@ -25,7 +25,7 @@ async def _workspace_billing_report(
25
25
  resolution: str = "d", # Resolution, e.g. "d" for daily or "h" for hourly
26
26
  tag_names: Optional[list[str]] = None, # Optional additional metadata to include
27
27
  client: Optional[_Client] = None,
28
- ) -> list[dict[str, Any]]:
28
+ ) -> list[WorkspaceBillingReportItem]:
29
29
  """Generate a tabular report of workspace usage by object and time.
30
30
 
31
31
  The result will be a list of dictionaries for each interval (determined by `resolution`)
@@ -40,8 +40,18 @@ 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.
51
+
52
+ It's also possible to generate reports using the
53
+ [`modal billing report`](https://modal.com/docs/reference/cli/billing) CLI command. The CLI
54
+ has a few convenience features for generating reports across relative time ranges.
45
55
 
46
56
  """
47
57
  if client is None:
@@ -71,7 +81,7 @@ async def _workspace_billing_report(
71
81
 
72
82
  rows = []
73
83
  async for pb_item in client.stub.WorkspaceBillingReport.unary_stream(request):
74
- item = {
84
+ item: WorkspaceBillingReportItem = {
75
85
  "object_id": pb_item.object_id,
76
86
  "description": pb_item.description,
77
87
  "environment_name": pb_item.environment_name,
@@ -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,
@@ -550,6 +550,7 @@ class FunctionStats:
550
550
 
551
551
  backlog: int
552
552
  num_total_runners: int
553
+ num_running_inputs: int
553
554
 
554
555
 
555
556
  def _parse_retries(
@@ -922,7 +923,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
922
923
  async def _load(
923
924
  self: _Function, resolver: Resolver, load_context: LoadContext, existing_object_id: Optional[str]
924
925
  ):
925
- with FunctionCreationStatus(resolver, tag) as function_creation_status:
926
+ with FunctionCreationStatus(tag) as function_creation_status:
926
927
  timeout_secs = timeout
927
928
 
928
929
  if app and app.is_interactive and not is_builder_function:
@@ -1639,10 +1640,7 @@ Use the `Function.get_web_url()` method instead.
1639
1640
  raise InvalidError("A generator function cannot be called with `.map(...)`.")
1640
1641
 
1641
1642
  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
1643
+ count_update_callback = OutputManager.get().function_progress_callback(self._function_name, total=None)
1646
1644
 
1647
1645
  if self._input_plane_url:
1648
1646
  async with aclosing(
@@ -1920,7 +1918,9 @@ Use the `Function.get_web_url()` method instead.
1920
1918
  api_pb2.FunctionGetCurrentStatsRequest(function_id=self.object_id),
1921
1919
  retry=Retry(total_timeout=10.0),
1922
1920
  )
1923
- return FunctionStats(backlog=resp.backlog, num_total_runners=resp.num_total_tasks)
1921
+ return FunctionStats(
1922
+ backlog=resp.backlog, num_total_runners=resp.num_total_tasks, num_running_inputs=resp.num_running_inputs
1923
+ )
1924
1924
 
1925
1925
  @live_method
1926
1926
  async def _get_schema(self) -> api_pb2.FunctionSchema:
@@ -0,0 +1 @@
1
+ # Copyright Modal Labs 2025