prefect-client 2.18.3__tar.gz → 2.19.1__tar.gz
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-client-2.18.3/src/prefect_client.egg-info → prefect-client-2.19.1}/PKG-INFO +1 -1
- {prefect-client-2.18.3 → prefect-client-2.19.1}/setup.cfg +1 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/__init__.py +1 -15
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/compatibility/experimental.py +11 -2
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/concurrency/cancellation.py +2 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/schemas/validators.py +10 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/testclient.py +1 -1
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/blocks/notifications.py +6 -6
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/client/base.py +244 -1
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/client/cloud.py +4 -2
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/client/orchestration.py +515 -106
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/client/schemas/actions.py +58 -8
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/client/schemas/objects.py +15 -1
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/client/schemas/responses.py +19 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/client/schemas/schedules.py +1 -1
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/client/utilities.py +2 -2
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/concurrency/asyncio.py +34 -4
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/concurrency/sync.py +40 -6
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/context.py +2 -2
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/engine.py +2 -2
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/events/clients.py +2 -2
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/flows.py +91 -17
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/infrastructure/process.py +0 -17
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/logging/formatters.py +1 -4
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/new_flow_engine.py +137 -168
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/new_task_engine.py +137 -202
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/runner/__init__.py +1 -1
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/runner/runner.py +2 -107
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/settings.py +21 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/tasks.py +76 -57
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/types/__init__.py +27 -5
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/annotations.py +1 -8
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/asyncutils.py +4 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/engine.py +106 -1
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/schema_tools/__init__.py +6 -1
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/schema_tools/validation.py +25 -8
- prefect-client-2.19.1/src/prefect/utilities/timeout.py +34 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/workers/base.py +7 -3
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/workers/process.py +0 -17
- {prefect-client-2.18.3 → prefect-client-2.19.1/src/prefect_client.egg-info}/PKG-INFO +1 -1
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect_client.egg-info/SOURCES.txt +1 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/LICENSE +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/MANIFEST.in +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/README.md +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/requirements-client.txt +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/requirements-dev.txt +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/requirements.txt +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/setup.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/.prefectignore +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/_logging.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/compatibility/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/compatibility/deprecated.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/concurrency/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/concurrency/api.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/concurrency/calls.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/concurrency/event_loop.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/concurrency/inspection.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/concurrency/primitives.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/concurrency/services.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/concurrency/threads.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/concurrency/waiters.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/_base_model.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/_compat.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/_flags.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/_types.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/annotations/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/annotations/pendulum.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/schemas.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/utilities/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/utilities/config_dict.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/utilities/field_validator.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/utilities/model_construct.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/utilities/model_copy.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/utilities/model_dump.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/utilities/model_dump_json.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/utilities/model_fields.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/utilities/model_fields_set.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/utilities/model_json_schema.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/utilities/model_rebuild.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/utilities/model_validate.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/utilities/model_validate_json.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/utilities/model_validator.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/utilities/type_adapter.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/v1_schema.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/v2_schema.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pydantic/v2_validated_func.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/pytz.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/schemas/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/schemas/bases.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/schemas/fields.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/schemas/serializers.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/applications.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/background.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/concurrency.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/datastructures.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/dependencies/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/dependencies/models.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/dependencies/utils.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/encoders.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/exception_handlers.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/exceptions.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/logger.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/middleware/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/middleware/asyncexitstack.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/middleware/cors.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/middleware/gzip.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/middleware/httpsredirect.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/middleware/trustedhost.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/middleware/wsgi.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/openapi/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/openapi/constants.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/openapi/docs.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/openapi/models.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/openapi/utils.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/param_functions.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/params.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/requests.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/responses.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/routing.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/security/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/security/api_key.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/security/base.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/security/http.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/security/oauth2.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/security/open_id_connect_url.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/security/utils.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/staticfiles.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/templating.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/testclient.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/types.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/utils.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/fastapi/websockets.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/_compat.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/_exception_handler.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/_utils.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/applications.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/authentication.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/background.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/concurrency.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/config.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/convertors.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/datastructures.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/endpoints.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/exceptions.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/formparsers.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/middleware/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/middleware/authentication.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/middleware/base.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/middleware/cors.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/middleware/errors.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/middleware/exceptions.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/middleware/gzip.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/middleware/httpsredirect.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/middleware/sessions.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/middleware/trustedhost.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/middleware/wsgi.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/requests.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/responses.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/routing.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/schemas.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/staticfiles.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/status.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/templating.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/types.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_vendor/starlette/websockets.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_version.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/agent.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/artifacts.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/automations.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/blocks/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/blocks/abstract.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/blocks/core.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/blocks/fields.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/blocks/kubernetes.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/blocks/system.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/blocks/webhook.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/client/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/client/collections.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/client/constants.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/client/schemas/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/client/schemas/filters.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/client/schemas/sorting.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/client/subscriptions.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/concurrency/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/concurrency/events.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/concurrency/services.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deployments/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deployments/base.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deployments/deployments.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deployments/runner.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deployments/schedules.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deployments/steps/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deployments/steps/core.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deployments/steps/pull.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deployments/steps/utility.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deprecated/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deprecated/data_documents.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deprecated/packaging/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deprecated/packaging/base.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deprecated/packaging/docker.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deprecated/packaging/file.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deprecated/packaging/orion.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/deprecated/packaging/serializers.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/events/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/events/actions.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/events/cli/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/events/cli/automations.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/events/filters.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/events/instrument.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/events/related.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/events/schemas/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/events/schemas/automations.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/events/schemas/deployment_triggers.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/events/schemas/events.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/events/schemas/labelling.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/events/utilities.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/events/worker.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/exceptions.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/filesystems.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/flow_runs.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/futures.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/infrastructure/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/infrastructure/base.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/infrastructure/container.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/infrastructure/kubernetes.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/infrastructure/provisioners/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/infrastructure/provisioners/cloud_run.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/infrastructure/provisioners/container_instance.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/infrastructure/provisioners/ecs.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/infrastructure/provisioners/modal.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/input/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/input/actions.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/input/run_input.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/logging/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/logging/configuration.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/logging/filters.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/logging/handlers.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/logging/highlighters.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/logging/loggers.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/logging/logging.yml +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/manifests.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/plugins.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/profiles.toml +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/py.typed +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/pydantic/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/pydantic/main.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/results.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/runner/server.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/runner/storage.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/runner/submit.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/runner/utils.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/runtime/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/runtime/deployment.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/runtime/flow_run.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/runtime/task_run.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/serializers.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/server/api/collections_data/views/aggregate-worker-metadata.json +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/server/api/static/prefect-logo-mark-gradient.png +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/software/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/software/base.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/software/conda.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/software/pip.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/software/python.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/states.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/task_engine.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/task_runners.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/task_server.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/callables.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/collections.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/compat.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/context.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/dispatch.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/dockerutils.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/filesystem.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/hashing.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/importtools.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/math.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/names.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/processutils.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/pydantic.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/render_swagger.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/schema_tools/hydration.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/services.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/slugify.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/templating.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/text.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/utilities/visualization.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/variables.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/workers/__init__.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/workers/block.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/workers/server.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/workers/utilities.py +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect_client.egg-info/dependency_links.txt +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect_client.egg-info/requires.txt +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect_client.egg-info/top_level.txt +0 -0
- {prefect-client-2.18.3 → prefect-client-2.19.1}/versioneer.py +0 -0
@@ -25,25 +25,12 @@ __ui_static_path__ = __module_path__ / "server" / "ui"
|
|
25
25
|
|
26
26
|
del _version, pathlib
|
27
27
|
|
28
|
-
if sys.version_info < (3, 8):
|
29
|
-
warnings.warn(
|
30
|
-
(
|
31
|
-
"Prefect dropped support for Python 3.7 when it reached end-of-life"
|
32
|
-
" . To use new versions of Prefect, you will need"
|
33
|
-
" to upgrade to Python 3.8+. See https://devguide.python.org/versions/ for "
|
34
|
-
" more details."
|
35
|
-
),
|
36
|
-
FutureWarning,
|
37
|
-
stacklevel=2,
|
38
|
-
)
|
39
|
-
|
40
28
|
|
41
29
|
# Import user-facing API
|
42
|
-
from prefect.runner import Runner, serve
|
43
30
|
from prefect.deployments import deploy
|
44
31
|
from prefect.states import State
|
45
32
|
from prefect.logging import get_run_logger
|
46
|
-
from prefect.flows import flow, Flow
|
33
|
+
from prefect.flows import flow, Flow, serve
|
47
34
|
from prefect.tasks import task, Task
|
48
35
|
from prefect.context import tags
|
49
36
|
from prefect.manifests import Manifest
|
@@ -159,7 +146,6 @@ __all__ = [
|
|
159
146
|
"task",
|
160
147
|
"Task",
|
161
148
|
"unmapped",
|
162
|
-
"Runner",
|
163
149
|
"serve",
|
164
150
|
"deploy",
|
165
151
|
"pause_flow_run",
|
{prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/compatibility/experimental.py
RENAMED
@@ -22,7 +22,12 @@ if HAS_PYDANTIC_V2:
|
|
22
22
|
else:
|
23
23
|
import pydantic
|
24
24
|
|
25
|
-
from prefect.settings import
|
25
|
+
from prefect.settings import (
|
26
|
+
PREFECT_EXPERIMENTAL_WARN,
|
27
|
+
SETTING_VARIABLES,
|
28
|
+
Setting,
|
29
|
+
automation_settings_enabled,
|
30
|
+
)
|
26
31
|
from prefect.utilities.callables import get_call_parameters
|
27
32
|
|
28
33
|
T = TypeVar("T", bound=Callable[..., Any])
|
@@ -254,8 +259,12 @@ def enabled_experiments() -> Set[str]:
|
|
254
259
|
"""
|
255
260
|
Return the set of all enabled experiments.
|
256
261
|
"""
|
257
|
-
|
262
|
+
enabled_experimental_settings = {
|
258
263
|
name[len("PREFECT_EXPERIMENTAL_ENABLE_") :].lower()
|
259
264
|
for name, setting in SETTING_VARIABLES.items()
|
260
265
|
if name.startswith("PREFECT_EXPERIMENTAL_ENABLE_") and setting.value()
|
261
266
|
}
|
267
|
+
if automation_settings_enabled():
|
268
|
+
enabled_experimental_settings.add("automations")
|
269
|
+
|
270
|
+
return enabled_experimental_settings
|
{prefect-client-2.18.3 → prefect-client-2.19.1}/src/prefect/_internal/concurrency/cancellation.py
RENAMED
@@ -581,6 +581,8 @@ def _send_exception_to_thread(thread: threading.Thread, exc_type: Type[BaseExcep
|
|
581
581
|
|
582
582
|
This will not interrupt long-running system calls like `sleep` or `wait`.
|
583
583
|
"""
|
584
|
+
if not thread.ident:
|
585
|
+
raise ValueError("Thread is not started.")
|
584
586
|
ret = ctypes.pythonapi.PyThreadState_SetAsyncExc(
|
585
587
|
ctypes.c_long(thread.ident), ctypes.py_object(exc_type)
|
586
588
|
)
|
@@ -112,6 +112,10 @@ def validate_values_conform_to_schema(
|
|
112
112
|
"""
|
113
113
|
Validate that the provided values conform to the provided json schema.
|
114
114
|
|
115
|
+
TODO: This schema validation is outdated. The latest version is
|
116
|
+
prefect.utilities.schema_tools.validate, which handles fixes to Pydantic v1
|
117
|
+
schemas for null values and tuples.
|
118
|
+
|
115
119
|
Args:
|
116
120
|
values: The values to validate.
|
117
121
|
schema: The schema to validate against.
|
@@ -322,6 +326,12 @@ def set_deployment_schedules(values: dict) -> dict:
|
|
322
326
|
return values
|
323
327
|
|
324
328
|
|
329
|
+
def validate_schedule_max_scheduled_runs(v: Optional[int], limit: int) -> Optional[int]:
|
330
|
+
if v is not None and v > limit:
|
331
|
+
raise ValueError(f"`max_scheduled_runs` must be less than or equal to {limit}.")
|
332
|
+
return v
|
333
|
+
|
334
|
+
|
325
335
|
def remove_old_deployment_fields(values: dict) -> dict:
|
326
336
|
# 2.7.7 removed worker_pool_queue_id in lieu of worker_pool_name and
|
327
337
|
# worker_pool_queue_name. Those fields were later renamed to work_pool_name
|
@@ -461,7 +461,7 @@ class TestClient(httpx.Client):
|
|
461
461
|
] = httpx._client.USE_CLIENT_DEFAULT,
|
462
462
|
extensions: typing.Optional[typing.Dict[str, typing.Any]] = None,
|
463
463
|
) -> httpx.Response:
|
464
|
-
url = self.
|
464
|
+
url = self._merge_url(url)
|
465
465
|
redirect = self._choose_redirect_arg(follow_redirects, allow_redirects)
|
466
466
|
return super().request(
|
467
467
|
method,
|
@@ -235,7 +235,7 @@ class PagerDutyWebHook(AbstractAppriseNotificationBlock):
|
|
235
235
|
)
|
236
236
|
|
237
237
|
def block_initialization(self) -> None:
|
238
|
-
from apprise.plugins.
|
238
|
+
from apprise.plugins.pagerduty import NotifyPagerDuty
|
239
239
|
|
240
240
|
url = SecretStr(
|
241
241
|
NotifyPagerDuty(
|
@@ -303,7 +303,7 @@ class TwilioSMS(AbstractAppriseNotificationBlock):
|
|
303
303
|
)
|
304
304
|
|
305
305
|
def block_initialization(self) -> None:
|
306
|
-
from apprise.plugins.
|
306
|
+
from apprise.plugins.twilio import NotifyTwilio
|
307
307
|
|
308
308
|
url = SecretStr(
|
309
309
|
NotifyTwilio(
|
@@ -401,7 +401,7 @@ class OpsgenieWebhook(AbstractAppriseNotificationBlock):
|
|
401
401
|
)
|
402
402
|
|
403
403
|
def block_initialization(self) -> None:
|
404
|
-
from apprise.plugins.
|
404
|
+
from apprise.plugins.opsgenie import NotifyOpsgenie
|
405
405
|
|
406
406
|
targets = []
|
407
407
|
if self.target_user:
|
@@ -489,7 +489,7 @@ class MattermostWebhook(AbstractAppriseNotificationBlock):
|
|
489
489
|
)
|
490
490
|
|
491
491
|
def block_initialization(self) -> None:
|
492
|
-
from apprise.plugins.
|
492
|
+
from apprise.plugins.mattermost import NotifyMattermost
|
493
493
|
|
494
494
|
url = SecretStr(
|
495
495
|
NotifyMattermost(
|
@@ -582,7 +582,7 @@ class DiscordWebhook(AbstractAppriseNotificationBlock):
|
|
582
582
|
)
|
583
583
|
|
584
584
|
def block_initialization(self) -> None:
|
585
|
-
from apprise.plugins.
|
585
|
+
from apprise.plugins.discord import NotifyDiscord
|
586
586
|
|
587
587
|
url = SecretStr(
|
588
588
|
NotifyDiscord(
|
@@ -773,7 +773,7 @@ class SendgridEmail(AbstractAppriseNotificationBlock):
|
|
773
773
|
)
|
774
774
|
|
775
775
|
def block_initialization(self) -> None:
|
776
|
-
from apprise.plugins.
|
776
|
+
from apprise.plugins.sendgrid import NotifySendGrid
|
777
777
|
|
778
778
|
url = SecretStr(
|
779
779
|
NotifySendGrid(
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import copy
|
2
2
|
import sys
|
3
3
|
import threading
|
4
|
+
import time
|
4
5
|
import uuid
|
5
6
|
from collections import defaultdict
|
6
7
|
from contextlib import asynccontextmanager
|
@@ -25,6 +26,7 @@ import httpx
|
|
25
26
|
from asgi_lifespan import LifespanManager
|
26
27
|
from httpx import HTTPStatusError, Request, Response
|
27
28
|
from prefect._vendor.starlette import status
|
29
|
+
from prefect._vendor.starlette.testclient import TestClient
|
28
30
|
from typing_extensions import Self
|
29
31
|
|
30
32
|
import prefect
|
@@ -182,7 +184,7 @@ class PrefectResponse(httpx.Response):
|
|
182
184
|
return new_response
|
183
185
|
|
184
186
|
|
185
|
-
class
|
187
|
+
class PrefectHttpxAsyncClient(httpx.AsyncClient):
|
186
188
|
"""
|
187
189
|
A Prefect wrapper for the async httpx client with support for retry-after headers
|
188
190
|
for the provided status codes (typically 429, 502 and 503).
|
@@ -394,3 +396,244 @@ class PrefectHttpxClient(httpx.AsyncClient):
|
|
394
396
|
|
395
397
|
request.headers["Prefect-Csrf-Token"] = self.csrf_token
|
396
398
|
request.headers["Prefect-Csrf-Client"] = str(self.csrf_client_id)
|
399
|
+
|
400
|
+
|
401
|
+
class PrefectHttpxSyncClient(httpx.Client):
|
402
|
+
"""
|
403
|
+
A Prefect wrapper for the async httpx client with support for retry-after headers
|
404
|
+
for the provided status codes (typically 429, 502 and 503).
|
405
|
+
|
406
|
+
Additionally, this client will always call `raise_for_status` on responses.
|
407
|
+
|
408
|
+
For more details on rate limit headers, see:
|
409
|
+
[Configuring Cloudflare Rate Limiting](https://support.cloudflare.com/hc/en-us/articles/115001635128-Configuring-Rate-Limiting-from-UI)
|
410
|
+
"""
|
411
|
+
|
412
|
+
def __init__(
|
413
|
+
self,
|
414
|
+
*args,
|
415
|
+
enable_csrf_support: bool = False,
|
416
|
+
raise_on_all_errors: bool = True,
|
417
|
+
**kwargs,
|
418
|
+
):
|
419
|
+
self.enable_csrf_support: bool = enable_csrf_support
|
420
|
+
self.csrf_token: Optional[str] = None
|
421
|
+
self.csrf_token_expiration: Optional[datetime] = None
|
422
|
+
self.csrf_client_id: uuid.UUID = uuid.uuid4()
|
423
|
+
self.raise_on_all_errors: bool = raise_on_all_errors
|
424
|
+
|
425
|
+
super().__init__(*args, **kwargs)
|
426
|
+
|
427
|
+
user_agent = (
|
428
|
+
f"prefect/{prefect.__version__} (API {constants.SERVER_API_VERSION})"
|
429
|
+
)
|
430
|
+
self.headers["User-Agent"] = user_agent
|
431
|
+
|
432
|
+
def _send_with_retry(
|
433
|
+
self,
|
434
|
+
request: Request,
|
435
|
+
send: Callable[[Request], Response],
|
436
|
+
send_args: Tuple,
|
437
|
+
send_kwargs: Dict,
|
438
|
+
retry_codes: Set[int] = set(),
|
439
|
+
retry_exceptions: Tuple[Exception, ...] = tuple(),
|
440
|
+
):
|
441
|
+
"""
|
442
|
+
Send a request and retry it if it fails.
|
443
|
+
|
444
|
+
Sends the provided request and retries it up to PREFECT_CLIENT_MAX_RETRIES times
|
445
|
+
if the request either raises an exception listed in `retry_exceptions` or
|
446
|
+
receives a response with a status code listed in `retry_codes`.
|
447
|
+
|
448
|
+
Retries will be delayed based on either the retry header (preferred) or
|
449
|
+
exponential backoff if a retry header is not provided.
|
450
|
+
"""
|
451
|
+
try_count = 0
|
452
|
+
response = None
|
453
|
+
|
454
|
+
is_change_request = request.method.lower() in {"post", "put", "patch", "delete"}
|
455
|
+
|
456
|
+
if self.enable_csrf_support and is_change_request:
|
457
|
+
self._add_csrf_headers(request=request)
|
458
|
+
|
459
|
+
while try_count <= PREFECT_CLIENT_MAX_RETRIES.value():
|
460
|
+
try_count += 1
|
461
|
+
retry_seconds = None
|
462
|
+
exc_info = None
|
463
|
+
|
464
|
+
try:
|
465
|
+
response = send(request, *send_args, **send_kwargs)
|
466
|
+
except retry_exceptions: # type: ignore
|
467
|
+
if try_count > PREFECT_CLIENT_MAX_RETRIES.value():
|
468
|
+
raise
|
469
|
+
# Otherwise, we will ignore this error but capture the info for logging
|
470
|
+
exc_info = sys.exc_info()
|
471
|
+
else:
|
472
|
+
# We got a response; check if it's a CSRF error, otherwise
|
473
|
+
# return immediately if it is not retryable
|
474
|
+
if (
|
475
|
+
response.status_code == status.HTTP_403_FORBIDDEN
|
476
|
+
and "Invalid CSRF token" in response.text
|
477
|
+
):
|
478
|
+
# We got a CSRF error, clear the token and try again
|
479
|
+
self.csrf_token = None
|
480
|
+
self._add_csrf_headers(request)
|
481
|
+
elif response.status_code not in retry_codes:
|
482
|
+
return response
|
483
|
+
|
484
|
+
if "Retry-After" in response.headers:
|
485
|
+
retry_seconds = float(response.headers["Retry-After"])
|
486
|
+
|
487
|
+
# Use an exponential back-off if not set in a header
|
488
|
+
if retry_seconds is None:
|
489
|
+
retry_seconds = 2**try_count
|
490
|
+
|
491
|
+
# Add jitter
|
492
|
+
jitter_factor = PREFECT_CLIENT_RETRY_JITTER_FACTOR.value()
|
493
|
+
if retry_seconds > 0 and jitter_factor > 0:
|
494
|
+
if response is not None and "Retry-After" in response.headers:
|
495
|
+
# Always wait for _at least_ retry seconds if requested by the API
|
496
|
+
retry_seconds = bounded_poisson_interval(
|
497
|
+
retry_seconds, retry_seconds * (1 + jitter_factor)
|
498
|
+
)
|
499
|
+
else:
|
500
|
+
# Otherwise, use a symmetrical jitter
|
501
|
+
retry_seconds = clamped_poisson_interval(
|
502
|
+
retry_seconds, jitter_factor
|
503
|
+
)
|
504
|
+
|
505
|
+
logger.debug(
|
506
|
+
(
|
507
|
+
"Encountered retryable exception during request. "
|
508
|
+
if exc_info
|
509
|
+
else (
|
510
|
+
"Received response with retryable status code"
|
511
|
+
f" {response.status_code}. "
|
512
|
+
)
|
513
|
+
)
|
514
|
+
+ f"Another attempt will be made in {retry_seconds}s. "
|
515
|
+
"This is attempt"
|
516
|
+
f" {try_count}/{PREFECT_CLIENT_MAX_RETRIES.value() + 1}.",
|
517
|
+
exc_info=exc_info,
|
518
|
+
)
|
519
|
+
time.sleep(retry_seconds)
|
520
|
+
|
521
|
+
assert (
|
522
|
+
response is not None
|
523
|
+
), "Retry handling ended without response or exception"
|
524
|
+
|
525
|
+
# We ran out of retries, return the failed response
|
526
|
+
return response
|
527
|
+
|
528
|
+
def send(self, request: Request, *args, **kwargs) -> Response:
|
529
|
+
"""
|
530
|
+
Send a request with automatic retry behavior for the following status codes:
|
531
|
+
|
532
|
+
- 403 Forbidden, if the request failed due to CSRF protection
|
533
|
+
- 408 Request Timeout
|
534
|
+
- 429 CloudFlare-style rate limiting
|
535
|
+
- 502 Bad Gateway
|
536
|
+
- 503 Service unavailable
|
537
|
+
- Any additional status codes provided in `PREFECT_CLIENT_RETRY_EXTRA_CODES`
|
538
|
+
"""
|
539
|
+
|
540
|
+
super_send = super().send
|
541
|
+
response = self._send_with_retry(
|
542
|
+
request=request,
|
543
|
+
send=super_send,
|
544
|
+
send_args=args,
|
545
|
+
send_kwargs=kwargs,
|
546
|
+
retry_codes={
|
547
|
+
status.HTTP_429_TOO_MANY_REQUESTS,
|
548
|
+
status.HTTP_503_SERVICE_UNAVAILABLE,
|
549
|
+
status.HTTP_502_BAD_GATEWAY,
|
550
|
+
status.HTTP_408_REQUEST_TIMEOUT,
|
551
|
+
*PREFECT_CLIENT_RETRY_EXTRA_CODES.value(),
|
552
|
+
},
|
553
|
+
retry_exceptions=(
|
554
|
+
httpx.ReadTimeout,
|
555
|
+
httpx.PoolTimeout,
|
556
|
+
httpx.ConnectTimeout,
|
557
|
+
# `ConnectionResetError` when reading socket raises as a `ReadError`
|
558
|
+
httpx.ReadError,
|
559
|
+
# Sockets can be closed during writes resulting in a `WriteError`
|
560
|
+
httpx.WriteError,
|
561
|
+
# Uvicorn bug, see https://github.com/PrefectHQ/prefect/issues/7512
|
562
|
+
httpx.RemoteProtocolError,
|
563
|
+
# HTTP2 bug, see https://github.com/PrefectHQ/prefect/issues/7442
|
564
|
+
httpx.LocalProtocolError,
|
565
|
+
),
|
566
|
+
)
|
567
|
+
|
568
|
+
# Convert to a Prefect response to add nicer errors messages
|
569
|
+
response = PrefectResponse.from_httpx_response(response)
|
570
|
+
|
571
|
+
if self.raise_on_all_errors:
|
572
|
+
response.raise_for_status()
|
573
|
+
|
574
|
+
return response
|
575
|
+
|
576
|
+
def _add_csrf_headers(self, request: Request):
|
577
|
+
now = datetime.now(timezone.utc)
|
578
|
+
|
579
|
+
if not self.enable_csrf_support:
|
580
|
+
return
|
581
|
+
|
582
|
+
if not self.csrf_token or (
|
583
|
+
self.csrf_token_expiration and now > self.csrf_token_expiration
|
584
|
+
):
|
585
|
+
token_request = self.build_request(
|
586
|
+
"GET", f"/csrf-token?client={self.csrf_client_id}"
|
587
|
+
)
|
588
|
+
|
589
|
+
try:
|
590
|
+
token_response = self.send(token_request)
|
591
|
+
except PrefectHTTPStatusError as exc:
|
592
|
+
old_server = exc.response.status_code == status.HTTP_404_NOT_FOUND
|
593
|
+
unconfigured_server = (
|
594
|
+
exc.response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
|
595
|
+
and "CSRF protection is disabled." in exc.response.text
|
596
|
+
)
|
597
|
+
|
598
|
+
if old_server or unconfigured_server:
|
599
|
+
# The token endpoint is either unavailable, suggesting an
|
600
|
+
# older server, or CSRF protection is disabled. In either
|
601
|
+
# case we should disable CSRF support.
|
602
|
+
self.enable_csrf_support = False
|
603
|
+
return
|
604
|
+
|
605
|
+
raise
|
606
|
+
|
607
|
+
token: CsrfToken = CsrfToken.parse_obj(token_response.json())
|
608
|
+
self.csrf_token = token.token
|
609
|
+
self.csrf_token_expiration = token.expiration
|
610
|
+
|
611
|
+
request.headers["Prefect-Csrf-Token"] = self.csrf_token
|
612
|
+
request.headers["Prefect-Csrf-Client"] = str(self.csrf_client_id)
|
613
|
+
|
614
|
+
|
615
|
+
class PrefectHttpxSyncEphemeralClient(TestClient, PrefectHttpxSyncClient):
|
616
|
+
"""
|
617
|
+
This client is a synchronous httpx client that can be used to talk directly
|
618
|
+
to an ASGI app, such as an ephemeral Prefect API.
|
619
|
+
|
620
|
+
It is a subclass of both Starlette's `TestClient` and Prefect's
|
621
|
+
`PrefectHttpxSyncClient`, so it combines the synchronous testing
|
622
|
+
capabilities of `TestClient` with the Prefect-specific behaviors of
|
623
|
+
`PrefectHttpxSyncClient`.
|
624
|
+
"""
|
625
|
+
|
626
|
+
def __init__(
|
627
|
+
self,
|
628
|
+
*args,
|
629
|
+
# override TestClient default
|
630
|
+
raise_server_exceptions=False,
|
631
|
+
**kwargs,
|
632
|
+
):
|
633
|
+
super().__init__(
|
634
|
+
*args,
|
635
|
+
raise_server_exceptions=raise_server_exceptions,
|
636
|
+
**kwargs,
|
637
|
+
)
|
638
|
+
|
639
|
+
pass
|
@@ -15,7 +15,7 @@ from prefect._vendor.starlette import status
|
|
15
15
|
|
16
16
|
import prefect.context
|
17
17
|
import prefect.settings
|
18
|
-
from prefect.client.base import
|
18
|
+
from prefect.client.base import PrefectHttpxAsyncClient
|
19
19
|
from prefect.client.schemas import Workspace
|
20
20
|
from prefect.exceptions import PrefectException
|
21
21
|
from prefect.settings import (
|
@@ -72,7 +72,9 @@ class CloudClient:
|
|
72
72
|
httpx_settings.setdefault("base_url", host)
|
73
73
|
if not PREFECT_UNIT_TEST_MODE.value():
|
74
74
|
httpx_settings.setdefault("follow_redirects", True)
|
75
|
-
self._client =
|
75
|
+
self._client = PrefectHttpxAsyncClient(
|
76
|
+
**httpx_settings, enable_csrf_support=False
|
77
|
+
)
|
76
78
|
|
77
79
|
async def api_healthcheck(self):
|
78
80
|
"""
|