prefect-client 2.17.1__py3-none-any.whl → 2.18.1__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 (71) hide show
  1. prefect/_internal/compatibility/deprecated.py +2 -0
  2. prefect/_internal/pydantic/_compat.py +1 -0
  3. prefect/_internal/pydantic/utilities/field_validator.py +25 -10
  4. prefect/_internal/pydantic/utilities/model_dump.py +1 -1
  5. prefect/_internal/pydantic/utilities/model_validate.py +1 -1
  6. prefect/_internal/pydantic/utilities/model_validator.py +11 -3
  7. prefect/_internal/schemas/fields.py +31 -12
  8. prefect/_internal/schemas/validators.py +0 -6
  9. prefect/_version.py +97 -38
  10. prefect/blocks/abstract.py +34 -1
  11. prefect/blocks/core.py +1 -1
  12. prefect/blocks/notifications.py +16 -7
  13. prefect/blocks/system.py +2 -3
  14. prefect/client/base.py +10 -5
  15. prefect/client/orchestration.py +405 -85
  16. prefect/client/schemas/actions.py +4 -3
  17. prefect/client/schemas/objects.py +6 -5
  18. prefect/client/schemas/schedules.py +2 -6
  19. prefect/client/schemas/sorting.py +9 -0
  20. prefect/client/utilities.py +25 -3
  21. prefect/concurrency/asyncio.py +11 -5
  22. prefect/concurrency/events.py +3 -3
  23. prefect/concurrency/services.py +1 -1
  24. prefect/concurrency/sync.py +9 -5
  25. prefect/deployments/__init__.py +0 -2
  26. prefect/deployments/base.py +2 -144
  27. prefect/deployments/deployments.py +29 -20
  28. prefect/deployments/runner.py +36 -28
  29. prefect/deployments/steps/core.py +3 -3
  30. prefect/deprecated/packaging/serializers.py +5 -4
  31. prefect/engine.py +3 -1
  32. prefect/events/__init__.py +45 -0
  33. prefect/events/actions.py +250 -18
  34. prefect/events/cli/automations.py +201 -0
  35. prefect/events/clients.py +179 -21
  36. prefect/events/filters.py +30 -3
  37. prefect/events/instrument.py +40 -40
  38. prefect/events/related.py +2 -1
  39. prefect/events/schemas/automations.py +126 -8
  40. prefect/events/schemas/deployment_triggers.py +23 -277
  41. prefect/events/schemas/events.py +7 -7
  42. prefect/events/utilities.py +3 -1
  43. prefect/events/worker.py +21 -8
  44. prefect/exceptions.py +1 -1
  45. prefect/flows.py +33 -18
  46. prefect/input/actions.py +9 -9
  47. prefect/input/run_input.py +49 -37
  48. prefect/logging/__init__.py +2 -2
  49. prefect/logging/loggers.py +64 -1
  50. prefect/new_flow_engine.py +293 -0
  51. prefect/new_task_engine.py +374 -0
  52. prefect/results.py +32 -12
  53. prefect/runner/runner.py +3 -2
  54. prefect/serializers.py +62 -31
  55. prefect/server/api/collections_data/views/aggregate-worker-metadata.json +44 -3
  56. prefect/settings.py +32 -10
  57. prefect/states.py +25 -19
  58. prefect/tasks.py +17 -0
  59. prefect/types/__init__.py +90 -0
  60. prefect/utilities/asyncutils.py +37 -0
  61. prefect/utilities/engine.py +6 -4
  62. prefect/utilities/pydantic.py +34 -15
  63. prefect/utilities/schema_tools/hydration.py +88 -19
  64. prefect/utilities/schema_tools/validation.py +1 -1
  65. prefect/variables.py +4 -4
  66. {prefect_client-2.17.1.dist-info → prefect_client-2.18.1.dist-info}/METADATA +1 -1
  67. {prefect_client-2.17.1.dist-info → prefect_client-2.18.1.dist-info}/RECORD +71 -67
  68. /prefect/{concurrency/common.py → events/cli/__init__.py} +0 -0
  69. {prefect_client-2.17.1.dist-info → prefect_client-2.18.1.dist-info}/LICENSE +0 -0
  70. {prefect_client-2.17.1.dist-info → prefect_client-2.18.1.dist-info}/WHEEL +0 -0
  71. {prefect_client-2.17.1.dist-info → prefect_client-2.18.1.dist-info}/top_level.txt +0 -0
