modal 1.4.4.dev15__tar.gz → 1.4.4.dev17__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 (223) hide show
  1. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/PKG-INFO +1 -1
  2. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_container_entrypoint.py +158 -95
  3. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_functions.py +13 -1
  4. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_image.py +8 -3
  5. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_object.py +0 -18
  6. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/grpc_utils.py +4 -1
  7. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/entry_point.py +2 -0
  8. modal-1.4.4.dev17/modal/cli/skills.py +310 -0
  9. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/client.pyi +2 -2
  10. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cls.py +8 -0
  11. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cls.pyi +14 -0
  12. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/dict.py +0 -21
  13. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/dict.pyi +0 -56
  14. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/functions.pyi +21 -7
  15. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/object.pyi +0 -6
  16. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/queue.py +0 -18
  17. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/queue.pyi +0 -56
  18. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/sandbox.py +19 -9
  19. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/sandbox.pyi +14 -0
  20. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/secret.py +0 -18
  21. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/secret.pyi +0 -41
  22. modal-1.4.4.dev17/modal/skills/modal/SKILL.md +86 -0
  23. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/volume.py +0 -54
  24. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/volume.pyi +0 -124
  25. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal.egg-info/PKG-INFO +1 -1
  26. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal.egg-info/SOURCES.txt +2 -0
  27. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_proto/api_grpc.py +16 -0
  28. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_proto/api_pb2.py +786 -786
  29. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_proto/api_pb2.pyi +34 -5
  30. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_proto/api_pb2_grpc.py +33 -0
  31. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_proto/api_pb2_grpc.pyi +10 -0
  32. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_proto/modal_api_grpc.py +1 -0
  33. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_version/__init__.py +1 -1
  34. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/pyproject.toml +1 -1
  35. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/LICENSE +0 -0
  36. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/README.md +0 -0
  37. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/__init__.py +0 -0
  38. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/__main__.py +0 -0
  39. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_billing.py +0 -0
  40. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_clustered_functions.py +0 -0
  41. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_clustered_functions.pyi +0 -0
  42. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_environments.py +0 -0
  43. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_function_variants.py +0 -0
  44. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_grpc_client.py +0 -0
  45. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_ipython.py +0 -0
  46. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_load_context.py +0 -0
  47. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_location.py +0 -0
  48. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_logs.py +0 -0
  49. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_output/__init__.py +0 -0
  50. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_output/manager.py +0 -0
  51. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_output/pty.py +0 -0
  52. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_output/rich.py +0 -0
  53. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_output/status.py +0 -0
  54. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_partial_function.py +0 -0
  55. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_resolver.py +0 -0
  56. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_resources.py +0 -0
  57. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_runtime/__init__.py +0 -0
  58. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_runtime/asgi.py +0 -0
  59. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_runtime/container_io_manager.py +0 -0
  60. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_runtime/container_io_manager.pyi +0 -0
  61. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_runtime/execution_context.py +0 -0
  62. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_runtime/execution_context.pyi +0 -0
  63. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  64. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_runtime/task_lifecycle_manager.py +0 -0
  65. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_runtime/task_lifecycle_manager.pyi +0 -0
  66. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_runtime/telemetry.py +0 -0
  67. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_runtime/user_code_event_loop.py +0 -0
  68. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_runtime/user_code_imports.py +0 -0
  69. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_serialization.py +0 -0
  70. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_server.py +0 -0
  71. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_traceback.py +0 -0
  72. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_tunnel.py +0 -0
  73. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_tunnel.pyi +0 -0
  74. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_type_manager.py +0 -0
  75. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/__init__.py +0 -0
  76. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/app_utils.py +0 -0
  77. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/async_utils.py +0 -0
  78. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/auth_token_manager.py +0 -0
  79. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/blob_utils.py +0 -0
  80. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/browser_utils.py +0 -0
  81. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/bytes_io_segment_payload.py +0 -0
  82. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/deprecation.py +0 -0
  83. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/docker_utils.py +0 -0
  84. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/function_utils.py +0 -0
  85. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/git_utils.py +0 -0
  86. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/grpc_testing.py +0 -0
  87. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/hash_utils.py +0 -0
  88. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/http_utils.py +0 -0
  89. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/jwt_utils.py +0 -0
  90. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/logger.py +0 -0
  91. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/mount_utils.py +0 -0
  92. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/name_utils.py +0 -0
  93. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/package_utils.py +0 -0
  94. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/pattern_utils.py +0 -0
  95. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/rand_pb_testing.py +0 -0
  96. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/sandbox_fs_utils.py +0 -0
  97. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/shell_utils.py +0 -0
  98. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/task_command_router_client.py +0 -0
  99. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_utils/time_utils.py +0 -0
  100. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_vendor/__init__.py +0 -0
  101. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  102. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_vendor/cloudpickle.py +0 -0
  103. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_vendor/tblib.py +0 -0
  104. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_vendor/version.py +0 -0
  105. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_watcher.py +0 -0
  106. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/_workspace.py +0 -0
  107. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/app.py +0 -0
  108. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/app.pyi +0 -0
  109. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/billing.py +0 -0
  110. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/builder/2023.12.312.txt +0 -0
  111. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/builder/2023.12.txt +0 -0
  112. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/builder/2024.04.txt +0 -0
  113. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/builder/2024.10.txt +0 -0
  114. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/builder/2025.06.txt +0 -0
  115. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/builder/PREVIEW.txt +0 -0
  116. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/builder/README.md +0 -0
  117. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/builder/base-images.json +0 -0
  118. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/call_graph.py +0 -0
  119. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/__init__.py +0 -0
  120. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/_download.py +0 -0
  121. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/_help.py +0 -0
  122. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/_traceback.py +0 -0
  123. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/app.py +0 -0
  124. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/billing.py +0 -0
  125. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/bootstrap.py +0 -0
  126. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/changelog.py +0 -0
  127. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/cluster.py +0 -0
  128. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/config.py +0 -0
  129. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/container.py +0 -0
  130. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/dashboard.py +0 -0
  131. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/dict.py +0 -0
  132. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/environment.py +0 -0
  133. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/import_refs.py +0 -0
  134. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/launch.py +0 -0
  135. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/logo.py +0 -0
  136. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/network_file_system.py +0 -0
  137. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/profile.py +0 -0
  138. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/programs/__init__.py +0 -0
  139. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/programs/run_jupyter.py +0 -0
  140. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/programs/vscode.py +0 -0
  141. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/queues.py +0 -0
  142. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/run.py +0 -0
  143. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/secret.py +0 -0
  144. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/selector.py +0 -0
  145. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/shell.py +0 -0
  146. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/token.py +0 -0
  147. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/utils.py +0 -0
  148. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cli/volume.py +0 -0
  149. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/client.py +0 -0
  150. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cloud_bucket_mount.py +0 -0
  151. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/cloud_bucket_mount.pyi +0 -0
  152. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/config.py +0 -0
  153. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/container_process.py +0 -0
  154. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/container_process.pyi +0 -0
  155. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/environments.py +0 -0
  156. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/environments.pyi +0 -0
  157. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/exception.py +0 -0
  158. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/experimental/__init__.py +0 -0
  159. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/experimental/flash.py +0 -0
  160. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/experimental/flash.pyi +0 -0
  161. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/experimental/ipython.py +0 -0
  162. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/file_io.py +0 -0
  163. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/file_io.pyi +0 -0
  164. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/file_pattern_matcher.py +0 -0
  165. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/functions.py +0 -0
  166. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/image.py +0 -0
  167. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/image.pyi +0 -0
  168. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/io_streams.py +0 -0
  169. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/io_streams.pyi +0 -0
  170. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/mount.py +0 -0
  171. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/mount.pyi +0 -0
  172. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/network_file_system.py +0 -0
  173. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/network_file_system.pyi +0 -0
  174. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/object.py +0 -0
  175. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/output.py +0 -0
  176. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/parallel_map.py +0 -0
  177. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/parallel_map.pyi +0 -0
  178. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/partial_function.py +0 -0
  179. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/partial_function.pyi +0 -0
  180. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/proxy.py +0 -0
  181. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/proxy.pyi +0 -0
  182. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/py.typed +0 -0
  183. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/retries.py +0 -0
  184. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/runner.py +0 -0
  185. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/runner.pyi +0 -0
  186. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/running_app.py +0 -0
  187. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/sandbox_fs.py +0 -0
  188. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/sandbox_fs.pyi +0 -0
  189. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/schedule.py +0 -0
  190. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/scheduler_placement.py +0 -0
  191. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/server.py +0 -0
  192. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/server.pyi +0 -0
  193. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/serving.py +0 -0
  194. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/serving.pyi +0 -0
  195. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/snapshot.py +0 -0
  196. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/snapshot.pyi +0 -0
  197. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/stream_type.py +0 -0
  198. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/token_flow.py +0 -0
  199. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/token_flow.pyi +0 -0
  200. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/workspace.py +0 -0
  201. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal/workspace.pyi +0 -0
  202. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal.egg-info/dependency_links.txt +0 -0
  203. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal.egg-info/entry_points.txt +0 -0
  204. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal.egg-info/requires.txt +0 -0
  205. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal.egg-info/top_level.txt +0 -0
  206. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_docs/__init__.py +0 -0
  207. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_docs/gen_cli_docs.py +0 -0
  208. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_docs/gen_cli_docs_main.py +0 -0
  209. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_docs/gen_reference_docs.py +0 -0
  210. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_docs/gen_reference_docs_main.py +0 -0
  211. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_docs/mdmd/__init__.py +0 -0
  212. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_docs/mdmd/mdmd.py +0 -0
  213. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_docs/mdmd/signatures.py +0 -0
  214. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_docs/mdmd/types.py +0 -0
  215. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_proto/__init__.py +0 -0
  216. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_proto/py.typed +0 -0
  217. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_proto/task_command_router_grpc.py +0 -0
  218. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_proto/task_command_router_pb2.py +0 -0
  219. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_proto/task_command_router_pb2.pyi +0 -0
  220. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  221. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  222. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/modal_version/__main__.py +0 -0
  223. {modal-1.4.4.dev15 → modal-1.4.4.dev17}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.4.4.dev15
3
+ Version: 1.4.4.dev17
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -14,7 +14,6 @@ if telemetry_socket:
14
14
  from ._runtime.telemetry import instrument_imports
15
15
 
16
16
  instrument_imports(telemetry_socket)
17
-
18
17
  import asyncio
19
18
  import queue
20
19
  import signal
@@ -41,10 +40,11 @@ from ._runtime.container_io_manager import (
41
40
  ContainerIOManager,
42
41
  IOContext,
43
42
  )
44
- from ._runtime.task_lifecycle_manager import UserException
43
+ from ._runtime.task_lifecycle_manager import TaskLifecycleManager, UserException
45
44
 
46
45
  if TYPE_CHECKING:
47
46
  import modal._runtime.container_io_manager
47
+ import modal._runtime.task_lifecycle_manager
48
48
  import modal._runtime.user_code_imports
49
49
 
50
50
 
@@ -287,12 +287,146 @@ def get_serialized_user_class_and_function(
287
287
  return ser_usr_cls, ser_fun
288
288
 
289
289
 
290
- def main(container_args: api_pb2.ContainerArguments, client: Client):
291
- # This is a bit weird but we need both the blocking and async versions of ContainerIOManager.
292
- # At some point, we should fix that by having built-in support for running "user code"
293
- container_io_manager = ContainerIOManager(container_args, client)
290
+ def get_server_service(
291
+ container_args: api_pb2.ContainerArguments, function_def: api_pb2.Function, _client: _Client, client: Client
292
+ ) -> Service:
293
+ ser_usr_cls, ser_fun = get_serialized_user_class_and_function(function_def, _client)
294
+ service_base_function_id = container_args.app_layout.function_ids[function_def.function_name]
295
+ service_function_hydration_data = [
296
+ o for o in container_args.app_layout.objects if o.object_id == service_base_function_id
297
+ ][0]
298
+ service = import_server_service(
299
+ function_def,
300
+ service_function_hydration_data,
301
+ client,
302
+ ser_usr_cls,
303
+ )
304
+ return service
305
+
306
+
307
+ def get_class_service(
308
+ container_args: api_pb2.ContainerArguments, function_def: api_pb2.Function, _client: _Client, client: Client
309
+ ) -> Service:
310
+ ser_usr_cls, ser_fun = get_serialized_user_class_and_function(function_def, _client)
311
+ if container_args.serialized_params:
312
+ param_args, param_kwargs = deserialize_params(container_args.serialized_params, function_def, _client)
313
+ else:
314
+ param_args = ()
315
+ param_kwargs = {}
316
+ # this is a bit ugly - match the function and class based on function name to get metadata
317
+ # This metadata is required in order to hydrate the class in case it's not globally
318
+ # decorated (or serialized)
319
+ service_base_function_id = container_args.app_layout.function_ids[function_def.function_name]
320
+ service_function_hydration_data = [
321
+ o for o in container_args.app_layout.objects if o.object_id == service_base_function_id
322
+ ][0]
323
+ class_id = container_args.app_layout.class_ids[function_def.function_name.removesuffix(".*")]
324
+
325
+ service = import_class_service(
326
+ function_def,
327
+ service_function_hydration_data,
328
+ class_id,
329
+ client,
330
+ ser_usr_cls,
331
+ param_args,
332
+ param_kwargs,
333
+ )
334
+ return service
335
+
336
+
337
+ def get_function_service(function_def: api_pb2.Function, _client: _Client) -> Service:
338
+ ser_usr_cls, ser_fun = get_serialized_user_class_and_function(function_def, _client)
339
+ assert ser_usr_cls is None
340
+ service = import_single_function_service(
341
+ function_def,
342
+ ser_fun,
343
+ )
344
+ return service
345
+
346
+
347
+ def hydrate_function(
348
+ container_args: api_pb2.ContainerArguments,
349
+ task_lifecycle_manager: TaskLifecycleManager,
350
+ function_def: api_pb2.Function,
351
+ _client: _Client,
352
+ client: Client,
353
+ ) -> Service:
294
354
  active_app: _App
295
355
  service: Service
356
+ with task_lifecycle_manager.handle_task_lifecycle_exception():
357
+ with execution_context._import_context():
358
+ if function_def.is_server:
359
+ service = get_server_service(container_args, function_def, _client, client)
360
+ elif function_def.is_class:
361
+ service = get_class_service(container_args, function_def, _client, client)
362
+ else:
363
+ service = get_function_service(function_def, _client)
364
+
365
+ active_app = service.app
366
+
367
+ # Get ids and metadata for objects (primarily functions and classes) on the app
368
+ container_app: RunningApp = running_app_from_layout(container_args.app_id, container_args.app_layout)
369
+
370
+ # Initialize objects on the app.
371
+ # This is basically only functions and classes - anything else is deprecated and will be unsupported soon
372
+ app: App = cast(App, synchronizer._translate_out(active_app))
373
+ app._init_container(client, container_app)
374
+
375
+ # Hydrate all function dependencies.
376
+ # TODO(erikbern): we an remove this once we
377
+ # 1. Enable lazy hydration for all objects
378
+ # 2. Fully deprecate .new() objects
379
+ if service.service_deps is not None: # this is not set for serialized or non-global scope functions
380
+ dep_object_ids: list[str] = [dep.object_id for dep in function_def.object_dependencies]
381
+ if len(service.service_deps) != len(dep_object_ids):
382
+ raise ExecutionError(
383
+ f"Function has {len(service.service_deps)} dependencies"
384
+ f" but container got {len(dep_object_ids)} object ids.\n"
385
+ f"Code deps: {service.service_deps}\n"
386
+ f"Object ids: {dep_object_ids}\n"
387
+ "\n"
388
+ "This can happen if you are defining Modal objects under a conditional statement "
389
+ "that evaluates differently in the local and remote environments."
390
+ )
391
+ for object_id, obj in zip(dep_object_ids, service.service_deps):
392
+ metadata: Message | None = container_app.object_handle_metadata[object_id]
393
+ obj._hydrate(object_id, _client, metadata)
394
+
395
+ return service
396
+
397
+
398
+ def run_server(container_args: api_pb2.ContainerArguments, client: Client):
399
+ function_def = container_args.function_def
400
+ _client: _Client = cast(_Client, synchronizer._translate_in(client)) # TODO(erikbern): ugly
401
+ task_lifecycle_manager = TaskLifecycleManager(
402
+ container_args.task_id,
403
+ container_args.function_id,
404
+ container_args.function_def,
405
+ container_args.checkpoint_id or None,
406
+ client,
407
+ )
408
+
409
+ service: Service = hydrate_function(container_args, task_lifecycle_manager, function_def, _client, client)
410
+ # Initialize clustered functions.
411
+ if function_def._experimental_group_size > 0:
412
+ initialize_clustered_function(
413
+ client,
414
+ container_args.task_id,
415
+ function_def._experimental_group_size,
416
+ )
417
+
418
+ with UserCodeEventLoop() as event_loop:
419
+ with service.lifecycle_context(
420
+ event_loop,
421
+ task_lifecycle_manager=task_lifecycle_manager,
422
+ ):
423
+ call_server(event_loop)
424
+
425
+
426
+ def run_function(container_args: api_pb2.ContainerArguments, client: Client):
427
+ # This is a bit weird but we need both the blocking and async versions of ContainerIOManager.
428
+ # At some point, we should fix that by having built-in support for running "user code"
429
+ container_io_manager: Any = ContainerIOManager(container_args, client)
296
430
  function_def = container_args.function_def
297
431
  # The worker sets this flag to "1" for snapshot and restore tasks. Otherwise, this flag is unset,
298
432
  # in which case snapshots should be disabled.
@@ -306,92 +440,17 @@ def main(container_args: api_pb2.ContainerArguments, client: Client):
306
440
  container_io_manager.hello()
307
441
 
308
442
  with container_io_manager.heartbeats(is_snapshotting_function), UserCodeEventLoop() as event_loop:
309
- # If this is a serialized function, fetch the definition from the server
310
- ser_usr_cls, ser_fun = get_serialized_user_class_and_function(function_def, _client)
311
-
312
443
  # Initialize the function, importing user code.
313
- with container_io_manager.get_task_lifecycle_manager().handle_task_lifecycle_exception():
314
- if container_args.serialized_params:
315
- param_args, param_kwargs = deserialize_params(container_args.serialized_params, function_def, _client)
316
- else:
317
- param_args = ()
318
- param_kwargs = {}
319
-
320
- with execution_context._import_context():
321
- if function_def.is_server:
322
- service_base_function_id = container_args.app_layout.function_ids[function_def.function_name]
323
- service_function_hydration_data = [
324
- o for o in container_args.app_layout.objects if o.object_id == service_base_function_id
325
- ][0]
326
- service = import_server_service(
327
- function_def,
328
- service_function_hydration_data,
329
- client,
330
- ser_usr_cls,
331
- )
332
- elif function_def.is_class:
333
- # this is a bit ugly - match the function and class based on function name to get metadata
334
- # This metadata is required in order to hydrate the class in case it's not globally
335
- # decorated (or serialized)
336
- service_base_function_id = container_args.app_layout.function_ids[function_def.function_name]
337
- service_function_hydration_data = [
338
- o for o in container_args.app_layout.objects if o.object_id == service_base_function_id
339
- ][0]
340
- class_id = container_args.app_layout.class_ids[function_def.function_name.removesuffix(".*")]
341
-
342
- service = import_class_service(
343
- function_def,
344
- service_function_hydration_data,
345
- class_id,
346
- client,
347
- ser_usr_cls,
348
- param_args,
349
- param_kwargs,
350
- )
351
- else:
352
- assert ser_usr_cls is None
353
- service = import_single_function_service(
354
- function_def,
355
- ser_fun,
356
- )
357
-
358
- active_app = service.app
359
-
360
- if function_def.pty_info.pty_type == api_pb2.PTYInfo.PTY_TYPE_SHELL:
361
- # Concurrency and batching doesn't apply for `modal shell`.
362
- batch_max_size = 0
363
- batch_wait_ms = 0
364
- else:
365
- batch_max_size = function_def.batch_max_size or 0
366
- batch_wait_ms = function_def.batch_linger_ms or 0
367
-
368
- # Get ids and metadata for objects (primarily functions and classes) on the app
369
- container_app: RunningApp = running_app_from_layout(container_args.app_id, container_args.app_layout)
370
-
371
- # Initialize objects on the app.
372
- # This is basically only functions and classes - anything else is deprecated and will be unsupported soon
373
- app: App = cast(App, synchronizer._translate_out(active_app))
374
- app._init_container(client, container_app)
375
-
376
- # Hydrate all function dependencies.
377
- # TODO(erikbern): we an remove this once we
378
- # 1. Enable lazy hydration for all objects
379
- # 2. Fully deprecate .new() objects
380
- if service.service_deps is not None: # this is not set for serialized or non-global scope functions
381
- dep_object_ids: list[str] = [dep.object_id for dep in function_def.object_dependencies]
382
- if len(service.service_deps) != len(dep_object_ids):
383
- raise ExecutionError(
384
- f"Function has {len(service.service_deps)} dependencies"
385
- f" but container got {len(dep_object_ids)} object ids.\n"
386
- f"Code deps: {service.service_deps}\n"
387
- f"Object ids: {dep_object_ids}\n"
388
- "\n"
389
- "This can happen if you are defining Modal objects under a conditional statement "
390
- "that evaluates differently in the local and remote environments."
391
- )
392
- for object_id, obj in zip(dep_object_ids, service.service_deps):
393
- metadata: Message | None = container_app.object_handle_metadata[object_id]
394
- obj._hydrate(object_id, _client, metadata)
444
+ service: Service = hydrate_function(
445
+ container_args, container_io_manager.get_task_lifecycle_manager(), function_def, _client, client
446
+ )
447
+ if function_def.pty_info.pty_type == api_pb2.PTYInfo.PTY_TYPE_SHELL:
448
+ # Concurrency and batching doesn't apply for `modal shell`.
449
+ batch_max_size = 0
450
+ batch_wait_ms = 0
451
+ else:
452
+ batch_max_size = function_def.batch_max_size or 0
453
+ batch_wait_ms = function_def.batch_linger_ms or 0
395
454
 
396
455
  # Initialize clustered functions.
397
456
  if function_def._experimental_group_size > 0:
@@ -407,10 +466,14 @@ def main(container_args: api_pb2.ContainerArguments, client: Client):
407
466
  ) as finalized_functions:
408
467
  # This context managers handles pre/post snapshot lifecycle of the user code,
409
468
  # finalized functions, ASGI/WSGI lifespan, and volume commit.
410
- if function_def.is_server:
411
- call_server(event_loop)
412
- else:
413
- call_function(event_loop, container_io_manager, finalized_functions, batch_max_size, batch_wait_ms)
469
+ call_function(event_loop, container_io_manager, finalized_functions, batch_max_size, batch_wait_ms)
470
+
471
+
472
+ def main(container_args: api_pb2.ContainerArguments, client: Client):
473
+ if container_args.function_def.is_server:
474
+ run_server(container_args, client)
475
+ else:
476
+ run_function(container_args, client)
414
477
 
415
478
 
416
479
  if __name__ == "__main__":
@@ -1208,6 +1208,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1208
1208
  app_name: str,
1209
1209
  name: str,
1210
1210
  *,
1211
+ version: int | None = None,
1211
1212
  load_context_overrides: LoadContext,
1212
1213
  ):
1213
1214
  # internal function lookup implementation that allows lookup of class "service functions"
@@ -1219,6 +1220,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1219
1220
  app_name=app_name,
1220
1221
  object_tag=name,
1221
1222
  environment_name=load_context.environment_name,
1223
+ app_version=version or 0,
1222
1224
  )
1223
1225
  try:
1224
1226
  response = await load_context.client.stub.FunctionGet(request)
@@ -1251,6 +1253,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1251
1253
  app_name: str,
1252
1254
  name: str,
1253
1255
  *,
1256
+ version: int | None = None,
1254
1257
  environment_name: str | None = None,
1255
1258
  client: _Client | None = None,
1256
1259
  ) -> "_Function":
@@ -1273,6 +1276,12 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1273
1276
  ```python
1274
1277
  f = modal.Function.from_name("other-app", "function")
1275
1278
  ```
1279
+
1280
+ The `version` parameter allows you to invoke a version-pinned function:
1281
+
1282
+ ```python
1283
+ f_v3 = modal.Function.from_name("other-app", "function", version=3)
1284
+ ```
1276
1285
  """
1277
1286
  if "." in name:
1278
1287
  raise InvalidError(
@@ -1281,7 +1290,10 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1281
1290
  )
1282
1291
 
1283
1292
  return cls._from_name(
1284
- app_name, name, load_context_overrides=LoadContext(environment_name=environment_name, client=client)
1293
+ app_name,
1294
+ name,
1295
+ load_context_overrides=LoadContext(environment_name=environment_name, client=client),
1296
+ version=version,
1285
1297
  )
1286
1298
 
1287
1299
  @property
@@ -60,6 +60,7 @@ from .secret import _Secret
60
60
  from .volume import _Volume, _volume_to_mount_proto
61
61
 
62
62
  if typing.TYPE_CHECKING:
63
+ import modal
63
64
  import modal._functions
64
65
  import modal.client
65
66
 
@@ -531,7 +532,7 @@ class _Image(_Object, type_prefix="im"):
531
532
 
532
533
  for secret in secrets:
533
534
  if not isinstance(secret, _Secret):
534
- raise InvalidError("All secrets of an image needs to be modal.Secret/AioSecret instances")
535
+ raise InvalidError("All secrets of an Image need to be modal.Secret instances.")
535
536
 
536
537
  if build_function and len(base_images) != 1:
537
538
  raise InvalidError("Cannot run a build function with multiple base images!")
@@ -2763,7 +2764,7 @@ class _Image(_Object, type_prefix="im"):
2763
2764
 
2764
2765
  def pipe(
2765
2766
  self,
2766
- func: Callable[Concatenate["_Image", P], "_Image"],
2767
+ func: Callable[Concatenate["modal.Image", P], "modal.Image"],
2767
2768
  *args: P.args,
2768
2769
  **kwargs: P.kwargs,
2769
2770
  ) -> "_Image":
@@ -2785,7 +2786,11 @@ class _Image(_Object, type_prefix="im"):
2785
2786
  )
2786
2787
  ```
2787
2788
  """
2788
- return func(self, *args, **kwargs)
2789
+ # Typing here is complicated because user callables accept the public
2790
+ # Image type, but `self` is an instance of the internal _Image type.
2791
+ self_ = synchronizer._translate_out(self)
2792
+ res = func(self_, *args, **kwargs) # type: ignore[reportUnknownReturnType]
2793
+ return typing.cast(_Image, synchronizer._translate_in(res))
2789
2794
 
2790
2795
  # Live handle methods
2791
2796
 
@@ -14,7 +14,6 @@ from modal._traceback import suppress_tb_frame
14
14
  from ._load_context import LoadContext
15
15
  from ._resolver import Resolver
16
16
  from ._utils.async_utils import TaskContext, aclosing
17
- from ._utils.deprecation import deprecation_warning
18
17
  from .client import _Client
19
18
  from .config import config, logger
20
19
  from .exception import ExecutionError, InvalidError
@@ -196,23 +195,6 @@ class _Object:
196
195
  f"{object_type} has not been hydrated with the metadata it needs to run on Modal{reason}."
197
196
  )
198
197
 
199
- def clone(self) -> Self:
200
- """mdmd:hidden Clone a given hydrated object.
201
-
202
- Note: This is not intended to be public API and has no public use. It will be removed in a future release.
203
- """
204
- object_class = self.__class__.__name__.strip("_")
205
- deprecation_warning(
206
- (2025, 6, 30),
207
- f"{object_class}.clone() is not intended to be public API and will be removed in a future release.",
208
- )
209
-
210
- # Object to clone must already be hydrated, otherwise from_loader is more suitable.
211
- self._validate_is_hydrated()
212
- obj = type(self).__new__(type(self))
213
- obj._initialize_from_other(self)
214
- return obj
215
-
216
198
  @classmethod
217
199
  def _from_loader(
218
200
  cls,
@@ -153,7 +153,10 @@ class CustomProtoStatusDetailsCodec(StatusDetailsCodecBase):
153
153
  if details is not None:
154
154
  for detail in details:
155
155
  detail_container = details_proto.details.add()
156
- detail_container.Pack(detail)
156
+ if detail.DESCRIPTOR.full_name.startswith("modal."):
157
+ detail_container.Pack(detail, type_url_prefix="type.modal.com/")
158
+ else:
159
+ detail_container.Pack(detail)
157
160
  return details_proto.SerializeToString()
158
161
 
159
162
  def decode(
@@ -25,6 +25,7 @@ from .network_file_system import nfs_cli
25
25
  from .profile import profile_cli
26
26
  from .queues import queue_cli
27
27
  from .secret import secret_cli
28
+ from .skills import skills_cli
28
29
  from .token import _new_token, token_cli
29
30
  from .volume import volume_cli
30
31
 
@@ -117,6 +118,7 @@ entrypoint_cli.add_command(bootstrap, panel="Onboarding")
117
118
  entrypoint_cli.add_command(config_cli, panel="Configuration")
118
119
  entrypoint_cli.add_command(environment_cli, panel="Configuration")
119
120
  entrypoint_cli.add_command(profile_cli, panel="Configuration")
121
+ entrypoint_cli.add_command(skills_cli, panel="Configuration")
120
122
  entrypoint_cli.add_command(token_cli, panel="Configuration")
121
123
 
122
124
  entrypoint_cli.add_command(billing_cli, panel="Observability")