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
@@ -1,423 +0,0 @@
1
- import inspect
2
- import logging
3
- import time
4
- from contextlib import contextmanager
5
- from dataclasses import dataclass, field
6
- from typing import (
7
- Any,
8
- Callable,
9
- Coroutine,
10
- Dict,
11
- Generator,
12
- Generic,
13
- Iterable,
14
- Literal,
15
- Optional,
16
- TypeVar,
17
- Union,
18
- cast,
19
- )
20
-
21
- import pendulum
22
- from typing_extensions import ParamSpec
23
-
24
- from prefect import Task, get_client
25
- from prefect.client.orchestration import SyncPrefectClient
26
- from prefect.client.schemas import TaskRun
27
- from prefect.context import FlowRunContext, TaskRunContext
28
- from prefect.futures import PrefectFuture, resolve_futures_to_states
29
- from prefect.logging.loggers import get_logger, task_run_logger
30
- from prefect.results import ResultFactory
31
- from prefect.server.schemas.states import State
32
- from prefect.settings import PREFECT_TASKS_REFRESH_CACHE
33
- from prefect.states import (
34
- Retrying,
35
- Running,
36
- StateDetails,
37
- exception_to_crashed_state,
38
- exception_to_failed_state,
39
- return_value_to_state,
40
- )
41
- from prefect.utilities.asyncutils import A, Async, run_sync
42
- from prefect.utilities.callables import parameters_to_args_kwargs
43
- from prefect.utilities.engine import (
44
- _get_hook_name,
45
- propose_state_sync,
46
- )
47
- from prefect.utilities.timeout import timeout, timeout_async
48
-
49
- P = ParamSpec("P")
50
- R = TypeVar("R")
51
-
52
-
53
- @dataclass
54
- class TaskRunEngine(Generic[P, R]):
55
- task: Union[Task[P, R], Task[P, Coroutine[Any, Any, R]]]
56
- logger: logging.Logger = field(default_factory=lambda: get_logger("engine"))
57
- parameters: Optional[Dict[str, Any]] = None
58
- task_run: Optional[TaskRun] = None
59
- retries: int = 0
60
- _is_started: bool = False
61
- _client: Optional[SyncPrefectClient] = None
62
-
63
- def __post_init__(self):
64
- if self.parameters is None:
65
- self.parameters = {}
66
-
67
- @property
68
- def client(self) -> SyncPrefectClient:
69
- if not self._is_started or self._client is None:
70
- raise RuntimeError("Engine has not started.")
71
- return self._client
72
-
73
- @property
74
- def state(self) -> State:
75
- if not self.task_run:
76
- raise ValueError("Task run is not set")
77
- return self.task_run.state
78
-
79
- @property
80
- def can_retry(self) -> bool:
81
- retry_condition: Optional[
82
- Callable[[Task[P, Coroutine[Any, Any, R]], TaskRun, State], bool]
83
- ] = self.task.retry_condition_fn
84
- if not self.task_run:
85
- raise ValueError("Task run is not set")
86
- return not retry_condition or retry_condition(
87
- self.task, self.task_run, self.state
88
- )
89
-
90
- def get_hooks(self, state: State, as_async: bool = False) -> Iterable[Callable]:
91
- task = self.task
92
- task_run = self.task_run
93
-
94
- if not task_run:
95
- raise ValueError("Task run is not set")
96
-
97
- hooks = None
98
- if state.is_failed() and task.on_failure:
99
- hooks = task.on_failure
100
- elif state.is_completed() and task.on_completion:
101
- hooks = task.on_completion
102
-
103
- for hook in hooks or []:
104
- hook_name = _get_hook_name(hook)
105
-
106
- @contextmanager
107
- def hook_context():
108
- try:
109
- self.logger.info(
110
- f"Running hook {hook_name!r} in response to entering state"
111
- f" {state.name!r}"
112
- )
113
- yield
114
- except Exception:
115
- self.logger.error(
116
- f"An error was encountered while running hook {hook_name!r}",
117
- exc_info=True,
118
- )
119
- else:
120
- self.logger.info(
121
- f"Hook {hook_name!r} finished running successfully"
122
- )
123
-
124
- if as_async:
125
-
126
- async def _hook_fn():
127
- with hook_context():
128
- result = hook(task, task_run, state)
129
- if inspect.isawaitable(result):
130
- await result
131
- else:
132
-
133
- def _hook_fn():
134
- with hook_context():
135
- hook(task, task_run, state)
136
-
137
- yield _hook_fn
138
-
139
- def _compute_state_details(
140
- self, include_cache_expiration: bool = False
141
- ) -> StateDetails:
142
- ## setup cache metadata
143
- task_run_context = TaskRunContext.get()
144
- cache_key = (
145
- self.task.cache_key_fn(
146
- task_run_context,
147
- self.parameters or {},
148
- )
149
- if self.task.cache_key_fn
150
- else None
151
- )
152
- # Ignore the cached results for a cache key, default = false
153
- # Setting on task level overrules the Prefect setting (env var)
154
- refresh_cache = (
155
- self.task.refresh_cache
156
- if self.task.refresh_cache is not None
157
- else PREFECT_TASKS_REFRESH_CACHE.value()
158
- )
159
-
160
- if include_cache_expiration:
161
- cache_expiration = (
162
- (pendulum.now("utc") + self.task.cache_expiration)
163
- if self.task.cache_expiration
164
- else None
165
- )
166
- else:
167
- cache_expiration = None
168
- return StateDetails(
169
- cache_key=cache_key,
170
- refresh_cache=refresh_cache,
171
- cache_expiration=cache_expiration,
172
- )
173
-
174
- def begin_run(self):
175
- state_details = self._compute_state_details()
176
- new_state = Running(state_details=state_details)
177
- state = self.set_state(new_state)
178
- while state.is_pending():
179
- time.sleep(0.2)
180
- state = self.set_state(new_state)
181
-
182
- def set_state(self, state: State, force: bool = False) -> State:
183
- if not self.task_run:
184
- raise ValueError("Task run is not set")
185
- new_state = propose_state_sync(
186
- self.client, state, task_run_id=self.task_run.id, force=force
187
- )
188
- # type: ignore
189
-
190
- # currently this is a hack to keep a reference to the state object
191
- # that has an in-memory result attached to it; using the API state
192
- # could result in losing that reference
193
- self.task_run.state = new_state
194
- return new_state
195
-
196
- def result(self, raise_on_failure: bool = True) -> "Union[R, State, None]":
197
- _result = self.state.result(raise_on_failure=raise_on_failure, fetch=True)
198
- # state.result is a `sync_compatible` function that may or may not return an awaitable
199
- # depending on whether the parent frame is sync or not
200
- if inspect.isawaitable(_result):
201
- _result = run_sync(_result)
202
- return _result
203
-
204
- def handle_success(self, result: R) -> R:
205
- result_factory = getattr(TaskRunContext.get(), "result_factory", None)
206
- if result_factory is None:
207
- raise ValueError("Result factory is not set")
208
- terminal_state = run_sync(
209
- return_value_to_state(
210
- run_sync(resolve_futures_to_states(result)),
211
- result_factory=result_factory,
212
- )
213
- )
214
- terminal_state.state_details = self._compute_state_details(
215
- include_cache_expiration=True
216
- )
217
- self.set_state(terminal_state)
218
- return result
219
-
220
- def handle_retry(self, exc: Exception) -> bool:
221
- """
222
- If the task has retries left, and the retry condition is met, set the task to retrying.
223
- - If the task has no retries left, or the retry condition is not met, return False.
224
- - If the task has retries left, and the retry condition is met, return True.
225
- """
226
- if self.retries < self.task.retries and self.can_retry:
227
- self.set_state(Retrying(), force=True)
228
- self.retries = self.retries + 1
229
- return True
230
- return False
231
-
232
- def handle_exception(self, exc: Exception) -> None:
233
- # If the task fails, and we have retries left, set the task to retrying.
234
- if not self.handle_retry(exc):
235
- # If the task has no retries left, or the retry condition is not met, set the task to failed.
236
- context = TaskRunContext.get()
237
- state = run_sync(
238
- exception_to_failed_state(
239
- exc,
240
- message="Task run encountered an exception",
241
- result_factory=getattr(context, "result_factory", None),
242
- )
243
- )
244
- self.set_state(state)
245
-
246
- def handle_crash(self, exc: BaseException) -> None:
247
- state = run_sync(exception_to_crashed_state(exc))
248
- self.logger.error(f"Crash detected! {state.message}")
249
- self.logger.debug("Crash details:", exc_info=exc)
250
- self.set_state(state, force=True)
251
-
252
- @contextmanager
253
- def enter_run_context(self, client: Optional[SyncPrefectClient] = None):
254
- if client is None:
255
- client = self.client
256
- if not self.task_run:
257
- raise ValueError("Task run is not set")
258
-
259
- self.task_run = client.read_task_run(self.task_run.id)
260
-
261
- with TaskRunContext(
262
- task=self.task,
263
- log_prints=self.task.log_prints or False,
264
- task_run=self.task_run,
265
- parameters=self.parameters,
266
- result_factory=run_sync(ResultFactory.from_autonomous_task(self.task)), # type: ignore
267
- client=client,
268
- ):
269
- # set the logger to the task run logger
270
- current_logger = self.logger
271
- try:
272
- self.logger = task_run_logger(task_run=self.task_run, task=self.task) # type: ignore
273
- yield
274
- finally:
275
- self.logger = current_logger
276
-
277
- @contextmanager
278
- def start(self) -> Generator["TaskRunEngine", Any, Any]:
279
- """
280
- Enters a client context and creates a task run if needed.
281
- """
282
- with get_client(sync_client=True) as client:
283
- self._client = client
284
- self._is_started = True
285
- try:
286
- if not self.task_run:
287
- self.task_run = run_sync(
288
- self.task.create_run(
289
- client=client,
290
- parameters=self.parameters,
291
- flow_run_context=FlowRunContext.get(),
292
- parent_task_run_context=TaskRunContext.get(),
293
- )
294
- )
295
-
296
- yield self
297
- except Exception:
298
- # regular exceptions are caught and re-raised to the user
299
- raise
300
- except BaseException as exc:
301
- # BaseExceptions are caught and handled as crashes
302
- self.handle_crash(exc)
303
- raise
304
- finally:
305
- self._is_started = False
306
- self._client = None
307
-
308
- async def get_client(self):
309
- if not self._is_started:
310
- raise RuntimeError("Engine has not started.")
311
- else:
312
- return self._client
313
-
314
- def is_running(self) -> bool:
315
- if getattr(self, "task_run", None) is None:
316
- return False
317
- return getattr(self, "task_run").state.is_running()
318
-
319
- def is_pending(self) -> bool:
320
- if getattr(self, "task_run", None) is None:
321
- return False # TODO: handle this differently?
322
- return getattr(self, "task_run").state.is_pending()
323
-
324
-
325
- def run_task_sync(
326
- task: Task[P, R],
327
- task_run: Optional[TaskRun] = None,
328
- parameters: Optional[Dict[str, Any]] = None,
329
- wait_for: Optional[Iterable[PrefectFuture[A, Async]]] = None,
330
- return_type: Literal["state", "result"] = "result",
331
- ) -> Union[R, State, None]:
332
- engine = TaskRunEngine[P, R](task=task, parameters=parameters, task_run=task_run)
333
-
334
- # This is a context manager that keeps track of the run of the task run.
335
- with engine.start() as run:
336
- run.begin_run()
337
-
338
- while run.is_running():
339
- with run.enter_run_context():
340
- try:
341
- # This is where the task is actually run.
342
- with timeout(seconds=run.task.timeout_seconds):
343
- call_args, call_kwargs = parameters_to_args_kwargs(
344
- task.fn, run.parameters or {}
345
- )
346
- result = cast(R, task.fn(*call_args, **call_kwargs)) # type: ignore
347
-
348
- # If the task run is successful, finalize it.
349
- run.handle_success(result)
350
-
351
- except Exception as exc:
352
- run.handle_exception(exc)
353
-
354
- if run.state.is_final():
355
- for hook in run.get_hooks(run.state):
356
- hook()
357
-
358
- if return_type == "state":
359
- return run.state
360
- return run.result()
361
-
362
-
363
- async def run_task_async(
364
- task: Task[P, Coroutine[Any, Any, R]],
365
- task_run: Optional[TaskRun] = None,
366
- parameters: Optional[Dict[str, Any]] = None,
367
- wait_for: Optional[Iterable[PrefectFuture[A, Async]]] = None,
368
- return_type: Literal["state", "result"] = "result",
369
- ) -> Union[R, State, None]:
370
- """
371
- Runs a task against the API.
372
-
373
- We will most likely want to use this logic as a wrapper and return a coroutine for type inference.
374
- """
375
- engine = TaskRunEngine[P, R](task=task, parameters=parameters, task_run=task_run)
376
-
377
- # This is a context manager that keeps track of the run of the task run.
378
- with engine.start() as run:
379
- run.begin_run()
380
-
381
- while run.is_running():
382
- with run.enter_run_context():
383
- try:
384
- # This is where the task is actually run.
385
- with timeout_async(seconds=run.task.timeout_seconds):
386
- call_args, call_kwargs = parameters_to_args_kwargs(
387
- task.fn, run.parameters or {}
388
- )
389
- result = cast(R, await task.fn(*call_args, **call_kwargs)) # type: ignore
390
-
391
- # If the task run is successful, finalize it.
392
- run.handle_success(result)
393
-
394
- except Exception as exc:
395
- run.handle_exception(exc)
396
-
397
- if run.state.is_final():
398
- for hook in run.get_hooks(run.state, as_async=True):
399
- await hook()
400
-
401
- if return_type == "state":
402
- return run.state
403
- return run.result()
404
-
405
-
406
- def run_task(
407
- task: Task[P, R],
408
- task_run: Optional[TaskRun] = None,
409
- parameters: Optional[Dict[str, Any]] = None,
410
- wait_for: Optional[Iterable[PrefectFuture[A, Async]]] = None,
411
- return_type: Literal["state", "result"] = "result",
412
- ) -> Union[R, State, None]:
413
- kwargs = dict(
414
- task=task,
415
- task_run=task_run,
416
- parameters=parameters,
417
- wait_for=wait_for,
418
- return_type=return_type,
419
- )
420
- if task.isasync:
421
- return run_task_async(**kwargs)
422
- else:
423
- return run_task_sync(**kwargs)
@@ -1,76 +0,0 @@
1
- """
2
- This initialization file makes the `BaseModel` and `PrefectBaseModel` classes available for import from the pydantic module within Prefect. This setup allows other parts of the Prefect codebase to use these models without needing to understand the underlying compatibility layer.
3
- """
4
- import typing
5
- from prefect._internal.pydantic._flags import HAS_PYDANTIC_V2, USE_PYDANTIC_V2
6
-
7
- if typing.TYPE_CHECKING:
8
- # import of virtually everything is supported via `__getattr__` below,
9
- # but we need them here for type checking and IDE support
10
- from pydantic import validator, root_validator
11
- from .main import (
12
- BaseModel,
13
- PrefectBaseModel,
14
- FieldInfo,
15
- Field,
16
- PrivateAttr,
17
- SecretStr,
18
- field_validator,
19
- model_validator,
20
- ConfigDict,
21
- ValidationError,
22
- )
23
-
24
- __all__ = [
25
- "BaseModel",
26
- "PrefectBaseModel",
27
- "Field",
28
- "FieldInfo",
29
- "PrivateAttr",
30
- "SecretStr",
31
- "validator",
32
- "root_validator",
33
- "field_validator",
34
- "model_validator",
35
- "ConfigDict",
36
- "ValidationError",
37
- ]
38
-
39
- _dynamic_imports: "typing.Dict[str, typing.Tuple[str, str]]" = {
40
- "BaseModel": ("prefect.pydantic", ".main"),
41
- "PrefectBaseModel": ("prefect.pydantic", ".main"),
42
- "Field": ("prefect.pydantic", ".main"),
43
- "FieldInfo": ("prefect.pydantic", ".main"),
44
- "PrivateAttr": ("prefect.pydantic", ".main"),
45
- "SecretStr": ("prefect.pydantic", ".main"),
46
- "field_validator": ("prefect.pydantic", ".main"),
47
- "model_validator": ("prefect.pydantic", ".main"),
48
- "ConfigDict": ("prefect.pydantic", ".main"),
49
- "ValidationError": ("prefect.pydantic", ".main"),
50
- }
51
-
52
-
53
- def __getattr__(attr_name: str) -> object:
54
- from importlib import import_module
55
-
56
- if attr_name in _dynamic_imports:
57
- # If the attribute is in the dynamic imports, import it from the specified module
58
- package, module_name = _dynamic_imports[attr_name]
59
-
60
- # Prevent recursive import
61
- if module_name == "__module__":
62
- return import_module(f".{attr_name}", package=package)
63
-
64
- # Import the module and return the attribute
65
- else:
66
- module = import_module(module_name, package=package)
67
- return getattr(module, attr_name)
68
-
69
- elif HAS_PYDANTIC_V2 and not USE_PYDANTIC_V2:
70
- # In this case, we are using Pydantic v2 but it is not enabled, so we should import from pydantic.v1
71
- module = import_module("pydantic.v1")
72
- return getattr(module, attr_name)
73
- else:
74
- # In this case, we are using either Pydantic v1 or Pydantic v2 is enabled, so we should import from pydantic
75
- module = import_module("pydantic")
76
- return getattr(module, attr_name)
prefect/pydantic/main.py DELETED
@@ -1,39 +0,0 @@
1
- """
2
- This file defines a `PrefectBaseModel` class that extends the `BaseModel` (imported from the internal compatibility layer).
3
- """
4
- import typing
5
-
6
- from prefect._internal.pydantic._compat import (
7
- BaseModel,
8
- ConfigDict,
9
- Field,
10
- FieldInfo,
11
- PrivateAttr,
12
- SecretStr,
13
- ValidationError,
14
- field_validator,
15
- model_validator,
16
- )
17
-
18
-
19
- class PrefectBaseModel(BaseModel):
20
- def _reset_fields(self) -> typing.Set[str]:
21
- """
22
- A set of field names that are reset when the PrefectBaseModel is copied.
23
- These fields are also disregarded for equality comparisons.
24
- """
25
- return set()
26
-
27
-
28
- __all__ = [
29
- "BaseModel",
30
- "PrefectBaseModel",
31
- "Field",
32
- "FieldInfo",
33
- "PrivateAttr",
34
- "SecretStr",
35
- "field_validator",
36
- "model_validator",
37
- "ConfigDict",
38
- "ValidationError",
39
- ]
@@ -1,2 +0,0 @@
1
- from prefect.software.conda import CondaEnvironment
2
- from prefect.software.python import PythonEnvironment
prefect/software/base.py DELETED
@@ -1,50 +0,0 @@
1
- from typing import Iterable, List, Optional
2
-
3
-
4
- class Requirement:
5
- # Implementations are expected to at least contain a name attribute
6
- name: str
7
-
8
- @classmethod
9
- def __get_validators__(cls):
10
- yield cls.validate
11
-
12
- @classmethod
13
- def validate(cls, value):
14
- if not isinstance(value, cls):
15
- # Attempt to parse the string representation of the input type
16
- return cls(str(value))
17
- return value
18
-
19
- def __eq__(self, other: object) -> bool:
20
- """
21
- Requirements are equal if their string specification matches.
22
- """
23
- if not isinstance(other, Requirement):
24
- return NotImplemented
25
-
26
- return str(self) == str(other)
27
-
28
- def __repr__(self) -> str:
29
- return f"{type(self).__name__}({str(self)!r})"
30
-
31
-
32
- def remove_duplicate_requirements(
33
- constant: Iterable[Requirement], to_deduplicate: Iterable[Requirement]
34
- ) -> List[Requirement]:
35
- """
36
- Returns a list of requirements that excludes requirements already specified
37
- in the first iterable.
38
- """
39
- constant_names = {req.name for req in constant}
40
- return [req for req in to_deduplicate if req.name not in constant_names]
41
-
42
-
43
- def pop_requirement_by_name(
44
- requirements: List[Requirement], name: str
45
- ) -> Optional[Requirement]:
46
- for index, requirement in enumerate(requirements):
47
- if requirement.name == name:
48
- requirements.pop(index)
49
- return requirement
50
- return None