prefect-client 2.19.3__py3-none-any.whl → 3.0.0rc1__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.
- prefect/__init__.py +8 -56
- prefect/_internal/compatibility/deprecated.py +6 -115
- prefect/_internal/compatibility/experimental.py +4 -79
- prefect/_internal/concurrency/api.py +0 -34
- prefect/_internal/concurrency/calls.py +0 -6
- prefect/_internal/concurrency/cancellation.py +0 -3
- prefect/_internal/concurrency/event_loop.py +0 -20
- prefect/_internal/concurrency/inspection.py +3 -3
- prefect/_internal/concurrency/threads.py +35 -0
- prefect/_internal/concurrency/waiters.py +0 -28
- prefect/_internal/pydantic/__init__.py +0 -45
- prefect/_internal/pydantic/v1_schema.py +21 -22
- prefect/_internal/pydantic/v2_schema.py +0 -2
- prefect/_internal/pydantic/v2_validated_func.py +18 -23
- prefect/_internal/schemas/bases.py +44 -177
- prefect/_internal/schemas/fields.py +1 -43
- prefect/_internal/schemas/validators.py +60 -158
- prefect/artifacts.py +161 -14
- prefect/automations.py +39 -4
- prefect/blocks/abstract.py +1 -1
- prefect/blocks/core.py +268 -148
- prefect/blocks/fields.py +2 -57
- prefect/blocks/kubernetes.py +8 -12
- prefect/blocks/notifications.py +40 -20
- prefect/blocks/system.py +22 -11
- prefect/blocks/webhook.py +2 -9
- prefect/client/base.py +4 -4
- prefect/client/cloud.py +8 -13
- prefect/client/orchestration.py +347 -341
- prefect/client/schemas/actions.py +92 -86
- prefect/client/schemas/filters.py +20 -40
- prefect/client/schemas/objects.py +147 -145
- prefect/client/schemas/responses.py +16 -24
- prefect/client/schemas/schedules.py +47 -35
- prefect/client/subscriptions.py +2 -2
- prefect/client/utilities.py +5 -2
- prefect/concurrency/asyncio.py +3 -1
- prefect/concurrency/events.py +1 -1
- prefect/concurrency/services.py +6 -3
- prefect/context.py +195 -27
- prefect/deployments/__init__.py +5 -6
- prefect/deployments/base.py +7 -5
- prefect/deployments/flow_runs.py +185 -0
- prefect/deployments/runner.py +50 -45
- prefect/deployments/schedules.py +28 -23
- prefect/deployments/steps/__init__.py +0 -1
- prefect/deployments/steps/core.py +1 -0
- prefect/deployments/steps/pull.py +7 -21
- prefect/engine.py +12 -2422
- prefect/events/actions.py +17 -23
- prefect/events/cli/automations.py +19 -6
- prefect/events/clients.py +14 -37
- prefect/events/filters.py +14 -18
- prefect/events/related.py +2 -2
- prefect/events/schemas/__init__.py +0 -5
- prefect/events/schemas/automations.py +55 -46
- prefect/events/schemas/deployment_triggers.py +7 -197
- prefect/events/schemas/events.py +34 -65
- prefect/events/schemas/labelling.py +10 -14
- prefect/events/utilities.py +2 -3
- prefect/events/worker.py +2 -3
- prefect/filesystems.py +6 -517
- prefect/{new_flow_engine.py → flow_engine.py} +313 -72
- prefect/flow_runs.py +377 -5
- prefect/flows.py +248 -165
- prefect/futures.py +186 -345
- prefect/infrastructure/__init__.py +0 -27
- prefect/infrastructure/provisioners/__init__.py +5 -3
- prefect/infrastructure/provisioners/cloud_run.py +11 -6
- prefect/infrastructure/provisioners/container_instance.py +11 -7
- prefect/infrastructure/provisioners/ecs.py +6 -4
- prefect/infrastructure/provisioners/modal.py +8 -5
- prefect/input/actions.py +2 -4
- prefect/input/run_input.py +5 -7
- prefect/logging/formatters.py +0 -2
- prefect/logging/handlers.py +3 -11
- prefect/logging/loggers.py +2 -2
- prefect/manifests.py +2 -1
- prefect/records/__init__.py +1 -0
- prefect/records/result_store.py +42 -0
- prefect/records/store.py +9 -0
- prefect/results.py +43 -39
- prefect/runner/runner.py +9 -9
- prefect/runner/server.py +6 -10
- prefect/runner/storage.py +3 -8
- prefect/runner/submit.py +2 -2
- prefect/runner/utils.py +2 -2
- prefect/serializers.py +24 -35
- prefect/server/api/collections_data/views/aggregate-worker-metadata.json +5 -14
- prefect/settings.py +70 -133
- prefect/states.py +17 -47
- prefect/task_engine.py +697 -58
- prefect/task_runners.py +269 -301
- prefect/task_server.py +53 -34
- prefect/tasks.py +327 -337
- prefect/transactions.py +220 -0
- prefect/types/__init__.py +61 -82
- prefect/utilities/asyncutils.py +195 -136
- prefect/utilities/callables.py +121 -41
- prefect/utilities/collections.py +23 -38
- prefect/utilities/dispatch.py +11 -3
- prefect/utilities/dockerutils.py +4 -0
- prefect/utilities/engine.py +140 -20
- prefect/utilities/importtools.py +26 -27
- prefect/utilities/pydantic.py +128 -38
- prefect/utilities/schema_tools/hydration.py +5 -1
- prefect/utilities/templating.py +12 -2
- prefect/variables.py +78 -61
- prefect/workers/__init__.py +0 -1
- prefect/workers/base.py +15 -17
- prefect/workers/process.py +3 -8
- prefect/workers/server.py +2 -2
- {prefect_client-2.19.3.dist-info → prefect_client-3.0.0rc1.dist-info}/METADATA +22 -21
- prefect_client-3.0.0rc1.dist-info/RECORD +176 -0
- prefect/_internal/pydantic/_base_model.py +0 -51
- prefect/_internal/pydantic/_compat.py +0 -82
- prefect/_internal/pydantic/_flags.py +0 -20
- prefect/_internal/pydantic/_types.py +0 -8
- prefect/_internal/pydantic/utilities/__init__.py +0 -0
- prefect/_internal/pydantic/utilities/config_dict.py +0 -72
- prefect/_internal/pydantic/utilities/field_validator.py +0 -150
- prefect/_internal/pydantic/utilities/model_construct.py +0 -56
- prefect/_internal/pydantic/utilities/model_copy.py +0 -55
- prefect/_internal/pydantic/utilities/model_dump.py +0 -136
- prefect/_internal/pydantic/utilities/model_dump_json.py +0 -112
- prefect/_internal/pydantic/utilities/model_fields.py +0 -50
- prefect/_internal/pydantic/utilities/model_fields_set.py +0 -29
- prefect/_internal/pydantic/utilities/model_json_schema.py +0 -82
- prefect/_internal/pydantic/utilities/model_rebuild.py +0 -80
- prefect/_internal/pydantic/utilities/model_validate.py +0 -75
- prefect/_internal/pydantic/utilities/model_validate_json.py +0 -68
- prefect/_internal/pydantic/utilities/model_validator.py +0 -87
- prefect/_internal/pydantic/utilities/type_adapter.py +0 -71
- prefect/_vendor/__init__.py +0 -0
- prefect/_vendor/fastapi/__init__.py +0 -25
- prefect/_vendor/fastapi/applications.py +0 -946
- prefect/_vendor/fastapi/background.py +0 -3
- prefect/_vendor/fastapi/concurrency.py +0 -44
- prefect/_vendor/fastapi/datastructures.py +0 -58
- prefect/_vendor/fastapi/dependencies/__init__.py +0 -0
- prefect/_vendor/fastapi/dependencies/models.py +0 -64
- prefect/_vendor/fastapi/dependencies/utils.py +0 -877
- prefect/_vendor/fastapi/encoders.py +0 -177
- prefect/_vendor/fastapi/exception_handlers.py +0 -40
- prefect/_vendor/fastapi/exceptions.py +0 -46
- prefect/_vendor/fastapi/logger.py +0 -3
- prefect/_vendor/fastapi/middleware/__init__.py +0 -1
- prefect/_vendor/fastapi/middleware/asyncexitstack.py +0 -25
- prefect/_vendor/fastapi/middleware/cors.py +0 -3
- prefect/_vendor/fastapi/middleware/gzip.py +0 -3
- prefect/_vendor/fastapi/middleware/httpsredirect.py +0 -3
- prefect/_vendor/fastapi/middleware/trustedhost.py +0 -3
- prefect/_vendor/fastapi/middleware/wsgi.py +0 -3
- prefect/_vendor/fastapi/openapi/__init__.py +0 -0
- prefect/_vendor/fastapi/openapi/constants.py +0 -2
- prefect/_vendor/fastapi/openapi/docs.py +0 -203
- prefect/_vendor/fastapi/openapi/models.py +0 -480
- prefect/_vendor/fastapi/openapi/utils.py +0 -485
- prefect/_vendor/fastapi/param_functions.py +0 -340
- prefect/_vendor/fastapi/params.py +0 -453
- prefect/_vendor/fastapi/requests.py +0 -4
- prefect/_vendor/fastapi/responses.py +0 -40
- prefect/_vendor/fastapi/routing.py +0 -1331
- prefect/_vendor/fastapi/security/__init__.py +0 -15
- prefect/_vendor/fastapi/security/api_key.py +0 -98
- prefect/_vendor/fastapi/security/base.py +0 -6
- prefect/_vendor/fastapi/security/http.py +0 -172
- prefect/_vendor/fastapi/security/oauth2.py +0 -227
- prefect/_vendor/fastapi/security/open_id_connect_url.py +0 -34
- prefect/_vendor/fastapi/security/utils.py +0 -10
- prefect/_vendor/fastapi/staticfiles.py +0 -1
- prefect/_vendor/fastapi/templating.py +0 -3
- prefect/_vendor/fastapi/testclient.py +0 -1
- prefect/_vendor/fastapi/types.py +0 -3
- prefect/_vendor/fastapi/utils.py +0 -235
- prefect/_vendor/fastapi/websockets.py +0 -7
- prefect/_vendor/starlette/__init__.py +0 -1
- prefect/_vendor/starlette/_compat.py +0 -28
- prefect/_vendor/starlette/_exception_handler.py +0 -80
- prefect/_vendor/starlette/_utils.py +0 -88
- prefect/_vendor/starlette/applications.py +0 -261
- prefect/_vendor/starlette/authentication.py +0 -159
- prefect/_vendor/starlette/background.py +0 -43
- prefect/_vendor/starlette/concurrency.py +0 -59
- prefect/_vendor/starlette/config.py +0 -151
- prefect/_vendor/starlette/convertors.py +0 -87
- prefect/_vendor/starlette/datastructures.py +0 -707
- prefect/_vendor/starlette/endpoints.py +0 -130
- prefect/_vendor/starlette/exceptions.py +0 -60
- prefect/_vendor/starlette/formparsers.py +0 -276
- prefect/_vendor/starlette/middleware/__init__.py +0 -17
- prefect/_vendor/starlette/middleware/authentication.py +0 -52
- prefect/_vendor/starlette/middleware/base.py +0 -220
- prefect/_vendor/starlette/middleware/cors.py +0 -176
- prefect/_vendor/starlette/middleware/errors.py +0 -265
- prefect/_vendor/starlette/middleware/exceptions.py +0 -74
- prefect/_vendor/starlette/middleware/gzip.py +0 -113
- prefect/_vendor/starlette/middleware/httpsredirect.py +0 -19
- prefect/_vendor/starlette/middleware/sessions.py +0 -82
- prefect/_vendor/starlette/middleware/trustedhost.py +0 -64
- prefect/_vendor/starlette/middleware/wsgi.py +0 -147
- prefect/_vendor/starlette/requests.py +0 -328
- prefect/_vendor/starlette/responses.py +0 -347
- prefect/_vendor/starlette/routing.py +0 -933
- prefect/_vendor/starlette/schemas.py +0 -154
- prefect/_vendor/starlette/staticfiles.py +0 -248
- prefect/_vendor/starlette/status.py +0 -199
- prefect/_vendor/starlette/templating.py +0 -231
- prefect/_vendor/starlette/testclient.py +0 -804
- prefect/_vendor/starlette/types.py +0 -30
- prefect/_vendor/starlette/websockets.py +0 -193
- prefect/agent.py +0 -698
- prefect/deployments/deployments.py +0 -1042
- prefect/deprecated/__init__.py +0 -0
- prefect/deprecated/data_documents.py +0 -350
- prefect/deprecated/packaging/__init__.py +0 -12
- prefect/deprecated/packaging/base.py +0 -96
- prefect/deprecated/packaging/docker.py +0 -146
- prefect/deprecated/packaging/file.py +0 -92
- prefect/deprecated/packaging/orion.py +0 -80
- prefect/deprecated/packaging/serializers.py +0 -171
- prefect/events/instrument.py +0 -135
- prefect/infrastructure/base.py +0 -323
- prefect/infrastructure/container.py +0 -818
- prefect/infrastructure/kubernetes.py +0 -920
- prefect/infrastructure/process.py +0 -289
- prefect/new_task_engine.py +0 -423
- prefect/pydantic/__init__.py +0 -76
- prefect/pydantic/main.py +0 -39
- prefect/software/__init__.py +0 -2
- prefect/software/base.py +0 -50
- prefect/software/conda.py +0 -199
- prefect/software/pip.py +0 -122
- prefect/software/python.py +0 -52
- prefect/workers/block.py +0 -218
- prefect_client-2.19.3.dist-info/RECORD +0 -292
- {prefect_client-2.19.3.dist-info → prefect_client-3.0.0rc1.dist-info}/LICENSE +0 -0
- {prefect_client-2.19.3.dist-info → prefect_client-3.0.0rc1.dist-info}/WHEEL +0 -0
- {prefect_client-2.19.3.dist-info → prefect_client-3.0.0rc1.dist-info}/top_level.txt +0 -0
@@ -1,177 +0,0 @@
|
|
1
|
-
import dataclasses
|
2
|
-
from collections import defaultdict, deque
|
3
|
-
from enum import Enum
|
4
|
-
from pathlib import PurePath
|
5
|
-
from types import GeneratorType
|
6
|
-
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
|
7
|
-
|
8
|
-
from prefect._internal.pydantic import HAS_PYDANTIC_V2
|
9
|
-
|
10
|
-
if HAS_PYDANTIC_V2:
|
11
|
-
from pydantic.v1 import BaseModel
|
12
|
-
from pydantic.v1.json import ENCODERS_BY_TYPE
|
13
|
-
else:
|
14
|
-
from pydantic import BaseModel
|
15
|
-
from pydantic.json import ENCODERS_BY_TYPE
|
16
|
-
|
17
|
-
SetIntStr = Set[Union[int, str]]
|
18
|
-
DictIntStrAny = Dict[Union[int, str], Any]
|
19
|
-
|
20
|
-
|
21
|
-
def generate_encoders_by_class_tuples(
|
22
|
-
type_encoder_map: Dict[Any, Callable[[Any], Any]],
|
23
|
-
) -> Dict[Callable[[Any], Any], Tuple[Any, ...]]:
|
24
|
-
encoders_by_class_tuples: Dict[Callable[[Any], Any], Tuple[Any, ...]] = defaultdict(
|
25
|
-
tuple
|
26
|
-
)
|
27
|
-
for type_, encoder in type_encoder_map.items():
|
28
|
-
encoders_by_class_tuples[encoder] += (type_,)
|
29
|
-
return encoders_by_class_tuples
|
30
|
-
|
31
|
-
|
32
|
-
encoders_by_class_tuples = generate_encoders_by_class_tuples(ENCODERS_BY_TYPE)
|
33
|
-
|
34
|
-
|
35
|
-
def jsonable_encoder(
|
36
|
-
obj: Any,
|
37
|
-
include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
|
38
|
-
exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None,
|
39
|
-
by_alias: bool = True,
|
40
|
-
exclude_unset: bool = False,
|
41
|
-
exclude_defaults: bool = False,
|
42
|
-
exclude_none: bool = False,
|
43
|
-
custom_encoder: Optional[Dict[Any, Callable[[Any], Any]]] = None,
|
44
|
-
sqlalchemy_safe: bool = True,
|
45
|
-
) -> Any:
|
46
|
-
custom_encoder = custom_encoder or {}
|
47
|
-
if custom_encoder:
|
48
|
-
if type(obj) in custom_encoder:
|
49
|
-
return custom_encoder[type(obj)](obj)
|
50
|
-
else:
|
51
|
-
for encoder_type, encoder_instance in custom_encoder.items():
|
52
|
-
if isinstance(obj, encoder_type):
|
53
|
-
return encoder_instance(obj)
|
54
|
-
if include is not None and not isinstance(include, (set, dict)):
|
55
|
-
include = set(include)
|
56
|
-
if exclude is not None and not isinstance(exclude, (set, dict)):
|
57
|
-
exclude = set(exclude)
|
58
|
-
if isinstance(obj, BaseModel):
|
59
|
-
encoder = getattr(obj.__config__, "json_encoders", {})
|
60
|
-
if custom_encoder:
|
61
|
-
encoder.update(custom_encoder)
|
62
|
-
obj_dict = obj.dict(
|
63
|
-
include=include,
|
64
|
-
exclude=exclude,
|
65
|
-
by_alias=by_alias,
|
66
|
-
exclude_unset=exclude_unset,
|
67
|
-
exclude_none=exclude_none,
|
68
|
-
exclude_defaults=exclude_defaults,
|
69
|
-
)
|
70
|
-
if "__root__" in obj_dict:
|
71
|
-
obj_dict = obj_dict["__root__"]
|
72
|
-
return jsonable_encoder(
|
73
|
-
obj_dict,
|
74
|
-
exclude_none=exclude_none,
|
75
|
-
exclude_defaults=exclude_defaults,
|
76
|
-
custom_encoder=encoder,
|
77
|
-
sqlalchemy_safe=sqlalchemy_safe,
|
78
|
-
)
|
79
|
-
if dataclasses.is_dataclass(obj):
|
80
|
-
obj_dict = dataclasses.asdict(obj)
|
81
|
-
return jsonable_encoder(
|
82
|
-
obj_dict,
|
83
|
-
include=include,
|
84
|
-
exclude=exclude,
|
85
|
-
by_alias=by_alias,
|
86
|
-
exclude_unset=exclude_unset,
|
87
|
-
exclude_defaults=exclude_defaults,
|
88
|
-
exclude_none=exclude_none,
|
89
|
-
custom_encoder=custom_encoder,
|
90
|
-
sqlalchemy_safe=sqlalchemy_safe,
|
91
|
-
)
|
92
|
-
if isinstance(obj, Enum):
|
93
|
-
return obj.value
|
94
|
-
if isinstance(obj, PurePath):
|
95
|
-
return str(obj)
|
96
|
-
if isinstance(obj, (str, int, float, type(None))):
|
97
|
-
return obj
|
98
|
-
if isinstance(obj, dict):
|
99
|
-
encoded_dict = {}
|
100
|
-
allowed_keys = set(obj.keys())
|
101
|
-
if include is not None:
|
102
|
-
allowed_keys &= set(include)
|
103
|
-
if exclude is not None:
|
104
|
-
allowed_keys -= set(exclude)
|
105
|
-
for key, value in obj.items():
|
106
|
-
if (
|
107
|
-
(
|
108
|
-
not sqlalchemy_safe
|
109
|
-
or (not isinstance(key, str))
|
110
|
-
or (not key.startswith("_sa"))
|
111
|
-
)
|
112
|
-
and (value is not None or not exclude_none)
|
113
|
-
and key in allowed_keys
|
114
|
-
):
|
115
|
-
encoded_key = jsonable_encoder(
|
116
|
-
key,
|
117
|
-
by_alias=by_alias,
|
118
|
-
exclude_unset=exclude_unset,
|
119
|
-
exclude_none=exclude_none,
|
120
|
-
custom_encoder=custom_encoder,
|
121
|
-
sqlalchemy_safe=sqlalchemy_safe,
|
122
|
-
)
|
123
|
-
encoded_value = jsonable_encoder(
|
124
|
-
value,
|
125
|
-
by_alias=by_alias,
|
126
|
-
exclude_unset=exclude_unset,
|
127
|
-
exclude_none=exclude_none,
|
128
|
-
custom_encoder=custom_encoder,
|
129
|
-
sqlalchemy_safe=sqlalchemy_safe,
|
130
|
-
)
|
131
|
-
encoded_dict[encoded_key] = encoded_value
|
132
|
-
return encoded_dict
|
133
|
-
if isinstance(obj, (list, set, frozenset, GeneratorType, tuple, deque)):
|
134
|
-
encoded_list = []
|
135
|
-
for item in obj:
|
136
|
-
encoded_list.append(
|
137
|
-
jsonable_encoder(
|
138
|
-
item,
|
139
|
-
include=include,
|
140
|
-
exclude=exclude,
|
141
|
-
by_alias=by_alias,
|
142
|
-
exclude_unset=exclude_unset,
|
143
|
-
exclude_defaults=exclude_defaults,
|
144
|
-
exclude_none=exclude_none,
|
145
|
-
custom_encoder=custom_encoder,
|
146
|
-
sqlalchemy_safe=sqlalchemy_safe,
|
147
|
-
)
|
148
|
-
)
|
149
|
-
return encoded_list
|
150
|
-
|
151
|
-
if type(obj) in ENCODERS_BY_TYPE:
|
152
|
-
return ENCODERS_BY_TYPE[type(obj)](obj)
|
153
|
-
for encoder, classes_tuple in encoders_by_class_tuples.items():
|
154
|
-
if isinstance(obj, classes_tuple):
|
155
|
-
return encoder(obj)
|
156
|
-
|
157
|
-
try:
|
158
|
-
data = dict(obj)
|
159
|
-
except Exception as e:
|
160
|
-
errors: List[Exception] = []
|
161
|
-
errors.append(e)
|
162
|
-
try:
|
163
|
-
data = vars(obj)
|
164
|
-
except Exception as e:
|
165
|
-
errors.append(e)
|
166
|
-
raise ValueError(errors) from e
|
167
|
-
return jsonable_encoder(
|
168
|
-
data,
|
169
|
-
include=include,
|
170
|
-
exclude=exclude,
|
171
|
-
by_alias=by_alias,
|
172
|
-
exclude_unset=exclude_unset,
|
173
|
-
exclude_defaults=exclude_defaults,
|
174
|
-
exclude_none=exclude_none,
|
175
|
-
custom_encoder=custom_encoder,
|
176
|
-
sqlalchemy_safe=sqlalchemy_safe,
|
177
|
-
)
|
@@ -1,40 +0,0 @@
|
|
1
|
-
from prefect._vendor.fastapi.encoders import jsonable_encoder
|
2
|
-
from prefect._vendor.fastapi.exceptions import (
|
3
|
-
RequestValidationError,
|
4
|
-
WebSocketRequestValidationError,
|
5
|
-
)
|
6
|
-
from prefect._vendor.fastapi.utils import is_body_allowed_for_status_code
|
7
|
-
from prefect._vendor.fastapi.websockets import WebSocket
|
8
|
-
from prefect._vendor.starlette.exceptions import HTTPException
|
9
|
-
from prefect._vendor.starlette.requests import Request
|
10
|
-
from prefect._vendor.starlette.responses import JSONResponse, Response
|
11
|
-
from prefect._vendor.starlette.status import (
|
12
|
-
HTTP_422_UNPROCESSABLE_ENTITY,
|
13
|
-
WS_1008_POLICY_VIOLATION,
|
14
|
-
)
|
15
|
-
|
16
|
-
|
17
|
-
async def http_exception_handler(request: Request, exc: HTTPException) -> Response:
|
18
|
-
headers = getattr(exc, "headers", None)
|
19
|
-
if not is_body_allowed_for_status_code(exc.status_code):
|
20
|
-
return Response(status_code=exc.status_code, headers=headers)
|
21
|
-
return JSONResponse(
|
22
|
-
{"detail": exc.detail}, status_code=exc.status_code, headers=headers
|
23
|
-
)
|
24
|
-
|
25
|
-
|
26
|
-
async def request_validation_exception_handler(
|
27
|
-
request: Request, exc: RequestValidationError
|
28
|
-
) -> JSONResponse:
|
29
|
-
return JSONResponse(
|
30
|
-
status_code=HTTP_422_UNPROCESSABLE_ENTITY,
|
31
|
-
content={"detail": jsonable_encoder(exc.errors())},
|
32
|
-
)
|
33
|
-
|
34
|
-
|
35
|
-
async def websocket_request_validation_exception_handler(
|
36
|
-
websocket: WebSocket, exc: WebSocketRequestValidationError
|
37
|
-
) -> None:
|
38
|
-
await websocket.close(
|
39
|
-
code=WS_1008_POLICY_VIOLATION, reason=jsonable_encoder(exc.errors())
|
40
|
-
)
|
@@ -1,46 +0,0 @@
|
|
1
|
-
from typing import Any, Dict, Optional, Sequence, Type
|
2
|
-
|
3
|
-
from prefect._internal.pydantic import HAS_PYDANTIC_V2
|
4
|
-
|
5
|
-
if HAS_PYDANTIC_V2:
|
6
|
-
from pydantic.v1 import BaseModel, ValidationError, create_model
|
7
|
-
from pydantic.v1.error_wrappers import ErrorList
|
8
|
-
else:
|
9
|
-
from pydantic import BaseModel, ValidationError, create_model
|
10
|
-
from pydantic.error_wrappers import ErrorList
|
11
|
-
|
12
|
-
from prefect._vendor.starlette.exceptions import HTTPException as StarletteHTTPException
|
13
|
-
from prefect._vendor.starlette.exceptions import (
|
14
|
-
WebSocketException as WebSocketException, # noqa: F401
|
15
|
-
)
|
16
|
-
|
17
|
-
|
18
|
-
class HTTPException(StarletteHTTPException):
|
19
|
-
def __init__(
|
20
|
-
self,
|
21
|
-
status_code: int,
|
22
|
-
detail: Any = None,
|
23
|
-
headers: Optional[Dict[str, str]] = None,
|
24
|
-
) -> None:
|
25
|
-
super().__init__(status_code=status_code, detail=detail, headers=headers)
|
26
|
-
|
27
|
-
|
28
|
-
RequestErrorModel: Type[BaseModel] = create_model("Request")
|
29
|
-
WebSocketErrorModel: Type[BaseModel] = create_model("WebSocket")
|
30
|
-
|
31
|
-
|
32
|
-
class FastAPIError(RuntimeError):
|
33
|
-
"""
|
34
|
-
A generic, FastAPI-specific error.
|
35
|
-
"""
|
36
|
-
|
37
|
-
|
38
|
-
class RequestValidationError(ValidationError):
|
39
|
-
def __init__(self, errors: Sequence[ErrorList], *, body: Any = None) -> None:
|
40
|
-
self.body = body
|
41
|
-
super().__init__(errors, RequestErrorModel)
|
42
|
-
|
43
|
-
|
44
|
-
class WebSocketRequestValidationError(ValidationError):
|
45
|
-
def __init__(self, errors: Sequence[ErrorList]) -> None:
|
46
|
-
super().__init__(errors, WebSocketErrorModel)
|
@@ -1 +0,0 @@
|
|
1
|
-
from prefect._vendor.starlette.middleware import Middleware as Middleware
|
@@ -1,25 +0,0 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
|
3
|
-
from prefect._vendor.fastapi.concurrency import AsyncExitStack
|
4
|
-
from prefect._vendor.starlette.types import ASGIApp, Receive, Scope, Send
|
5
|
-
|
6
|
-
|
7
|
-
class AsyncExitStackMiddleware:
|
8
|
-
def __init__(self, app: ASGIApp, context_name: str = "fastapi_astack") -> None:
|
9
|
-
self.app = app
|
10
|
-
self.context_name = context_name
|
11
|
-
|
12
|
-
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
|
13
|
-
dependency_exception: Optional[Exception] = None
|
14
|
-
async with AsyncExitStack() as stack:
|
15
|
-
scope[self.context_name] = stack
|
16
|
-
try:
|
17
|
-
await self.app(scope, receive, send)
|
18
|
-
except Exception as e:
|
19
|
-
dependency_exception = e
|
20
|
-
raise e
|
21
|
-
if dependency_exception:
|
22
|
-
# This exception was possibly handled by the dependency but it should
|
23
|
-
# still bubble up so that the ServerErrorMiddleware can return a 500
|
24
|
-
# or the ExceptionMiddleware can catch and handle any other exceptions
|
25
|
-
raise dependency_exception
|
File without changes
|
@@ -1,203 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
from typing import Any, Dict, Optional
|
3
|
-
|
4
|
-
from prefect._vendor.fastapi.encoders import jsonable_encoder
|
5
|
-
from prefect._vendor.starlette.responses import HTMLResponse
|
6
|
-
|
7
|
-
swagger_ui_default_parameters = {
|
8
|
-
"dom_id": "#swagger-ui",
|
9
|
-
"layout": "BaseLayout",
|
10
|
-
"deepLinking": True,
|
11
|
-
"showExtensions": True,
|
12
|
-
"showCommonExtensions": True,
|
13
|
-
}
|
14
|
-
|
15
|
-
|
16
|
-
def get_swagger_ui_html(
|
17
|
-
*,
|
18
|
-
openapi_url: str,
|
19
|
-
title: str,
|
20
|
-
swagger_js_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js",
|
21
|
-
swagger_css_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css",
|
22
|
-
swagger_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png",
|
23
|
-
oauth2_redirect_url: Optional[str] = None,
|
24
|
-
init_oauth: Optional[Dict[str, Any]] = None,
|
25
|
-
swagger_ui_parameters: Optional[Dict[str, Any]] = None,
|
26
|
-
) -> HTMLResponse:
|
27
|
-
current_swagger_ui_parameters = swagger_ui_default_parameters.copy()
|
28
|
-
if swagger_ui_parameters:
|
29
|
-
current_swagger_ui_parameters.update(swagger_ui_parameters)
|
30
|
-
|
31
|
-
html = f"""
|
32
|
-
<!DOCTYPE html>
|
33
|
-
<html>
|
34
|
-
<head>
|
35
|
-
<link type="text/css" rel="stylesheet" href="{swagger_css_url}">
|
36
|
-
<link rel="shortcut icon" href="{swagger_favicon_url}">
|
37
|
-
<title>{title}</title>
|
38
|
-
</head>
|
39
|
-
<body>
|
40
|
-
<div id="swagger-ui">
|
41
|
-
</div>
|
42
|
-
<script src="{swagger_js_url}"></script>
|
43
|
-
<!-- `SwaggerUIBundle` is now available on the page -->
|
44
|
-
<script>
|
45
|
-
const ui = SwaggerUIBundle({{
|
46
|
-
url: '{openapi_url}',
|
47
|
-
"""
|
48
|
-
|
49
|
-
for key, value in current_swagger_ui_parameters.items():
|
50
|
-
html += f"{json.dumps(key)}: {json.dumps(jsonable_encoder(value))},\n"
|
51
|
-
|
52
|
-
if oauth2_redirect_url:
|
53
|
-
html += f"oauth2RedirectUrl: window.location.origin + '{oauth2_redirect_url}',"
|
54
|
-
|
55
|
-
html += """
|
56
|
-
presets: [
|
57
|
-
SwaggerUIBundle.presets.apis,
|
58
|
-
SwaggerUIBundle.SwaggerUIStandalonePreset
|
59
|
-
],
|
60
|
-
})"""
|
61
|
-
|
62
|
-
if init_oauth:
|
63
|
-
html += f"""
|
64
|
-
ui.initOAuth({json.dumps(jsonable_encoder(init_oauth))})
|
65
|
-
"""
|
66
|
-
|
67
|
-
html += """
|
68
|
-
</script>
|
69
|
-
</body>
|
70
|
-
</html>
|
71
|
-
"""
|
72
|
-
return HTMLResponse(html)
|
73
|
-
|
74
|
-
|
75
|
-
def get_redoc_html(
|
76
|
-
*,
|
77
|
-
openapi_url: str,
|
78
|
-
title: str,
|
79
|
-
redoc_js_url: str = "https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js",
|
80
|
-
redoc_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png",
|
81
|
-
with_google_fonts: bool = True,
|
82
|
-
) -> HTMLResponse:
|
83
|
-
html = f"""
|
84
|
-
<!DOCTYPE html>
|
85
|
-
<html>
|
86
|
-
<head>
|
87
|
-
<title>{title}</title>
|
88
|
-
<!-- needed for adaptive design -->
|
89
|
-
<meta charset="utf-8"/>
|
90
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
91
|
-
"""
|
92
|
-
if with_google_fonts:
|
93
|
-
html += """
|
94
|
-
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
95
|
-
"""
|
96
|
-
html += f"""
|
97
|
-
<link rel="shortcut icon" href="{redoc_favicon_url}">
|
98
|
-
<!--
|
99
|
-
ReDoc doesn't change outer page styles
|
100
|
-
-->
|
101
|
-
<style>
|
102
|
-
body {{
|
103
|
-
margin: 0;
|
104
|
-
padding: 0;
|
105
|
-
}}
|
106
|
-
</style>
|
107
|
-
</head>
|
108
|
-
<body>
|
109
|
-
<noscript>
|
110
|
-
ReDoc requires Javascript to function. Please enable it to browse the documentation.
|
111
|
-
</noscript>
|
112
|
-
<redoc spec-url="{openapi_url}"></redoc>
|
113
|
-
<script src="{redoc_js_url}"> </script>
|
114
|
-
</body>
|
115
|
-
</html>
|
116
|
-
"""
|
117
|
-
return HTMLResponse(html)
|
118
|
-
|
119
|
-
|
120
|
-
def get_swagger_ui_oauth2_redirect_html() -> HTMLResponse:
|
121
|
-
# copied from https://github.com/swagger-api/swagger-ui/blob/v4.14.0/dist/oauth2-redirect.html
|
122
|
-
html = """
|
123
|
-
<!doctype html>
|
124
|
-
<html lang="en-US">
|
125
|
-
<head>
|
126
|
-
<title>Swagger UI: OAuth2 Redirect</title>
|
127
|
-
</head>
|
128
|
-
<body>
|
129
|
-
<script>
|
130
|
-
'use strict';
|
131
|
-
function run () {
|
132
|
-
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
133
|
-
var sentState = oauth2.state;
|
134
|
-
var redirectUrl = oauth2.redirectUrl;
|
135
|
-
var isValid, qp, arr;
|
136
|
-
|
137
|
-
if (/code|token|error/.test(window.location.hash)) {
|
138
|
-
qp = window.location.hash.substring(1).replace('?', '&');
|
139
|
-
} else {
|
140
|
-
qp = location.search.substring(1);
|
141
|
-
}
|
142
|
-
|
143
|
-
arr = qp.split("&");
|
144
|
-
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
|
145
|
-
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
146
|
-
function (key, value) {
|
147
|
-
return key === "" ? value : decodeURIComponent(value);
|
148
|
-
}
|
149
|
-
) : {};
|
150
|
-
|
151
|
-
isValid = qp.state === sentState;
|
152
|
-
|
153
|
-
if ((
|
154
|
-
oauth2.auth.schema.get("flow") === "accessCode" ||
|
155
|
-
oauth2.auth.schema.get("flow") === "authorizationCode" ||
|
156
|
-
oauth2.auth.schema.get("flow") === "authorization_code"
|
157
|
-
) && !oauth2.auth.code) {
|
158
|
-
if (!isValid) {
|
159
|
-
oauth2.errCb({
|
160
|
-
authId: oauth2.auth.name,
|
161
|
-
source: "auth",
|
162
|
-
level: "warning",
|
163
|
-
message: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
|
164
|
-
});
|
165
|
-
}
|
166
|
-
|
167
|
-
if (qp.code) {
|
168
|
-
delete oauth2.state;
|
169
|
-
oauth2.auth.code = qp.code;
|
170
|
-
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
171
|
-
} else {
|
172
|
-
let oauthErrorMsg;
|
173
|
-
if (qp.error) {
|
174
|
-
oauthErrorMsg = "["+qp.error+"]: " +
|
175
|
-
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
|
176
|
-
(qp.error_uri ? "More info: "+qp.error_uri : "");
|
177
|
-
}
|
178
|
-
|
179
|
-
oauth2.errCb({
|
180
|
-
authId: oauth2.auth.name,
|
181
|
-
source: "auth",
|
182
|
-
level: "error",
|
183
|
-
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server."
|
184
|
-
});
|
185
|
-
}
|
186
|
-
} else {
|
187
|
-
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
188
|
-
}
|
189
|
-
window.close();
|
190
|
-
}
|
191
|
-
|
192
|
-
if (document.readyState !== 'loading') {
|
193
|
-
run();
|
194
|
-
} else {
|
195
|
-
document.addEventListener('DOMContentLoaded', function () {
|
196
|
-
run();
|
197
|
-
});
|
198
|
-
}
|
199
|
-
</script>
|
200
|
-
</body>
|
201
|
-
</html>
|
202
|
-
"""
|
203
|
-
return HTMLResponse(content=html)
|