modal 1.0.4.dev10__tar.gz → 1.0.4.dev12__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 (184) hide show
  1. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/PKG-INFO +1 -1
  2. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/client.pyi +2 -2
  3. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cls.py +50 -9
  4. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cls.pyi +1 -0
  5. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal.egg-info/PKG-INFO +1 -1
  6. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_proto/api.proto +1 -0
  7. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_proto/api_pb2.py +170 -170
  8. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_proto/api_pb2.pyi +4 -1
  9. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_version/__init__.py +1 -1
  10. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/LICENSE +0 -0
  11. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/README.md +0 -0
  12. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/__init__.py +0 -0
  13. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/__main__.py +0 -0
  14. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_clustered_functions.py +0 -0
  15. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_clustered_functions.pyi +0 -0
  16. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_container_entrypoint.py +0 -0
  17. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_functions.py +0 -0
  18. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_ipython.py +0 -0
  19. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_location.py +0 -0
  20. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_object.py +0 -0
  21. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_output.py +0 -0
  22. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_partial_function.py +0 -0
  23. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_pty.py +0 -0
  24. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_resolver.py +0 -0
  25. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_resources.py +0 -0
  26. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_runtime/__init__.py +0 -0
  27. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_runtime/asgi.py +0 -0
  28. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_runtime/container_io_manager.py +0 -0
  29. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_runtime/container_io_manager.pyi +0 -0
  30. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_runtime/execution_context.py +0 -0
  31. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_runtime/execution_context.pyi +0 -0
  32. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  33. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_runtime/telemetry.py +0 -0
  34. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_runtime/user_code_imports.py +0 -0
  35. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_serialization.py +0 -0
  36. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_traceback.py +0 -0
  37. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_tunnel.py +0 -0
  38. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_tunnel.pyi +0 -0
  39. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_type_manager.py +0 -0
  40. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/__init__.py +0 -0
  41. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/app_utils.py +0 -0
  42. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/async_utils.py +0 -0
  43. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/blob_utils.py +0 -0
  44. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/bytes_io_segment_payload.py +0 -0
  45. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/deprecation.py +0 -0
  46. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/docker_utils.py +0 -0
  47. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/function_utils.py +0 -0
  48. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/git_utils.py +0 -0
  49. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/grpc_testing.py +0 -0
  50. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/grpc_utils.py +0 -0
  51. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/hash_utils.py +0 -0
  52. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/http_utils.py +0 -0
  53. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/jwt_utils.py +0 -0
  54. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/logger.py +0 -0
  55. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/mount_utils.py +0 -0
  56. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/name_utils.py +0 -0
  57. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/package_utils.py +0 -0
  58. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/pattern_utils.py +0 -0
  59. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/rand_pb_testing.py +0 -0
  60. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/shell_utils.py +0 -0
  61. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_utils/time_utils.py +0 -0
  62. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_vendor/__init__.py +0 -0
  63. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  64. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_vendor/cloudpickle.py +0 -0
  65. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_vendor/tblib.py +0 -0
  66. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/_watcher.py +0 -0
  67. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/app.py +0 -0
  68. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/app.pyi +0 -0
  69. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/call_graph.py +0 -0
  70. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/__init__.py +0 -0
  71. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/_download.py +0 -0
  72. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/_traceback.py +0 -0
  73. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/app.py +0 -0
  74. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/cluster.py +0 -0
  75. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/config.py +0 -0
  76. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/container.py +0 -0
  77. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/dict.py +0 -0
  78. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/entry_point.py +0 -0
  79. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/environment.py +0 -0
  80. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/import_refs.py +0 -0
  81. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/launch.py +0 -0
  82. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/network_file_system.py +0 -0
  83. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/profile.py +0 -0
  84. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/programs/__init__.py +0 -0
  85. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/programs/run_jupyter.py +0 -0
  86. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/programs/vscode.py +0 -0
  87. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/queues.py +0 -0
  88. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/run.py +0 -0
  89. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/secret.py +0 -0
  90. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/token.py +0 -0
  91. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/utils.py +0 -0
  92. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cli/volume.py +0 -0
  93. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/client.py +0 -0
  94. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cloud_bucket_mount.py +0 -0
  95. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/cloud_bucket_mount.pyi +0 -0
  96. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/config.py +0 -0
  97. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/container_process.py +0 -0
  98. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/container_process.pyi +0 -0
  99. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/dict.py +0 -0
  100. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/dict.pyi +0 -0
  101. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/environments.py +0 -0
  102. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/environments.pyi +0 -0
  103. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/exception.py +0 -0
  104. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/experimental/__init__.py +0 -0
  105. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/experimental/ipython.py +0 -0
  106. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/file_io.py +0 -0
  107. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/file_io.pyi +0 -0
  108. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/file_pattern_matcher.py +0 -0
  109. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/functions.py +0 -0
  110. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/functions.pyi +0 -0
  111. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/gpu.py +0 -0
  112. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/image.py +0 -0
  113. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/image.pyi +0 -0
  114. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/io_streams.py +0 -0
  115. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/io_streams.pyi +0 -0
  116. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/mount.py +0 -0
  117. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/mount.pyi +0 -0
  118. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/network_file_system.py +0 -0
  119. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/network_file_system.pyi +0 -0
  120. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/object.py +0 -0
  121. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/object.pyi +0 -0
  122. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/output.py +0 -0
  123. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/parallel_map.py +0 -0
  124. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/parallel_map.pyi +0 -0
  125. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/partial_function.py +0 -0
  126. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/partial_function.pyi +0 -0
  127. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/proxy.py +0 -0
  128. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/proxy.pyi +0 -0
  129. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/py.typed +0 -0
  130. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/queue.py +0 -0
  131. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/queue.pyi +0 -0
  132. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/requirements/2023.12.312.txt +0 -0
  133. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/requirements/2023.12.txt +0 -0
  134. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/requirements/2024.04.txt +0 -0
  135. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/requirements/2024.10.txt +0 -0
  136. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/requirements/PREVIEW.txt +0 -0
  137. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/requirements/README.md +0 -0
  138. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/requirements/base-images.json +0 -0
  139. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/retries.py +0 -0
  140. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/runner.py +0 -0
  141. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/runner.pyi +0 -0
  142. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/running_app.py +0 -0
  143. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/sandbox.py +0 -0
  144. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/sandbox.pyi +0 -0
  145. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/schedule.py +0 -0
  146. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/scheduler_placement.py +0 -0
  147. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/secret.py +0 -0
  148. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/secret.pyi +0 -0
  149. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/serving.py +0 -0
  150. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/serving.pyi +0 -0
  151. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/snapshot.py +0 -0
  152. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/snapshot.pyi +0 -0
  153. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/stream_type.py +0 -0
  154. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/token_flow.py +0 -0
  155. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/token_flow.pyi +0 -0
  156. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/volume.py +0 -0
  157. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal/volume.pyi +0 -0
  158. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal.egg-info/SOURCES.txt +0 -0
  159. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal.egg-info/dependency_links.txt +0 -0
  160. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal.egg-info/entry_points.txt +0 -0
  161. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal.egg-info/requires.txt +0 -0
  162. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal.egg-info/top_level.txt +0 -0
  163. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_docs/__init__.py +0 -0
  164. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_docs/gen_cli_docs.py +0 -0
  165. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_docs/gen_reference_docs.py +0 -0
  166. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_docs/mdmd/__init__.py +0 -0
  167. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_docs/mdmd/mdmd.py +0 -0
  168. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_docs/mdmd/signatures.py +0 -0
  169. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_proto/__init__.py +0 -0
  170. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_proto/api_grpc.py +0 -0
  171. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_proto/api_pb2_grpc.py +0 -0
  172. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_proto/api_pb2_grpc.pyi +0 -0
  173. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_proto/modal_api_grpc.py +0 -0
  174. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_proto/modal_options_grpc.py +0 -0
  175. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_proto/options.proto +0 -0
  176. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_proto/options_grpc.py +0 -0
  177. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_proto/options_pb2.py +0 -0
  178. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_proto/options_pb2.pyi +0 -0
  179. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_proto/options_pb2_grpc.py +0 -0
  180. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_proto/options_pb2_grpc.pyi +0 -0
  181. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_proto/py.typed +0 -0
  182. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/modal_version/__main__.py +0 -0
  183. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/pyproject.toml +0 -0
  184. {modal-1.0.4.dev10 → modal-1.0.4.dev12}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.0.4.dev10
