prefect-client 3.4.6.dev1__py3-none-any.whl → 3.4.6.dev2__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/_build_info.py CHANGED
@@ -1,5 +1,5 @@
1
1
  # Generated by versioningit
2
- __version__ = "3.4.6.dev1"
3
- __build_date__ = "2025-06-10 08:09:30.415238+00:00"
4
- __git_commit__ = "cd3c98b5dbb76efc127c1ee052df55873c1723dc"
2
+ __version__ = "3.4.6.dev2"
3
+ __build_date__ = "2025-06-11 08:09:26.576114+00:00"
4
+ __git_commit__ = "4e82c8d6b8d529a8d8804a58781a68023465c7d4"
5
5
  __dirty__ = False
prefect/context.py CHANGED
@@ -492,6 +492,7 @@ class AssetContext(ContextModel):
492
492
  materialized_by: Optional[str] = None
493
493
  task_run_id: Optional[UUID] = None
494
494
  materialization_metadata: dict[str, dict[str, Any]] = Field(default_factory=dict)
495
+ copy_to_child_ctx: bool = False
495
496
 
496
497
  __var__: ClassVar[ContextVar[Self]] = ContextVar("asset_context")
497
498
 
@@ -501,6 +502,7 @@ class AssetContext(ContextModel):
501
502
  task: "Task[Any, Any]",
502
503
  task_run_id: UUID,
503
504
  task_inputs: Optional[dict[str, set[Any]]] = None,
505
+ copy_to_child_ctx: bool = False,
504
506
  ) -> "AssetContext":
505
507
  """
506
508
  Create an AssetContext from a task and its resolved inputs.
@@ -509,6 +511,7 @@ class AssetContext(ContextModel):
509
511
  task: The task instance
510
512
  task_run_id: The task run ID
511
513
  task_inputs: The resolved task inputs (TaskRunResult objects)
514
+ copy_to_child_ctx: Whether this context should be copied on a child AssetContext
512
515
 
513
516
  Returns:
514
517
  Configured AssetContext
@@ -518,13 +521,16 @@ class AssetContext(ContextModel):
518
521
 
519
522
  upstream_assets: set[Asset] = set()
520
523
 
521
- # Get upstream assets from engine context instead of TaskRunResult.assets
522
524
  flow_ctx = FlowRunContext.get()
523
525
  if task_inputs and flow_ctx:
524
- for inputs in task_inputs.values():
526
+ for name, inputs in task_inputs.items():
527
+ # Parent task runs are not dependencies
528
+ # that we want to track
529
+ if name == "__parents__":
530
+ continue
531
+
525
532
  for task_input in inputs:
526
533
  if isinstance(task_input, TaskRunResult):
527
- # Look up assets in the engine context
528
534
  task_assets = flow_ctx.task_run_assets.get(task_input.id)
529
535
  if task_assets:
530
536
  upstream_assets.update(task_assets)
@@ -541,6 +547,7 @@ class AssetContext(ContextModel):
541
547
  if isinstance(task, MaterializingTask)
542
548
  else None,
543
549
  task_run_id=task_run_id,
550
+ copy_to_child_ctx=copy_to_child_ctx,
544
551
  )
545
552
  ctx.update_tracked_assets()
546
553
 
prefect/task_engine.py CHANGED
@@ -454,8 +454,6 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
454
454
  result = state.data
455
455
 
456
456
  link_state_to_result(new_state, result)
457
- if asset_context := AssetContext.get():
458
- asset_context.emit_events(new_state)
459
457
 
460
458
  # emit a state change event
461
459
  self._last_event = emit_task_run_state_change_event(
@@ -641,15 +639,6 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
641
639
  else:
642
640
  persist_result = should_persist_result()
643
641
 
644
- asset_context = AssetContext.get()
645
- if not asset_context:
646
- asset_context = AssetContext.from_task_and_inputs(
647
- task=self.task,
648
- task_run_id=self.task_run.id,
649
- task_inputs=self.task_run.task_inputs,
650
- )
651
- stack.enter_context(asset_context)
652
-
653
642
  stack.enter_context(
654
643
  TaskRunContext(
655
644
  task=self.task,
@@ -672,6 +661,24 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
672
661
 
673
662
  yield
674
663
 
664
+ @contextmanager
665
+ def asset_context(self):
666
+ parent_asset_ctx = AssetContext.get()
667
+
668
+ if parent_asset_ctx and parent_asset_ctx.copy_to_child_ctx:
669
+ asset_ctx = parent_asset_ctx.model_copy()
670
+ asset_ctx.copy_to_child_ctx = False
671
+ else:
672
+ asset_ctx = AssetContext.from_task_and_inputs(
673
+ self.task, self.task_run.id, self.task_run.task_inputs
674
+ )
675
+
676
+ with asset_ctx as ctx:
677
+ try:
678
+ yield
679
+ finally:
680
+ ctx.emit_events(self.state)
681
+
675
682
  @contextmanager
676
683
  def initialize_run(
677
684
  self,
@@ -1032,8 +1039,6 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
1032
1039
  result = new_state.data
1033
1040
 
1034
1041
  link_state_to_result(new_state, result)
1035
- if asset_context := AssetContext.get():
1036
- asset_context.emit_events(new_state)
1037
1042
 
1038
1043
  # emit a state change event
1039
1044
  self._last_event = emit_task_run_state_change_event(
@@ -1219,15 +1224,6 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
1219
1224
  else:
1220
1225
  persist_result = should_persist_result()
1221
1226
 
1222
- asset_context = AssetContext.get()
1223
- if not asset_context:
1224
- asset_context = AssetContext.from_task_and_inputs(
1225
- task=self.task,
1226
- task_run_id=self.task_run.id,
1227
- task_inputs=self.task_run.task_inputs,
1228
- )
1229
- stack.enter_context(asset_context)
1230
-
1231
1227
  stack.enter_context(
1232
1228
  TaskRunContext(
1233
1229
  task=self.task,
@@ -1249,6 +1245,24 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
1249
1245
 
1250
1246
  yield
1251
1247
 
1248
+ @asynccontextmanager
1249
+ async def asset_context(self):
1250
+ parent_asset_ctx = AssetContext.get()
1251
+
1252
+ if parent_asset_ctx and parent_asset_ctx.copy_to_child_ctx:
1253
+ asset_ctx = parent_asset_ctx.model_copy()
1254
+ asset_ctx.copy_to_child_ctx = False
1255
+ else:
1256
+ asset_ctx = AssetContext.from_task_and_inputs(
1257
+ self.task, self.task_run.id, self.task_run.task_inputs
1258
+ )
1259
+
1260
+ with asset_ctx as ctx:
1261
+ try:
1262
+ yield
1263
+ finally:
1264
+ ctx.emit_events(self.state)
1265
+
1252
1266
  @asynccontextmanager
1253
1267
  async def initialize_run(
1254
1268
  self,
@@ -1465,7 +1479,11 @@ def run_task_sync(
1465
1479
  with engine.start(task_run_id=task_run_id, dependencies=dependencies):
1466
1480
  while engine.is_running():
1467
1481
  run_coro_as_sync(engine.wait_until_ready())
1468
- with engine.run_context(), engine.transaction_context() as txn:
1482
+ with (
1483
+ engine.asset_context(),
1484
+ engine.run_context(),
1485
+ engine.transaction_context() as txn,
1486
+ ):
1469
1487
  engine.call_task_fn(txn)
1470
1488
 
1471
1489
  return engine.state if return_type == "state" else engine.result()
@@ -1492,7 +1510,11 @@ async def run_task_async(
1492
1510
  async with engine.start(task_run_id=task_run_id, dependencies=dependencies):
1493
1511
  while engine.is_running():
1494
1512
  await engine.wait_until_ready()
1495
- async with engine.run_context(), engine.transaction_context() as txn:
1513
+ async with (
1514
+ engine.asset_context(),
1515
+ engine.run_context(),
1516
+ engine.transaction_context() as txn,
1517
+ ):
1496
1518
  await engine.call_task_fn(txn)
1497
1519
 
1498
1520
  return engine.state if return_type == "state" else await engine.result()
@@ -1522,7 +1544,11 @@ def run_generator_task_sync(
1522
1544
  with engine.start(task_run_id=task_run_id, dependencies=dependencies):
1523
1545
  while engine.is_running():
1524
1546
  run_coro_as_sync(engine.wait_until_ready())
1525
- with engine.run_context(), engine.transaction_context() as txn:
1547
+ with (
1548
+ engine.asset_context(),
1549
+ engine.run_context(),
1550
+ engine.transaction_context() as txn,
1551
+ ):
1526
1552
  # TODO: generators should default to commit_mode=OFF
1527
1553
  # because they are dynamic by definition
1528
1554
  # for now we just prevent this branch explicitly
@@ -1576,7 +1602,11 @@ async def run_generator_task_async(
1576
1602
  async with engine.start(task_run_id=task_run_id, dependencies=dependencies):
1577
1603
  while engine.is_running():
1578
1604
  await engine.wait_until_ready()
1579
- async with engine.run_context(), engine.transaction_context() as txn:
1605
+ async with (
1606
+ engine.asset_context(),
1607
+ engine.run_context(),
1608
+ engine.transaction_context() as txn,
1609
+ ):
1580
1610
  # TODO: generators should default to commit_mode=OFF
1581
1611
  # because they are dynamic by definition
1582
1612
  # for now we just prevent this branch explicitly
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prefect-client
3
- Version: 3.4.6.dev1
3
+ Version: 3.4.6.dev2
4
4
  Summary: Workflow orchestration and management.
5
5
  Project-URL: Changelog, https://github.com/PrefectHQ/prefect/releases
6
6
  Project-URL: Documentation, https://docs.prefect.io
@@ -1,7 +1,7 @@
1
1
  prefect/.prefectignore,sha256=awSprvKT0vI8a64mEOLrMxhxqcO-b0ERQeYpA2rNKVQ,390
2
2
  prefect/__init__.py,sha256=iCdcC5ZmeewikCdnPEP6YBAjPNV5dvfxpYCTpw30Hkw,3685
3
3
  prefect/__main__.py,sha256=WFjw3kaYJY6pOTA7WDOgqjsz8zUEUZHCcj3P5wyVa-g,66
4
- prefect/_build_info.py,sha256=anQ2Ihm1thsUa1BS14M6szZYmckpRpFzK4RdlenQRwY,185
4
+ prefect/_build_info.py,sha256=V3_F4_IM1pb_b1odsYUDPji-Zd3GoGOPgeSAHUGdDeE,185
5
5
  prefect/_result_records.py,sha256=S6QmsODkehGVSzbMm6ig022PYbI6gNKz671p_8kBYx4,7789
6
6
  prefect/_versioning.py,sha256=YqR5cxXrY4P6LM1Pmhd8iMo7v_G2KJpGNdsf4EvDFQ0,14132
7
7
  prefect/_waiters.py,sha256=Ia2ITaXdHzevtyWIgJoOg95lrEXQqNEOquHvw3T33UQ,9026
@@ -9,7 +9,7 @@ prefect/agent.py,sha256=dPvG1jDGD5HSH7aM2utwtk6RaJ9qg13XjkA0lAIgQmY,287
9
9
  prefect/artifacts.py,sha256=dMBUOAWnUamzjb5HSqwB5-GR2Qb-Gxee26XG5NDCUuw,22720
10
10
  prefect/automations.py,sha256=ZzPxn2tINdlXTQo805V4rIlbXuNWxd7cdb3gTJxZIeY,12567
11
11
  prefect/cache_policies.py,sha256=jH1aDW6vItTcsEytuTCrNYyjbq87IQPwdOgF0yxiUts,12749
12
- prefect/context.py,sha256=5KcO92Us9uGu7ZGyr4xfmTs1K6NgcrRJnEJO_eZMsF0,32342
12
+ prefect/context.py,sha256=9IbfzBrhd6nqVicgcqeAqihRxKUYYZDg-psTByCYcZo,32589
13
13
  prefect/engine.py,sha256=uB5JN4l045i5JTlRQNT1x7MwlSiGQ5Bop2Q6jHHOgxY,3699
14
14
  prefect/exceptions.py,sha256=wZLQQMRB_DyiYkeEdIC5OKwbba5A94Dlnics-lrWI7A,11581
15
15
  prefect/filesystems.py,sha256=v5YqGB4uXf9Ew2VuB9VCSkawvYMMVvEtZf7w1VmAmr8,18036
@@ -24,7 +24,7 @@ prefect/results.py,sha256=Amm3TQu8U_oakSn__tCogIJ5DsTj0w_kLzuENWsxK6A,36824
24
24
  prefect/schedules.py,sha256=dhq4OhImRvcmtxF7UH1m8RbwYdHT5RQsp_FrxVXfODE,7289
25
25
  prefect/serializers.py,sha256=lU9A1rGEfAfhr8nTl3rf-K7ED78QNShXOrmRBhgNk3Y,9566
26
26
  prefect/states.py,sha256=rh7l1bnIYpTXdlXt5nnpz66y9KLjBWAJrN9Eo5RwgQs,26023
27
- prefect/task_engine.py,sha256=fOaEgusqNX0kqjOqG46nLUJc2prqVHvjFmqum0DTrHA,64956
27
+ prefect/task_engine.py,sha256=j7i_UiLvijV4Vut1Bw5-72kSlOqAPxqeS7-3cMVEBPA,65509
28
28
  prefect/task_runners.py,sha256=ptgE5wuXg_IVHM0j7d6l7ELAVg3SXSy4vggnoHRF8dA,17040
29
29
  prefect/task_runs.py,sha256=7LIzfo3fondCyEUpU05sYFN5IfpZigBDXrhG5yc-8t0,9039
30
30
  prefect/task_worker.py,sha256=RifZ3bOl6ppoYPiOAd4TQp2_GEw9eDQoW483rq1q52Q,20805
@@ -325,7 +325,7 @@ prefect/workers/cloud.py,sha256=dPvG1jDGD5HSH7aM2utwtk6RaJ9qg13XjkA0lAIgQmY,287
325
325
  prefect/workers/process.py,sha256=Yi5D0U5AQ51wHT86GdwtImXSefe0gJf3LGq4r4z9zwM,11090
326
326
  prefect/workers/server.py,sha256=2pmVeJZiVbEK02SO6BEZaBIvHMsn6G8LzjW8BXyiTtk,1952
327
327
  prefect/workers/utilities.py,sha256=VfPfAlGtTuDj0-Kb8WlMgAuOfgXCdrGAnKMapPSBrwc,2483
328
- prefect_client-3.4.6.dev1.dist-info/METADATA,sha256=OV-Hx2ECucNwu2iJSuWwT2QLIULHvgVxR2iOQsQzRiE,7517
329
- prefect_client-3.4.6.dev1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
330
- prefect_client-3.4.6.dev1.dist-info/licenses/LICENSE,sha256=MCxsn8osAkzfxKC4CC_dLcUkU8DZLkyihZ8mGs3Ah3Q,11357
331
- prefect_client-3.4.6.dev1.dist-info/RECORD,,
328
+ prefect_client-3.4.6.dev2.dist-info/METADATA,sha256=g3s7EUAokVYJwBVf_kHkf5Qz8_6Q_bF-a5ooMROAONQ,7517
329
+ prefect_client-3.4.6.dev2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
330
+ prefect_client-3.4.6.dev2.dist-info/licenses/LICENSE,sha256=MCxsn8osAkzfxKC4CC_dLcUkU8DZLkyihZ8mGs3Ah3Q,11357
331
+ prefect_client-3.4.6.dev2.dist-info/RECORD,,