prefect/blocks/system.py CHANGED
@@ -1,7 +1,5 @@
1
1
  from typing import Any
2
2
 
3
- import pendulum
4
-
5
3
  from prefect._internal.pydantic import HAS_PYDANTIC_V2
6
4
 
7
5
  if HAS_PYDANTIC_V2:
@@ -9,6 +7,7 @@ if HAS_PYDANTIC_V2:
9
7
  else:
10
8
  from pydantic import Field, SecretStr
11
9
 
10
+ from prefect._internal.schemas.fields import DateTimeTZ
12
11
  from prefect.blocks.core import Block
13
12
 
14
13
 
@@ -76,7 +75,7 @@ class DateTime(Block):
76
75
  _logo_url = "https://cdn.sanity.io/images/3ugk85nk/production/8b3da9a6621e92108b8e6a75b82e15374e170ff7-48x48.png"
77
76
  _documentation_url = "https://docs.prefect.io/api-ref/prefect/blocks/system/#prefect.blocks.system.DateTime"
78
77
 
79
- value: pendulum.DateTime = Field(
78
+ value: DateTimeTZ = Field(
80
79
  default=...,
81
80
  description="An ISO 8601-compatible datetime value.",
82
81
  )
prefect/client/base.py CHANGED
@@ -193,11 +193,18 @@ class PrefectHttpxClient(httpx.AsyncClient):
193
193
  [Configuring Cloudflare Rate Limiting](https://support.cloudflare.com/hc/en-us/articles/115001635128-Configuring-Rate-Limiting-from-UI)
194
194
  """
195
195
 
196
- def __init__(self, *args, enable_csrf_support: bool = False, **kwargs):
196
+ def __init__(
197
+ self,
198
+ *args,
199
+ enable_csrf_support: bool = False,
200
+ raise_on_all_errors: bool = True,
201
+ **kwargs,
202
+ ):
197
203
  self.enable_csrf_support: bool = enable_csrf_support
198
204
  self.csrf_token: Optional[str] = None
199
205
  self.csrf_token_expiration: Optional[datetime] = None
200
206
  self.csrf_client_id: uuid.UUID = uuid.uuid4()
207
+ self.raise_on_all_errors: bool = raise_on_all_errors
201
208
 
202
209
  super().__init__(*args, **kwargs)
203
210
 
@@ -345,10 +352,8 @@ class PrefectHttpxClient(httpx.AsyncClient):
345
352
  # Convert to a Prefect response to add nicer errors messages
346
353
  response = PrefectResponse.from_httpx_response(response)
347
354
 
348
- # Always raise bad responses
349
- # NOTE: We may want to remove this and handle responses per route in the
350
- # `PrefectClient`
351
- response.raise_for_status()
355
+ if self.raise_on_all_errors:
356
+ response.raise_for_status()
352
357
 
353
358
  return response
354
359
 
@@ -8,9 +8,11 @@ from typing import (
8
8
  Dict,
9
9
  Iterable,
10
10
  List,
11
+ NoReturn,
11
12
  Optional,
12
13
  Set,
13
14
  Tuple,
15
+ TypeVar,
14
16
  Union,
15
17
  )
16
18
  from uuid import UUID, uuid4
@@ -19,20 +21,19 @@ import certifi
19
21
  import httpcore
20
22
  import httpx
21
23
  import pendulum
24
+ from typing_extensions import ParamSpec
22
25
 
23
26
  from prefect._internal.compatibility.deprecated import (
24
27
  handle_deprecated_infra_overrides_parameter,
25
28
  )
26
- from prefect._internal.compatibility.experimental import (
27
- EXPERIMENTAL_WARNING,
28
- ExperimentalFeature,
29
- experiment_enabled,
30
- )
31
29
  from prefect._internal.pydantic import HAS_PYDANTIC_V2
30
+ from prefect.client.schemas import sorting
31
+ from prefect.events import filters
32
32
  from prefect.settings import (
33
- PREFECT_EXPERIMENTAL_WARN,
34
- PREFECT_EXPERIMENTAL_WARN_FLOW_RUN_INFRA_OVERRIDES,
33
+ PREFECT_API_SERVICES_TRIGGERS_ENABLED,
34
+ PREFECT_EXPERIMENTAL_EVENTS,
35
35
  )
36
+ from prefect.utilities.asyncutils import run_sync
36
37
 
37
38
  if HAS_PYDANTIC_V2:
38
39
  import pydantic.v1 as pydantic
@@ -133,7 +134,7 @@ from prefect.client.schemas.sorting import (
133
134
  TaskRunSort,
134
135
  )
135
136
  from prefect.deprecated.data_documents import DataDocument
136
- from prefect.events.schemas.automations import Automation, ExistingAutomation
137
+ from prefect.events.schemas.automations import Automation, AutomationCore
137
138
  from prefect.logging import get_logger
138
139
  from prefect.settings import (
139
140
  PREFECT_API_DATABASE_CONNECTION_URL,
@@ -155,14 +156,25 @@ if TYPE_CHECKING:
155
156
 
156
157
  from prefect.client.base import ASGIApp, PrefectHttpxClient, app_lifespan_context
157
158
 
159
+ P = ParamSpec("P")
160
+ R = TypeVar("R")
161
+
158
162
 
159
163
  class ServerType(AutoEnum):
160
164
  EPHEMERAL = AutoEnum.auto()
161
165
  SERVER = AutoEnum.auto()
162
166
  CLOUD = AutoEnum.auto()
163
167
 
168
+ def supports_automations(self) -> bool:
169
+ if self == ServerType.CLOUD:
170
+ return True
171
+
172
+ return PREFECT_EXPERIMENTAL_EVENTS and PREFECT_API_SERVICES_TRIGGERS_ENABLED
173
+
164
174
 
165
- def get_client(httpx_settings: Optional[dict] = None) -> "PrefectClient":
175
+ def get_client(
176
+ httpx_settings: Optional[Dict[str, Any]] = None, sync_client: bool = False
177
+ ) -> "PrefectClient":
166
178
  """
167
179
  Retrieve a HTTP client for communicating with the Prefect REST API.
168
180
 
@@ -172,6 +184,13 @@ def get_client(httpx_settings: Optional[dict] = None) -> "PrefectClient":
172
184
  async with get_client() as client:
173
185
  await client.hello()
174
186
  ```
187
+
188
+ To return a synchronous client, pass sync_client=True:
189
+
190
+ ```python
191
+ with get_client(sync_client=True) as client:
192
+ client.hello()
193
+ ```
175
194
  """
176
195
  ctx = prefect.context.get_settings_context()
177
196
  api = PREFECT_API_URL.value()
@@ -182,11 +201,18 @@ def get_client(httpx_settings: Optional[dict] = None) -> "PrefectClient":
182
201
 
183
202
  api = create_app(ctx.settings, ephemeral=True)
184
203
 
185
- return PrefectClient(
186
- api,
187
- api_key=PREFECT_API_KEY.value(),
188
- httpx_settings=httpx_settings,
189
- )
204
+ if sync_client:
205
+ return SyncPrefectClient(
206
+ api,
207
+ api_key=PREFECT_API_KEY.value(),
208
+ httpx_settings=httpx_settings,
209
+ )
210
+ else:
211
+ return PrefectClient(
212
+ api,
213
+ api_key=PREFECT_API_KEY.value(),
214
+ httpx_settings=httpx_settings,
215
+ )
190
216
 
191
217
 
192
218
  class PrefectClient:
@@ -568,21 +594,6 @@ class PrefectClient:
568
594
  Returns:
569
595
  The flow run model
570
596
  """
571
- if job_variables is not None and experiment_enabled("flow_run_infra_overrides"):
572
- if (
573
- PREFECT_EXPERIMENTAL_WARN
574
- and PREFECT_EXPERIMENTAL_WARN_FLOW_RUN_INFRA_OVERRIDES
575
- ):
576
- warnings.warn(
577
- EXPERIMENTAL_WARNING.format(
578
- feature="Flow run job variables",
579
- group="flow_run_infra_overrides",
580
- help="To use this feature, update your workers to Prefect 2.16.4 or later. ",
581
- ),
582
- ExperimentalFeature,
583
- stacklevel=3,
584
- )
585
-
586
597
  parameters = parameters or {}
587
598
  context = context or {}
588
599
  state = state or prefect.states.Scheduled()
@@ -703,21 +714,6 @@ class PrefectClient:
703
714
  Returns:
704
715
  an `httpx.Response` object from the PATCH request
705
716
  """
706
- if job_variables is not None and experiment_enabled("flow_run_infra_overrides"):
707
- if (
708
- PREFECT_EXPERIMENTAL_WARN
709
- and PREFECT_EXPERIMENTAL_WARN_FLOW_RUN_INFRA_OVERRIDES
710
- ):
711
- warnings.warn(
712
- EXPERIMENTAL_WARNING.format(
713
- feature="Flow run job variables",
714
- group="flow_run_infra_overrides",
715
- help="To use this feature, update your workers to Prefect 2.16.4 or later. ",
716
- ),
717
- ExperimentalFeature,
718
- stacklevel=3,
719
- )
720
-
721
717
  params = {}
722
718
  if flow_version is not None:
723
719
  params["flow_version"] = flow_version
@@ -2164,21 +2160,23 @@ class PrefectClient:
2164
2160
 
2165
2161
  async def create_task_run(
2166
2162
  self,
2167
- task: "TaskObject",
2163
+ task: "TaskObject[P, R]",
2168
2164
  flow_run_id: Optional[UUID],
2169
2165
  dynamic_key: str,
2170
- name: str = None,
2171
- extra_tags: Iterable[str] = None,
2172
- state: prefect.states.State = None,
2173
- task_inputs: Dict[
2174
- str,
2175
- List[
2176
- Union[
2177
- TaskRunResult,
2178
- Parameter,
2179
- Constant,
2180
- ]
2181
- ],
2166
+ name: Optional[str] = None,
2167
+ extra_tags: Optional[Iterable[str]] = None,
2168
+ state: Optional[prefect.states.State[R]] = None,
2169
+ task_inputs: Optional[
2170
+ Dict[
2171
+ str,
2172
+ List[
2173
+ Union[
2174
+ TaskRunResult,
2175
+ Parameter,
2176
+ Constant,
2177
+ ]
2178
+ ],
2179
+ ]
2182
2180
  ] = None,
2183
2181
  ) -> TaskRun:
2184
2182
  """
@@ -2998,34 +2996,6 @@ class PrefectClient:
2998
2996
  response.raise_for_status()
2999
2997
  return response.json()
3000
2998
 
3001
- async def create_automation(self, automation: Automation) -> UUID:
3002
- """Creates an automation in Prefect Cloud."""
3003
- if self.server_type != ServerType.CLOUD:
3004
- raise RuntimeError("Automations are only supported for Prefect Cloud.")
3005
-
3006
- response = await self._client.post(
3007
- "/automations/",
3008
- json=automation.dict(json_compatible=True),
3009
- )
3010
-
3011
- return UUID(response.json()["id"])
3012
-
3013
- async def read_resource_related_automations(
3014
- self, resource_id: str
3015
- ) -> List[ExistingAutomation]:
3016
- if self.server_type != ServerType.CLOUD:
3017
- raise RuntimeError("Automations are only supported for Prefect Cloud.")
3018
-
3019
- response = await self._client.get(f"/automations/related-to/{resource_id}")
3020
- response.raise_for_status()
3021
- return pydantic.parse_obj_as(List[ExistingAutomation], response.json())
3022
-
3023
- async def delete_resource_owned_automations(self, resource_id: str):
3024
- if self.server_type != ServerType.CLOUD:
3025
- raise RuntimeError("Automations are only supported for Prefect Cloud.")
3026
-
3027
- await self._client.delete(f"/automations/owned-by/{resource_id}")
3028
-
3029
2999
  async def increment_concurrency_slots(
3030
3000
  self, names: List[str], slots: int, mode: str
3031
3001
  ) -> httpx.Response:
@@ -3165,6 +3135,147 @@ class PrefectClient:
3165
3135
  response = await self._client.delete(f"/flow_runs/{flow_run_id}/input/{key}")
3166
3136
  response.raise_for_status()
3167
3137
 
3138
+ def _raise_for_unsupported_automations(self) -> NoReturn:
3139
+ if not PREFECT_EXPERIMENTAL_EVENTS:
3140
+ raise RuntimeError(
3141
+ "The current server and client configuration does not support "
3142
+ "events. Enable experimental events support with the "
3143
+ "PREFECT_EXPERIMENTAL_EVENTS setting."
3144
+ )
3145
+ else:
3146
+ raise RuntimeError(
3147
+ "The current server and client configuration does not support "
3148
+ "automations. Enable experimental automations with the "
3149
+ "PREFECT_API_SERVICES_TRIGGERS_ENABLED setting."
3150
+ )
3151
+
3152
+ async def create_automation(self, automation: AutomationCore) -> UUID:
3153
+ """Creates an automation in Prefect Cloud."""
3154
+ if not self.server_type.supports_automations():
3155
+ self._raise_for_unsupported_automations()
3156
+
3157
+ response = await self._client.post(
3158
+ "/automations/",
3159
+ json=automation.dict(json_compatible=True),
3160
+ )
3161
+
3162
+ return UUID(response.json()["id"])
3163
+
3164
+ async def read_automations(self) -> List[Automation]:
3165
+ if not self.server_type.supports_automations():
3166
+ self._raise_for_unsupported_automations()
3167
+
3168
+ response = await self._client.post("/automations/filter")
3169
+ response.raise_for_status()
3170
+ return pydantic.parse_obj_as(List[Automation], response.json())
3171
+
3172
+ async def find_automation(self, id_or_name: str) -> Optional[Automation]:
3173
+ try:
3174
+ id = UUID(id_or_name)
3175
+ except ValueError:
3176
+ id = None
3177
+
3178
+ if id:
3179
+ automation = await self.read_automation(id)
3180
+ if automation:
3181
+ return automation
3182
+
3183
+ automations = await self.read_automations()
3184
+
3185
+ # Look for it by an exact name
3186
+ for automation in automations:
3187
+ if automation.name == id_or_name:
3188
+ return automation
3189
+
3190
+ # Look for it by a case-insensitive name
3191
+ for automation in automations:
3192
+ if automation.name.lower() == id_or_name.lower():
3193
+ return automation
3194
+
3195
+ return None
3196
+
3197
+ async def read_automation(self, automation_id: UUID) -> Optional[Automation]:
3198
+ if not self.server_type.supports_automations():
3199
+ self._raise_for_unsupported_automations()
3200
+
3201
+ response = await self._client.get(f"/automations/{automation_id}")
3202
+ if response.status_code == 404:
3203
+ return None
3204
+ response.raise_for_status()
3205
+ return Automation.parse_obj(response.json())
3206
+
3207
+ async def read_automations_by_name(self, name: str) -> List[Automation]:
3208
+ """
3209
+ Query the Prefect API for an automation by name. Only automations matching the provided name will be returned.
3210
+
3211
+ Args:
3212
+ name: the name of the automation to query
3213
+
3214
+ Returns:
3215
+ a list of Automation model representations of the automations
3216
+ """
3217
+ if not self.server_type.supports_automations():
3218
+ self._raise_for_unsupported_automations()
3219
+ automation_filter = filters.AutomationFilter(name=dict(any_=[name]))
3220
+
3221
+ response = await self._client.post(
3222
+ "/automations/filter",
3223
+ json={
3224
+ "sort": sorting.AutomationSort.UPDATED_DESC,
3225
+ "automations": automation_filter.dict(json_compatible=True)
3226
+ if automation_filter
3227
+ else None,
3228
+ },
3229
+ )
3230
+
3231
+ response.raise_for_status()
3232
+
3233
+ return pydantic.parse_obj_as(List[Automation], response.json())
3234
+
3235
+ async def pause_automation(self, automation_id: UUID):
3236
+ if not self.server_type.supports_automations():
3237
+ self._raise_for_unsupported_automations()
3238
+
3239
+ response = await self._client.patch(
3240
+ f"/automations/{automation_id}", json={"enabled": False}
3241
+ )
3242
+ response.raise_for_status()
3243
+
3244
+ async def resume_automation(self, automation_id: UUID):
3245
+ if not self.server_type.supports_automations():
3246
+ self._raise_for_unsupported_automations()
3247
+
3248
+ response = await self._client.patch(
3249
+ f"/automations/{automation_id}", json={"enabled": True}
3250
+ )
3251
+ response.raise_for_status()
3252
+
3253
+ async def delete_automation(self, automation_id: UUID):
3254
+ if not self.server_type.supports_automations():
3255
+ self._raise_for_unsupported_automations()
3256
+
3257
+ response = await self._client.delete(f"/automations/{automation_id}")
3258
+ if response.status_code == 404:
3259
+ return
3260
+
3261
+ response.raise_for_status()
3262
+
3263
+ async def read_resource_related_automations(
3264
+ self, resource_id: str
3265
+ ) -> List[Automation]:
3266
+ if not self.server_type.supports_automations():
3267
+ self._raise_for_unsupported_automations()
3268
+
3269
+ response = await self._client.get(f"/automations/related-to/{resource_id}")
3270
+ response.raise_for_status()
3271
+ return pydantic.parse_obj_as(List[Automation], response.json())
3272
+
3273
+ async def delete_resource_owned_automations(self, resource_id: str):
3274
+ if not self.server_type.supports_automations():
3275
+ self._raise_for_unsupported_automations()
3276
+
3277
+ await self._client.delete(f"/automations/owned-by/{resource_id}")
3278
+
3168
3279
  async def __aenter__(self):
3169
3280
  """
3170
3281
  Start the client.
@@ -3225,3 +3336,212 @@ class PrefectClient:
3225
3336
 
3226
3337
  def __exit__(self, *_):
3227
3338
  assert False, "This should never be called but must be defined for __enter__"
3339
+
3340
+
3341
+ class SyncPrefectClient:
3342
+ """
3343
+ A synchronous client for interacting with the [Prefect REST API](/api-ref/rest-api/).
3344
+
3345
+ Args:
3346
+ api: the REST API URL or FastAPI application to connect to
3347
+ api_key: An optional API key for authentication.
3348
+ api_version: The API version this client is compatible with.
3349
+ httpx_settings: An optional dictionary of settings to pass to the underlying
3350
+ `httpx.AsyncClient`
3351
+
3352
+ Examples:
3353
+
3354
+ Say hello to a Prefect REST API
3355
+
3356
+ <div class="terminal">
3357
+ ```
3358
+ >>> with get_client(sync_client=True) as client:
3359
+ >>> response = client.hello()
3360
+ >>>
3361
+ >>> print(response.json())
3362
+ 👋
3363
+ ```
3364
+ </div>
3365
+ """
3366
+
3367
+ def __init__(
3368
+ self,
3369
+ api: Union[str, ASGIApp],
3370
+ *,
3371
+ api_key: Optional[str] = None,
3372
+ api_version: Optional[str] = None,
3373
+ httpx_settings: Optional[Dict[str, Any]] = None,
3374
+ ) -> None:
3375
+ self._prefect_client = PrefectClient(
3376
+ api=api,
3377
+ api_key=api_key,
3378
+ api_version=api_version,
3379
+ httpx_settings=httpx_settings,
3380
+ )
3381
+
3382
+ def __enter__(self):
3383
+ run_sync(self._prefect_client.__aenter__())
3384
+ return self
3385
+
3386
+ def __exit__(self, *exc_info):
3387
+ return run_sync(self._prefect_client.__aexit__(*exc_info))
3388
+
3389
+ async def __aenter__(self):
3390
+ raise RuntimeError(
3391
+ "The `SyncPrefectClient` must be entered with a sync context. Use '"
3392
+ "with SyncPrefectClient(...)' not 'async with SyncPrefectClient(...)'"
3393
+ )
3394
+
3395
+ async def __aexit__(self, *_):
3396
+ assert False, "This should never be called but must be defined for __aenter__"
3397
+
3398
+ def hello(self) -> httpx.Response:
3399
+ """
3400
+ Send a GET request to /hello for testing purposes.
3401
+ """
3402
+ return run_sync(self._prefect_client.hello())
3403
+
3404
+ def create_task_run(
3405
+ self,
3406
+ task: "TaskObject[P, R]",
3407
+ flow_run_id: Optional[UUID],
3408
+ dynamic_key: str,
3409
+ name: Optional[str] = None,
3410
+ extra_tags: Optional[Iterable[str]] = None,
3411
+ state: Optional[prefect.states.State[R]] = None,
3412
+ task_inputs: Optional[
3413
+ Dict[
3414
+ str,
3415
+ List[
3416
+ Union[
3417
+ TaskRunResult,
3418
+ Parameter,
3419
+ Constant,
3420
+ ]
3421
+ ],
3422
+ ]
3423
+ ] = None,
3424
+ ) -> TaskRun:
3425
+ """
3426
+ Create a task run
3427
+
3428
+ Args:
3429
+ task: The Task to run
3430
+ flow_run_id: The flow run id with which to associate the task run
3431
+ dynamic_key: A key unique to this particular run of a Task within the flow
3432
+ name: An optional name for the task run
3433
+ extra_tags: an optional list of extra tags to apply to the task run in
3434
+ addition to `task.tags`
3435
+ state: The initial state for the run. If not provided, defaults to
3436
+ `Pending` for now. Should always be a `Scheduled` type.
3437
+ task_inputs: the set of inputs passed to the task
3438
+
3439
+ Returns:
3440
+ The created task run.
3441
+ """
3442
+ return run_sync(
3443
+ self._prefect_client.create_task_run(
3444
+ task=task,
3445
+ flow_run_id=flow_run_id,
3446
+ dynamic_key=dynamic_key,
3447
+ name=name,
3448
+ extra_tags=extra_tags,
3449
+ state=state,
3450
+ task_inputs=task_inputs,
3451
+ )
3452
+ )
3453
+
3454
+ def set_task_run_state(
3455
+ self,
3456
+ task_run_id: UUID,
3457
+ state: prefect.states.State,
3458
+ force: bool = False,
3459
+ ) -> OrchestrationResult:
3460
+ """
3461
+ Set the state of a task run.
3462
+
3463
+ Args:
3464
+ task_run_id: the id of the task run
3465
+ state: the state to set
3466
+ force: if True, disregard orchestration logic when setting the state,
3467
+ forcing the Prefect API to accept the state
3468
+
3469
+ Returns:
3470
+ an OrchestrationResult model representation of state orchestration output
3471
+ """
3472
+ return run_sync(
3473
+ self._prefect_client.set_task_run_state(
3474
+ task_run_id=task_run_id,
3475
+ state=state,
3476
+ force=force,
3477
+ )
3478
+ )
3479
+
3480
+ def create_flow_run(
3481
+ self,
3482
+ flow_id: UUID,
3483
+ parameters: Optional[Dict[str, Any]] = None,
3484
+ context: Optional[Dict[str, Any]] = None,
3485
+ scheduled_start_time: Optional[datetime.datetime] = None,
3486
+ run_name: Optional[str] = None,
3487
+ labels: Optional[List[str]] = None,
3488
+ parameters_json: Optional[str] = None,
3489
+ run_config: Optional[Dict[str, Any]] = None,
3490
+ idempotency_key: Optional[str] = None,
3491
+ ) -> FlowRunResponse:
3492
+ """
3493
+ Create a new flow run.
3494
+
3495
+ Args:
3496
+ - flow_id (UUID): the ID of the flow to create a run for
3497
+ - parameters (Optional[Dict[str, Any]]): a dictionary of parameter values to pass to the flow
3498
+ - context (Optional[Dict[str, Any]]): a dictionary of context values to pass to the flow
3499
+ - scheduled_start_time (Optional[datetime.datetime]): the scheduled start time for the flow run
3500
+ - run_name (Optional[str]): a name to assign to the flow run
3501
+ - labels (Optional[List[str]]): a list of labels to assign to the flow run
3502
+ - parameters_json (Optional[str]): a JSON string of parameter values to pass to the flow
3503
+ - run_config (Optional[Dict[str, Any]]): a dictionary of run configuration options
3504
+ - idempotency_key (Optional[str]): a key to ensure idempotency when creating the flow run
3505
+
3506
+ Returns:
3507
+ - FlowRunResponse: the created flow run
3508
+ """
3509
+ return run_sync(
3510
+ self._prefect_client.create_flow_run(
3511
+ flow_id=flow_id,
3512
+ parameters=parameters,
3513
+ context=context,
3514
+ scheduled_start_time=scheduled_start_time,
3515
+ run_name=run_name,
3516
+ labels=labels,
3517
+ parameters_json=parameters_json,
3518
+ run_config=run_config,
3519
+ idempotency_key=idempotency_key,
3520
+ )
3521
+ )
3522
+
3523
+ async def set_flow_run_state(
3524
+ self,
3525
+ flow_run_id: UUID,
3526
+ state: "prefect.states.State",
3527
+ force: bool = False,
3528
+ ) -> OrchestrationResult:
3529
+ """
3530
+ Set the state of a flow run.
3531
+
3532
+ Args:
3533
+ flow_run_id: the id of the flow run
3534
+ state: the state to set
3535
+ force: if True, disregard orchestration logic when setting the state,
3536
+ forcing the Prefect API to accept the state
3537
+
3538
+ Returns:
3539
+ an OrchestrationResult model representation of state orchestration output
3540
+ """
3541
+ return run_sync(
3542
+ self._prefect_client.set_flow_run_state(
3543
+ flow_run_id=flow_run_id,
3544
+ state=state,
3545
+ force=force,
3546
+ )
3547
+ )
@@ -8,9 +8,9 @@ from prefect._internal.compatibility.deprecated import DeprecatedInfraOverridesF
8
8
  from prefect._internal.pydantic import HAS_PYDANTIC_V2
9
9
 
10
10
  if HAS_PYDANTIC_V2:
11
- from pydantic.v1 import Field, conint, root_validator, validator
11
+ from pydantic.v1 import Field, root_validator, validator
12
12
  else:
13
- from pydantic import Field, conint, root_validator, validator
13
+ from pydantic import Field, root_validator, validator
14
14
 
15
15
  import prefect.client.schemas.objects as objects
16
16
  from prefect._internal.schemas.bases import ActionBaseModel
@@ -26,6 +26,7 @@ from prefect._internal.schemas.validators import (
26
26
  )
27
27
  from prefect.client.schemas.objects import StateDetails, StateType
28
28
  from prefect.client.schemas.schedules import SCHEDULE_TYPES
29
+ from prefect.types import NonNegativeInteger
29
30
  from prefect.utilities.collections import listrepr
30
31
  from prefect.utilities.pydantic import get_class_fields_only
31
32
 
@@ -525,7 +526,7 @@ class WorkPoolCreate(ActionBaseModel):
525
526
  default=False,
526
527
  description="Whether the work pool is paused.",
527
528
  )
528
- concurrency_limit: Optional[conint(ge=0)] = Field(
529
+ concurrency_limit: Optional[NonNegativeInteger] = Field(
529
530
  default=None, description="A concurrency limit for the work pool."
530
531
  )
531
532