modal 0.73.81__py3-none-any.whl → 0.73.83__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.
modal/__init__.py CHANGED
@@ -23,7 +23,18 @@ try:
23
23
  from .mount import Mount
24
24
  from .network_file_system import NetworkFileSystem
25
25
  from .output import enable_output
26
- from .partial_function import asgi_app, batched, build, enter, exit, method, web_endpoint, web_server, wsgi_app
26
+ from .partial_function import (
27
+ asgi_app,
28
+ batched,
29
+ build,
30
+ enter,
31
+ exit,
32
+ fastapi_endpoint,
33
+ method,
34
+ web_endpoint,
35
+ web_server,
36
+ wsgi_app,
37
+ )
27
38
  from .proxy import Proxy
28
39
  from .queue import Queue
29
40
  from .retries import Retries
@@ -76,6 +87,7 @@ __all__ = [
76
87
  "enable_output",
77
88
  "enter",
78
89
  "exit",
90
+ "fastapi_endpoint",
79
91
  "forward",
80
92
  "is_local",
81
93
  "interact",
@@ -256,6 +256,64 @@ def _parse_custom_domains(custom_domains: Optional[Iterable[str]] = None) -> lis
256
256
  return _custom_domains
257
257
 
258
258
 
259
+ def _fastapi_endpoint(
260
+ _warn_parentheses_missing=None,
261
+ *,
262
+ method: str = "GET", # REST method for the created endpoint.
263
+ label: Optional[str] = None, # Label for created endpoint. Final subdomain will be <workspace>--<label>.modal.run.
264
+ custom_domains: Optional[Iterable[str]] = None, # Custom fully-qualified domain name (FQDN) for the endpoint.
265
+ docs: bool = False, # Whether to enable interactive documentation for this endpoint at /docs.
266
+ requires_proxy_auth: bool = False, # Require Modal-Key and Modal-Secret HTTP Headers on requests.
267
+ ) -> Callable[[Callable[P, ReturnType]], _PartialFunction[P, ReturnType, ReturnType]]:
268
+ """Register a basic web endpoint with this application.
269
+
270
+ This is the simple way to create a web endpoint on Modal. The function
271
+ behaves as a [FastAPI](https://fastapi.tiangolo.com/) handler and should
272
+ return a response object to the caller.
273
+
274
+ Endpoints created with `@app.fastapi_endpoint` are meant to be simple, single
275
+ request handlers and automatically have
276
+ [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) enabled.
277
+ For more flexibility, use `@app.asgi_app`.
278
+
279
+ To learn how to use Modal with popular web frameworks, see the
280
+ [guide on web endpoints](https://modal.com/docs/guide/webhooks).
281
+
282
+ This function replaces the deprecated `@web_endpoint` decorator.
283
+ """
284
+ if isinstance(_warn_parentheses_missing, str):
285
+ # Probably passing the method string as a positional argument.
286
+ raise InvalidError('Positional arguments are not allowed. Suggestion: `@fastapi_endpoint(method="GET")`.')
287
+ elif _warn_parentheses_missing is not None:
288
+ raise InvalidError(
289
+ "Positional arguments are not allowed. Did you forget parentheses? Suggestion: `@fastapi_endpoint()`."
290
+ )
291
+
292
+ def wrapper(raw_f: Callable[..., Any]) -> _PartialFunction:
293
+ if isinstance(raw_f, _Function):
294
+ raw_f = raw_f.get_raw_f()
295
+ raise InvalidError(
296
+ f"Applying decorators for {raw_f} in the wrong order!\nUsage:\n\n"
297
+ "@app.function()\n@app.fastapi_endpoint()\ndef my_webhook():\n ..."
298
+ )
299
+
300
+ return _PartialFunction(
301
+ raw_f,
302
+ _PartialFunctionFlags.FUNCTION,
303
+ api_pb2.WebhookConfig(
304
+ type=api_pb2.WEBHOOK_TYPE_FUNCTION,
305
+ method=method,
306
+ web_endpoint_docs=docs,
307
+ requested_suffix=label or "",
308
+ async_mode=api_pb2.WEBHOOK_ASYNC_MODE_AUTO,
309
+ custom_domains=_parse_custom_domains(custom_domains),
310
+ requires_proxy_auth=requires_proxy_auth,
311
+ ),
312
+ )
313
+
314
+ return wrapper
315
+
316
+
259
317
  def _web_endpoint(
260
318
  _warn_parentheses_missing=None,
261
319
  *,
modal/app.py CHANGED
@@ -658,13 +658,13 @@ class _App:
658
658
  if is_method_fn(f.raw_f.__qualname__):
659
659
  raise InvalidError(
660
660
  "The `@app.function` decorator cannot be used on class methods. "
661
- "Swap with `@modal.method` or `@modal.web_endpoint`, or drop the `@app.function` decorator. "
661
+ "Swap with `@modal.method` or one of the web endpoint decorators. "
662
662
  "Example: "
663
663
  "\n\n"
664
664
  "```python\n"
665
665
  "@app.cls()\n"
666
666
  "class MyClass:\n"
667
- " @modal.web_endpoint()\n"
667
+ " @modal.method()\n"
668
668
  " def f(self, x):\n"
669
669
  " ...\n"
670
670
  "```\n"
modal/client.pyi CHANGED
@@ -27,7 +27,7 @@ class _Client:
27
27
  _snapshotted: bool
28
28
 
29
29
  def __init__(
30
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.81"
30
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.83"
31
31
  ): ...
32
32
  def is_closed(self) -> bool: ...
33
33
  @property
@@ -85,7 +85,7 @@ class Client:
85
85
  _snapshotted: bool
86
86
 
87
87
  def __init__(
88
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.81"
88
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.83"
89
89
  ): ...
90
90
  def is_closed(self) -> bool: ...
91
91
  @property
modal/partial_function.py CHANGED
@@ -7,6 +7,7 @@ from ._partial_function import (
7
7
  _build,
8
8
  _enter,
9
9
  _exit,
10
+ _fastapi_endpoint,
10
11
  _method,
11
12
  _PartialFunction,
12
13
  _web_endpoint,
@@ -19,6 +20,7 @@ from ._partial_function import (
19
20
  PartialFunction = synchronize_api(_PartialFunction, target_module=__name__)
20
21
  method = synchronize_api(_method, target_module=__name__)
21
22
  web_endpoint = synchronize_api(_web_endpoint, target_module=__name__)
23
+ fastapi_endpoint = synchronize_api(_fastapi_endpoint, target_module=__name__)
22
24
  asgi_app = synchronize_api(_asgi_app, target_module=__name__)
23
25
  wsgi_app = synchronize_api(_wsgi_app, target_module=__name__)
24
26
  web_server = synchronize_api(_web_server, target_module=__name__)
@@ -61,6 +61,18 @@ def web_endpoint(
61
61
  [collections.abc.Callable[modal._partial_function.P, modal._partial_function.ReturnType]],
62
62
  PartialFunction[modal._partial_function.P, modal._partial_function.ReturnType, modal._partial_function.ReturnType],
63
63
  ]: ...
64
+ def fastapi_endpoint(
65
+ _warn_parentheses_missing=None,
66
+ *,
67
+ method: str = "GET",
68
+ label: typing.Optional[str] = None,
69
+ custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
70
+ docs: bool = False,
71
+ requires_proxy_auth: bool = False,
72
+ ) -> collections.abc.Callable[
73
+ [collections.abc.Callable[modal._partial_function.P, modal._partial_function.ReturnType]],
74
+ PartialFunction[modal._partial_function.P, modal._partial_function.ReturnType, modal._partial_function.ReturnType],
75
+ ]: ...
64
76
  def asgi_app(
65
77
  _warn_parentheses_missing=None,
66
78
  *,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: modal
3
- Version: 0.73.81
3
+ Version: 0.73.83
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
- modal/__init__.py,sha256=8tE3_OhuKF5UkP4dcmMe8NAbLNNJyuwJFNgDQRBgCig,2333
1
+ modal/__init__.py,sha256=KcoVQVCfwuHmIJ74OxQPn66MHfiJcWi8V5srBW12jTA,2464
2
2
  modal/__main__.py,sha256=CgIjP8m1xJjjd4AXc-delmR6LdBCZclw2A_V38CFIio,2870
3
3
  modal/_clustered_functions.py,sha256=kTf-9YBXY88NutC1akI-gCbvf01RhMPCw-zoOI_YIUE,2700
4
4
  modal/_clustered_functions.pyi,sha256=vllkegc99A0jrUOWa8mdlSbdp6uz36TsHhGxysAOpaQ,771
@@ -8,7 +8,7 @@ modal/_ipython.py,sha256=TW1fkVOmZL3YYqdS2YlM1hqpf654Yf8ZyybHdBnlhSw,301
8
8
  modal/_location.py,sha256=joiX-0ZeutEUDTrrqLF1GHXCdVLF-rHzstocbMcd_-k,366
9
9
  modal/_object.py,sha256=ItQcsMNkz9Y3kdTsvfNarbW-paJ2qabDyQ7njaqY0XI,11359
10
10
  modal/_output.py,sha256=Z0nngPh2mKHMQc4MQ92YjVPc3ewOLa3I4dFBlL9nvQY,25656
11
- modal/_partial_function.py,sha256=5MKkd66aKB6NlFjnLCNidY4E6L2SDjmChp0ByYYV6sU,27881
11
+ modal/_partial_function.py,sha256=YlmHjFSQKj64ypBV8O0BCPogDzZwnbbNNeOveiEDKjQ,30592
12
12
  modal/_proxy_tunnel.py,sha256=gnKyCfmVB7x2d1A6c-JDysNIP3kEFxmXzhcXhPrzPn0,1906
13
13
  modal/_pty.py,sha256=JZfPDDpzqICZqtyPI_oMJf_9w-p_lLNuzHhwhodUXio,1329
14
14
  modal/_resolver.py,sha256=RtoXoYzSllPlFu0D1vel_FWiEmDO7RyToiC2bxeN8ZY,6917
@@ -18,11 +18,11 @@ modal/_traceback.py,sha256=IZQzB3fVlUfMHOSyKUgw0H6qv4yHnpyq-XVCNZKfUdA,5023
18
18
  modal/_tunnel.py,sha256=zTBxBiuH1O22tS1OliAJdIsSmaZS8PlnifS_6S5z-mk,6320
19
19
  modal/_tunnel.pyi,sha256=JmmDYAy9F1FpgJ_hWx0xkom2nTOFQjn4mTPYlU3PFo4,1245
20
20
  modal/_watcher.py,sha256=K6LYnlmSGQB4tWWI9JADv-tvSvQ1j522FwT71B51CX8,3584
21
- modal/app.py,sha256=kF3frIt4eRKVYYCjusMMhKJpO_lDdm2z37HOXPwpjT8,45506
21
+ modal/app.py,sha256=PPYAQ7ts6PeJHcV2D5DWsJw-vfZzM4Rpnw7S2BNnEk8,45474
22
22
  modal/app.pyi,sha256=tZFbcsu20SuvfB2puxCyuXLFNJ9bQulzag55rVpgZmc,26827
23
23
  modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
24
24
  modal/client.py,sha256=8SQawr7P1PNUCq1UmJMUQXG2jIo4Nmdcs311XqrNLRE,15276
25
- modal/client.pyi,sha256=nTyGF9yDiFVLdzSX_DFF5LGAH-PqxoY_6ZRX6hN4ODw,7593
25
+ modal/client.pyi,sha256=VhQbhPoaANowtJn4AuOcwpZidsEwTkcA25UCePu0jQo,7593
26
26
  modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
27
27
  modal/cloud_bucket_mount.pyi,sha256=30T3K1a89l6wzmEJ_J9iWv9SknoGqaZDx59Xs-ZQcmk,1607
28
28
  modal/cls.py,sha256=5DjpSBP1IyROKZm5ItDiEGdbRnfTT6K1Ul0jEvEKw_Q,31695
@@ -56,8 +56,8 @@ modal/object.pyi,sha256=kyJkRQcVv3ct7zSAxvvXcuhBVeH914v80uSlqeS7cA4,5632
56
56
  modal/output.py,sha256=q4T9uHduunj4NwY-YSwkHGgjZlCXMuJbfQ5UFaAGRAc,1968
57
57
  modal/parallel_map.py,sha256=POBTyiWabe2e4qBNlsjjksiu1AAPEsNqI-mM8cgNFco,16042
58
58
  modal/parallel_map.pyi,sha256=-YKY_bVuQv8B4gtFrHnXtuNV0_JpmU9vqMJzR7beeCU,2524
59
- modal/partial_function.py,sha256=KkATL56zEe_Kzp4hDX0c0e6BrXeO8V8mZBjfIs_ldqI,1016
60
- modal/partial_function.pyi,sha256=RO76Hg9DAYHd1gW3ntPMucbUpvu19ZLZTRjtBSIwIV0,4541
59
+ modal/partial_function.py,sha256=uu8zvIV0Big0jiTlC4-VPL16dOScNB5jhfPeqxvvCrI,1117
60
+ modal/partial_function.pyi,sha256=gkTHo5Rna5ShL7dCTSY8Pq5XA0-9C3sqrT8MznIQW_g,5062
61
61
  modal/proxy.py,sha256=NrOevrWxG3G7-zlyRzG6BcIvop7AWLeyahZxitbBaOk,1418
62
62
  modal/proxy.pyi,sha256=1OEKIVUyC-xb7fHMzngakQso0nTsK60TVhXtlcMj6Wk,390
63
63
  modal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -168,10 +168,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
168
168
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
169
169
  modal_version/__init__.py,sha256=wiJQ53c-OMs0Xf1UeXOxQ7FwlV1VzIjnX6o-pRYZ_Pk,470
170
170
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
171
- modal_version/_version_generated.py,sha256=6ZSRrr6DXex_JOkeoVsVZjwFK4LTYXrAZvlvZT0uolE,149
172
- modal-0.73.81.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
173
- modal-0.73.81.dist-info/METADATA,sha256=yxfDvZoNZuehaLqU2nFgYWGTZRQdTVSIpzUr8rehM0I,2452
174
- modal-0.73.81.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
175
- modal-0.73.81.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
176
- modal-0.73.81.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
177
- modal-0.73.81.dist-info/RECORD,,
171
+ modal_version/_version_generated.py,sha256=WWhQ9EsX7hOXL_fw1PKf34S8S0oZ8dXMOe00dA2Iic0,149
172
+ modal-0.73.83.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
173
+ modal-0.73.83.dist-info/METADATA,sha256=t05P4HjQIdinKolQpHNHwxLrk7nL6blEqC1IZR3yFUQ,2452
174
+ modal-0.73.83.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
175
+ modal-0.73.83.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
176
+ modal-0.73.83.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
177
+ modal-0.73.83.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2025
2
2
 
3
3
  # Note: Reset this value to -1 whenever you make a minor `0.X` release of the client.
4
- build_number = 81 # git: fa53b89
4
+ build_number = 83 # git: a4a605c