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.
- modal/__init__.py +13 -9
- modal/__main__.py +41 -3
- modal/_clustered_functions.py +80 -0
- modal/_clustered_functions.pyi +22 -0
- modal/_container_entrypoint.py +402 -398
- modal/_ipython.py +3 -13
- modal/_location.py +17 -10
- modal/_output.py +243 -99
- modal/_pty.py +2 -2
- modal/_resolver.py +55 -60
- modal/_resources.py +26 -7
- modal/_runtime/__init__.py +1 -0
- modal/_runtime/asgi.py +519 -0
- modal/_runtime/container_io_manager.py +1025 -0
- modal/{execution_context.py → _runtime/execution_context.py} +11 -2
- modal/_runtime/telemetry.py +169 -0
- modal/_runtime/user_code_imports.py +356 -0
- modal/_serialization.py +123 -6
- modal/_traceback.py +47 -187
- modal/_tunnel.py +50 -14
- modal/_tunnel.pyi +19 -36
- modal/_utils/app_utils.py +3 -17
- modal/_utils/async_utils.py +386 -104
- 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 +299 -98
- modal/_utils/grpc_testing.py +47 -34
- modal/_utils/grpc_utils.py +54 -21
- modal/_utils/hash_utils.py +51 -10
- 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 +3 -3
- modal/_utils/shell_utils.py +15 -49
- modal/_vendor/a2wsgi_wsgi.py +62 -72
- modal/_vendor/cloudpickle.py +1 -1
- modal/_watcher.py +12 -10
- modal/app.py +561 -323
- modal/app.pyi +474 -262
- modal/call_graph.py +7 -6
- modal/cli/_download.py +22 -6
- modal/cli/_traceback.py +200 -0
- modal/cli/app.py +203 -42
- modal/cli/config.py +12 -5
- modal/cli/container.py +61 -13
- modal/cli/dict.py +128 -0
- modal/cli/entry_point.py +26 -13
- modal/cli/environment.py +40 -9
- modal/cli/import_refs.py +21 -48
- modal/cli/launch.py +28 -14
- modal/cli/network_file_system.py +57 -21
- modal/cli/profile.py +1 -1
- modal/cli/programs/run_jupyter.py +34 -9
- modal/cli/programs/vscode.py +58 -8
- modal/cli/queues.py +131 -0
- modal/cli/run.py +199 -96
- modal/cli/secret.py +5 -4
- modal/cli/token.py +7 -2
- modal/cli/utils.py +74 -8
- modal/cli/volume.py +97 -56
- modal/client.py +248 -144
- modal/client.pyi +156 -124
- modal/cloud_bucket_mount.py +43 -30
- modal/cloud_bucket_mount.pyi +32 -25
- modal/cls.py +528 -141
- modal/cls.pyi +189 -145
- modal/config.py +32 -15
- modal/container_process.py +177 -0
- modal/container_process.pyi +82 -0
- modal/dict.py +50 -54
- modal/dict.pyi +120 -164
- modal/environments.py +106 -5
- modal/environments.pyi +77 -25
- modal/exception.py +30 -43
- modal/experimental.py +62 -2
- modal/file_io.py +537 -0
- modal/file_io.pyi +235 -0
- modal/file_pattern_matcher.py +196 -0
- modal/functions.py +846 -428
- modal/functions.pyi +446 -387
- modal/gpu.py +57 -44
- modal/image.py +943 -417
- modal/image.pyi +584 -245
- modal/io_streams.py +434 -0
- modal/io_streams.pyi +122 -0
- modal/mount.py +223 -90
- modal/mount.pyi +241 -243
- modal/network_file_system.py +85 -86
- modal/network_file_system.pyi +151 -110
- modal/object.py +66 -36
- modal/object.pyi +166 -143
- modal/output.py +63 -0
- modal/parallel_map.py +73 -47
- modal/parallel_map.pyi +51 -63
- modal/partial_function.py +272 -107
- modal/partial_function.pyi +219 -120
- modal/proxy.py +15 -12
- modal/proxy.pyi +3 -8
- modal/queue.py +96 -72
- modal/queue.pyi +210 -135
- modal/requirements/2024.04.txt +2 -1
- modal/requirements/2024.10.txt +16 -0
- modal/requirements/README.md +21 -0
- modal/requirements/base-images.json +22 -0
- modal/retries.py +45 -4
- modal/runner.py +325 -203
- modal/runner.pyi +124 -110
- modal/running_app.py +27 -4
- modal/sandbox.py +509 -231
- modal/sandbox.pyi +396 -169
- modal/schedule.py +2 -2
- modal/scheduler_placement.py +20 -3
- modal/secret.py +41 -25
- modal/secret.pyi +62 -42
- modal/serving.py +39 -49
- modal/serving.pyi +37 -43
- modal/stream_type.py +15 -0
- modal/token_flow.py +5 -3
- modal/token_flow.pyi +37 -32
- modal/volume.py +123 -137
- modal/volume.pyi +228 -221
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/METADATA +5 -5
- modal-0.72.13.dist-info/RECORD +174 -0
- {modal-0.62.115.dist-info → modal-0.72.13.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 +1 -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 +1231 -531
- modal_proto/api_grpc.py +750 -430
- modal_proto/api_pb2.py +2102 -1176
- modal_proto/api_pb2.pyi +8859 -0
- modal_proto/api_pb2_grpc.py +1329 -675
- 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_exec.py +0 -128
- modal/_container_io_manager.py +0 -646
- modal/_container_io_manager.pyi +0 -412
- modal/_sandbox_shell.py +0 -49
- modal/app_utils.py +0 -20
- modal/app_utils.pyi +0 -17
- modal/execution_context.pyi +0 -37
- modal/shared_volume.py +0 -23
- modal/shared_volume.pyi +0 -24
- modal-0.62.115.dist-info/RECORD +0 -207
- 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 -279
- test/blob_test.py +0 -67
- test/cli_imports_test.py +0 -149
- test/cli_test.py +0 -674
- test/client_test.py +0 -203
- test/cloud_bucket_mount_test.py +0 -22
- test/cls_test.py +0 -636
- test/config_test.py +0 -149
- test/conftest.py +0 -1485
- test/container_app_test.py +0 -50
- test/container_test.py +0 -1405
- test/cpu_test.py +0 -23
- test/decorator_test.py +0 -85
- test/deprecation_test.py +0 -34
- test/dict_test.py +0 -51
- test/e2e_test.py +0 -68
- test/error_test.py +0 -7
- test/function_serialization_test.py +0 -32
- test/function_test.py +0 -791
- test/function_utils_test.py +0 -101
- test/gpu_test.py +0 -159
- test/grpc_utils_test.py +0 -82
- test/helpers.py +0 -47
- test/image_test.py +0 -814
- 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 -327
- test/network_file_system_test.py +0 -188
- test/notebook_test.py +0 -66
- test/object_test.py +0 -41
- test/package_utils_test.py +0 -25
- test/queue_test.py +0 -115
- test/resolver_test.py +0 -59
- 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 -57
- test/secret_test.py +0 -89
- test/serialization_test.py +0 -50
- test/stub_composition_test.py +0 -10
- test/stub_test.py +0 -361
- 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 -397
- test/watcher_test.py +0 -58
- test/webhook_test.py +0 -145
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/LICENSE +0 -0
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/WHEEL +0 -0
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,149 @@
|
|
1
|
+
# Generated by the Modal Protocol Buffers compiler. DO NOT EDIT!
|
2
|
+
# source: modal_proto/api.proto
|
3
|
+
# plugin: __main__
|
4
|
+
|
5
|
+
import modal._utils.grpc_utils
|
6
|
+
import modal_proto.api_grpc
|
7
|
+
import typing
|
8
|
+
if typing.TYPE_CHECKING:
|
9
|
+
import modal.client
|
10
|
+
|
11
|
+
|
12
|
+
class ModalClientModal:
|
13
|
+
|
14
|
+
def __init__(self, grpclib_stub: modal_proto.api_grpc.ModalClientStub, client: "modal.client._Client") -> None:
|
15
|
+
self.AppClientDisconnect = modal.client.UnaryUnaryWrapper(grpclib_stub.AppClientDisconnect, client)
|
16
|
+
self.AppCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.AppCreate, client)
|
17
|
+
self.AppDeploy = modal.client.UnaryUnaryWrapper(grpclib_stub.AppDeploy, client)
|
18
|
+
self.AppDeploymentHistory = modal.client.UnaryUnaryWrapper(grpclib_stub.AppDeploymentHistory, client)
|
19
|
+
self.AppGetByDeploymentName = modal.client.UnaryUnaryWrapper(grpclib_stub.AppGetByDeploymentName, client)
|
20
|
+
self.AppGetLayout = modal.client.UnaryUnaryWrapper(grpclib_stub.AppGetLayout, client)
|
21
|
+
self.AppGetLogs = modal.client.UnaryStreamWrapper(grpclib_stub.AppGetLogs, client)
|
22
|
+
self.AppGetObjects = modal.client.UnaryUnaryWrapper(grpclib_stub.AppGetObjects, client)
|
23
|
+
self.AppGetOrCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.AppGetOrCreate, client)
|
24
|
+
self.AppHeartbeat = modal.client.UnaryUnaryWrapper(grpclib_stub.AppHeartbeat, client)
|
25
|
+
self.AppList = modal.client.UnaryUnaryWrapper(grpclib_stub.AppList, client)
|
26
|
+
self.AppLookup = modal.client.UnaryUnaryWrapper(grpclib_stub.AppLookup, client)
|
27
|
+
self.AppPublish = modal.client.UnaryUnaryWrapper(grpclib_stub.AppPublish, client)
|
28
|
+
self.AppRollback = modal.client.UnaryUnaryWrapper(grpclib_stub.AppRollback, client)
|
29
|
+
self.AppSetObjects = modal.client.UnaryUnaryWrapper(grpclib_stub.AppSetObjects, client)
|
30
|
+
self.AppStop = modal.client.UnaryUnaryWrapper(grpclib_stub.AppStop, client)
|
31
|
+
self.BlobCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.BlobCreate, client)
|
32
|
+
self.BlobGet = modal.client.UnaryUnaryWrapper(grpclib_stub.BlobGet, client)
|
33
|
+
self.ClassCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.ClassCreate, client)
|
34
|
+
self.ClassGet = modal.client.UnaryUnaryWrapper(grpclib_stub.ClassGet, client)
|
35
|
+
self.ClientHello = modal.client.UnaryUnaryWrapper(grpclib_stub.ClientHello, client)
|
36
|
+
self.ContainerCheckpoint = modal.client.UnaryUnaryWrapper(grpclib_stub.ContainerCheckpoint, client)
|
37
|
+
self.ContainerExec = modal.client.UnaryUnaryWrapper(grpclib_stub.ContainerExec, client)
|
38
|
+
self.ContainerExecGetOutput = modal.client.UnaryStreamWrapper(grpclib_stub.ContainerExecGetOutput, client)
|
39
|
+
self.ContainerExecPutInput = modal.client.UnaryUnaryWrapper(grpclib_stub.ContainerExecPutInput, client)
|
40
|
+
self.ContainerExecWait = modal.client.UnaryUnaryWrapper(grpclib_stub.ContainerExecWait, client)
|
41
|
+
self.ContainerFilesystemExec = modal.client.UnaryUnaryWrapper(grpclib_stub.ContainerFilesystemExec, client)
|
42
|
+
self.ContainerFilesystemExecGetOutput = modal.client.UnaryStreamWrapper(grpclib_stub.ContainerFilesystemExecGetOutput, client)
|
43
|
+
self.ContainerHeartbeat = modal.client.UnaryUnaryWrapper(grpclib_stub.ContainerHeartbeat, client)
|
44
|
+
self.ContainerHello = modal.client.UnaryUnaryWrapper(grpclib_stub.ContainerHello, client)
|
45
|
+
self.ContainerLog = modal.client.UnaryUnaryWrapper(grpclib_stub.ContainerLog, client)
|
46
|
+
self.ContainerStop = modal.client.UnaryUnaryWrapper(grpclib_stub.ContainerStop, client)
|
47
|
+
self.DictClear = modal.client.UnaryUnaryWrapper(grpclib_stub.DictClear, client)
|
48
|
+
self.DictContains = modal.client.UnaryUnaryWrapper(grpclib_stub.DictContains, client)
|
49
|
+
self.DictContents = modal.client.UnaryStreamWrapper(grpclib_stub.DictContents, client)
|
50
|
+
self.DictDelete = modal.client.UnaryUnaryWrapper(grpclib_stub.DictDelete, client)
|
51
|
+
self.DictGet = modal.client.UnaryUnaryWrapper(grpclib_stub.DictGet, client)
|
52
|
+
self.DictGetOrCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.DictGetOrCreate, client)
|
53
|
+
self.DictHeartbeat = modal.client.UnaryUnaryWrapper(grpclib_stub.DictHeartbeat, client)
|
54
|
+
self.DictLen = modal.client.UnaryUnaryWrapper(grpclib_stub.DictLen, client)
|
55
|
+
self.DictList = modal.client.UnaryUnaryWrapper(grpclib_stub.DictList, client)
|
56
|
+
self.DictPop = modal.client.UnaryUnaryWrapper(grpclib_stub.DictPop, client)
|
57
|
+
self.DictUpdate = modal.client.UnaryUnaryWrapper(grpclib_stub.DictUpdate, client)
|
58
|
+
self.DomainCertificateVerify = modal.client.UnaryUnaryWrapper(grpclib_stub.DomainCertificateVerify, client)
|
59
|
+
self.DomainCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.DomainCreate, client)
|
60
|
+
self.DomainList = modal.client.UnaryUnaryWrapper(grpclib_stub.DomainList, client)
|
61
|
+
self.EnvironmentCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.EnvironmentCreate, client)
|
62
|
+
self.EnvironmentDelete = modal.client.UnaryUnaryWrapper(grpclib_stub.EnvironmentDelete, client)
|
63
|
+
self.EnvironmentGetOrCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.EnvironmentGetOrCreate, client)
|
64
|
+
self.EnvironmentList = modal.client.UnaryUnaryWrapper(grpclib_stub.EnvironmentList, client)
|
65
|
+
self.EnvironmentUpdate = modal.client.UnaryUnaryWrapper(grpclib_stub.EnvironmentUpdate, client)
|
66
|
+
self.FunctionAsyncInvoke = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionAsyncInvoke, client)
|
67
|
+
self.FunctionBindParams = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionBindParams, client)
|
68
|
+
self.FunctionCallCancel = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionCallCancel, client)
|
69
|
+
self.FunctionCallGetDataIn = modal.client.UnaryStreamWrapper(grpclib_stub.FunctionCallGetDataIn, client)
|
70
|
+
self.FunctionCallGetDataOut = modal.client.UnaryStreamWrapper(grpclib_stub.FunctionCallGetDataOut, client)
|
71
|
+
self.FunctionCallList = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionCallList, client)
|
72
|
+
self.FunctionCallPutDataOut = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionCallPutDataOut, client)
|
73
|
+
self.FunctionCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionCreate, client)
|
74
|
+
self.FunctionGet = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionGet, client)
|
75
|
+
self.FunctionGetCallGraph = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionGetCallGraph, client)
|
76
|
+
self.FunctionGetCurrentStats = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionGetCurrentStats, client)
|
77
|
+
self.FunctionGetDynamicConcurrency = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionGetDynamicConcurrency, client)
|
78
|
+
self.FunctionGetInputs = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionGetInputs, client)
|
79
|
+
self.FunctionGetOutputs = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionGetOutputs, client)
|
80
|
+
self.FunctionGetSerialized = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionGetSerialized, client)
|
81
|
+
self.FunctionMap = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionMap, client)
|
82
|
+
self.FunctionPrecreate = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionPrecreate, client)
|
83
|
+
self.FunctionPutInputs = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionPutInputs, client)
|
84
|
+
self.FunctionPutOutputs = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionPutOutputs, client)
|
85
|
+
self.FunctionRetryInputs = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionRetryInputs, client)
|
86
|
+
self.FunctionStartPtyShell = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionStartPtyShell, client)
|
87
|
+
self.FunctionUpdateSchedulingParams = modal.client.UnaryUnaryWrapper(grpclib_stub.FunctionUpdateSchedulingParams, client)
|
88
|
+
self.ImageFromId = modal.client.UnaryUnaryWrapper(grpclib_stub.ImageFromId, client)
|
89
|
+
self.ImageGetOrCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.ImageGetOrCreate, client)
|
90
|
+
self.ImageJoinStreaming = modal.client.UnaryStreamWrapper(grpclib_stub.ImageJoinStreaming, client)
|
91
|
+
self.MountGetOrCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.MountGetOrCreate, client)
|
92
|
+
self.MountPutFile = modal.client.UnaryUnaryWrapper(grpclib_stub.MountPutFile, client)
|
93
|
+
self.ProxyCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.ProxyCreate, client)
|
94
|
+
self.ProxyDelete = modal.client.UnaryUnaryWrapper(grpclib_stub.ProxyDelete, client)
|
95
|
+
self.ProxyGet = modal.client.UnaryUnaryWrapper(grpclib_stub.ProxyGet, client)
|
96
|
+
self.ProxyGetOrCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.ProxyGetOrCreate, client)
|
97
|
+
self.ProxyList = modal.client.UnaryUnaryWrapper(grpclib_stub.ProxyList, client)
|
98
|
+
self.QueueClear = modal.client.UnaryUnaryWrapper(grpclib_stub.QueueClear, client)
|
99
|
+
self.QueueDelete = modal.client.UnaryUnaryWrapper(grpclib_stub.QueueDelete, client)
|
100
|
+
self.QueueGet = modal.client.UnaryUnaryWrapper(grpclib_stub.QueueGet, client)
|
101
|
+
self.QueueGetOrCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.QueueGetOrCreate, client)
|
102
|
+
self.QueueHeartbeat = modal.client.UnaryUnaryWrapper(grpclib_stub.QueueHeartbeat, client)
|
103
|
+
self.QueueLen = modal.client.UnaryUnaryWrapper(grpclib_stub.QueueLen, client)
|
104
|
+
self.QueueList = modal.client.UnaryUnaryWrapper(grpclib_stub.QueueList, client)
|
105
|
+
self.QueueNextItems = modal.client.UnaryUnaryWrapper(grpclib_stub.QueueNextItems, client)
|
106
|
+
self.QueuePut = modal.client.UnaryUnaryWrapper(grpclib_stub.QueuePut, client)
|
107
|
+
self.SandboxCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.SandboxCreate, client)
|
108
|
+
self.SandboxGetLogs = modal.client.UnaryStreamWrapper(grpclib_stub.SandboxGetLogs, client)
|
109
|
+
self.SandboxGetTaskId = modal.client.UnaryUnaryWrapper(grpclib_stub.SandboxGetTaskId, client)
|
110
|
+
self.SandboxGetTunnels = modal.client.UnaryUnaryWrapper(grpclib_stub.SandboxGetTunnels, client)
|
111
|
+
self.SandboxList = modal.client.UnaryUnaryWrapper(grpclib_stub.SandboxList, client)
|
112
|
+
self.SandboxSnapshotFs = modal.client.UnaryUnaryWrapper(grpclib_stub.SandboxSnapshotFs, client)
|
113
|
+
self.SandboxStdinWrite = modal.client.UnaryUnaryWrapper(grpclib_stub.SandboxStdinWrite, client)
|
114
|
+
self.SandboxTagsSet = modal.client.UnaryUnaryWrapper(grpclib_stub.SandboxTagsSet, client)
|
115
|
+
self.SandboxTerminate = modal.client.UnaryUnaryWrapper(grpclib_stub.SandboxTerminate, client)
|
116
|
+
self.SandboxWait = modal.client.UnaryUnaryWrapper(grpclib_stub.SandboxWait, client)
|
117
|
+
self.SecretDelete = modal.client.UnaryUnaryWrapper(grpclib_stub.SecretDelete, client)
|
118
|
+
self.SecretGetOrCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.SecretGetOrCreate, client)
|
119
|
+
self.SecretList = modal.client.UnaryUnaryWrapper(grpclib_stub.SecretList, client)
|
120
|
+
self.SharedVolumeDelete = modal.client.UnaryUnaryWrapper(grpclib_stub.SharedVolumeDelete, client)
|
121
|
+
self.SharedVolumeGetFile = modal.client.UnaryUnaryWrapper(grpclib_stub.SharedVolumeGetFile, client)
|
122
|
+
self.SharedVolumeGetOrCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.SharedVolumeGetOrCreate, client)
|
123
|
+
self.SharedVolumeHeartbeat = modal.client.UnaryUnaryWrapper(grpclib_stub.SharedVolumeHeartbeat, client)
|
124
|
+
self.SharedVolumeList = modal.client.UnaryUnaryWrapper(grpclib_stub.SharedVolumeList, client)
|
125
|
+
self.SharedVolumeListFiles = modal.client.UnaryUnaryWrapper(grpclib_stub.SharedVolumeListFiles, client)
|
126
|
+
self.SharedVolumeListFilesStream = modal.client.UnaryStreamWrapper(grpclib_stub.SharedVolumeListFilesStream, client)
|
127
|
+
self.SharedVolumePutFile = modal.client.UnaryUnaryWrapper(grpclib_stub.SharedVolumePutFile, client)
|
128
|
+
self.SharedVolumeRemoveFile = modal.client.UnaryUnaryWrapper(grpclib_stub.SharedVolumeRemoveFile, client)
|
129
|
+
self.TaskClusterHello = modal.client.UnaryUnaryWrapper(grpclib_stub.TaskClusterHello, client)
|
130
|
+
self.TaskCurrentInputs = modal.client.UnaryUnaryWrapper(grpclib_stub.TaskCurrentInputs, client)
|
131
|
+
self.TaskList = modal.client.UnaryUnaryWrapper(grpclib_stub.TaskList, client)
|
132
|
+
self.TaskResult = modal.client.UnaryUnaryWrapper(grpclib_stub.TaskResult, client)
|
133
|
+
self.TokenFlowCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.TokenFlowCreate, client)
|
134
|
+
self.TokenFlowWait = modal.client.UnaryUnaryWrapper(grpclib_stub.TokenFlowWait, client)
|
135
|
+
self.TunnelStart = modal.client.UnaryUnaryWrapper(grpclib_stub.TunnelStart, client)
|
136
|
+
self.TunnelStop = modal.client.UnaryUnaryWrapper(grpclib_stub.TunnelStop, client)
|
137
|
+
self.VolumeCommit = modal.client.UnaryUnaryWrapper(grpclib_stub.VolumeCommit, client)
|
138
|
+
self.VolumeCopyFiles = modal.client.UnaryUnaryWrapper(grpclib_stub.VolumeCopyFiles, client)
|
139
|
+
self.VolumeDelete = modal.client.UnaryUnaryWrapper(grpclib_stub.VolumeDelete, client)
|
140
|
+
self.VolumeGetFile = modal.client.UnaryUnaryWrapper(grpclib_stub.VolumeGetFile, client)
|
141
|
+
self.VolumeGetOrCreate = modal.client.UnaryUnaryWrapper(grpclib_stub.VolumeGetOrCreate, client)
|
142
|
+
self.VolumeHeartbeat = modal.client.UnaryUnaryWrapper(grpclib_stub.VolumeHeartbeat, client)
|
143
|
+
self.VolumeList = modal.client.UnaryUnaryWrapper(grpclib_stub.VolumeList, client)
|
144
|
+
self.VolumeListFiles = modal.client.UnaryStreamWrapper(grpclib_stub.VolumeListFiles, client)
|
145
|
+
self.VolumePutFiles = modal.client.UnaryUnaryWrapper(grpclib_stub.VolumePutFiles, client)
|
146
|
+
self.VolumeReload = modal.client.UnaryUnaryWrapper(grpclib_stub.VolumeReload, client)
|
147
|
+
self.VolumeRemoveFile = modal.client.UnaryUnaryWrapper(grpclib_stub.VolumeRemoveFile, client)
|
148
|
+
self.VolumeRename = modal.client.UnaryUnaryWrapper(grpclib_stub.VolumeRename, client)
|
149
|
+
self.WorkspaceNameLookup = modal.client.UnaryUnaryWrapper(grpclib_stub.WorkspaceNameLookup, client)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
"""
|
2
|
+
@generated by mypy-protobuf. Do not edit manually!
|
3
|
+
isort:skip_file
|
4
|
+
Defines custom options used internally at Modal.
|
5
|
+
Custom options must be in the range 50000-99999.
|
6
|
+
Reference: https://protobuf.dev/programming-guides/proto2/#customoptions
|
7
|
+
"""
|
8
|
+
import builtins
|
9
|
+
import google.protobuf.descriptor
|
10
|
+
import google.protobuf.descriptor_pb2
|
11
|
+
import google.protobuf.internal.extension_dict
|
12
|
+
|
13
|
+
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
|
14
|
+
|
15
|
+
AUDIT_TARGET_ATTR_FIELD_NUMBER: builtins.int
|
16
|
+
AUDIT_EVENT_NAME_FIELD_NUMBER: builtins.int
|
17
|
+
AUDIT_EVENT_DESCRIPTION_FIELD_NUMBER: builtins.int
|
18
|
+
audit_target_attr: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.FieldOptions, builtins.bool]
|
19
|
+
audit_event_name: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.MethodOptions, builtins.str]
|
20
|
+
audit_event_description: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.MethodOptions, builtins.str]
|
modal_proto/py.typed
ADDED
File without changes
|
modal_version/__init__.py
CHANGED
@@ -7,7 +7,7 @@ from ._version_generated import build_number
|
|
7
7
|
major_number = 0
|
8
8
|
|
9
9
|
# Bump this manually on breaking changes, then reset the number in _version_generated.py
|
10
|
-
minor_number =
|
10
|
+
minor_number = 72
|
11
11
|
|
12
12
|
# Right now, automatically increment the patch number in CI
|
13
13
|
__version__ = f"{major_number}.{minor_number}.{max(build_number, 0)}"
|
modal/_asgi.py
DELETED
@@ -1,370 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2022
|
2
|
-
import asyncio
|
3
|
-
from typing import Any, AsyncGenerator, Callable, Dict, Optional, cast
|
4
|
-
|
5
|
-
import aiohttp
|
6
|
-
|
7
|
-
from ._utils.async_utils import TaskContext
|
8
|
-
from ._utils.blob_utils import MAX_OBJECT_SIZE_BYTES
|
9
|
-
from .config import logger
|
10
|
-
from .exception import ExecutionError, InvalidError
|
11
|
-
from .execution_context import current_function_call_id
|
12
|
-
from .experimental import stop_fetching_inputs
|
13
|
-
|
14
|
-
FIRST_MESSAGE_TIMEOUT_SECONDS = 5.0
|
15
|
-
|
16
|
-
|
17
|
-
def asgi_app_wrapper(asgi_app, function_io_manager) -> Callable[..., AsyncGenerator]:
|
18
|
-
async def fn(scope):
|
19
|
-
function_call_id = current_function_call_id()
|
20
|
-
assert function_call_id, "internal error: function_call_id not set in asgi_app() scope"
|
21
|
-
|
22
|
-
# TODO: Add support for the ASGI lifecycle spec.
|
23
|
-
messages_from_app: asyncio.Queue[Dict[str, Any]] = asyncio.Queue(1)
|
24
|
-
messages_to_app: asyncio.Queue[Dict[str, Any]] = asyncio.Queue(1)
|
25
|
-
|
26
|
-
async def disconnect_app():
|
27
|
-
if scope["type"] == "http":
|
28
|
-
await messages_to_app.put({"type": "http.disconnect"})
|
29
|
-
elif scope["type"] == "websocket":
|
30
|
-
await messages_to_app.put({"type": "websocket.disconnect"})
|
31
|
-
|
32
|
-
async def handle_first_input_timeout():
|
33
|
-
if scope["type"] == "http":
|
34
|
-
await messages_from_app.put({"type": "http.response.start", "status": 502})
|
35
|
-
await messages_from_app.put(
|
36
|
-
{
|
37
|
-
"type": "http.response.body",
|
38
|
-
"body": b"Missing request, possibly due to cancellation or crash",
|
39
|
-
}
|
40
|
-
)
|
41
|
-
elif scope["type"] == "websocket":
|
42
|
-
await messages_from_app.put(
|
43
|
-
{
|
44
|
-
"type": "websocket.close",
|
45
|
-
"code": 1011,
|
46
|
-
"reason": "Missing request, possibly due to cancellation or crash",
|
47
|
-
}
|
48
|
-
)
|
49
|
-
await disconnect_app()
|
50
|
-
|
51
|
-
async def fetch_data_in():
|
52
|
-
# Cancel an ASGI app call if the initial message is not received within a short timeout.
|
53
|
-
#
|
54
|
-
# This initial message, "http.request" or "websocket.connect", should be sent
|
55
|
-
# immediately after starting the ASGI app's function call. If it is not received, that
|
56
|
-
# indicates a request cancellation or other abnormal circumstance.
|
57
|
-
message_gen = function_io_manager.get_data_in.aio(function_call_id)
|
58
|
-
|
59
|
-
try:
|
60
|
-
first_message = await asyncio.wait_for(message_gen.__anext__(), FIRST_MESSAGE_TIMEOUT_SECONDS)
|
61
|
-
except (asyncio.TimeoutError, StopAsyncIteration):
|
62
|
-
# About `StopAsyncIteration` above: The generator shouldn't typically exit,
|
63
|
-
# but if it does, we handle it like a timeout in that case.
|
64
|
-
await handle_first_input_timeout()
|
65
|
-
return
|
66
|
-
except Exception:
|
67
|
-
logger.exception("Internal error in asgi_app_wrapper")
|
68
|
-
await disconnect_app()
|
69
|
-
return
|
70
|
-
|
71
|
-
await messages_to_app.put(first_message)
|
72
|
-
async for message in message_gen:
|
73
|
-
await messages_to_app.put(message)
|
74
|
-
|
75
|
-
async def send(msg):
|
76
|
-
# Automatically split body chunks that are greater than the output size limit, to
|
77
|
-
# prevent them from being uploaded to S3.
|
78
|
-
if msg["type"] == "http.response.body":
|
79
|
-
body_chunk_size = MAX_OBJECT_SIZE_BYTES - 1024 # reserve 1 KiB for framing
|
80
|
-
body_chunk_limit = 20 * body_chunk_size
|
81
|
-
s3_chunk_size = 150 * body_chunk_size
|
82
|
-
|
83
|
-
size = len(msg.get("body", b""))
|
84
|
-
if size <= body_chunk_limit:
|
85
|
-
chunk_size = body_chunk_size
|
86
|
-
else:
|
87
|
-
# If the body is _very large_, we should still split it up to avoid sending all
|
88
|
-
# of the data in a huge chunk in S3.
|
89
|
-
chunk_size = s3_chunk_size
|
90
|
-
|
91
|
-
if size > chunk_size:
|
92
|
-
indices = list(range(0, size, chunk_size))
|
93
|
-
for i in indices[:-1]:
|
94
|
-
chunk = msg["body"][i : i + chunk_size]
|
95
|
-
await messages_from_app.put({"type": "http.response.body", "body": chunk, "more_body": True})
|
96
|
-
msg["body"] = msg["body"][indices[-1] :]
|
97
|
-
|
98
|
-
await messages_from_app.put(msg)
|
99
|
-
|
100
|
-
# Run the ASGI app, while draining the send message queue at the same time,
|
101
|
-
# and yielding results.
|
102
|
-
async with TaskContext(grace=0.01) as tc:
|
103
|
-
fetch_data_in_task = tc.create_task(fetch_data_in())
|
104
|
-
|
105
|
-
async def receive():
|
106
|
-
return await messages_to_app.get()
|
107
|
-
|
108
|
-
app_task = tc.create_task(asgi_app(scope, receive, send))
|
109
|
-
pop_task = None
|
110
|
-
try:
|
111
|
-
while True:
|
112
|
-
pop_task = tc.create_task(messages_from_app.get())
|
113
|
-
|
114
|
-
try:
|
115
|
-
done, pending = await asyncio.wait([pop_task, app_task], return_when=asyncio.FIRST_COMPLETED)
|
116
|
-
except asyncio.CancelledError:
|
117
|
-
break
|
118
|
-
|
119
|
-
if pop_task in done:
|
120
|
-
yield pop_task.result()
|
121
|
-
else:
|
122
|
-
pop_task.cancel() # clean up the popping task, or we will leak unresolved tasks every loop iteration
|
123
|
-
|
124
|
-
if app_task in done:
|
125
|
-
while not messages_from_app.empty():
|
126
|
-
yield messages_from_app.get_nowait()
|
127
|
-
app_task.result() # consume/raise exceptions if there are any!
|
128
|
-
break
|
129
|
-
finally:
|
130
|
-
fetch_data_in_task.cancel()
|
131
|
-
# Only cancel tasks if they're not done. This lets tracebacks from potential errors
|
132
|
-
# still get displayed when the task gets garbage collected.
|
133
|
-
if not app_task.done():
|
134
|
-
app_task.cancel()
|
135
|
-
if not pop_task.done():
|
136
|
-
pop_task.cancel()
|
137
|
-
|
138
|
-
return fn
|
139
|
-
|
140
|
-
|
141
|
-
def wsgi_app_wrapper(wsgi_app, function_io_manager):
|
142
|
-
from ._vendor.a2wsgi_wsgi import WSGIMiddleware
|
143
|
-
|
144
|
-
asgi_app = WSGIMiddleware(wsgi_app, workers=10000, send_queue_size=1) # unlimited workers
|
145
|
-
return asgi_app_wrapper(asgi_app, function_io_manager)
|
146
|
-
|
147
|
-
|
148
|
-
def webhook_asgi_app(fn: Callable, method: str):
|
149
|
-
"""Return a FastAPI app wrapping a function handler."""
|
150
|
-
# Pulls in `fastapi` module, which is slow to import.
|
151
|
-
from fastapi import FastAPI
|
152
|
-
from fastapi.middleware.cors import CORSMiddleware
|
153
|
-
|
154
|
-
app = FastAPI(docs_url=None, redoc_url=None)
|
155
|
-
app.add_middleware(
|
156
|
-
CORSMiddleware,
|
157
|
-
allow_origins=["*"],
|
158
|
-
allow_credentials=True,
|
159
|
-
allow_methods=["*"],
|
160
|
-
allow_headers=["*"],
|
161
|
-
)
|
162
|
-
app.add_api_route("/", fn, methods=[method])
|
163
|
-
return app
|
164
|
-
|
165
|
-
|
166
|
-
def get_ip_address(ifname: bytes):
|
167
|
-
"""Get the IP address associated with a network interface in Linux."""
|
168
|
-
import fcntl
|
169
|
-
import socket
|
170
|
-
import struct
|
171
|
-
|
172
|
-
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
173
|
-
return socket.inet_ntoa(
|
174
|
-
fcntl.ioctl(
|
175
|
-
s.fileno(),
|
176
|
-
0x8915, # SIOCGIFADDR
|
177
|
-
struct.pack("256s", ifname[:15]),
|
178
|
-
)[20:24]
|
179
|
-
)
|
180
|
-
|
181
|
-
|
182
|
-
def wait_for_web_server(host: str, port: int, *, timeout: float) -> None:
|
183
|
-
"""Wait until a web server port starts accepting TCP connections."""
|
184
|
-
import socket
|
185
|
-
import time
|
186
|
-
|
187
|
-
start_time = time.monotonic()
|
188
|
-
while True:
|
189
|
-
try:
|
190
|
-
with socket.create_connection((host, port), timeout=timeout):
|
191
|
-
break
|
192
|
-
except OSError as ex:
|
193
|
-
time.sleep(0.01)
|
194
|
-
if time.monotonic() - start_time >= timeout:
|
195
|
-
raise TimeoutError(
|
196
|
-
f"Waited too long for port {port} to start accepting connections. "
|
197
|
-
+ "Make sure the web server is listening on all interfaces, or adjust `startup_timeout`."
|
198
|
-
) from ex
|
199
|
-
|
200
|
-
|
201
|
-
async def _proxy_http_request(session: aiohttp.ClientSession, scope, receive, send) -> None:
|
202
|
-
proxy_response: Optional[aiohttp.ClientResponse] = None
|
203
|
-
|
204
|
-
async def request_generator():
|
205
|
-
while True:
|
206
|
-
message = await receive()
|
207
|
-
if message["type"] == "http.request":
|
208
|
-
body = message.get("body", b"")
|
209
|
-
if body:
|
210
|
-
yield body
|
211
|
-
if not message.get("more_body", False):
|
212
|
-
break
|
213
|
-
elif message["type"] == "http.disconnect":
|
214
|
-
proxy_response.connection.transport.abort() # Abort the connection.
|
215
|
-
break
|
216
|
-
else:
|
217
|
-
raise ExecutionError(f"Unexpected message type: {message['type']}")
|
218
|
-
|
219
|
-
path = scope["path"]
|
220
|
-
if scope.get("query_string"):
|
221
|
-
path += "?" + scope["query_string"].decode()
|
222
|
-
|
223
|
-
proxy_response = await session.request(
|
224
|
-
method=scope["method"],
|
225
|
-
url=path,
|
226
|
-
headers=[(k.decode(), v.decode()) for k, v in scope["headers"]],
|
227
|
-
data=None if scope["method"] in aiohttp.ClientRequest.GET_METHODS else request_generator(),
|
228
|
-
allow_redirects=False,
|
229
|
-
)
|
230
|
-
|
231
|
-
async def send_response():
|
232
|
-
msg = {
|
233
|
-
"type": "http.response.start",
|
234
|
-
"status": proxy_response.status,
|
235
|
-
"headers": [(k.encode(), v.encode()) for k, v in proxy_response.headers.items()],
|
236
|
-
}
|
237
|
-
await send(msg)
|
238
|
-
async for data in proxy_response.content.iter_any():
|
239
|
-
msg = {"type": "http.response.body", "body": data, "more_body": True}
|
240
|
-
await send(msg)
|
241
|
-
await send({"type": "http.response.body"})
|
242
|
-
|
243
|
-
async def listen_for_disconnect():
|
244
|
-
while True:
|
245
|
-
message = await receive()
|
246
|
-
if message["type"] == "http.disconnect":
|
247
|
-
proxy_response.connection.transport.abort()
|
248
|
-
|
249
|
-
try:
|
250
|
-
send_response_task = asyncio.create_task(send_response())
|
251
|
-
disconnect_task = asyncio.create_task(listen_for_disconnect())
|
252
|
-
await asyncio.wait([send_response_task, disconnect_task], return_when=asyncio.FIRST_COMPLETED)
|
253
|
-
finally:
|
254
|
-
if send_response_task.done():
|
255
|
-
send_response_task.result()
|
256
|
-
else:
|
257
|
-
send_response_task.cancel()
|
258
|
-
if disconnect_task.done():
|
259
|
-
disconnect_task.result()
|
260
|
-
else:
|
261
|
-
disconnect_task.cancel()
|
262
|
-
|
263
|
-
|
264
|
-
async def _proxy_websocket_request(session: aiohttp.ClientSession, scope, receive, send) -> None:
|
265
|
-
first_message = await receive() # Consume the initial "websocket.connect" message.
|
266
|
-
if first_message["type"] == "websocket.disconnect":
|
267
|
-
return
|
268
|
-
elif first_message["type"] != "websocket.connect":
|
269
|
-
raise ExecutionError(f"Unexpected message type: {first_message['type']}")
|
270
|
-
|
271
|
-
path = scope["path"]
|
272
|
-
if scope.get("query_string"):
|
273
|
-
path += "?" + scope["query_string"].decode()
|
274
|
-
|
275
|
-
async with session.ws_connect(
|
276
|
-
url=path,
|
277
|
-
headers=[(k.decode(), v.decode()) for k, v in scope["headers"]], # type: ignore
|
278
|
-
protocols=scope.get("subprotocols", []),
|
279
|
-
) as upstream_ws:
|
280
|
-
|
281
|
-
async def client_to_upstream():
|
282
|
-
while True:
|
283
|
-
client_message = await receive()
|
284
|
-
if client_message["type"] == "websocket.disconnect":
|
285
|
-
await upstream_ws.close(code=client_message.get("code", 1005))
|
286
|
-
break
|
287
|
-
elif client_message["type"] == "websocket.receive":
|
288
|
-
if client_message.get("text") is not None:
|
289
|
-
await upstream_ws.send_str(client_message["text"])
|
290
|
-
elif client_message.get("bytes") is not None:
|
291
|
-
await upstream_ws.send_bytes(client_message["bytes"])
|
292
|
-
else:
|
293
|
-
raise ExecutionError(f"Unexpected message type: {client_message['type']}")
|
294
|
-
|
295
|
-
async def upstream_to_client():
|
296
|
-
msg: Dict[str, Any] = {
|
297
|
-
"type": "websocket.accept",
|
298
|
-
"subprotocol": upstream_ws.protocol,
|
299
|
-
}
|
300
|
-
await send(msg)
|
301
|
-
|
302
|
-
while True:
|
303
|
-
upstream_message = await upstream_ws.receive()
|
304
|
-
if upstream_message.type == aiohttp.WSMsgType.closed:
|
305
|
-
msg = {"type": "websocket.close"}
|
306
|
-
if upstream_message.data is not None:
|
307
|
-
msg["code"] = cast(aiohttp.WSCloseCode, upstream_message.data).value
|
308
|
-
msg["reason"] = upstream_message.extra
|
309
|
-
await send(msg)
|
310
|
-
break
|
311
|
-
elif upstream_message.type == aiohttp.WSMsgType.text:
|
312
|
-
await send({"type": "websocket.send", "text": upstream_message.data})
|
313
|
-
elif upstream_message.type == aiohttp.WSMsgType.binary:
|
314
|
-
await send({"type": "websocket.send", "bytes": upstream_message.data})
|
315
|
-
else:
|
316
|
-
pass # Ignore all other upstream WebSocket message types.
|
317
|
-
|
318
|
-
client_to_upstream_task = asyncio.create_task(client_to_upstream())
|
319
|
-
upstream_to_client_task = asyncio.create_task(upstream_to_client())
|
320
|
-
try:
|
321
|
-
await asyncio.wait([client_to_upstream_task, upstream_to_client_task], return_when=asyncio.FIRST_COMPLETED)
|
322
|
-
finally:
|
323
|
-
if client_to_upstream_task.done():
|
324
|
-
client_to_upstream_task.result()
|
325
|
-
else:
|
326
|
-
client_to_upstream_task.cancel()
|
327
|
-
if upstream_to_client_task.done():
|
328
|
-
upstream_to_client_task.result()
|
329
|
-
else:
|
330
|
-
upstream_to_client_task.cancel()
|
331
|
-
|
332
|
-
|
333
|
-
def web_server_proxy(host: str, port: int):
|
334
|
-
"""Return an ASGI app that proxies requests to a web server running on the same host."""
|
335
|
-
if not 0 < port < 65536:
|
336
|
-
raise InvalidError(f"Invalid port number: {port}")
|
337
|
-
|
338
|
-
base_url = f"http://{host}:{port}"
|
339
|
-
session: Optional[aiohttp.ClientSession] = None
|
340
|
-
|
341
|
-
async def web_server_proxy_app(scope, receive, send):
|
342
|
-
nonlocal session
|
343
|
-
if session is None:
|
344
|
-
# TODO: We currently create the ClientSession on container startup and never close it.
|
345
|
-
# This outputs an "Unclosed client session" warning during runner termination. We should
|
346
|
-
# properly close the session once we implement the ASGI lifespan protocol.
|
347
|
-
session = aiohttp.ClientSession(
|
348
|
-
base_url,
|
349
|
-
cookie_jar=aiohttp.DummyCookieJar(),
|
350
|
-
timeout=aiohttp.ClientTimeout(total=3600),
|
351
|
-
auto_decompress=False,
|
352
|
-
read_bufsize=1024 * 1024, # 1 MiB
|
353
|
-
)
|
354
|
-
|
355
|
-
try:
|
356
|
-
if scope["type"] == "lifespan":
|
357
|
-
pass # Do nothing for lifespan events.
|
358
|
-
elif scope["type"] == "http":
|
359
|
-
await _proxy_http_request(session, scope, receive, send)
|
360
|
-
elif scope["type"] == "websocket":
|
361
|
-
await _proxy_websocket_request(session, scope, receive, send)
|
362
|
-
else:
|
363
|
-
raise NotImplementedError(f"Scope {scope} is not understood")
|
364
|
-
|
365
|
-
except aiohttp.ClientConnectorError as exc:
|
366
|
-
# If the server is not running or not reachable, we should stop fetching new inputs.
|
367
|
-
logger.warning(f"Terminating runner due to @web_server connection issue: {exc}")
|
368
|
-
stop_fetching_inputs()
|
369
|
-
|
370
|
-
return web_server_proxy_app
|