dirigent-plugin 0.17.1__tar.gz → 0.17.3__tar.gz

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.
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dirigent-plugin
3
- Version: 0.17.1
3
+ Version: 0.17.3
4
4
  Summary: The dirigent plugin contract: block specs, protocols, and markers.
5
5
  License-Expression: LicenseRef-Proprietary
6
6
  License-File: LICENSE
7
7
  Classifier: Programming Language :: Python :: 3
8
8
  Classifier: Programming Language :: Python :: 3.13
9
- Requires-Dist: dirigent-common==0.17.1
9
+ Requires-Dist: dirigent-common==0.17.3
10
10
  Requires-Dist: httpx2>=2.12.0
11
11
  Requires-Dist: pluginkit>=0.5.0
12
12
  Requires-Dist: pydantic>=2.13.5
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dirigent-plugin"
3
- version = "0.17.1"
3
+ version = "0.17.3"
4
4
  description = "The dirigent plugin contract: block specs, protocols, and markers."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -11,7 +11,7 @@ classifiers = [
11
11
  "Programming Language :: Python :: 3.13",
12
12
  ]
13
13
  dependencies = [
14
- "dirigent-common==0.17.1",
14
+ "dirigent-common==0.17.3",
15
15
  "httpx2>=2.12.0",
16
16
  "pluginkit>=0.5.0",
17
17
  "pydantic>=2.13.5",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dirigent-plugin"
3
- version = "0.17.1"
3
+ version = "0.17.3"
4
4
  description = "The dirigent plugin contract: block specs, protocols, and markers."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -11,7 +11,7 @@ classifiers = [
11
11
  "Programming Language :: Python :: 3.13",
12
12
  ]
13
13
  dependencies = [
14
- "dirigent-common==0.17.1",
14
+ "dirigent-common==0.17.3",
15
15
  "httpx2>=2.12.0",
16
16
  "pluginkit>=0.5.0",
17
17
  "pydantic>=2.13.5",
@@ -10,6 +10,7 @@ from dirigent_plugin.blocks import (
10
10
  AnySensor,
11
11
  BlockFailure,
12
12
  ByteSink,
13
+ Capture,
13
14
  ConnectionKind,
14
15
  ConnectionRef,
15
16
  Contribution,
@@ -74,6 +75,7 @@ __all__ = [
74
75
  "BLOCK_ID_PATTERN",
75
76
  "BlockFailure",
76
77
  "ByteSink",
78
+ "Capture",
77
79
  "ConnectionKind",
78
80
  "ConnectionRef",
79
81
  "Contribution",
@@ -367,6 +367,13 @@ class ByteSink(Protocol):
367
367
  ...
368
368
 
369
369
 
370
+ class Capture(ByteSink, Protocol):
371
+ """The write end of a captured stream, carrying the URI the engine wrote it under."""
372
+
373
+ uri: str
374
+ """Where the whole of the stream is being written, which is what the block's output carries."""
375
+
376
+
370
377
  class Logger(Protocol):
371
378
  """The scoped, batched log writer a block is handed; it produces run-visible entries."""
372
379
 
@@ -572,6 +579,17 @@ class StepContext(Protocol):
572
579
  """Return the run-scoped URI prefix for intermediate artifacts."""
573
580
  ...
574
581
 
582
+ def capture(self, name: str, *, content_type: str = "text/plain") -> AbstractAsyncContextManager[Capture]:
583
+ """Open the storage object a stream this block captures is written to.
584
+
585
+ The engine names the object under the run's scratch prefix, after the step, the
586
+ fan-out item and the attempt, so two attempts of one step never write over each
587
+ other, and opens it with the content type given. A block writes the stream through
588
+ the sink as it arrives and puts the sink's ``uri`` in its output; a block never names
589
+ a storage URI of its own.
590
+ """
591
+ ...
592
+
575
593
  @property
576
594
  def work(self) -> Path:
577
595
  """Return the run's directory on this worker's own filesystem, made on first read.
@@ -613,9 +631,10 @@ class Operator[ConfigT: BaseModel, OutputT: BaseModel](ABC):
613
631
  async def fetch(self, handle: RemoteHandle, config: ConfigT, ctx: StepContext) -> OutputT:
614
632
  """Retrieve the result after a probe reported SUCCEEDED; safe to call again.
615
633
 
616
- The only thing that ends an attempt is the transaction recording its outcome, and a
617
- worker that dies between fetching and that commit leaves the attempt to be claimed,
618
- probed and fetched again. So this is at-least-once: retrieve, do not consume.
634
+ What comes back is committed on its own before the outcome settles the attempt, so a
635
+ replay finds the result and never asks for it twice. A worker that dies between
636
+ fetching and that commit leaves the attempt to be claimed, probed and fetched again,
637
+ so this is still at-least-once: retrieve, do not consume.
619
638
  """
620
639
  raise NotImplementedError(f"{type(self).__name__} returned a RemoteHandle but does not implement fetch()")
621
640