modAL 1.2.2.dev31__tar.gz → 1.2.2.dev33__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 (200) hide show
  1. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/PKG-INFO +1 -1
  2. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_functions.py +13 -20
  3. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_object.py +4 -4
  4. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/client.pyi +2 -2
  5. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/functions.pyi +0 -1
  6. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/secret.py +32 -31
  7. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/secret.pyi +9 -2
  8. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal.egg-info/PKG-INFO +1 -1
  9. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_version/__init__.py +1 -1
  10. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/LICENSE +0 -0
  11. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/README.md +0 -0
  12. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/__init__.py +0 -0
  13. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/__main__.py +0 -0
  14. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_billing.py +0 -0
  15. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_clustered_functions.py +0 -0
  16. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_clustered_functions.pyi +0 -0
  17. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_container_entrypoint.py +0 -0
  18. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_grpc_client.py +0 -0
  19. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_ipython.py +0 -0
  20. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_load_context.py +0 -0
  21. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_location.py +0 -0
  22. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_output.py +0 -0
  23. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_partial_function.py +0 -0
  24. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_pty.py +0 -0
  25. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_resolver.py +0 -0
  26. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_resources.py +0 -0
  27. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_runtime/__init__.py +0 -0
  28. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_runtime/asgi.py +0 -0
  29. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_runtime/container_io_manager.py +0 -0
  30. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_runtime/container_io_manager.pyi +0 -0
  31. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_runtime/execution_context.py +0 -0
  32. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_runtime/execution_context.pyi +0 -0
  33. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  34. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_runtime/telemetry.py +0 -0
  35. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_runtime/user_code_imports.py +0 -0
  36. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_serialization.py +0 -0
  37. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_traceback.py +0 -0
  38. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_tunnel.py +0 -0
  39. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_tunnel.pyi +0 -0
  40. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_type_manager.py +0 -0
  41. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/__init__.py +0 -0
  42. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/app_utils.py +0 -0
  43. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/async_utils.py +0 -0
  44. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/auth_token_manager.py +0 -0
  45. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/blob_utils.py +0 -0
  46. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/bytes_io_segment_payload.py +0 -0
  47. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/deprecation.py +0 -0
  48. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/docker_utils.py +0 -0
  49. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/function_utils.py +0 -0
  50. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/git_utils.py +0 -0
  51. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/grpc_testing.py +0 -0
  52. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/grpc_utils.py +0 -0
  53. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/hash_utils.py +0 -0
  54. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/http_utils.py +0 -0
  55. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/jwt_utils.py +0 -0
  56. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/logger.py +0 -0
  57. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/mount_utils.py +0 -0
  58. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/name_utils.py +0 -0
  59. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/package_utils.py +0 -0
  60. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/pattern_utils.py +0 -0
  61. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/rand_pb_testing.py +0 -0
  62. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/shell_utils.py +0 -0
  63. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/task_command_router_client.py +0 -0
  64. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_utils/time_utils.py +0 -0
  65. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_vendor/__init__.py +0 -0
  66. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  67. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_vendor/cloudpickle.py +0 -0
  68. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_vendor/tblib.py +0 -0
  69. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/_watcher.py +0 -0
  70. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/app.py +0 -0
  71. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/app.pyi +0 -0
  72. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/billing.py +0 -0
  73. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/builder/2023.12.312.txt +0 -0
  74. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/builder/2023.12.txt +0 -0
  75. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/builder/2024.04.txt +0 -0
  76. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/builder/2024.10.txt +0 -0
  77. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/builder/2025.06.txt +0 -0
  78. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/builder/PREVIEW.txt +0 -0
  79. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/builder/README.md +0 -0
  80. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/builder/base-images.json +0 -0
  81. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/call_graph.py +0 -0
  82. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/__init__.py +0 -0
  83. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/_download.py +0 -0
  84. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/_traceback.py +0 -0
  85. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/app.py +0 -0
  86. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/cluster.py +0 -0
  87. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/config.py +0 -0
  88. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/container.py +0 -0
  89. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/dict.py +0 -0
  90. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/entry_point.py +0 -0
  91. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/environment.py +0 -0
  92. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/import_refs.py +0 -0
  93. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/launch.py +0 -0
  94. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/network_file_system.py +0 -0
  95. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/profile.py +0 -0
  96. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/programs/__init__.py +0 -0
  97. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/programs/launch_instance_ssh.py +0 -0
  98. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/programs/run_jupyter.py +0 -0
  99. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/programs/run_marimo.py +0 -0
  100. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/programs/vscode.py +0 -0
  101. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/queues.py +0 -0
  102. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/run.py +0 -0
  103. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/secret.py +0 -0
  104. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/token.py +0 -0
  105. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/utils.py +0 -0
  106. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cli/volume.py +0 -0
  107. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/client.py +0 -0
  108. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cloud_bucket_mount.py +0 -0
  109. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cloud_bucket_mount.pyi +0 -0
  110. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cls.py +0 -0
  111. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/cls.pyi +0 -0
  112. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/config.py +0 -0
  113. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/container_process.py +0 -0
  114. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/container_process.pyi +0 -0
  115. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/dict.py +0 -0
  116. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/dict.pyi +0 -0
  117. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/environments.py +0 -0
  118. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/environments.pyi +0 -0
  119. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/exception.py +0 -0
  120. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/experimental/__init__.py +0 -0
  121. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/experimental/flash.py +0 -0
  122. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/experimental/flash.pyi +0 -0
  123. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/experimental/ipython.py +0 -0
  124. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/file_io.py +0 -0
  125. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/file_io.pyi +0 -0
  126. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/file_pattern_matcher.py +0 -0
  127. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/functions.py +0 -0
  128. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/gpu.py +0 -0
  129. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/image.py +0 -0
  130. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/image.pyi +0 -0
  131. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/io_streams.py +0 -0
  132. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/io_streams.pyi +0 -0
  133. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/mount.py +0 -0
  134. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/mount.pyi +0 -0
  135. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/network_file_system.py +0 -0
  136. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/network_file_system.pyi +0 -0
  137. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/object.py +0 -0
  138. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/object.pyi +0 -0
  139. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/output.py +0 -0
  140. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/parallel_map.py +0 -0
  141. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/parallel_map.pyi +0 -0
  142. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/partial_function.py +0 -0
  143. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/partial_function.pyi +0 -0
  144. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/proxy.py +0 -0
  145. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/proxy.pyi +0 -0
  146. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/py.typed +0 -0
  147. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/queue.py +0 -0
  148. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/queue.pyi +0 -0
  149. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/retries.py +0 -0
  150. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/runner.py +0 -0
  151. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/runner.pyi +0 -0
  152. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/running_app.py +0 -0
  153. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/sandbox.py +0 -0
  154. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/sandbox.pyi +0 -0
  155. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/schedule.py +0 -0
  156. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/scheduler_placement.py +0 -0
  157. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/serving.py +0 -0
  158. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/serving.pyi +0 -0
  159. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/snapshot.py +0 -0
  160. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/snapshot.pyi +0 -0
  161. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/stream_type.py +0 -0
  162. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/token_flow.py +0 -0
  163. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/token_flow.pyi +0 -0
  164. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/volume.py +0 -0
  165. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal/volume.pyi +0 -0
  166. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal.egg-info/SOURCES.txt +0 -0
  167. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal.egg-info/dependency_links.txt +0 -0
  168. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal.egg-info/entry_points.txt +0 -0
  169. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal.egg-info/requires.txt +0 -0
  170. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal.egg-info/top_level.txt +0 -0
  171. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_docs/__init__.py +0 -0
  172. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_docs/gen_cli_docs.py +0 -0
  173. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_docs/gen_reference_docs.py +0 -0
  174. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_docs/mdmd/__init__.py +0 -0
  175. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_docs/mdmd/mdmd.py +0 -0
  176. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_docs/mdmd/signatures.py +0 -0
  177. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/__init__.py +0 -0
  178. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/api.proto +0 -0
  179. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/api_grpc.py +0 -0
  180. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/api_pb2.py +0 -0
  181. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/api_pb2.pyi +0 -0
  182. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/api_pb2_grpc.py +0 -0
  183. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/api_pb2_grpc.pyi +0 -0
  184. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/modal_api_grpc.py +0 -0
  185. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/py.typed +0 -0
  186. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/sandbox_router.proto +0 -0
  187. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/sandbox_router_grpc.py +0 -0
  188. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/sandbox_router_pb2.py +0 -0
  189. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/sandbox_router_pb2.pyi +0 -0
  190. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/sandbox_router_pb2_grpc.py +0 -0
  191. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/sandbox_router_pb2_grpc.pyi +0 -0
  192. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/task_command_router.proto +0 -0
  193. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/task_command_router_grpc.py +0 -0
  194. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/task_command_router_pb2.py +0 -0
  195. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/task_command_router_pb2.pyi +0 -0
  196. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  197. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  198. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/modal_version/__main__.py +0 -0
  199. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/pyproject.toml +0 -0
  200. {modal-1.2.2.dev31 → modal-1.2.2.dev33}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.2.dev31
3
+ Version: 1.2.2.dev33
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -1671,8 +1671,8 @@ Use the `Function.get_web_url()` method instead.
1671
1671
  input_queue,
1672
1672
  self.client,
1673
1673
  )
1674
- metadata = api_pb2.FunctionCallFromIdResponse(function_call_id=function_call_id, num_inputs=num_inputs)
1675
- fc: _FunctionCall[ReturnType] = _FunctionCall._new_hydrated(function_call_id, self.client, metadata)
1674
+ fc: _FunctionCall[ReturnType] = _FunctionCall._new_hydrated(function_call_id, self.client, None)
1675
+ fc._num_inputs = num_inputs # set the cached value of num_inputs
1676
1676
  return fc
1677
1677
 
1678
1678
  async def _call_function(self, args, kwargs) -> ReturnType:
@@ -1941,19 +1941,16 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
1941
1941
  def _invocation(self):
1942
1942
  return _Invocation(self.client.stub, self.object_id, self.client)
1943
1943
 
1944
- def _hydrate_metadata(self, metadata: Optional[Message]):
1945
- if not metadata:
1946
- return
1947
- assert isinstance(metadata, api_pb2.FunctionCallFromIdResponse)
1948
- self._num_inputs = metadata.num_inputs
1949
-
1950
1944
  @live_method
