prefect-client 3.1.13__py3-none-any.whl → 3.1.14__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/flow_engine.py CHANGED
@@ -39,6 +39,7 @@ from prefect.context import (
39
39
  FlowRunContext,
40
40
  SyncClientContext,
41
41
  TagsContext,
42
+ hydrated_context,
42
43
  )
43
44
  from prefect.exceptions import (
44
45
  Abort,
@@ -137,6 +138,7 @@ class BaseFlowRunEngine(Generic[P, R]):
137
138
  flow_run_id: Optional[UUID] = None
138
139
  logger: logging.Logger = field(default_factory=lambda: get_logger("engine"))
139
140
  wait_for: Optional[Iterable[PrefectFuture[Any]]] = None
141
+ context: Optional[dict[str, Any]] = None
140
142
  # holds the return value from the user code
141
143
  _return_value: Union[R, Type[NotSet]] = NotSet
142
144
  # holds the exception raised by the user code, if any
@@ -647,65 +649,68 @@ class FlowRunEngine(BaseFlowRunEngine[P, R]):
647
649
  """
648
650
  Enters a client context and creates a flow run if needed.
649
651
  """
650
- with SyncClientContext.get_or_create() as client_ctx:
651
- self._client = client_ctx.client
652
- self._is_started = True
652
+ with hydrated_context(self.context):
653
+ with SyncClientContext.get_or_create() as client_ctx:
654
+ self._client = client_ctx.client
655
+ self._is_started = True
653
656
 
654
- if not self.flow_run:
655
- self.flow_run = self.create_flow_run(self.client)
656
- else:
657
- # Update the empirical policy to match the flow if it is not set
658
- if self.flow_run.empirical_policy.retry_delay is None:
659
- self.flow_run.empirical_policy.retry_delay = (
660
- self.flow.retry_delay_seconds
661
- )
657
+ if not self.flow_run:
658
+ self.flow_run = self.create_flow_run(self.client)
659
+ else:
660
+ # Update the empirical policy to match the flow if it is not set
661
+ if self.flow_run.empirical_policy.retry_delay is None:
662
+ self.flow_run.empirical_policy.retry_delay = (
663
+ self.flow.retry_delay_seconds
664
+ )
662
665
 
663
- if self.flow_run.empirical_policy.retries is None:
664
- self.flow_run.empirical_policy.retries = self.flow.retries
666
+ if self.flow_run.empirical_policy.retries is None:
667
+ self.flow_run.empirical_policy.retries = self.flow.retries
665
668
 
666
- self.client.update_flow_run(
667
- flow_run_id=self.flow_run.id,
668
- flow_version=self.flow.version,
669
- empirical_policy=self.flow_run.empirical_policy,
670
- )
669
+ self.client.update_flow_run(
670
+ flow_run_id=self.flow_run.id,
671
+ flow_version=self.flow.version,
672
+ empirical_policy=self.flow_run.empirical_policy,
673
+ )
671
674
 
672
- self._telemetry.start_span(
673
- run=self.flow_run,
674
- client=self.client,
675
- parameters=self.parameters,
676
- )
675
+ self._telemetry.start_span(
676
+ run=self.flow_run,
677
+ client=self.client,
678
+ parameters=self.parameters,
679
+ )
677
680
 
678
- try:
679
- yield self
681
+ try:
682
+ yield self
680
683
 
681
- except TerminationSignal as exc:
682
- self.cancel_all_tasks()
683
- self.handle_crash(exc)
684
- raise
685
- except Exception:
686
- # regular exceptions are caught and re-raised to the user
687
- raise
688
- except (Abort, Pause):
689
- raise
690
- except GeneratorExit:
691
- # Do not capture generator exits as crashes
692
- raise
693
- except BaseException as exc:
694
- # BaseExceptions are caught and handled as crashes
695
- self.handle_crash(exc)
696
- raise
697
- finally:
698
- # If debugging, use the more complete `repr` than the usual `str` description
699
- display_state = (
700
- repr(self.state) if PREFECT_DEBUG_MODE else str(self.state)
701
- )
702
- self.logger.log(
703
- level=logging.INFO if self.state.is_completed() else logging.ERROR,
704
- msg=f"Finished in state {display_state}",
705
- )
684
+ except TerminationSignal as exc:
685
+ self.cancel_all_tasks()
686
+ self.handle_crash(exc)
687
+ raise
688
+ except Exception:
689
+ # regular exceptions are caught and re-raised to the user
690
+ raise
691
+ except (Abort, Pause):
692
+ raise
693
+ except GeneratorExit:
694
+ # Do not capture generator exits as crashes
695
+ raise
696
+ except BaseException as exc:
697
+ # BaseExceptions are caught and handled as crashes
698
+ self.handle_crash(exc)
699
+ raise
700
+ finally:
701
+ # If debugging, use the more complete `repr` than the usual `str` description
702
+ display_state = (
703
+ repr(self.state) if PREFECT_DEBUG_MODE else str(self.state)
704
+ )
705
+ self.logger.log(
706
+ level=logging.INFO
707
+ if self.state.is_completed()
708
+ else logging.ERROR,
709
+ msg=f"Finished in state {display_state}",
710
+ )
706
711
 
707
- self._is_started = False
708
- self._client = None
712
+ self._is_started = False
713
+ self._client = None
709
714
 
710
715
  # --------------------------
711
716
  #
@@ -1208,71 +1213,74 @@ class AsyncFlowRunEngine(BaseFlowRunEngine[P, R]):
1208
1213
  """
1209
1214
  Enters a client context and creates a flow run if needed.
1210
1215
  """
1211
- async with AsyncClientContext.get_or_create() as client_ctx:
1212
- self._client = client_ctx.client
1213
- self._is_started = True
1216
+ with hydrated_context(self.context):
1217
+ async with AsyncClientContext.get_or_create() as client_ctx:
1218
+ self._client = client_ctx.client
1219
+ self._is_started = True
1220
+
1221
+ if not self.flow_run:
1222
+ self.flow_run = await self.create_flow_run(self.client)
1223
+ flow_run_url = url_for(self.flow_run)
1224
+
1225
+ if flow_run_url:
1226
+ self.logger.info(
1227
+ f"View at {flow_run_url}", extra={"send_to_api": False}
1228
+ )
1229
+ else:
1230
+ # Update the empirical policy to match the flow if it is not set
1231
+ if self.flow_run.empirical_policy.retry_delay is None:
1232
+ self.flow_run.empirical_policy.retry_delay = (
1233
+ self.flow.retry_delay_seconds
1234
+ )
1214
1235
 
1215
- if not self.flow_run:
1216
- self.flow_run = await self.create_flow_run(self.client)
1217
- flow_run_url = url_for(self.flow_run)
1236
+ if self.flow_run.empirical_policy.retries is None:
1237
+ self.flow_run.empirical_policy.retries = self.flow.retries
1218
1238
 
1219
- if flow_run_url:
1220
- self.logger.info(
1221
- f"View at {flow_run_url}", extra={"send_to_api": False}
1222
- )
1223
- else:
1224
- # Update the empirical policy to match the flow if it is not set
1225
- if self.flow_run.empirical_policy.retry_delay is None:
1226
- self.flow_run.empirical_policy.retry_delay = (
1227
- self.flow.retry_delay_seconds
1239
+ await self.client.update_flow_run(
1240
+ flow_run_id=self.flow_run.id,
1241
+ flow_version=self.flow.version,
1242
+ empirical_policy=self.flow_run.empirical_policy,
1228
1243
  )
1229
1244
 
1230
- if self.flow_run.empirical_policy.retries is None:
1231
- self.flow_run.empirical_policy.retries = self.flow.retries
1232
-
1233
- await self.client.update_flow_run(
1234
- flow_run_id=self.flow_run.id,
1235
- flow_version=self.flow.version,
1236
- empirical_policy=self.flow_run.empirical_policy,
1245
+ await self._telemetry.async_start_span(
1246
+ run=self.flow_run,
1247
+ client=self.client,
1248
+ parameters=self.parameters,
1237
1249
  )
1238
1250
 
1239
- await self._telemetry.async_start_span(
1240
- run=self.flow_run,
1241
- client=self.client,
1242
- parameters=self.parameters,
1243
- )
1244
-
1245
- try:
1246
- yield self
1251
+ try:
1252
+ yield self
1247
1253
 
1248
- except TerminationSignal as exc:
1249
- self.cancel_all_tasks()
1250
- await self.handle_crash(exc)
1251
- raise
1252
- except Exception:
1253
- # regular exceptions are caught and re-raised to the user
1254
- raise
1255
- except (Abort, Pause):
1256
- raise
1257
- except GeneratorExit:
1258
- # Do not capture generator exits as crashes
1259
- raise
1260
- except BaseException as exc:
1261
- # BaseExceptions are caught and handled as crashes
1262
- await self.handle_crash(exc)
1263
- raise
1264
- finally:
1265
- # If debugging, use the more complete `repr` than the usual `str` description
1266
- display_state = (
1267
- repr(self.state) if PREFECT_DEBUG_MODE else str(self.state)
1268
- )
1269
- self.logger.log(
1270
- level=logging.INFO if self.state.is_completed() else logging.ERROR,
1271
- msg=f"Finished in state {display_state}",
1272
- )
1254
+ except TerminationSignal as exc:
1255
+ self.cancel_all_tasks()
1256
+ await self.handle_crash(exc)
1257
+ raise
1258
+ except Exception:
1259
+ # regular exceptions are caught and re-raised to the user
1260
+ raise
1261
+ except (Abort, Pause):
1262
+ raise
1263
+ except GeneratorExit:
1264
+ # Do not capture generator exits as crashes
1265
+ raise
1266
+ except BaseException as exc:
1267
+ # BaseExceptions are caught and handled as crashes
1268
+ await self.handle_crash(exc)
1269
+ raise
1270
+ finally:
1271
+ # If debugging, use the more complete `repr` than the usual `str` description
1272
+ display_state = (
1273
+ repr(self.state) if PREFECT_DEBUG_MODE else str(self.state)
1274
+ )
1275
+ self.logger.log(
1276
+ level=logging.INFO
1277
+ if self.state.is_completed()
1278
+ else logging.ERROR,
1279
+ msg=f"Finished in state {display_state}",
1280
+ )
1273
1281
 
1274
- self._is_started = False
1275
- self._client = None
1282
+ self._is_started = False
1283
+ self._client = None
1276
1284
 
1277
1285
  # --------------------------
1278
1286
  #
@@ -1330,12 +1338,14 @@ def run_flow_sync(
1330
1338
  parameters: Optional[Dict[str, Any]] = None,
1331
1339
  wait_for: Optional[Iterable[PrefectFuture[Any]]] = None,
1332
1340
  return_type: Literal["state", "result"] = "result",
1341
+ context: Optional[dict[str, Any]] = None,
1333
1342
  ) -> Union[R, State, None]:
1334
1343
  engine = FlowRunEngine[P, R](
1335
1344
  flow=flow,
1336
1345
  parameters=parameters,
1337
1346
  flow_run=flow_run,
1338
1347
  wait_for=wait_for,
1348
+ context=context,
1339
1349
  )
1340
1350
 
1341
1351
  with engine.start():
@@ -1352,9 +1362,14 @@ async def run_flow_async(
1352
1362
  parameters: Optional[Dict[str, Any]] = None,
1353
1363
  wait_for: Optional[Iterable[PrefectFuture[Any]]] = None,
1354
1364
  return_type: Literal["state", "result"] = "result",
1365
+ context: Optional[dict[str, Any]] = None,
1355
1366
  ) -> Union[R, State, None]:
1356
1367
  engine = AsyncFlowRunEngine[P, R](
1357
- flow=flow, parameters=parameters, flow_run=flow_run, wait_for=wait_for
1368
+ flow=flow,
1369
+ parameters=parameters,
1370
+ flow_run=flow_run,
1371
+ wait_for=wait_for,
1372
+ context=context,
1358
1373
  )
1359
1374
 
1360
1375
  async with engine.start():
@@ -1371,12 +1386,17 @@ def run_generator_flow_sync(
1371
1386
  parameters: Optional[Dict[str, Any]] = None,
1372
1387
  wait_for: Optional[Iterable[PrefectFuture[Any]]] = None,
1373
1388
  return_type: Literal["state", "result"] = "result",
1389
+ context: Optional[dict[str, Any]] = None,
1374
1390
  ) -> Generator[R, None, None]:
1375
1391
  if return_type != "result":
1376
1392
  raise ValueError("The return_type for a generator flow must be 'result'")
1377
1393
 
1378
1394
  engine = FlowRunEngine[P, R](
1379
- flow=flow, parameters=parameters, flow_run=flow_run, wait_for=wait_for
1395
+ flow=flow,
1396
+ parameters=parameters,
1397
+ flow_run=flow_run,
1398
+ wait_for=wait_for,
1399
+ context=context,
1380
1400
  )
1381
1401
 
1382
1402
  with engine.start():
@@ -1407,12 +1427,17 @@ async def run_generator_flow_async(
1407
1427
  parameters: Optional[Dict[str, Any]] = None,
1408
1428
  wait_for: Optional[Iterable[PrefectFuture[R]]] = None,
1409
1429
  return_type: Literal["state", "result"] = "result",
1430
+ context: Optional[dict[str, Any]] = None,
1410
1431
  ) -> AsyncGenerator[R, None]:
1411
1432
  if return_type != "result":
1412
1433
  raise ValueError("The return_type for a generator flow must be 'result'")
1413
1434
 
1414
1435
  engine = AsyncFlowRunEngine[P, R](
1415
- flow=flow, parameters=parameters, flow_run=flow_run, wait_for=wait_for
1436
+ flow=flow,
1437
+ parameters=parameters,
1438
+ flow_run=flow_run,
1439
+ wait_for=wait_for,
1440
+ context=context,
1416
1441
  )
1417
1442
 
1418
1443
  async with engine.start():
@@ -1446,8 +1471,23 @@ def run_flow(
1446
1471
  wait_for: Optional[Iterable[PrefectFuture[R]]] = None,
1447
1472
  return_type: Literal["state", "result"] = "result",
1448
1473
  error_logger: Optional[logging.Logger] = None,
1449
- ) -> Union[R, State, None]:
1450
- ret_val: Union[R, State, None] = None
1474
+ context: Optional[dict[str, Any]] = None,
1475
+ ) -> (
1476
+ R
1477
+ | State
1478
+ | None
1479
+ | Coroutine[Any, Any, R | State | None]
1480
+ | Generator[R, None, None]
1481
+ | AsyncGenerator[R, None]
1482
+ ):
1483
+ ret_val: Union[
1484
+ R,
1485
+ State,
1486
+ None,
1487
+ Coroutine[Any, Any, R | State | None],
1488
+ Generator[R, None, None],
1489
+ AsyncGenerator[R, None],
1490
+ ] = None
1451
1491
 
1452
1492
  try:
1453
1493
  kwargs: dict[str, Any] = dict(
@@ -1458,6 +1498,7 @@ def run_flow(
1458
1498
  ),
1459
1499
  wait_for=wait_for,
1460
1500
  return_type=return_type,
1501
+ context=context,
1461
1502
  )
1462
1503
 
1463
1504
  if flow.isasync and flow.isgenerator:
prefect/flows.py CHANGED
@@ -127,9 +127,9 @@ if TYPE_CHECKING:
127
127
  import logging
128
128
 
129
129
  from prefect.client.orchestration import PrefectClient
130
+ from prefect.client.schemas.objects import FlowRun
130
131
  from prefect.client.types.flexible_schedule_list import FlexibleScheduleList
131
132
  from prefect.deployments.runner import RunnerDeployment
132
- from prefect.flows import FlowRun
133
133
  from prefect.runner.storage import RunnerStorage
134
134
 
135
135
  logger: "logging.Logger" = get_logger("flows")
@@ -94,12 +94,9 @@ def setup_logging(incremental: Optional[bool] = None) -> dict[str, Any]:
94
94
 
95
95
  for logger_name in PREFECT_LOGGING_EXTRA_LOGGERS.value():
96
96
  logger = logging.getLogger(logger_name)
97
- for handler in extra_config.handlers:
98
- if not config["incremental"]:
97
+ if not config["incremental"]:
98
+ for handler in extra_config.handlers:
99
99
  logger.addHandler(handler)
100
- if logger.level == logging.NOTSET:
101
- logger.setLevel(extra_config.level)
102
- logger.propagate = extra_config.propagate
103
100
 
104
101
  PROCESS_LOGGING_CONFIG = config
105
102
 
@@ -24,7 +24,6 @@ else:
24
24
  LoggingAdapter = logging.LoggerAdapter
25
25
 
26
26
  if TYPE_CHECKING:
27
- from prefect.client.schemas import FlowRun as ClientFlowRun
28
27
  from prefect.client.schemas.objects import FlowRun, TaskRun
29
28
  from prefect.context import RunContext
30
29
  from prefect.flows import Flow
@@ -164,7 +163,7 @@ def get_run_logger(
164
163
 
165
164
 
166
165
  def flow_run_logger(
167
- flow_run: Union["FlowRun", "ClientFlowRun"],
166
+ flow_run: "FlowRun",
168
167
  flow: Optional["Flow[Any, Any]"] = None,
169
168
  **kwargs: str,
170
169
  ) -> PrefectLogAdapter: