modal 0.62.16__py3-none-any.whl → 0.72.11__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 +17 -13
- modal/__main__.py +41 -3
- modal/_clustered_functions.py +80 -0
- modal/_clustered_functions.pyi +22 -0
- modal/_container_entrypoint.py +420 -937
- modal/_ipython.py +3 -13
- modal/_location.py +17 -10
- modal/_output.py +243 -99
- modal/_pty.py +2 -2
- modal/_resolver.py +55 -59
- modal/_resources.py +51 -0
- modal/_runtime/__init__.py +1 -0
- modal/_runtime/asgi.py +519 -0
- modal/_runtime/container_io_manager.py +1036 -0
- modal/_runtime/execution_context.py +89 -0
- modal/_runtime/telemetry.py +169 -0
- modal/_runtime/user_code_imports.py +356 -0
- modal/_serialization.py +134 -9
- modal/_traceback.py +47 -187
- modal/_tunnel.py +52 -16
- modal/_tunnel.pyi +19 -36
- modal/_utils/app_utils.py +3 -17
- modal/_utils/async_utils.py +479 -100
- modal/_utils/blob_utils.py +157 -186
- modal/_utils/bytes_io_segment_payload.py +97 -0
- modal/_utils/deprecation.py +89 -0
- modal/_utils/docker_utils.py +98 -0
- modal/_utils/function_utils.py +460 -171
- modal/_utils/grpc_testing.py +47 -31
- modal/_utils/grpc_utils.py +62 -109
- modal/_utils/hash_utils.py +61 -19
- modal/_utils/http_utils.py +39 -9
- modal/_utils/logger.py +2 -1
- modal/_utils/mount_utils.py +34 -16
- modal/_utils/name_utils.py +58 -0
- modal/_utils/package_utils.py +14 -1
- modal/_utils/pattern_utils.py +205 -0
- modal/_utils/rand_pb_testing.py +5 -7
- modal/_utils/shell_utils.py +15 -49
- modal/_vendor/a2wsgi_wsgi.py +62 -72
- modal/_vendor/cloudpickle.py +1 -1
- modal/_watcher.py +14 -12
- modal/app.py +1003 -314
- modal/app.pyi +540 -264
- modal/call_graph.py +7 -6
- modal/cli/_download.py +63 -53
- modal/cli/_traceback.py +200 -0
- modal/cli/app.py +205 -45
- modal/cli/config.py +12 -5
- modal/cli/container.py +62 -14
- modal/cli/dict.py +128 -0
- modal/cli/entry_point.py +26 -13
- modal/cli/environment.py +40 -9
- modal/cli/import_refs.py +64 -58
- modal/cli/launch.py +32 -18
- modal/cli/network_file_system.py +64 -83
- modal/cli/profile.py +1 -1
- modal/cli/programs/run_jupyter.py +35 -10
- modal/cli/programs/vscode.py +60 -10
- modal/cli/queues.py +131 -0
- modal/cli/run.py +234 -131
- modal/cli/secret.py +8 -7
- modal/cli/token.py +7 -2
- modal/cli/utils.py +79 -10
- modal/cli/volume.py +110 -109
- modal/client.py +250 -144
- modal/client.pyi +157 -118
- modal/cloud_bucket_mount.py +108 -34
- modal/cloud_bucket_mount.pyi +32 -38
- modal/cls.py +535 -148
- modal/cls.pyi +190 -146
- modal/config.py +41 -19
- modal/container_process.py +177 -0
- modal/container_process.pyi +82 -0
- modal/dict.py +111 -65
- modal/dict.pyi +136 -131
- modal/environments.py +106 -5
- modal/environments.pyi +77 -25
- modal/exception.py +34 -43
- modal/experimental.py +61 -2
- modal/extensions/ipython.py +5 -5
- modal/file_io.py +537 -0
- modal/file_io.pyi +235 -0
- modal/file_pattern_matcher.py +197 -0
- modal/functions.py +906 -911
- modal/functions.pyi +466 -430
- modal/gpu.py +57 -44
- modal/image.py +1089 -479
- modal/image.pyi +584 -228
- modal/io_streams.py +434 -0
- modal/io_streams.pyi +122 -0
- modal/mount.py +314 -101
- modal/mount.pyi +241 -235
- modal/network_file_system.py +92 -92
- modal/network_file_system.pyi +152 -110
- modal/object.py +67 -36
- modal/object.pyi +166 -143
- modal/output.py +63 -0
- modal/parallel_map.py +434 -0
- modal/parallel_map.pyi +75 -0
- modal/partial_function.py +282 -117
- modal/partial_function.pyi +222 -129
- modal/proxy.py +15 -12
- modal/proxy.pyi +3 -8
- modal/queue.py +182 -65
- modal/queue.pyi +218 -118
- modal/requirements/2024.04.txt +29 -0
- modal/requirements/2024.10.txt +16 -0
- modal/requirements/README.md +21 -0
- modal/requirements/base-images.json +22 -0
- modal/retries.py +48 -7
- modal/runner.py +459 -156
- modal/runner.pyi +135 -71
- modal/running_app.py +38 -0
- modal/sandbox.py +514 -236
- modal/sandbox.pyi +397 -169
- modal/schedule.py +4 -4
- modal/scheduler_placement.py +20 -3
- modal/secret.py +56 -31
- modal/secret.pyi +62 -42
- modal/serving.py +51 -56
- modal/serving.pyi +44 -36
- modal/stream_type.py +15 -0
- modal/token_flow.py +5 -3
- modal/token_flow.pyi +37 -32
- modal/volume.py +285 -157
- modal/volume.pyi +249 -184
- {modal-0.62.16.dist-info → modal-0.72.11.dist-info}/METADATA +7 -7
- modal-0.72.11.dist-info/RECORD +174 -0
- {modal-0.62.16.dist-info → modal-0.72.11.dist-info}/top_level.txt +0 -1
- modal_docs/gen_reference_docs.py +3 -1
- modal_docs/mdmd/mdmd.py +0 -1
- modal_docs/mdmd/signatures.py +5 -2
- modal_global_objects/images/base_images.py +28 -0
- modal_global_objects/mounts/python_standalone.py +2 -2
- modal_proto/__init__.py +1 -1
- modal_proto/api.proto +1288 -533
- modal_proto/api_grpc.py +856 -456
- modal_proto/api_pb2.py +2165 -1157
- modal_proto/api_pb2.pyi +8859 -0
- modal_proto/api_pb2_grpc.py +1674 -855
- modal_proto/api_pb2_grpc.pyi +1416 -0
- modal_proto/modal_api_grpc.py +149 -0
- modal_proto/modal_options_grpc.py +3 -0
- modal_proto/options_pb2.pyi +20 -0
- modal_proto/options_pb2_grpc.pyi +7 -0
- modal_proto/py.typed +0 -0
- modal_version/__init__.py +1 -1
- modal_version/_version_generated.py +2 -2
- modal/_asgi.py +0 -370
- modal/_container_entrypoint.pyi +0 -378
- modal/_container_exec.py +0 -128
- modal/_sandbox_shell.py +0 -49
- modal/shared_volume.py +0 -23
- modal/shared_volume.pyi +0 -24
- modal/stub.py +0 -783
- modal/stub.pyi +0 -332
- modal-0.62.16.dist-info/RECORD +0 -198
- modal_global_objects/images/conda.py +0 -15
- modal_global_objects/images/debian_slim.py +0 -15
- modal_global_objects/images/micromamba.py +0 -15
- test/__init__.py +0 -1
- test/aio_test.py +0 -12
- test/async_utils_test.py +0 -262
- test/blob_test.py +0 -67
- test/cli_imports_test.py +0 -149
- test/cli_test.py +0 -659
- test/client_test.py +0 -194
- test/cls_test.py +0 -630
- test/config_test.py +0 -137
- test/conftest.py +0 -1420
- test/container_app_test.py +0 -32
- test/container_test.py +0 -1389
- test/cpu_test.py +0 -23
- test/decorator_test.py +0 -85
- test/deprecation_test.py +0 -34
- test/dict_test.py +0 -33
- test/e2e_test.py +0 -68
- test/error_test.py +0 -7
- test/function_serialization_test.py +0 -32
- test/function_test.py +0 -653
- test/function_utils_test.py +0 -101
- test/gpu_test.py +0 -159
- test/grpc_utils_test.py +0 -141
- test/helpers.py +0 -42
- test/image_test.py +0 -669
- test/live_reload_test.py +0 -80
- test/lookup_test.py +0 -70
- test/mdmd_test.py +0 -329
- test/mount_test.py +0 -162
- test/mounted_files_test.py +0 -329
- test/network_file_system_test.py +0 -181
- test/notebook_test.py +0 -66
- test/object_test.py +0 -41
- test/package_utils_test.py +0 -25
- test/queue_test.py +0 -97
- test/resolver_test.py +0 -58
- test/retries_test.py +0 -67
- test/runner_test.py +0 -85
- test/sandbox_test.py +0 -191
- test/schedule_test.py +0 -15
- test/scheduler_placement_test.py +0 -29
- test/secret_test.py +0 -78
- test/serialization_test.py +0 -42
- test/stub_composition_test.py +0 -10
- test/stub_test.py +0 -360
- test/test_asgi_wrapper.py +0 -234
- test/token_flow_test.py +0 -18
- test/traceback_test.py +0 -135
- test/tunnel_test.py +0 -29
- test/utils_test.py +0 -88
- test/version_test.py +0 -14
- test/volume_test.py +0 -341
- test/watcher_test.py +0 -30
- test/webhook_test.py +0 -146
- /modal/{requirements.312.txt → requirements/2023.12.312.txt} +0 -0
- /modal/{requirements.txt → requirements/2023.12.txt} +0 -0
- {modal-0.62.16.dist-info → modal-0.72.11.dist-info}/LICENSE +0 -0
- {modal-0.62.16.dist-info → modal-0.72.11.dist-info}/WHEEL +0 -0
- {modal-0.62.16.dist-info → modal-0.72.11.dist-info}/entry_points.txt +0 -0
test/webhook_test.py
DELETED
@@ -1,146 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2022
|
2
|
-
import pathlib
|
3
|
-
import pytest
|
4
|
-
import subprocess
|
5
|
-
import sys
|
6
|
-
|
7
|
-
from fastapi.testclient import TestClient
|
8
|
-
|
9
|
-
from modal import Stub, asgi_app, web_endpoint, wsgi_app
|
10
|
-
from modal._asgi import webhook_asgi_app
|
11
|
-
from modal.app import ContainerApp
|
12
|
-
from modal.exception import InvalidError
|
13
|
-
from modal.functions import Function
|
14
|
-
from modal_proto import api_pb2
|
15
|
-
|
16
|
-
stub = Stub()
|
17
|
-
|
18
|
-
|
19
|
-
@stub.function(cpu=42)
|
20
|
-
@web_endpoint(method="PATCH")
|
21
|
-
async def f(x):
|
22
|
-
return {"square": x**2}
|
23
|
-
|
24
|
-
|
25
|
-
@pytest.mark.asyncio
|
26
|
-
async def test_webhook(servicer, client):
|
27
|
-
async with stub.run(client=client):
|
28
|
-
assert f.web_url
|
29
|
-
|
30
|
-
assert servicer.app_functions["fu-1"].webhook_config.type == api_pb2.WEBHOOK_TYPE_FUNCTION
|
31
|
-
assert servicer.app_functions["fu-1"].webhook_config.method == "PATCH"
|
32
|
-
|
33
|
-
# Make sure we can call the webhooks
|
34
|
-
# TODO: reinstate `.remote` check when direct webhook fn invocation is fixed.
|
35
|
-
# assert await f.remote(10)
|
36
|
-
assert await f.local(100) == {"square": 10000}
|
37
|
-
|
38
|
-
# Make sure the container gets the app id as well
|
39
|
-
container_app = ContainerApp()
|
40
|
-
await ContainerApp.init.aio(client, stub.app_id)
|
41
|
-
container_app.associate_stub_container(stub)
|
42
|
-
assert isinstance(f, Function)
|
43
|
-
assert f.web_url
|
44
|
-
|
45
|
-
|
46
|
-
def test_webhook_cors():
|
47
|
-
def handler():
|
48
|
-
return {"message": "Hello, World!"}
|
49
|
-
|
50
|
-
app = webhook_asgi_app(handler, method="GET")
|
51
|
-
client = TestClient(app)
|
52
|
-
resp = client.options(
|
53
|
-
"/",
|
54
|
-
headers={
|
55
|
-
"Origin": "http://example.com",
|
56
|
-
"Access-Control-Request-Method": "POST",
|
57
|
-
},
|
58
|
-
)
|
59
|
-
assert resp.headers["Access-Control-Allow-Origin"] == "http://example.com"
|
60
|
-
|
61
|
-
assert client.get("/").json() == {"message": "Hello, World!"}
|
62
|
-
assert client.post("/").status_code == 405 # Method Not Allowed
|
63
|
-
|
64
|
-
|
65
|
-
@pytest.mark.asyncio
|
66
|
-
async def test_webhook_no_docs():
|
67
|
-
# FastAPI automatically sets docs URLs for apps, which we disable because it
|
68
|
-
# can be unexpected for users who are unfamilar with FastAPI.
|
69
|
-
#
|
70
|
-
# https://fastapi.tiangolo.com/tutorial/metadata/#docs-urls
|
71
|
-
|
72
|
-
def handler():
|
73
|
-
return {"message": "Hello, World!"}
|
74
|
-
|
75
|
-
app = webhook_asgi_app(handler, method="GET")
|
76
|
-
client = TestClient(app)
|
77
|
-
assert client.get("/docs").status_code == 404
|
78
|
-
assert client.get("/redoc").status_code == 404
|
79
|
-
|
80
|
-
|
81
|
-
def test_webhook_generator():
|
82
|
-
stub = Stub()
|
83
|
-
|
84
|
-
with pytest.raises(InvalidError) as excinfo:
|
85
|
-
|
86
|
-
@stub.function(serialized=True)
|
87
|
-
@web_endpoint()
|
88
|
-
def web_gen():
|
89
|
-
yield None
|
90
|
-
|
91
|
-
assert "streaming" in str(excinfo.value).lower()
|
92
|
-
|
93
|
-
|
94
|
-
@pytest.mark.asyncio
|
95
|
-
async def test_webhook_forgot_function(servicer, client):
|
96
|
-
lib_dir = pathlib.Path(__file__).parent.parent
|
97
|
-
args = [sys.executable, "-m", "test.supports.webhook_forgot_function"]
|
98
|
-
ret = subprocess.run(args, cwd=lib_dir, stderr=subprocess.PIPE)
|
99
|
-
stderr = ret.stderr.decode()
|
100
|
-
assert "absent_minded_function" in stderr
|
101
|
-
assert "@stub.function" in stderr
|
102
|
-
|
103
|
-
|
104
|
-
@pytest.mark.asyncio
|
105
|
-
async def test_webhook_decorator_in_wrong_order(servicer, client):
|
106
|
-
stub = Stub()
|
107
|
-
|
108
|
-
with pytest.raises(InvalidError) as excinfo:
|
109
|
-
|
110
|
-
@web_endpoint() # type: ignore
|
111
|
-
@stub.function(serialized=True)
|
112
|
-
async def g(x):
|
113
|
-
pass
|
114
|
-
|
115
|
-
assert "wrong order" in str(excinfo.value).lower()
|
116
|
-
|
117
|
-
|
118
|
-
@pytest.mark.asyncio
|
119
|
-
async def test_asgi_wsgi(servicer, client):
|
120
|
-
stub = Stub()
|
121
|
-
|
122
|
-
@stub.function(serialized=True)
|
123
|
-
@asgi_app()
|
124
|
-
async def my_asgi(x):
|
125
|
-
pass
|
126
|
-
|
127
|
-
@stub.function(serialized=True)
|
128
|
-
@wsgi_app()
|
129
|
-
async def my_wsgi(x):
|
130
|
-
pass
|
131
|
-
|
132
|
-
async with stub.run(client=client):
|
133
|
-
pass
|
134
|
-
|
135
|
-
assert len(servicer.app_functions) == 2
|
136
|
-
assert servicer.app_functions["fu-1"].webhook_config.type == api_pb2.WEBHOOK_TYPE_ASGI_APP
|
137
|
-
assert servicer.app_functions["fu-2"].webhook_config.type == api_pb2.WEBHOOK_TYPE_WSGI_APP
|
138
|
-
|
139
|
-
|
140
|
-
def test_positional_method(servicer, client):
|
141
|
-
with pytest.raises(InvalidError, match="method="):
|
142
|
-
web_endpoint("GET")
|
143
|
-
with pytest.raises(InvalidError, match="label="):
|
144
|
-
asgi_app("baz")
|
145
|
-
with pytest.raises(InvalidError, match="label="):
|
146
|
-
wsgi_app("baz")
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|