prefect-client 2.19.2__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 +151 -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 +307 -166
- 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 +19 -15
- 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 +311 -43
- 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 +97 -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.2.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.2.dist-info/RECORD +0 -292
- {prefect_client-2.19.2.dist-info → prefect_client-3.0.0rc1.dist-info}/LICENSE +0 -0
- {prefect_client-2.19.2.dist-info → prefect_client-3.0.0rc1.dist-info}/WHEEL +0 -0
- {prefect_client-2.19.2.dist-info → prefect_client-3.0.0rc1.dist-info}/top_level.txt +0 -0
@@ -2,19 +2,13 @@ import datetime
|
|
2
2
|
from typing import Any, Dict, List, Optional, TypeVar, Union
|
3
3
|
from uuid import UUID
|
4
4
|
|
5
|
-
from
|
6
|
-
from
|
7
|
-
|
8
|
-
if HAS_PYDANTIC_V2:
|
9
|
-
from pydantic.v1 import Field
|
10
|
-
else:
|
11
|
-
from pydantic import Field
|
12
|
-
|
5
|
+
from pydantic import ConfigDict, Field
|
6
|
+
from pydantic_extra_types.pendulum_dt import DateTime
|
13
7
|
from typing_extensions import Literal
|
14
8
|
|
15
9
|
import prefect.client.schemas.objects as objects
|
16
10
|
from prefect._internal.schemas.bases import ObjectBaseModel, PrefectBaseModel
|
17
|
-
from prefect._internal.schemas.fields import CreatedBy,
|
11
|
+
from prefect._internal.schemas.fields import CreatedBy, UpdatedBy
|
18
12
|
from prefect.client.schemas.schedules import SCHEDULE_TYPES
|
19
13
|
from prefect.utilities.collections import AutoEnum
|
20
14
|
from prefect.utilities.names import generate_slug
|
@@ -120,10 +114,10 @@ class HistoryResponseState(PrefectBaseModel):
|
|
120
114
|
class HistoryResponse(PrefectBaseModel):
|
121
115
|
"""Represents a history of aggregation states over an interval"""
|
122
116
|
|
123
|
-
interval_start:
|
117
|
+
interval_start: DateTime = Field(
|
124
118
|
default=..., description="The start date of the interval."
|
125
119
|
)
|
126
|
-
interval_end:
|
120
|
+
interval_end: DateTime = Field(
|
127
121
|
default=..., description="The end date of the interval."
|
128
122
|
)
|
129
123
|
states: List[HistoryResponseState] = Field(
|
@@ -147,8 +141,7 @@ class OrchestrationResult(PrefectBaseModel):
|
|
147
141
|
|
148
142
|
|
149
143
|
class WorkerFlowRunResponse(PrefectBaseModel):
|
150
|
-
|
151
|
-
arbitrary_types_allowed = True
|
144
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
152
145
|
|
153
146
|
work_pool_id: UUID
|
154
147
|
work_queue_id: UUID
|
@@ -219,18 +212,18 @@ class FlowRunResponse(ObjectBaseModel):
|
|
219
212
|
run_count: int = Field(
|
220
213
|
default=0, description="The number of times the flow run was executed."
|
221
214
|
)
|
222
|
-
expected_start_time: Optional[
|
215
|
+
expected_start_time: Optional[DateTime] = Field(
|
223
216
|
default=None,
|
224
217
|
description="The flow run's expected start time.",
|
225
218
|
)
|
226
|
-
next_scheduled_start_time: Optional[
|
219
|
+
next_scheduled_start_time: Optional[DateTime] = Field(
|
227
220
|
default=None,
|
228
221
|
description="The next time the flow run is scheduled to start.",
|
229
222
|
)
|
230
|
-
start_time: Optional[
|
223
|
+
start_time: Optional[DateTime] = Field(
|
231
224
|
default=None, description="The actual start time."
|
232
225
|
)
|
233
|
-
end_time: Optional[
|
226
|
+
end_time: Optional[DateTime] = Field(
|
234
227
|
default=None, description="The actual end time."
|
235
228
|
)
|
236
229
|
total_run_time: datetime.timedelta = Field(
|
@@ -279,7 +272,7 @@ class FlowRunResponse(ObjectBaseModel):
|
|
279
272
|
state: Optional[objects.State] = Field(
|
280
273
|
default=None,
|
281
274
|
description="The state of the flow run.",
|
282
|
-
examples=[objects.State(type=objects.StateType.COMPLETED)],
|
275
|
+
examples=["objects.State(type=objects.StateType.COMPLETED)"],
|
283
276
|
)
|
284
277
|
job_variables: Optional[dict] = Field(
|
285
278
|
default=None, description="Job variables for the flow run."
|
@@ -304,13 +297,13 @@ class FlowRunResponse(ObjectBaseModel):
|
|
304
297
|
"""
|
305
298
|
if isinstance(other, objects.FlowRun):
|
306
299
|
exclude_fields = {"estimated_run_time", "estimated_start_time_delta"}
|
307
|
-
return self.
|
300
|
+
return self.model_dump(exclude=exclude_fields) == other.model_dump(
|
308
301
|
exclude=exclude_fields
|
309
302
|
)
|
310
303
|
return super().__eq__(other)
|
311
304
|
|
312
305
|
|
313
|
-
class DeploymentResponse(
|
306
|
+
class DeploymentResponse(ObjectBaseModel):
|
314
307
|
name: str = Field(default=..., description="The name of the deployment.")
|
315
308
|
version: Optional[str] = Field(
|
316
309
|
default=None, description="An optional version for the deployment."
|
@@ -357,7 +350,7 @@ class DeploymentResponse(DeprecatedInfraOverridesField, ObjectBaseModel):
|
|
357
350
|
" be scheduled."
|
358
351
|
),
|
359
352
|
)
|
360
|
-
last_polled: Optional[
|
353
|
+
last_polled: Optional[DateTime] = Field(
|
361
354
|
default=None,
|
362
355
|
description="The last time the deployment was polled for status updates.",
|
363
356
|
)
|
@@ -407,7 +400,7 @@ class DeploymentResponse(DeprecatedInfraOverridesField, ObjectBaseModel):
|
|
407
400
|
),
|
408
401
|
)
|
409
402
|
enforce_parameter_schema: bool = Field(
|
410
|
-
default=
|
403
|
+
default=True,
|
411
404
|
description=(
|
412
405
|
"Whether or not the deployment should enforce the parameter schema."
|
413
406
|
),
|
@@ -423,8 +416,7 @@ class DeploymentResponse(DeprecatedInfraOverridesField, ObjectBaseModel):
|
|
423
416
|
|
424
417
|
|
425
418
|
class MinimalConcurrencyLimitResponse(PrefectBaseModel):
|
426
|
-
|
427
|
-
extra = "ignore" # 2024/4/1
|
419
|
+
model_config = ConfigDict(extra="ignore")
|
428
420
|
|
429
421
|
id: UUID
|
430
422
|
name: str
|
@@ -3,28 +3,21 @@ Schedule schemas
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
import datetime
|
6
|
-
from typing import Optional, Union
|
6
|
+
from typing import Annotated, Optional, Union
|
7
7
|
|
8
8
|
import dateutil
|
9
9
|
import dateutil.rrule
|
10
10
|
import pendulum
|
11
|
+
from pydantic import AfterValidator, ConfigDict, Field, field_validator, model_validator
|
12
|
+
from pydantic_extra_types.pendulum_dt import DateTime
|
11
13
|
|
12
|
-
from prefect._internal.pydantic import HAS_PYDANTIC_V2
|
13
14
|
from prefect._internal.schemas.bases import PrefectBaseModel
|
14
|
-
from prefect._internal.schemas.fields import DateTimeTZ
|
15
15
|
from prefect._internal.schemas.validators import (
|
16
16
|
default_anchor_date,
|
17
17
|
default_timezone,
|
18
18
|
validate_cron_string,
|
19
19
|
validate_rrule_string,
|
20
|
-
validate_rrule_timezone,
|
21
20
|
)
|
22
|
-
from prefect.types import PositiveDuration
|
23
|
-
|
24
|
-
if HAS_PYDANTIC_V2:
|
25
|
-
from pydantic.v1 import Field, validator
|
26
|
-
else:
|
27
|
-
from pydantic import Field, validator
|
28
21
|
|
29
22
|
MAX_ITERATIONS = 1000
|
30
23
|
# approx. 1 years worth of RDATEs + buffer
|
@@ -55,26 +48,24 @@ class IntervalSchedule(PrefectBaseModel):
|
|
55
48
|
|
56
49
|
Args:
|
57
50
|
interval (datetime.timedelta): an interval to schedule on
|
58
|
-
anchor_date (
|
51
|
+
anchor_date (DateTime, optional): an anchor date to schedule increments against;
|
59
52
|
if not provided, the current timestamp will be used
|
60
53
|
timezone (str, optional): a valid timezone string
|
61
54
|
"""
|
62
55
|
|
63
|
-
|
64
|
-
extra = "forbid"
|
65
|
-
exclude_none = True
|
56
|
+
model_config = ConfigDict(extra="forbid", exclude_none=True)
|
66
57
|
|
67
|
-
interval:
|
68
|
-
anchor_date:
|
58
|
+
interval: datetime.timedelta = Field(gt=datetime.timedelta(0))
|
59
|
+
anchor_date: Annotated[DateTime, AfterValidator(default_anchor_date)] = Field(
|
60
|
+
default_factory=lambda: pendulum.now("UTC"),
|
61
|
+
examples=["2020-01-01T00:00:00Z"],
|
62
|
+
)
|
69
63
|
timezone: Optional[str] = Field(default=None, examples=["America/New_York"])
|
70
64
|
|
71
|
-
@
|
72
|
-
def
|
73
|
-
|
74
|
-
|
75
|
-
@validator("timezone", always=True)
|
76
|
-
def validate_default_timezone(cls, v, values):
|
77
|
-
return default_timezone(v, values=values)
|
65
|
+
@model_validator(mode="after")
|
66
|
+
def validate_timezone(self):
|
67
|
+
self.timezone = default_timezone(self.timezone, self.model_dump())
|
68
|
+
return self
|
78
69
|
|
79
70
|
|
80
71
|
class CronSchedule(PrefectBaseModel):
|
@@ -102,8 +93,7 @@ class CronSchedule(PrefectBaseModel):
|
|
102
93
|
|
103
94
|
"""
|
104
95
|
|
105
|
-
|
106
|
-
extra = "forbid"
|
96
|
+
model_config = ConfigDict(extra="forbid")
|
107
97
|
|
108
98
|
cron: str = Field(default=..., examples=["0 0 * * *"])
|
109
99
|
timezone: Optional[str] = Field(default=None, examples=["America/New_York"])
|
@@ -114,11 +104,13 @@ class CronSchedule(PrefectBaseModel):
|
|
114
104
|
),
|
115
105
|
)
|
116
106
|
|
117
|
-
@
|
107
|
+
@field_validator("timezone")
|
108
|
+
@classmethod
|
118
109
|
def valid_timezone(cls, v):
|
119
110
|
return default_timezone(v)
|
120
111
|
|
121
|
-
@
|
112
|
+
@field_validator("cron")
|
113
|
+
@classmethod
|
122
114
|
def valid_cron_string(cls, v):
|
123
115
|
return validate_cron_string(v)
|
124
116
|
|
@@ -146,13 +138,15 @@ class RRuleSchedule(PrefectBaseModel):
|
|
146
138
|
timezone (str, optional): a valid timezone string
|
147
139
|
"""
|
148
140
|
|
149
|
-
|
150
|
-
extra = "forbid"
|
141
|
+
model_config = ConfigDict(extra="forbid")
|
151
142
|
|
152
143
|
rrule: str
|
153
|
-
timezone: Optional[str] = Field(
|
144
|
+
timezone: Optional[str] = Field(
|
145
|
+
default="UTC", examples=["America/New_York"], validate_default=True
|
146
|
+
)
|
154
147
|
|
155
|
-
@
|
148
|
+
@field_validator("rrule")
|
149
|
+
@classmethod
|
156
150
|
def validate_rrule_str(cls, v):
|
157
151
|
return validate_rrule_string(v)
|
158
152
|
|
@@ -259,14 +253,30 @@ class RRuleSchedule(PrefectBaseModel):
|
|
259
253
|
|
260
254
|
return rrule
|
261
255
|
|
262
|
-
@
|
256
|
+
@field_validator("timezone")
|
263
257
|
def valid_timezone(cls, v):
|
264
|
-
|
258
|
+
"""
|
259
|
+
Validate that the provided timezone is a valid IANA timezone.
|
260
|
+
|
261
|
+
Unfortunately this list is slightly different from the list of valid
|
262
|
+
timezones in pendulum that we use for cron and interval timezone validation.
|
263
|
+
"""
|
264
|
+
from prefect._internal.pytz import HAS_PYTZ
|
265
|
+
|
266
|
+
if HAS_PYTZ:
|
267
|
+
import pytz
|
268
|
+
else:
|
269
|
+
from prefect._internal import pytz
|
270
|
+
|
271
|
+
if v and v not in pytz.all_timezones_set:
|
272
|
+
raise ValueError(f'Invalid timezone: "{v}"')
|
273
|
+
elif v is None:
|
274
|
+
return "UTC"
|
275
|
+
return v
|
265
276
|
|
266
277
|
|
267
278
|
class NoSchedule(PrefectBaseModel):
|
268
|
-
|
269
|
-
extra = "forbid"
|
279
|
+
model_config = ConfigDict(extra="forbid")
|
270
280
|
|
271
281
|
|
272
282
|
SCHEDULE_TYPES = Union[IntervalSchedule, CronSchedule, RRuleSchedule, NoSchedule]
|
@@ -308,6 +318,8 @@ def construct_schedule(
|
|
308
318
|
if interval:
|
309
319
|
if isinstance(interval, (int, float)):
|
310
320
|
interval = datetime.timedelta(seconds=interval)
|
321
|
+
if not anchor_date:
|
322
|
+
anchor_date = DateTime.now()
|
311
323
|
schedule = IntervalSchedule(
|
312
324
|
interval=interval, anchor_date=anchor_date, timezone=timezone
|
313
325
|
)
|
prefect/client/subscriptions.py
CHANGED
@@ -4,7 +4,7 @@ from typing import Any, Dict, Generic, List, Optional, Type, TypeVar
|
|
4
4
|
import orjson
|
5
5
|
import websockets
|
6
6
|
import websockets.exceptions
|
7
|
-
from
|
7
|
+
from starlette.status import WS_1008_POLICY_VIOLATION
|
8
8
|
from typing_extensions import Self
|
9
9
|
|
10
10
|
from prefect._internal.schemas.bases import IDBaseModel
|
@@ -48,7 +48,7 @@ class Subscription(Generic[S]):
|
|
48
48
|
|
49
49
|
await self._websocket.send(orjson.dumps({"type": "ack"}).decode())
|
50
50
|
|
51
|
-
return self.model.
|
51
|
+
return self.model.model_validate_json(message)
|
52
52
|
except (
|
53
53
|
ConnectionRefusedError,
|
54
54
|
websockets.exceptions.ConnectionClosedError,
|
prefect/client/utilities.py
CHANGED
@@ -42,12 +42,15 @@ def get_or_create_client(
|
|
42
42
|
if client is not None:
|
43
43
|
return client, True
|
44
44
|
from prefect._internal.concurrency.event_loop import get_running_loop
|
45
|
-
from prefect.context import FlowRunContext, TaskRunContext
|
45
|
+
from prefect.context import ClientContext, FlowRunContext, TaskRunContext
|
46
46
|
|
47
|
+
client_context = ClientContext.get()
|
47
48
|
flow_run_context = FlowRunContext.get()
|
48
49
|
task_run_context = TaskRunContext.get()
|
49
50
|
|
50
|
-
if (
|
51
|
+
if client_context and client_context.async_client._loop == get_running_loop():
|
52
|
+
return client_context.async_client, True
|
53
|
+
elif (
|
51
54
|
flow_run_context
|
52
55
|
and getattr(flow_run_context.client, "_loop", None) == get_running_loop()
|
53
56
|
):
|
prefect/concurrency/asyncio.py
CHANGED
@@ -117,4 +117,6 @@ async def _release_concurrency_slots(
|
|
117
117
|
def _response_to_minimal_concurrency_limit_response(
|
118
118
|
response: httpx.Response,
|
119
119
|
) -> List[MinimalConcurrencyLimitResponse]:
|
120
|
-
return [
|
120
|
+
return [
|
121
|
+
MinimalConcurrencyLimitResponse.model_validate(obj_) for obj_ in response.json()
|
122
|
+
]
|
prefect/concurrency/events.py
CHANGED
prefect/concurrency/services.py
CHANGED
@@ -2,23 +2,26 @@ import asyncio
|
|
2
2
|
import concurrent.futures
|
3
3
|
from contextlib import asynccontextmanager
|
4
4
|
from typing import (
|
5
|
+
TYPE_CHECKING,
|
5
6
|
FrozenSet,
|
6
7
|
Tuple,
|
7
8
|
)
|
8
9
|
|
9
10
|
import httpx
|
10
|
-
from
|
11
|
+
from starlette import status
|
11
12
|
|
12
13
|
from prefect import get_client
|
13
14
|
from prefect._internal.concurrency import logger
|
14
15
|
from prefect._internal.concurrency.services import QueueService
|
15
|
-
|
16
|
+
|
17
|
+
if TYPE_CHECKING:
|
18
|
+
from prefect.client.orchestration import PrefectClient
|
16
19
|
|
17
20
|
|
18
21
|
class ConcurrencySlotAcquisitionService(QueueService):
|
19
22
|
def __init__(self, concurrency_limit_names: FrozenSet[str]):
|
20
23
|
super().__init__(concurrency_limit_names)
|
21
|
-
self._client: PrefectClient
|
24
|
+
self._client: "PrefectClient"
|
22
25
|
self.concurrency_limit_names = sorted(list(concurrency_limit_names))
|
23
26
|
|
24
27
|
@asynccontextmanager
|