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.
Files changed (239) hide show
  1. prefect/__init__.py +8 -56
  2. prefect/_internal/compatibility/deprecated.py +6 -115
  3. prefect/_internal/compatibility/experimental.py +4 -79
  4. prefect/_internal/concurrency/api.py +0 -34
  5. prefect/_internal/concurrency/calls.py +0 -6
  6. prefect/_internal/concurrency/cancellation.py +0 -3
  7. prefect/_internal/concurrency/event_loop.py +0 -20
  8. prefect/_internal/concurrency/inspection.py +3 -3
  9. prefect/_internal/concurrency/threads.py +35 -0
  10. prefect/_internal/concurrency/waiters.py +0 -28
  11. prefect/_internal/pydantic/__init__.py +0 -45
  12. prefect/_internal/pydantic/v1_schema.py +21 -22
  13. prefect/_internal/pydantic/v2_schema.py +0 -2
  14. prefect/_internal/pydantic/v2_validated_func.py +18 -23
  15. prefect/_internal/schemas/bases.py +44 -177
  16. prefect/_internal/schemas/fields.py +1 -43
  17. prefect/_internal/schemas/validators.py +60 -158
  18. prefect/artifacts.py +161 -14
  19. prefect/automations.py +39 -4
  20. prefect/blocks/abstract.py +1 -1
  21. prefect/blocks/core.py +268 -148
  22. prefect/blocks/fields.py +2 -57
  23. prefect/blocks/kubernetes.py +8 -12
  24. prefect/blocks/notifications.py +40 -20
  25. prefect/blocks/system.py +22 -11
  26. prefect/blocks/webhook.py +2 -9
  27. prefect/client/base.py +4 -4
  28. prefect/client/cloud.py +8 -13
  29. prefect/client/orchestration.py +347 -341
  30. prefect/client/schemas/actions.py +92 -86
  31. prefect/client/schemas/filters.py +20 -40
  32. prefect/client/schemas/objects.py +151 -145
  33. prefect/client/schemas/responses.py +16 -24
  34. prefect/client/schemas/schedules.py +47 -35
  35. prefect/client/subscriptions.py +2 -2
  36. prefect/client/utilities.py +5 -2
  37. prefect/concurrency/asyncio.py +3 -1
  38. prefect/concurrency/events.py +1 -1
  39. prefect/concurrency/services.py +6 -3
  40. prefect/context.py +195 -27
  41. prefect/deployments/__init__.py +5 -6
  42. prefect/deployments/base.py +7 -5
  43. prefect/deployments/flow_runs.py +185 -0
  44. prefect/deployments/runner.py +50 -45
  45. prefect/deployments/schedules.py +28 -23
  46. prefect/deployments/steps/__init__.py +0 -1
  47. prefect/deployments/steps/core.py +1 -0
  48. prefect/deployments/steps/pull.py +7 -21
  49. prefect/engine.py +12 -2422
  50. prefect/events/actions.py +17 -23
  51. prefect/events/cli/automations.py +19 -6
  52. prefect/events/clients.py +14 -37
  53. prefect/events/filters.py +14 -18
  54. prefect/events/related.py +2 -2
  55. prefect/events/schemas/__init__.py +0 -5
  56. prefect/events/schemas/automations.py +55 -46
  57. prefect/events/schemas/deployment_triggers.py +7 -197
  58. prefect/events/schemas/events.py +34 -65
  59. prefect/events/schemas/labelling.py +10 -14
  60. prefect/events/utilities.py +2 -3
  61. prefect/events/worker.py +2 -3
  62. prefect/filesystems.py +6 -517
  63. prefect/{new_flow_engine.py → flow_engine.py} +313 -72
  64. prefect/flow_runs.py +377 -5
  65. prefect/flows.py +307 -166
  66. prefect/futures.py +186 -345
  67. prefect/infrastructure/__init__.py +0 -27
  68. prefect/infrastructure/provisioners/__init__.py +5 -3
  69. prefect/infrastructure/provisioners/cloud_run.py +11 -6
  70. prefect/infrastructure/provisioners/container_instance.py +11 -7
  71. prefect/infrastructure/provisioners/ecs.py +6 -4
  72. prefect/infrastructure/provisioners/modal.py +8 -5
  73. prefect/input/actions.py +2 -4
  74. prefect/input/run_input.py +5 -7
  75. prefect/logging/formatters.py +0 -2
  76. prefect/logging/handlers.py +3 -11
  77. prefect/logging/loggers.py +2 -2
  78. prefect/manifests.py +2 -1
  79. prefect/records/__init__.py +1 -0
  80. prefect/records/result_store.py +42 -0
  81. prefect/records/store.py +9 -0
  82. prefect/results.py +43 -39
  83. prefect/runner/runner.py +19 -15
  84. prefect/runner/server.py +6 -10
  85. prefect/runner/storage.py +3 -8
  86. prefect/runner/submit.py +2 -2
  87. prefect/runner/utils.py +2 -2
  88. prefect/serializers.py +24 -35
  89. prefect/server/api/collections_data/views/aggregate-worker-metadata.json +5 -14
  90. prefect/settings.py +70 -133
  91. prefect/states.py +17 -47
  92. prefect/task_engine.py +697 -58
  93. prefect/task_runners.py +269 -301
  94. prefect/task_server.py +53 -34
  95. prefect/tasks.py +327 -337
  96. prefect/transactions.py +220 -0
  97. prefect/types/__init__.py +61 -82
  98. prefect/utilities/asyncutils.py +195 -136
  99. prefect/utilities/callables.py +311 -43
  100. prefect/utilities/collections.py +23 -38
  101. prefect/utilities/dispatch.py +11 -3
  102. prefect/utilities/dockerutils.py +4 -0
  103. prefect/utilities/engine.py +140 -20
  104. prefect/utilities/importtools.py +97 -27
  105. prefect/utilities/pydantic.py +128 -38
  106. prefect/utilities/schema_tools/hydration.py +5 -1
  107. prefect/utilities/templating.py +12 -2
  108. prefect/variables.py +78 -61
  109. prefect/workers/__init__.py +0 -1
  110. prefect/workers/base.py +15 -17
  111. prefect/workers/process.py +3 -8
  112. prefect/workers/server.py +2 -2
  113. {prefect_client-2.19.2.dist-info → prefect_client-3.0.0rc1.dist-info}/METADATA +22 -21
  114. prefect_client-3.0.0rc1.dist-info/RECORD +176 -0
  115. prefect/_internal/pydantic/_base_model.py +0 -51
  116. prefect/_internal/pydantic/_compat.py +0 -82
  117. prefect/_internal/pydantic/_flags.py +0 -20
  118. prefect/_internal/pydantic/_types.py +0 -8
  119. prefect/_internal/pydantic/utilities/__init__.py +0 -0
  120. prefect/_internal/pydantic/utilities/config_dict.py +0 -72
  121. prefect/_internal/pydantic/utilities/field_validator.py +0 -150
  122. prefect/_internal/pydantic/utilities/model_construct.py +0 -56
  123. prefect/_internal/pydantic/utilities/model_copy.py +0 -55
  124. prefect/_internal/pydantic/utilities/model_dump.py +0 -136
  125. prefect/_internal/pydantic/utilities/model_dump_json.py +0 -112
  126. prefect/_internal/pydantic/utilities/model_fields.py +0 -50
  127. prefect/_internal/pydantic/utilities/model_fields_set.py +0 -29
  128. prefect/_internal/pydantic/utilities/model_json_schema.py +0 -82
  129. prefect/_internal/pydantic/utilities/model_rebuild.py +0 -80
  130. prefect/_internal/pydantic/utilities/model_validate.py +0 -75
  131. prefect/_internal/pydantic/utilities/model_validate_json.py +0 -68
  132. prefect/_internal/pydantic/utilities/model_validator.py +0 -87
  133. prefect/_internal/pydantic/utilities/type_adapter.py +0 -71
  134. prefect/_vendor/__init__.py +0 -0
  135. prefect/_vendor/fastapi/__init__.py +0 -25
  136. prefect/_vendor/fastapi/applications.py +0 -946
  137. prefect/_vendor/fastapi/background.py +0 -3
  138. prefect/_vendor/fastapi/concurrency.py +0 -44
  139. prefect/_vendor/fastapi/datastructures.py +0 -58
  140. prefect/_vendor/fastapi/dependencies/__init__.py +0 -0
  141. prefect/_vendor/fastapi/dependencies/models.py +0 -64
  142. prefect/_vendor/fastapi/dependencies/utils.py +0 -877
  143. prefect/_vendor/fastapi/encoders.py +0 -177
  144. prefect/_vendor/fastapi/exception_handlers.py +0 -40
  145. prefect/_vendor/fastapi/exceptions.py +0 -46
  146. prefect/_vendor/fastapi/logger.py +0 -3
  147. prefect/_vendor/fastapi/middleware/__init__.py +0 -1
  148. prefect/_vendor/fastapi/middleware/asyncexitstack.py +0 -25
  149. prefect/_vendor/fastapi/middleware/cors.py +0 -3
  150. prefect/_vendor/fastapi/middleware/gzip.py +0 -3
  151. prefect/_vendor/fastapi/middleware/httpsredirect.py +0 -3
  152. prefect/_vendor/fastapi/middleware/trustedhost.py +0 -3
  153. prefect/_vendor/fastapi/middleware/wsgi.py +0 -3
  154. prefect/_vendor/fastapi/openapi/__init__.py +0 -0
  155. prefect/_vendor/fastapi/openapi/constants.py +0 -2
  156. prefect/_vendor/fastapi/openapi/docs.py +0 -203
  157. prefect/_vendor/fastapi/openapi/models.py +0 -480
  158. prefect/_vendor/fastapi/openapi/utils.py +0 -485
  159. prefect/_vendor/fastapi/param_functions.py +0 -340
  160. prefect/_vendor/fastapi/params.py +0 -453
  161. prefect/_vendor/fastapi/requests.py +0 -4
  162. prefect/_vendor/fastapi/responses.py +0 -40
  163. prefect/_vendor/fastapi/routing.py +0 -1331
  164. prefect/_vendor/fastapi/security/__init__.py +0 -15
  165. prefect/_vendor/fastapi/security/api_key.py +0 -98
  166. prefect/_vendor/fastapi/security/base.py +0 -6
  167. prefect/_vendor/fastapi/security/http.py +0 -172
  168. prefect/_vendor/fastapi/security/oauth2.py +0 -227
  169. prefect/_vendor/fastapi/security/open_id_connect_url.py +0 -34
  170. prefect/_vendor/fastapi/security/utils.py +0 -10
  171. prefect/_vendor/fastapi/staticfiles.py +0 -1
  172. prefect/_vendor/fastapi/templating.py +0 -3
  173. prefect/_vendor/fastapi/testclient.py +0 -1
  174. prefect/_vendor/fastapi/types.py +0 -3
  175. prefect/_vendor/fastapi/utils.py +0 -235
  176. prefect/_vendor/fastapi/websockets.py +0 -7
  177. prefect/_vendor/starlette/__init__.py +0 -1
  178. prefect/_vendor/starlette/_compat.py +0 -28
  179. prefect/_vendor/starlette/_exception_handler.py +0 -80
  180. prefect/_vendor/starlette/_utils.py +0 -88
  181. prefect/_vendor/starlette/applications.py +0 -261
  182. prefect/_vendor/starlette/authentication.py +0 -159
  183. prefect/_vendor/starlette/background.py +0 -43
  184. prefect/_vendor/starlette/concurrency.py +0 -59
  185. prefect/_vendor/starlette/config.py +0 -151
  186. prefect/_vendor/starlette/convertors.py +0 -87
  187. prefect/_vendor/starlette/datastructures.py +0 -707
  188. prefect/_vendor/starlette/endpoints.py +0 -130
  189. prefect/_vendor/starlette/exceptions.py +0 -60
  190. prefect/_vendor/starlette/formparsers.py +0 -276
  191. prefect/_vendor/starlette/middleware/__init__.py +0 -17
  192. prefect/_vendor/starlette/middleware/authentication.py +0 -52
  193. prefect/_vendor/starlette/middleware/base.py +0 -220
  194. prefect/_vendor/starlette/middleware/cors.py +0 -176
  195. prefect/_vendor/starlette/middleware/errors.py +0 -265
  196. prefect/_vendor/starlette/middleware/exceptions.py +0 -74
  197. prefect/_vendor/starlette/middleware/gzip.py +0 -113
  198. prefect/_vendor/starlette/middleware/httpsredirect.py +0 -19
  199. prefect/_vendor/starlette/middleware/sessions.py +0 -82
  200. prefect/_vendor/starlette/middleware/trustedhost.py +0 -64
  201. prefect/_vendor/starlette/middleware/wsgi.py +0 -147
  202. prefect/_vendor/starlette/requests.py +0 -328
  203. prefect/_vendor/starlette/responses.py +0 -347
  204. prefect/_vendor/starlette/routing.py +0 -933
  205. prefect/_vendor/starlette/schemas.py +0 -154
  206. prefect/_vendor/starlette/staticfiles.py +0 -248
  207. prefect/_vendor/starlette/status.py +0 -199
  208. prefect/_vendor/starlette/templating.py +0 -231
  209. prefect/_vendor/starlette/testclient.py +0 -804
  210. prefect/_vendor/starlette/types.py +0 -30
  211. prefect/_vendor/starlette/websockets.py +0 -193
  212. prefect/agent.py +0 -698
  213. prefect/deployments/deployments.py +0 -1042
  214. prefect/deprecated/__init__.py +0 -0
  215. prefect/deprecated/data_documents.py +0 -350
  216. prefect/deprecated/packaging/__init__.py +0 -12
  217. prefect/deprecated/packaging/base.py +0 -96
  218. prefect/deprecated/packaging/docker.py +0 -146
  219. prefect/deprecated/packaging/file.py +0 -92
  220. prefect/deprecated/packaging/orion.py +0 -80
  221. prefect/deprecated/packaging/serializers.py +0 -171
  222. prefect/events/instrument.py +0 -135
  223. prefect/infrastructure/base.py +0 -323
  224. prefect/infrastructure/container.py +0 -818
  225. prefect/infrastructure/kubernetes.py +0 -920
  226. prefect/infrastructure/process.py +0 -289
  227. prefect/new_task_engine.py +0 -423
  228. prefect/pydantic/__init__.py +0 -76
  229. prefect/pydantic/main.py +0 -39
  230. prefect/software/__init__.py +0 -2
  231. prefect/software/base.py +0 -50
  232. prefect/software/conda.py +0 -199
  233. prefect/software/pip.py +0 -122
  234. prefect/software/python.py +0 -52
  235. prefect/workers/block.py +0 -218
  236. prefect_client-2.19.2.dist-info/RECORD +0 -292
  237. {prefect_client-2.19.2.dist-info → prefect_client-3.0.0rc1.dist-info}/LICENSE +0 -0
  238. {prefect_client-2.19.2.dist-info → prefect_client-3.0.0rc1.dist-info}/WHEEL +0 -0
  239. {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 prefect._internal.compatibility.deprecated import DeprecatedInfraOverridesField
6
- from prefect._internal.pydantic import HAS_PYDANTIC_V2
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, DateTimeTZ, UpdatedBy
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: DateTimeTZ = Field(
117
+ interval_start: DateTime = Field(
124
118
  default=..., description="The start date of the interval."
125
119
  )
126
- interval_end: DateTimeTZ = Field(
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
- class Config:
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[DateTimeTZ] = Field(
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[DateTimeTZ] = Field(
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[DateTimeTZ] = Field(
223
+ start_time: Optional[DateTime] = Field(
231
224
  default=None, description="The actual start time."
232
225
  )
233
- end_time: Optional[DateTimeTZ] = Field(
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.dict(exclude=exclude_fields) == other.dict(
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(DeprecatedInfraOverridesField, ObjectBaseModel):
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[DateTimeTZ] = Field(
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=False,
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
- class Config:
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 (DateTimeTZ, optional): an anchor date to schedule increments against;
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
- class Config:
64
- extra = "forbid"
65
- exclude_none = True
56
+ model_config = ConfigDict(extra="forbid", exclude_none=True)
66
57
 
67
- interval: PositiveDuration
68
- anchor_date: Optional[DateTimeTZ] = None
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
- @validator("anchor_date", always=True)
72
- def validate_anchor_date(cls, v):
73
- return default_anchor_date(v)
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
- class Config:
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
- @validator("timezone")
107
+ @field_validator("timezone")
108
+ @classmethod
118
109
  def valid_timezone(cls, v):
119
110
  return default_timezone(v)
120
111
 
121
- @validator("cron")
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
- class Config:
150
- extra = "forbid"
141
+ model_config = ConfigDict(extra="forbid")
151
142
 
152
143
  rrule: str
153
- timezone: Optional[str] = Field(default=None, examples=["America/New_York"])
144
+ timezone: Optional[str] = Field(
145
+ default="UTC", examples=["America/New_York"], validate_default=True
146
+ )
154
147
 
155
- @validator("rrule")
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
- @validator("timezone", always=True)
256
+ @field_validator("timezone")
263
257
  def valid_timezone(cls, v):
264
- return validate_rrule_timezone(v)
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
- class Config:
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
  )
@@ -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 prefect._vendor.starlette.status import WS_1008_POLICY_VIOLATION
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.parse_raw(message)
51
+ return self.model.model_validate_json(message)
52
52
  except (
53
53
  ConnectionRefusedError,
54
54
  websockets.exceptions.ConnectionClosedError,
@@ -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
  ):
@@ -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 [MinimalConcurrencyLimitResponse.parse_obj(obj_) for obj_ in response.json()]
120
+ return [
121
+ MinimalConcurrencyLimitResponse.model_validate(obj_) for obj_ in response.json()
122
+ ]
@@ -20,7 +20,7 @@ def _emit_concurrency_event(
20
20
  }
21
21
 
22
22
  related = [
23
- RelatedResource.parse_obj(
23
+ RelatedResource.model_validate(
24
24
  {
25
25
  "prefect.resource.id": f"prefect.concurrency-limit.{limit.id}",
26
26
  "prefect.resource.role": "concurrency-limit",
@@ -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 prefect._vendor.starlette import status
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
- from prefect.client.orchestration import PrefectClient
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