modal 0.62.115__py3-none-any.whl → 0.72.13__py3-none-any.whl

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 (220) hide show
  1. modal/__init__.py +13 -9
  2. modal/__main__.py +41 -3
  3. modal/_clustered_functions.py +80 -0
  4. modal/_clustered_functions.pyi +22 -0
  5. modal/_container_entrypoint.py +402 -398
  6. modal/_ipython.py +3 -13
  7. modal/_location.py +17 -10
  8. modal/_output.py +243 -99
  9. modal/_pty.py +2 -2
  10. modal/_resolver.py +55 -60
  11. modal/_resources.py +26 -7
  12. modal/_runtime/__init__.py +1 -0
  13. modal/_runtime/asgi.py +519 -0
  14. modal/_runtime/container_io_manager.py +1025 -0
  15. modal/{execution_context.py → _runtime/execution_context.py} +11 -2
  16. modal/_runtime/telemetry.py +169 -0
  17. modal/_runtime/user_code_imports.py +356 -0
  18. modal/_serialization.py +123 -6
  19. modal/_traceback.py +47 -187
  20. modal/_tunnel.py +50 -14
  21. modal/_tunnel.pyi +19 -36
  22. modal/_utils/app_utils.py +3 -17
  23. modal/_utils/async_utils.py +386 -104
  24. modal/_utils/blob_utils.py +157 -186
  25. modal/_utils/bytes_io_segment_payload.py +97 -0
  26. modal/_utils/deprecation.py +89 -0
  27. modal/_utils/docker_utils.py +98 -0
  28. modal/_utils/function_utils.py +299 -98
  29. modal/_utils/grpc_testing.py +47 -34
  30. modal/_utils/grpc_utils.py +54 -21
  31. modal/_utils/hash_utils.py +51 -10
  32. modal/_utils/http_utils.py +39 -9
  33. modal/_utils/logger.py +2 -1
  34. modal/_utils/mount_utils.py +34 -16
  35. modal/_utils/name_utils.py +58 -0
  36. modal/_utils/package_utils.py +14 -1
  37. modal/_utils/pattern_utils.py +205 -0
  38. modal/_utils/rand_pb_testing.py +3 -3
  39. modal/_utils/shell_utils.py +15 -49
  40. modal/_vendor/a2wsgi_wsgi.py +62 -72
  41. modal/_vendor/cloudpickle.py +1 -1
  42. modal/_watcher.py +12 -10
  43. modal/app.py +561 -323
  44. modal/app.pyi +474 -262
  45. modal/call_graph.py +7 -6
  46. modal/cli/_download.py +22 -6
  47. modal/cli/_traceback.py +200 -0
  48. modal/cli/app.py +203 -42
  49. modal/cli/config.py +12 -5
  50. modal/cli/container.py +61 -13
  51. modal/cli/dict.py +128 -0
  52. modal/cli/entry_point.py +26 -13
  53. modal/cli/environment.py +40 -9
  54. modal/cli/import_refs.py +21 -48
  55. modal/cli/launch.py +28 -14
  56. modal/cli/network_file_system.py +57 -21
  57. modal/cli/profile.py +1 -1
  58. modal/cli/programs/run_jupyter.py +34 -9
  59. modal/cli/programs/vscode.py +58 -8
  60. modal/cli/queues.py +131 -0
  61. modal/cli/run.py +199 -96
  62. modal/cli/secret.py +5 -4
  63. modal/cli/token.py +7 -2
  64. modal/cli/utils.py +74 -8
  65. modal/cli/volume.py +97 -56
  66. modal/client.py +248 -144
  67. modal/client.pyi +156 -124
  68. modal/cloud_bucket_mount.py +43 -30
  69. modal/cloud_bucket_mount.pyi +32 -25
  70. modal/cls.py +528 -141
  71. modal/cls.pyi +189 -145
  72. modal/config.py +32 -15
  73. modal/container_process.py +177 -0
  74. modal/container_process.pyi +82 -0
  75. modal/dict.py +50 -54
  76. modal/dict.pyi +120 -164
  77. modal/environments.py +106 -5
  78. modal/environments.pyi +77 -25
  79. modal/exception.py +30 -43
  80. modal/experimental.py +62 -2
  81. modal/file_io.py +537 -0
  82. modal/file_io.pyi +235 -0
  83. modal/file_pattern_matcher.py +196 -0
  84. modal/functions.py +846 -428
  85. modal/functions.pyi +446 -387
  86. modal/gpu.py +57 -44
  87. modal/image.py +943 -417
  88. modal/image.pyi +584 -245
  89. modal/io_streams.py +434 -0
  90. modal/io_streams.pyi +122 -0
  91. modal/mount.py +223 -90
  92. modal/mount.pyi +241 -243
  93. modal/network_file_system.py +85 -86
  94. modal/network_file_system.pyi +151 -110
  95. modal/object.py +66 -36
  96. modal/object.pyi +166 -143
  97. modal/output.py +63 -0
  98. modal/parallel_map.py +73 -47
  99. modal/parallel_map.pyi +51 -63
  100. modal/partial_function.py +272 -107
  101. modal/partial_function.pyi +219 -120
  102. modal/proxy.py +15 -12
  103. modal/proxy.pyi +3 -8
  104. modal/queue.py +96 -72
  105. modal/queue.pyi +210 -135
  106. modal/requirements/2024.04.txt +2 -1
  107. modal/requirements/2024.10.txt +16 -0
  108. modal/requirements/README.md +21 -0
  109. modal/requirements/base-images.json +22 -0
  110. modal/retries.py +45 -4
  111. modal/runner.py +325 -203
  112. modal/runner.pyi +124 -110
  113. modal/running_app.py +27 -4
  114. modal/sandbox.py +509 -231
  115. modal/sandbox.pyi +396 -169
  116. modal/schedule.py +2 -2
  117. modal/scheduler_placement.py +20 -3
  118. modal/secret.py +41 -25
  119. modal/secret.pyi +62 -42
  120. modal/serving.py +39 -49
  121. modal/serving.pyi +37 -43
  122. modal/stream_type.py +15 -0
  123. modal/token_flow.py +5 -3
  124. modal/token_flow.pyi +37 -32
  125. modal/volume.py +123 -137
  126. modal/volume.pyi +228 -221
  127. {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/METADATA +5 -5
  128. modal-0.72.13.dist-info/RECORD +174 -0
  129. {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/top_level.txt +0 -1
  130. modal_docs/gen_reference_docs.py +3 -1
  131. modal_docs/mdmd/mdmd.py +0 -1
  132. modal_docs/mdmd/signatures.py +1 -2
  133. modal_global_objects/images/base_images.py +28 -0
  134. modal_global_objects/mounts/python_standalone.py +2 -2
  135. modal_proto/__init__.py +1 -1
  136. modal_proto/api.proto +1231 -531
  137. modal_proto/api_grpc.py +750 -430
  138. modal_proto/api_pb2.py +2102 -1176
  139. modal_proto/api_pb2.pyi +8859 -0
  140. modal_proto/api_pb2_grpc.py +1329 -675
  141. modal_proto/api_pb2_grpc.pyi +1416 -0
  142. modal_proto/modal_api_grpc.py +149 -0
  143. modal_proto/modal_options_grpc.py +3 -0
  144. modal_proto/options_pb2.pyi +20 -0
  145. modal_proto/options_pb2_grpc.pyi +7 -0
  146. modal_proto/py.typed +0 -0
  147. modal_version/__init__.py +1 -1
  148. modal_version/_version_generated.py +2 -2
  149. modal/_asgi.py +0 -370
  150. modal/_container_exec.py +0 -128
  151. modal/_container_io_manager.py +0 -646
  152. modal/_container_io_manager.pyi +0 -412
  153. modal/_sandbox_shell.py +0 -49
  154. modal/app_utils.py +0 -20
  155. modal/app_utils.pyi +0 -17
  156. modal/execution_context.pyi +0 -37
  157. modal/shared_volume.py +0 -23
  158. modal/shared_volume.pyi +0 -24
  159. modal-0.62.115.dist-info/RECORD +0 -207
  160. modal_global_objects/images/conda.py +0 -15
  161. modal_global_objects/images/debian_slim.py +0 -15
  162. modal_global_objects/images/micromamba.py +0 -15
  163. test/__init__.py +0 -1
  164. test/aio_test.py +0 -12
  165. test/async_utils_test.py +0 -279
  166. test/blob_test.py +0 -67
  167. test/cli_imports_test.py +0 -149
  168. test/cli_test.py +0 -674
  169. test/client_test.py +0 -203
  170. test/cloud_bucket_mount_test.py +0 -22
  171. test/cls_test.py +0 -636
  172. test/config_test.py +0 -149
  173. test/conftest.py +0 -1485
  174. test/container_app_test.py +0 -50
  175. test/container_test.py +0 -1405
  176. test/cpu_test.py +0 -23
  177. test/decorator_test.py +0 -85
  178. test/deprecation_test.py +0 -34
  179. test/dict_test.py +0 -51
  180. test/e2e_test.py +0 -68
  181. test/error_test.py +0 -7
  182. test/function_serialization_test.py +0 -32
  183. test/function_test.py +0 -791
  184. test/function_utils_test.py +0 -101
  185. test/gpu_test.py +0 -159
  186. test/grpc_utils_test.py +0 -82
  187. test/helpers.py +0 -47
  188. test/image_test.py +0 -814
  189. test/live_reload_test.py +0 -80
  190. test/lookup_test.py +0 -70
  191. test/mdmd_test.py +0 -329
  192. test/mount_test.py +0 -162
  193. test/mounted_files_test.py +0 -327
  194. test/network_file_system_test.py +0 -188
  195. test/notebook_test.py +0 -66
  196. test/object_test.py +0 -41
  197. test/package_utils_test.py +0 -25
  198. test/queue_test.py +0 -115
  199. test/resolver_test.py +0 -59
  200. test/retries_test.py +0 -67
  201. test/runner_test.py +0 -85
  202. test/sandbox_test.py +0 -191
  203. test/schedule_test.py +0 -15
  204. test/scheduler_placement_test.py +0 -57
  205. test/secret_test.py +0 -89
  206. test/serialization_test.py +0 -50
  207. test/stub_composition_test.py +0 -10
  208. test/stub_test.py +0 -361
  209. test/test_asgi_wrapper.py +0 -234
  210. test/token_flow_test.py +0 -18
  211. test/traceback_test.py +0 -135
  212. test/tunnel_test.py +0 -29
  213. test/utils_test.py +0 -88
  214. test/version_test.py +0 -14
  215. test/volume_test.py +0 -397
  216. test/watcher_test.py +0 -58
  217. test/webhook_test.py +0 -145
  218. {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/LICENSE +0 -0
  219. {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/WHEEL +0 -0
  220. {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/entry_points.txt +0 -0
@@ -1,135 +1,234 @@
1
+ import collections.abc
1
2
  import enum
2
3
  import modal.functions
3
4
  import modal_proto.api_pb2
4
5
  import typing
6
+ import typing_extensions
5
7
 
6
8
  class _PartialFunctionFlags(enum.IntFlag):
7
9
  FUNCTION: int = 1
8
10
  BUILD: int = 2
9
- ENTER_PRE_CHECKPOINT: int = 4
10
- ENTER_POST_CHECKPOINT: int = 8
11
+ ENTER_PRE_SNAPSHOT: int = 4
12
+ ENTER_POST_SNAPSHOT: int = 8
11
13
  EXIT: int = 16
14
+ BATCHED: int = 32
15
+ CLUSTERED: int = 64 # Experimental: Clustered functions
12
16
 
17
+ @staticmethod
18
+ def all() -> int:
19
+ return ~_PartialFunctionFlags(0)
13
20
 
14
- class _PartialFunction:
15
- raw_f: typing.Callable[..., typing.Any]
16
- flags: _PartialFunctionFlags
17
- webhook_config: typing.Union[modal_proto.api_pb2.WebhookConfig, None]
18
- is_generator: typing.Union[bool, None]
19
- keep_warm: typing.Union[int, None]
20
-
21
- def __init__(self, raw_f: typing.Callable[..., typing.Any], flags: _PartialFunctionFlags, webhook_config: typing.Union[modal_proto.api_pb2.WebhookConfig, None] = None, is_generator: typing.Union[bool, None] = None, keep_warm: typing.Union[int, None] = None):
22
- ...
23
-
24
- def __get__(self, obj, objtype=None) -> modal.functions._Function:
25
- ...
26
-
27
- def __del__(self):
28
- ...
21
+ P = typing_extensions.ParamSpec("P")
29
22
 
30
- def add_flags(self, flags) -> _PartialFunction:
31
- ...
23
+ ReturnType = typing.TypeVar("ReturnType", covariant=True)
32
24
 
25
+ OriginalReturnType = typing.TypeVar("OriginalReturnType", covariant=True)
33
26
 
34
- class PartialFunction:
35
- raw_f: typing.Callable[..., typing.Any]
27
+ class _PartialFunction(typing.Generic[P, ReturnType, OriginalReturnType]):
28
+ raw_f: typing.Callable[P, ReturnType]
36
29
  flags: _PartialFunctionFlags
37
- webhook_config: typing.Union[modal_proto.api_pb2.WebhookConfig, None]
38
- is_generator: typing.Union[bool, None]
39
- keep_warm: typing.Union[int, None]
40
-
41
- def __init__(self, raw_f: typing.Callable[..., typing.Any], flags: _PartialFunctionFlags, webhook_config: typing.Union[modal_proto.api_pb2.WebhookConfig, None] = None, is_generator: typing.Union[bool, None] = None, keep_warm: typing.Union[int, None] = None):
42
- ...
43
-
44
- def __get__(self, obj, objtype=None) -> modal.functions.Function:
45
- ...
46
-
47
- def __del__(self):
48
- ...
49
-
50
- def add_flags(self, flags) -> PartialFunction:
51
- ...
52
-
53
-
54
- def _find_partial_methods_for_cls(user_cls: typing.Type, flags: _PartialFunctionFlags) -> typing.Dict[str, _PartialFunction]:
55
- ...
56
-
57
-
58
- def _find_callables_for_cls(user_cls: typing.Type, flags: _PartialFunctionFlags) -> typing.Dict[str, typing.Callable]:
59
- ...
60
-
61
-
62
- def _find_callables_for_obj(user_obj: typing.Any, flags: _PartialFunctionFlags) -> typing.Dict[str, typing.Callable]:
63
- ...
64
-
65
-
66
- def _method(_warn_parentheses_missing=None, *, is_generator: typing.Union[bool, None] = None, keep_warm: typing.Union[int, None] = None) -> typing.Callable[[typing.Callable[..., typing.Any]], _PartialFunction]:
67
- ...
68
-
69
-
70
- def _parse_custom_domains(custom_domains: typing.Union[typing.Iterable[str], None] = None) -> typing.List[modal_proto.api_pb2.CustomDomainConfig]:
71
- ...
72
-
73
-
74
- def _web_endpoint(_warn_parentheses_missing=None, *, method: str = 'GET', label: typing.Union[str, None] = None, wait_for_response: bool = True, custom_domains: typing.Union[typing.Iterable[str], None] = None) -> typing.Callable[[typing.Callable[..., typing.Any]], _PartialFunction]:
75
- ...
76
-
77
-
78
- def _asgi_app(_warn_parentheses_missing=None, *, label: typing.Union[str, None] = None, wait_for_response: bool = True, custom_domains: typing.Union[typing.Iterable[str], None] = None) -> typing.Callable[[typing.Callable[..., typing.Any]], _PartialFunction]:
79
- ...
80
-
81
-
82
- def _wsgi_app(_warn_parentheses_missing=None, *, label: typing.Union[str, None] = None, wait_for_response: bool = True, custom_domains: typing.Union[typing.Iterable[str], None] = None) -> typing.Callable[[typing.Callable[..., typing.Any]], _PartialFunction]:
83
- ...
84
-
85
-
86
- def _web_server(port: int, *, startup_timeout: float = 5.0, label: typing.Union[str, None] = None, custom_domains: typing.Union[typing.Iterable[str], None] = None) -> typing.Callable[[typing.Callable[..., typing.Any]], _PartialFunction]:
87
- ...
88
-
89
-
90
- def _disallow_wrapping_method(f: _PartialFunction, wrapper: str) -> None:
91
- ...
92
-
93
-
94
- def _build(_warn_parentheses_missing=None) -> typing.Callable[[typing.Union[typing.Callable[[typing.Any], typing.Any], _PartialFunction]], _PartialFunction]:
95
- ...
96
-
97
-
98
- def _enter(_warn_parentheses_missing=None, *, snap: bool = False) -> typing.Callable[[typing.Union[typing.Callable[[typing.Any], typing.Any], _PartialFunction]], _PartialFunction]:
99
- ...
100
-
101
-
102
- def _exit(_warn_parentheses_missing=None) -> typing.Callable[[typing.Union[typing.Callable[[typing.Any, typing.Union[typing.Type[BaseException], None], typing.Union[BaseException, None], typing.Any], None], typing.Callable[[typing.Any], None]]], _PartialFunction]:
103
- ...
104
-
105
-
106
- def method(_warn_parentheses_missing=None, *, is_generator: typing.Union[bool, None] = None, keep_warm: typing.Union[int, None] = None) -> typing.Callable[[typing.Callable[..., typing.Any]], PartialFunction]:
107
- ...
108
-
109
-
110
- def web_endpoint(_warn_parentheses_missing=None, *, method: str = 'GET', label: typing.Union[str, None] = None, wait_for_response: bool = True, custom_domains: typing.Union[typing.Iterable[str], None] = None) -> typing.Callable[[typing.Callable[..., typing.Any]], PartialFunction]:
111
- ...
112
-
113
-
114
- def asgi_app(_warn_parentheses_missing=None, *, label: typing.Union[str, None] = None, wait_for_response: bool = True, custom_domains: typing.Union[typing.Iterable[str], None] = None) -> typing.Callable[[typing.Callable[..., typing.Any]], PartialFunction]:
115
- ...
116
-
117
-
118
- def wsgi_app(_warn_parentheses_missing=None, *, label: typing.Union[str, None] = None, wait_for_response: bool = True, custom_domains: typing.Union[typing.Iterable[str], None] = None) -> typing.Callable[[typing.Callable[..., typing.Any]], PartialFunction]:
119
- ...
120
-
121
-
122
- def web_server(port: int, *, startup_timeout: float = 5.0, label: typing.Union[str, None] = None, custom_domains: typing.Union[typing.Iterable[str], None] = None) -> typing.Callable[[typing.Callable[..., typing.Any]], PartialFunction]:
123
- ...
124
-
125
-
126
- def build(_warn_parentheses_missing=None) -> typing.Callable[[typing.Union[typing.Callable[[typing.Any], typing.Any], PartialFunction]], PartialFunction]:
127
- ...
128
-
129
-
130
- def enter(_warn_parentheses_missing=None, *, snap: bool = False) -> typing.Callable[[typing.Union[typing.Callable[[typing.Any], typing.Any], PartialFunction]], PartialFunction]:
131
- ...
132
-
133
-
134
- def exit(_warn_parentheses_missing=None) -> typing.Callable[[typing.Union[typing.Callable[[typing.Any, typing.Union[typing.Type[BaseException], None], typing.Union[BaseException, None], typing.Any], None], typing.Callable[[typing.Any], None]]], PartialFunction]:
135
- ...
30
+ webhook_config: typing.Optional[modal_proto.api_pb2.WebhookConfig]
31
+ is_generator: bool
32
+ keep_warm: typing.Optional[int]
33
+ batch_max_size: typing.Optional[int]
34
+ batch_wait_ms: typing.Optional[int]
35
+ force_build: bool
36
+ cluster_size: typing.Optional[int]
37
+ build_timeout: typing.Optional[int]
38
+
39
+ def __init__(
40
+ self,
41
+ raw_f: typing.Callable[P, ReturnType],
42
+ flags: _PartialFunctionFlags,
43
+ webhook_config: typing.Optional[modal_proto.api_pb2.WebhookConfig] = None,
44
+ is_generator: typing.Optional[bool] = None,
45
+ keep_warm: typing.Optional[int] = None,
46
+ batch_max_size: typing.Optional[int] = None,
47
+ batch_wait_ms: typing.Optional[int] = None,
48
+ cluster_size: typing.Optional[int] = None,
49
+ force_build: bool = False,
50
+ build_timeout: typing.Optional[int] = None,
51
+ ): ...
52
+ def __get__(self, obj, objtype=None) -> modal.functions._Function[P, ReturnType, OriginalReturnType]: ...
53
+ def __del__(self): ...
54
+ def add_flags(self, flags) -> _PartialFunction: ...
55
+
56
+ class PartialFunction(typing.Generic[P, ReturnType, OriginalReturnType]):
57
+ raw_f: typing.Callable[P, ReturnType]
58
+ flags: _PartialFunctionFlags
59
+ webhook_config: typing.Optional[modal_proto.api_pb2.WebhookConfig]
60
+ is_generator: bool
61
+ keep_warm: typing.Optional[int]
62
+ batch_max_size: typing.Optional[int]
63
+ batch_wait_ms: typing.Optional[int]
64
+ force_build: bool
65
+ cluster_size: typing.Optional[int]
66
+ build_timeout: typing.Optional[int]
67
+
68
+ def __init__(
69
+ self,
70
+ raw_f: typing.Callable[P, ReturnType],
71
+ flags: _PartialFunctionFlags,
72
+ webhook_config: typing.Optional[modal_proto.api_pb2.WebhookConfig] = None,
73
+ is_generator: typing.Optional[bool] = None,
74
+ keep_warm: typing.Optional[int] = None,
75
+ batch_max_size: typing.Optional[int] = None,
76
+ batch_wait_ms: typing.Optional[int] = None,
77
+ cluster_size: typing.Optional[int] = None,
78
+ force_build: bool = False,
79
+ build_timeout: typing.Optional[int] = None,
80
+ ): ...
81
+ def __get__(self, obj, objtype=None) -> modal.functions.Function[P, ReturnType, OriginalReturnType]: ...
82
+ def __del__(self): ...
83
+ def add_flags(self, flags) -> PartialFunction: ...
84
+
85
+ def _find_partial_methods_for_user_cls(user_cls: type[typing.Any], flags: int) -> dict[str, _PartialFunction]: ...
86
+ def _find_callables_for_obj(user_obj: typing.Any, flags: int) -> dict[str, typing.Callable[..., typing.Any]]: ...
87
+
88
+ class _MethodDecoratorType:
89
+ @typing.overload
90
+ def __call__(
91
+ self, func: PartialFunction[typing_extensions.Concatenate[typing.Any, P], ReturnType, OriginalReturnType]
92
+ ) -> PartialFunction[P, ReturnType, OriginalReturnType]: ...
93
+ @typing.overload
94
+ def __call__(
95
+ self,
96
+ func: typing.Callable[
97
+ typing_extensions.Concatenate[typing.Any, P], collections.abc.Coroutine[typing.Any, typing.Any, ReturnType]
98
+ ],
99
+ ) -> PartialFunction[P, ReturnType, collections.abc.Coroutine[typing.Any, typing.Any, ReturnType]]: ...
100
+ @typing.overload
101
+ def __call__(
102
+ self, func: typing.Callable[typing_extensions.Concatenate[typing.Any, P], ReturnType]
103
+ ) -> PartialFunction[P, ReturnType, ReturnType]: ...
104
+
105
+ def _method(
106
+ _warn_parentheses_missing=None,
107
+ *,
108
+ is_generator: typing.Optional[bool] = None,
109
+ keep_warm: typing.Optional[int] = None,
110
+ ) -> _MethodDecoratorType: ...
111
+ def _parse_custom_domains(
112
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
113
+ ) -> list[modal_proto.api_pb2.CustomDomainConfig]: ...
114
+ def _web_endpoint(
115
+ _warn_parentheses_missing=None,
116
+ *,
117
+ method: str = "GET",
118
+ label: typing.Optional[str] = None,
119
+ docs: bool = False,
120
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
121
+ requires_proxy_auth: bool = False,
122
+ wait_for_response: bool = True,
123
+ ) -> typing.Callable[[typing.Callable[P, ReturnType]], _PartialFunction[P, ReturnType, ReturnType]]: ...
124
+ def _asgi_app(
125
+ _warn_parentheses_missing=None,
126
+ *,
127
+ label: typing.Optional[str] = None,
128
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
129
+ requires_proxy_auth: bool = False,
130
+ wait_for_response: bool = True,
131
+ ) -> typing.Callable[[typing.Callable[..., typing.Any]], _PartialFunction]: ...
132
+ def _wsgi_app(
133
+ _warn_parentheses_missing=None,
134
+ *,
135
+ label: typing.Optional[str] = None,
136
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
137
+ requires_proxy_auth: bool = False,
138
+ wait_for_response: bool = True,
139
+ ) -> typing.Callable[[typing.Callable[..., typing.Any]], _PartialFunction]: ...
140
+ def _web_server(
141
+ port: int,
142
+ *,
143
+ startup_timeout: float = 5.0,
144
+ label: typing.Optional[str] = None,
145
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
146
+ requires_proxy_auth: bool = False,
147
+ ) -> typing.Callable[[typing.Callable[..., typing.Any]], _PartialFunction]: ...
148
+ def _disallow_wrapping_method(f: _PartialFunction, wrapper: str) -> None: ...
149
+ def _build(
150
+ _warn_parentheses_missing=None, *, force: bool = False, timeout: int = 86400
151
+ ) -> typing.Callable[[typing.Union[typing.Callable[[typing.Any], typing.Any], _PartialFunction]], _PartialFunction]: ...
152
+ def _enter(
153
+ _warn_parentheses_missing=None, *, snap: bool = False
154
+ ) -> typing.Callable[[typing.Union[typing.Callable[[typing.Any], typing.Any], _PartialFunction]], _PartialFunction]: ...
155
+ def _exit(
156
+ _warn_parentheses_missing=None,
157
+ ) -> typing.Callable[
158
+ [
159
+ typing.Union[
160
+ typing.Callable[
161
+ [typing.Any, typing.Optional[type[BaseException]], typing.Optional[BaseException], typing.Any],
162
+ typing.Any,
163
+ ],
164
+ typing.Callable[[typing.Any], typing.Any],
165
+ ]
166
+ ],
167
+ _PartialFunction,
168
+ ]: ...
169
+ def _batched(
170
+ _warn_parentheses_missing=None, *, max_batch_size: int, wait_ms: int
171
+ ) -> typing.Callable[[typing.Callable[..., typing.Any]], _PartialFunction]: ...
172
+ def method(
173
+ _warn_parentheses_missing=None,
174
+ *,
175
+ is_generator: typing.Optional[bool] = None,
176
+ keep_warm: typing.Optional[int] = None,
177
+ ) -> _MethodDecoratorType: ...
178
+ def web_endpoint(
179
+ _warn_parentheses_missing=None,
180
+ *,
181
+ method: str = "GET",
182
+ label: typing.Optional[str] = None,
183
+ docs: bool = False,
184
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
185
+ requires_proxy_auth: bool = False,
186
+ wait_for_response: bool = True,
187
+ ) -> typing.Callable[[typing.Callable[P, ReturnType]], PartialFunction[P, ReturnType, ReturnType]]: ...
188
+ def asgi_app(
189
+ _warn_parentheses_missing=None,
190
+ *,
191
+ label: typing.Optional[str] = None,
192
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
193
+ requires_proxy_auth: bool = False,
194
+ wait_for_response: bool = True,
195
+ ) -> typing.Callable[[typing.Callable[..., typing.Any]], PartialFunction]: ...
196
+ def wsgi_app(
197
+ _warn_parentheses_missing=None,
198
+ *,
199
+ label: typing.Optional[str] = None,
200
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
201
+ requires_proxy_auth: bool = False,
202
+ wait_for_response: bool = True,
203
+ ) -> typing.Callable[[typing.Callable[..., typing.Any]], PartialFunction]: ...
204
+ def web_server(
205
+ port: int,
206
+ *,
207
+ startup_timeout: float = 5.0,
208
+ label: typing.Optional[str] = None,
209
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
210
+ requires_proxy_auth: bool = False,
211
+ ) -> typing.Callable[[typing.Callable[..., typing.Any]], PartialFunction]: ...
212
+ def build(
213
+ _warn_parentheses_missing=None, *, force: bool = False, timeout: int = 86400
214
+ ) -> typing.Callable[[typing.Union[typing.Callable[[typing.Any], typing.Any], PartialFunction]], PartialFunction]: ...
215
+ def enter(
216
+ _warn_parentheses_missing=None, *, snap: bool = False
217
+ ) -> typing.Callable[[typing.Union[typing.Callable[[typing.Any], typing.Any], PartialFunction]], PartialFunction]: ...
218
+ def exit(
219
+ _warn_parentheses_missing=None,
220
+ ) -> typing.Callable[
221
+ [
222
+ typing.Union[
223
+ typing.Callable[
224
+ [typing.Any, typing.Optional[type[BaseException]], typing.Optional[BaseException], typing.Any],
225
+ typing.Any,
226
+ ],
227
+ typing.Callable[[typing.Any], typing.Any],
228
+ ]
229
+ ],
230
+ PartialFunction,
231
+ ]: ...
232
+ def batched(
233
+ _warn_parentheses_missing=None, *, max_batch_size: int, wait_ms: int
234
+ ) -> typing.Callable[[typing.Callable[..., typing.Any]], PartialFunction]: ...
modal/proxy.py CHANGED
@@ -9,28 +9,31 @@ from .object import _get_environment_name, _Object
9
9
 
10
10
 
11
11
  class _Proxy(_Object, type_prefix="pr"):
12
- """
13
- Proxy objects are used to setup secure tunnel connections to a private remote address, for example
14
- a database.
12
+ """Proxy objects give your Modal containers a static outbound IP address.
15
13
 
16
- Currently `modal.Proxy` objects must be setup with the assistance of Modal staff. If you require a proxy
17
- please contact us.
14
+ This can be used for connecting to a remote address with network whitelist, for example
15
+ a database. See [the guide](/docs/guide/proxy-ips) for more information.
18
16
  """
19
17
 
20
18
  @staticmethod
21
19
  def from_name(
22
- label: str,
23
- namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
20
+ name: str,
24
21
  environment_name: Optional[str] = None,
25
22
  ) -> "_Proxy":
23
+ """Reference a Proxy by its name.
24
+
25
+ In contrast to most other Modal objects, new Proxy objects must be
26
+ provisioned via the Dashboard and cannot be created on the fly from code.
27
+
28
+ """
29
+
26
30
  async def _load(self: _Proxy, resolver: Resolver, existing_object_id: Optional[str]):
27
- req = api_pb2.ProxyGetOrCreateRequest(
28
- deployment_name=label,
29
- namespace=namespace,
31
+ req = api_pb2.ProxyGetRequest(
32
+ name=name,
30
33
  environment_name=_get_environment_name(environment_name, resolver),
31
34
  )
32
- response = await resolver.client.stub.ProxyGetOrCreate(req)
33
- self._hydrate(response.proxy_id, resolver.client, None)
35
+ response: api_pb2.ProxyGetResponse = await resolver.client.stub.ProxyGet(req)
36
+ self._hydrate(response.proxy.proxy_id, resolver.client, None)
34
37
 
35
38
  return _Proxy._from_loader(_load, "Proxy()", is_another_app=True)
36
39
 
modal/proxy.pyi CHANGED
@@ -3,14 +3,9 @@ import typing
3
3
 
4
4
  class _Proxy(modal.object._Object):
5
5
  @staticmethod
6
- def from_name(label: str, namespace=1, environment_name: typing.Union[str, None] = None) -> _Proxy:
7
- ...
8
-
6
+ def from_name(name: str, environment_name: typing.Optional[str] = None) -> _Proxy: ...
9
7
 
10
8
  class Proxy(modal.object.Object):
11
- def __init__(self, *args, **kwargs):
12
- ...
13
-
9
+ def __init__(self, *args, **kwargs): ...
14
10
  @staticmethod
15
- def from_name(label: str, namespace=1, environment_name: typing.Union[str, None] = None) -> Proxy:
16
- ...
11
+ def from_name(name: str, environment_name: typing.Optional[str] = None) -> Proxy: ...