3
+ Version: 1.0.4.dev12
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -31,7 +31,7 @@ class _Client:
31
31
  server_url: str,
32
32
  client_type: int,
33
33
  credentials: typing.Optional[tuple[str, str]],
34
- version: str = "1.0.4.dev10",
34
+ version: str = "1.0.4.dev12",
35
35
  ): ...
36
36
  def is_closed(self) -> bool: ...
37
37
  @property
@@ -94,7 +94,7 @@ class Client:
94
94
  server_url: str,
95
95
  client_type: int,
96
96
  credentials: typing.Optional[tuple[str, str]],
97
- version: str = "1.0.4.dev10",
97
+ version: str = "1.0.4.dev12",
98
98
  ): ...
99
99
  def is_closed(self) -> bool: ...
100
100
  @property
@@ -75,6 +75,7 @@ def _get_class_constructor_signature(user_cls: type) -> inspect.Signature:
75
75
 
76
76
  @dataclasses.dataclass()
77
77
  class _ServiceOptions:
78
+ # Note that default values should always be "untruthy" so we can detect when they are not set
78
79
  secrets: typing.Collection[_Secret] = ()
79
80
  validated_volumes: typing.Sequence[tuple[str, _Volume]] = ()
80
81
  resources: Optional[api_pb2.Resources] = None
@@ -88,6 +89,25 @@ class _ServiceOptions:
88
89
  batch_max_size: Optional[int] = None
89
90
  batch_wait_ms: Optional[int] = None
90
91
 
92
+ def merge_options(self, new_options: "_ServiceOptions") -> "_ServiceOptions":
93
+ """Implement protobuf-like MergeFrom semantics for this dataclass.
94
+
95
+ This mostly exists to support "stacking" of `.with_options()` calls.
96
+ """
97
+ new_options_dict = dataclasses.asdict(new_options)
98
+
99
+ # Resources needs special merge handling because individual fields are parameters in the public API
100
+ merged_resources = api_pb2.Resources()
101
+ if self.resources:
102
+ merged_resources.MergeFrom(self.resources)
103
+ if new_resources := new_options_dict.pop("resources"):
104
+ merged_resources.MergeFrom(new_resources)
105
+ self.resources = merged_resources
106
+
107
+ for key, value in new_options_dict.items():
108
+ if value: # Only overwrite data when the value was set in the new options
109
+ setattr(self, key, value)
110
+
91
111
 
92
112
  def _bind_instance_method(cls: "_Cls", service_function: _Function, method_name: str):
93
113
  """Binds an "instance service function" to a specific method using metadata for that method
@@ -664,15 +684,32 @@ More information on class parameterization can be found here: https://modal.com/
664
684
  container_idle_timeout: Optional[int] = None, # Now called `scaledown_window`
665
685
  allow_concurrent_inputs: Optional[int] = None, # See `.with_concurrency`
666
686
  ) -> "_Cls":
667
- """Create an instance of the Cls with configuration options overridden with new values.
687
+ """Override the static Function configuration at runtime.
688
+
689
+ This method will return a new instance of the cls that will autoscale independently of the
690
+ original instance. Note that options cannot be "unset" with this method (i.e., if a GPU
691
+ is configured in the `@app.cls()` decorator, passing `gpu=None` here will not create a
692
+ CPU-only instance).
668
693
 
669
694
  **Usage:**
670
695
 
696
+ You can use this method after looking up the Cls from a deployed App or if you have a
697
+ direct reference to a Cls from another Function or local entrypoint on its App:
698
+
671
699
  ```python notest
672
700
  Model = modal.Cls.from_name("my_app", "Model")
673
701
  ModelUsingGPU = Model.with_options(gpu="A100")
674
- ModelUsingGPU().generate.remote(42) # will run with an A100 GPU
702
+ ModelUsingGPU().generate.remote(input_prompt) # Run with an A100 GPU
675
703
  ```
704
+
705
+ The method can be called multiple times to "stack" updates:
706
+
707
+ ```python notest
708
+ Model.with_options(gpu="A100").with_options(scaledown_window=300) # Use an A100 with slow scaledown
709
+ ```
710
+
711
+ Note that container arguments (i.e. `volumes` and `secrets`) passed in subsequent calls
712
+ will not be merged.
676
713
  """
677
714
  retry_policy = _parse_retries(retries, f"Class {self.__name__}" if self._user_cls else "")
678
715
  if gpu or cpu or memory:
@@ -705,21 +742,23 @@ More information on class parameterization can be found here: https://modal.com/
705
742
 
706
743
  cls = _Cls._from_loader(_load_from_base, rep=f"{self._name}.with_options(...)", is_another_app=True, deps=_deps)
707
744
  cls._initialize_from_other(self)
708
- cls._options = dataclasses.replace(
709
- cls._options,
745
+
746
+ new_options = _ServiceOptions(
710
747
  secrets=secrets,
748
+ validated_volumes=validate_volumes(volumes),
711
749
  resources=resources,
712
750
  retry_policy=retry_policy,
713
751
  max_containers=max_containers,
714
752
  buffer_containers=buffer_containers,
715
753
  scaledown_window=scaledown_window,
716
754
  timeout_secs=timeout,
717
- validated_volumes=validate_volumes(volumes),
718
755
  # Note: set both for backwards / forwards compatibility
719
756
  # But going forward `.with_concurrency` is the preferred method with distinct parameterization
720
757
  max_concurrent_inputs=allow_concurrent_inputs,
721
758
  target_concurrent_inputs=allow_concurrent_inputs,
722
759
  )
760
+
761
+ cls._options.merge_options(new_options)
723
762
  return cls
724
763
 
725
764
  def with_concurrency(self: "_Cls", *, max_inputs: int, target_inputs: Optional[int] = None) -> "_Cls":
@@ -746,9 +785,9 @@ More information on class parameterization can be found here: https://modal.com/
746
785
  _load_from_base, rep=f"{self._name}.with_concurrency(...)", is_another_app=True, deps=_deps
747
786
  )
748
787
  cls._initialize_from_other(self)
749
- cls._options = dataclasses.replace(
750
- cls._options, max_concurrent_inputs=max_inputs, target_concurrent_inputs=target_inputs
751
- )
788
+
789
+ concurrency_options = _ServiceOptions(max_concurrent_inputs=max_inputs, target_concurrent_inputs=target_inputs)
790
+ cls._options.merge_options(concurrency_options)
752
791
  return cls
753
792
 
754
793
  def with_batching(self: "_Cls", *, max_batch_size: int, wait_ms: int) -> "_Cls":
@@ -775,7 +814,9 @@ More information on class parameterization can be found here: https://modal.com/
775
814
  _load_from_base, rep=f"{self._name}.with_concurrency(...)", is_another_app=True, deps=_deps
776
815
  )
777
816
  cls._initialize_from_other(self)
778
- cls._options = dataclasses.replace(cls._options, batch_max_size=max_batch_size, batch_wait_ms=wait_ms)
817
+
818
+ batching_options = _ServiceOptions(batch_max_size=max_batch_size, batch_wait_ms=wait_ms)
819
+ cls._options.merge_options(batching_options)
779
820
  return cls
780
821
 
781
822
  @staticmethod
@@ -37,6 +37,7 @@ class _ServiceOptions:
37
37
  batch_max_size: typing.Optional[int]
38
38
  batch_wait_ms: typing.Optional[int]
39
39
 
40
+ def merge_options(self, new_options: _ServiceOptions) -> _ServiceOptions: ...
40
41
  def __init__(
41
42
  self,
42
43
  secrets: typing.Collection[modal.secret._Secret] = (),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.0.4.dev10
3
+ Version: 1.0.4.dev12
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -2796,6 +2796,7 @@ message TaskInfo {
2796
2796
  modal.client.GenericResult result = 4;
2797
2797
  double enqueued_at = 5;
2798
2798
  string gpu_type = 6;
2799
+ string sandbox_id = 7;
2799
2800
  }
2800
2801
 
2801
2802
  message TaskListRequest {