1951
1945
  async def num_inputs(self) -> int:
1952
1946
  """Get the number of inputs in the function call."""
1953
- # Should have been hydrated.
1954
- assert self._num_inputs is not None
1947
+ if self._num_inputs is None:
1948
+ request = api_pb2.FunctionCallFromIdRequest(function_call_id=self.object_id)
1949
+ resp = await self.client.stub.FunctionCallFromId(request)
1950
+ self._num_inputs = resp.num_inputs # cached
1955
1951
  return self._num_inputs
1956
1952
 
1953
+ @live_method
1957
1954
  async def get(self, timeout: Optional[float] = None, *, index: int = 0) -> ReturnType:
1958
1955
  """Get the result of the index-th input of the function call.
1959
1956
  `.spawn()` calls have a single output, so only specifying `index=0` is valid.
@@ -1997,6 +1994,7 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
1997
1994
  async for _, item in self._invocation().enumerate(start_index=start, end_index=end):
1998
1995
  yield item
1999
1996
 
1997
+ @live_method
2000
1998
  async def get_call_graph(self) -> list[InputInfo]:
2001
1999
  """Returns a structure representing the call graph from a given root
2002
2000
  call ID, along with the status of execution for each node.
@@ -2009,6 +2007,7 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
2009
2007
  response = await self._client.stub.FunctionGetCallGraph(request)
2010
2008
  return _reconstruct_call_graph(response)
2011
2009
 
2010
+ @live_method
2012
2011
  async def cancel(
2013
2012
  self,
2014
2013
  # if true, containers running the inputs are forcibly terminated
@@ -2050,21 +2049,15 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
2050
2049
  async def _load(
2051
2050
  self: _FunctionCall, resolver: Resolver, load_context: LoadContext, existing_object_id: Optional[str]
2052
2051
  ):
2053
- request = api_pb2.FunctionCallFromIdRequest(function_call_id=function_call_id)
2054
- resp = await load_context.client.stub.FunctionCallFromId(request)
2055
- self._hydrate(function_call_id, load_context.client, resp)
2052
+ # this loader doesn't do anything in practice, but it will get the client from the load_context
2053
+ self._hydrate(function_call_id, load_context.client, None)
2056
2054
 
2057
2055
  rep = f"FunctionCall.from_id({function_call_id!r})"
2058
- fc: _FunctionCall[Any] = _FunctionCall._from_loader(
2056
+
2057
+ return _FunctionCall._from_loader(
2059
2058
  _load, rep, hydrate_lazily=True, load_context_overrides=LoadContext(client=client)
2060
2059
  )
2061
2060
 
2062
- # TODO(elias): Remove these
2063
- # We already know the object ID, so we can set it directly
2064
- fc._object_id = function_call_id
2065
- fc._client = client
2066
- return fc
2067
-
2068
2061
  @staticmethod
2069
2062
  async def gather(*function_calls: "_FunctionCall[T]") -> typing.Sequence[T]:
2070
2063
  """Wait until all Modal FunctionCall objects have results before returning.
@@ -310,19 +310,19 @@ class _Object:
310
310
  logger.debug(f"rehydrating {self} after snapshot")
311
311
  self._is_hydrated = False # un-hydrate and re-resolve
312
312
  # Set the client on LoadContext before loading
313
- root_context = LoadContext(client=client)
313
+ root_load_context = LoadContext(client=client)
314
314
  resolver = Resolver()
315
- await resolver.load(typing.cast(_Object, self), root_context, existing_object_id=None)
315
+ await resolver.load(typing.cast(_Object, self), root_load_context)
316
316
  self._is_rehydrated = True
317
317
  logger.debug(f"rehydrated {self} with client {id(self.client)}")
318
318
  elif not self._hydrate_lazily:
319
319
  self._validate_is_hydrated()
320
320
  else:
321
321
  # Set the client on LoadContext before loading
322
- root_context = LoadContext(client=client)
322
+ root_load_context = LoadContext(client=client)
323
323
  resolver = Resolver()
324
324
  with suppress_tb_frames(1): # skip this frame by default
325
- await resolver.load(self, root_context)
325
+ await resolver.load(self, root_load_context)
326
326
  return self
327
327
 
328
328
 
@@ -33,7 +33,7 @@ class _Client:
33
33
  server_url: str,
34
34
  client_type: int,
35
35
  credentials: typing.Optional[tuple[str, str]],
36
- version: str = "1.2.2.dev31",
36
+ version: str = "1.2.2.dev33",
37
37
  ):
38
38
  """mdmd:hidden
39
39
  The Modal client object is not intended to be instantiated directly by users.
@@ -164,7 +164,7 @@ class Client:
164
164
  server_url: str,
165
165
  client_type: int,
166
166
  credentials: typing.Optional[tuple[str, str]],
167
- version: str = "1.2.2.dev31",
167
+ version: str = "1.2.2.dev33",
168
168
  ):
169
169
  """mdmd:hidden
170
170
  The Modal client object is not intended to be instantiated directly by users.
@@ -721,7 +721,6 @@ class FunctionCall(typing.Generic[modal._functions.ReturnType], modal.object.Obj
721
721
  ...
722
722
 
723
723
  def _invocation(self): ...
724
- def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
725
724
 
726
725
  class __num_inputs_spec(typing_extensions.Protocol[SUPERSELF]):
727
726
  def __call__(self, /) -> int:
@@ -206,6 +206,33 @@ class _SecretManager:
206
206
  SecretManager = synchronize_api(_SecretManager)
207
207
 
208
208
 
209
+ async def _load_from_env_dict(instance: "_Secret", load_context: LoadContext, env_dict: dict[str, str]):
210
+ """helper method for loaders .from_dict and .from_dotenv etc."""
211
+ if load_context.app_id is not None:
212
+ req = api_pb2.SecretGetOrCreateRequest(
213
+ object_creation_type=api_pb2.OBJECT_CREATION_TYPE_ANONYMOUS_OWNED_BY_APP,
214
+ env_dict=env_dict,
215
+ app_id=load_context.app_id,
216
+ environment_name=load_context.environment_name,
217
+ )
218
+ else:
219
+ req = api_pb2.SecretGetOrCreateRequest(
220
+ object_creation_type=api_pb2.OBJECT_CREATION_TYPE_EPHEMERAL,
221
+ env_dict=env_dict,
222
+ environment_name=load_context.environment_name,
223
+ )
224
+
225
+ try:
226
+ resp = await load_context.client.stub.SecretGetOrCreate(req)
227
+ except GRPCError as exc:
228
+ if exc.status == Status.INVALID_ARGUMENT:
229
+ raise InvalidError(exc.message)
230
+ if exc.status == Status.FAILED_PRECONDITION:
231
+ raise InvalidError(exc.message)
232
+ raise
233
+ instance._hydrate(resp.secret_id, load_context.client, resp.metadata)
234
+
235
+
209
236
  class _Secret(_Object, type_prefix="st"):
210
237
  """Secrets provide a dictionary of environment variables for images.
211
238
 
@@ -263,26 +290,7 @@ class _Secret(_Object, type_prefix="st"):
263
290
  async def _load(
264
291
  self: _Secret, resolver: Resolver, load_context: LoadContext, existing_object_id: Optional[str]
265
292
  ):
266
- if load_context.app_id is not None:
267
- object_creation_type = api_pb2.OBJECT_CREATION_TYPE_ANONYMOUS_OWNED_BY_APP
268
- else:
269
- object_creation_type = api_pb2.OBJECT_CREATION_TYPE_EPHEMERAL
270
-
271
- req = api_pb2.SecretGetOrCreateRequest(
272
- object_creation_type=object_creation_type,
273
- env_dict=env_dict_filtered,
274
- app_id=load_context.app_id,
275
- environment_name=load_context.environment_name,
276
- )
277
- try:
278
- resp = await load_context.client.stub.SecretGetOrCreate(req)
279
- except GRPCError as exc:
280
- if exc.status == Status.INVALID_ARGUMENT:
281
- raise InvalidError(exc.message)
282
- if exc.status == Status.FAILED_PRECONDITION:
283
- raise InvalidError(exc.message)
284
- raise
285
- self._hydrate(resp.secret_id, load_context.client, resp.metadata)
293
+ await _load_from_env_dict(self, load_context, env_dict_filtered)
286
294
 
287
295
  rep = f"Secret.from_dict([{', '.join(env_dict.keys())}])"
288
296
  # TODO: scoping - these should probably not be lazily hydrated without having an app and/or sandbox association
@@ -306,7 +314,7 @@ class _Secret(_Object, type_prefix="st"):
306
314
  return _Secret.from_dict({})
307
315
 
308
316
  @staticmethod
309
- def from_dotenv(path=None, *, filename=".env") -> "_Secret":
317
+ def from_dotenv(path=None, *, filename=".env", client: Optional[_Client] = None) -> "_Secret":
310
318
  """Create secrets from a .env file automatically.
311
319
 
312
320
  If no argument is provided, it will use the current working directory as the starting
@@ -360,19 +368,12 @@ class _Secret(_Object, type_prefix="st"):
360
368
  # To simplify this, we just support the cwd and don't do any automatic path inference.
361
369
  dotenv_path = find_dotenv(filename, usecwd=True)
362
370
 
363
- env_dict = dotenv_values(dotenv_path)
364
-
365
- req = api_pb2.SecretGetOrCreateRequest(
366
- object_creation_type=api_pb2.OBJECT_CREATION_TYPE_ANONYMOUS_OWNED_BY_APP,
367
- env_dict=env_dict,
368
- app_id=load_context.app_id, # TODO: what if app_id isn't set here (e.g. .hydrate())
369
- )
370
- resp = await load_context.client.stub.SecretGetOrCreate(req)
371
+ env_dict = {k: v or "" for k, v in dotenv_values(dotenv_path).items()}
371
372
 
372
- self._hydrate(resp.secret_id, load_context.client, resp.metadata)
373
+ await _load_from_env_dict(self, load_context, env_dict)
373
374
 
374
375
  return _Secret._from_loader(
375
- _load, "Secret.from_dotenv()", hydrate_lazily=True, load_context_overrides=LoadContext.empty()
376
+ _load, "Secret.from_dotenv()", hydrate_lazily=True, load_context_overrides=LoadContext(client=client)
376
377
  )
377
378
 
378
379
  @staticmethod
@@ -1,5 +1,6 @@
1
1
  import datetime
2
2
  import google.protobuf.message
3
+ import modal._load_context
3
4
  import modal._object
4
5
  import modal.client
5
6
  import modal.object
@@ -355,6 +356,12 @@ class SecretManager:
355
356
 
356
357
  delete: __delete_spec
357
358
 
359
+ async def _load_from_env_dict(
360
+ instance: _Secret, load_context: modal._load_context.LoadContext, env_dict: dict[str, str]
361
+ ):
362
+ """helper method for loaders .from_dict and .from_dotenv etc."""
363
+ ...
364
+
358
365
  class _Secret(modal._object._Object):
359
366
  """Secrets provide a dictionary of environment variables for images.
360
367
 
@@ -392,7 +399,7 @@ class _Secret(modal._object._Object):
392
399
  ...
393
400
 
394
401
  @staticmethod
395
- def from_dotenv(path=None, *, filename=".env") -> _Secret:
402
+ def from_dotenv(path=None, *, filename=".env", client: typing.Optional[modal.client._Client] = None) -> _Secret:
396
403
  """Create secrets from a .env file automatically.
397
404
 
398
405
  If no argument is provided, it will use the current working directory as the starting
@@ -517,7 +524,7 @@ class Secret(modal.object.Object):
517
524
  ...
518
525
 
519
526
  @staticmethod
520
- def from_dotenv(path=None, *, filename=".env") -> Secret:
527
+ def from_dotenv(path=None, *, filename=".env", client: typing.Optional[modal.client.Client] = None) -> Secret:
521
528
  """Create secrets from a .env file automatically.
522
529
 
523
530
  If no argument is provided, it will use the current working directory as the starting
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.2.dev31
3
+ Version: 1.2.2.dev33
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2025
2
2
  """Supplies the current version of the modal client library."""
3
3
 
4
- __version__ = "1.2.2.dev31"
4
+ __version__ = "1.2.2.dev33"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes