dirigent-testing 0.19.0__tar.gz → 0.21.0__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,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dirigent-testing
3
- Version: 0.19.0
3
+ Version: 0.21.0
4
4
  Summary: Test doubles and pytest fixtures for writing and testing dirigent blocks.
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.19.0
10
- Requires-Dist: dirigent-plugin==0.19.0
9
+ Requires-Dist: dirigent-common==0.21.0
10
+ Requires-Dist: dirigent-plugin==0.21.0
11
11
  Requires-Dist: httpx2>=2.12.0
12
12
  Requires-Dist: pydantic>=2.13.5
13
13
  Requires-Dist: pytest>=9.1.1
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dirigent-testing"
3
- version = "0.19.0"
3
+ version = "0.21.0"
4
4
  description = "Test doubles and pytest fixtures for writing and testing dirigent blocks."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -11,8 +11,8 @@ classifiers = [
11
11
  "Programming Language :: Python :: 3.13",
12
12
  ]
13
13
  dependencies = [
14
- "dirigent-common==0.19.0",
15
- "dirigent-plugin==0.19.0",
14
+ "dirigent-common==0.21.0",
15
+ "dirigent-plugin==0.21.0",
16
16
  "httpx2>=2.12.0",
17
17
  "pydantic>=2.13.5",
18
18
  "pytest>=9.1.1",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dirigent-testing"
3
- version = "0.19.0"
3
+ version = "0.21.0"
4
4
  description = "Test doubles and pytest fixtures for writing and testing dirigent blocks."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -11,8 +11,8 @@ classifiers = [
11
11
  "Programming Language :: Python :: 3.13",
12
12
  ]
13
13
  dependencies = [
14
- "dirigent-common==0.19.0",
15
- "dirigent-plugin==0.19.0",
14
+ "dirigent-common==0.21.0",
15
+ "dirigent-plugin==0.21.0",
16
16
  "httpx2>=2.12.0",
17
17
  "pydantic>=2.13.5",
18
18
  "pytest>=9.1.1",
@@ -4,7 +4,7 @@ from dirigent_testing.conformance import assert_contribution_conforms, check_pac
4
4
  from dirigent_testing.doubles import FakeCapture, FakeContext, FakeRuns, FakeSink, FakeStorage, RecordingLogger
5
5
  from dirigent_testing.environment import CONFIGURING_PREFIXES, TEST_WIDTH, pin_terminal, scrub_configuration
6
6
  from dirigent_testing.fixtures import no_connection_outlives_its_loop
7
- from dirigent_testing.running import call_block
7
+ from dirigent_testing.running import call_block, carry_cursor
8
8
 
9
9
  __all__ = [
10
10
  "CONFIGURING_PREFIXES",
@@ -17,6 +17,7 @@ __all__ = [
17
17
  "RecordingLogger",
18
18
  "assert_contribution_conforms",
19
19
  "call_block",
20
+ "carry_cursor",
20
21
  "check_pack_examples",
21
22
  "no_connection_outlives_its_loop",
22
23
  "pin_terminal",
@@ -226,7 +226,7 @@ class FakeContext:
226
226
  self.started_at = datetime.now(UTC)
227
227
  self.inline_capture = 8 * 1024
228
228
  self.cursor: dict[str, JsonValue] | None = None
229
- """What the last committed ``NotYet`` returned, which a test sets to poke again."""
229
+ """What the next poke is handed: set by a test, or by ``carry_cursor`` as the engine would."""
230
230
  self.params: dict[str, JsonValue] = {}
231
231
  self.log = RecordingLogger()
232
232
  self.connections: dict[str, BaseModel] = {}
@@ -5,7 +5,7 @@ from typing import Any
5
5
 
6
6
  from pydantic import BaseModel
7
7
 
8
- from dirigent_plugin import AnyOperator, AnySensor, Operator, StepContext
8
+ from dirigent_plugin import AnyOperator, AnySensor, NotYet, Operator, StepContext
9
9
  from dirigent_testing.doubles import FakeContext
10
10
 
11
11
 
@@ -25,3 +25,18 @@ async def call_block(
25
25
  if isinstance(block, Operator):
26
26
  return await block.execute(validated, context)
27
27
  return await block.poke(validated, context)
28
+
29
+
30
+ def carry_cursor(sensor: AnySensor, answer: BaseModel, ctx: FakeContext) -> None:
31
+ """Hand the next poke the cursor the engine would, after one poke answered this.
32
+
33
+ A park that returned a cursor replaces the one the context held, and one that returned
34
+ none leaves it. A success hands on what :meth:`Sensor.resume_cursor` says, as a watch
35
+ hands it to the first poke of its next run.
36
+ """
37
+ if isinstance(answer, NotYet):
38
+ if answer.cursor is not None:
39
+ ctx.cursor = dict(answer.cursor)
40
+ return
41
+ resumed = sensor.resume_cursor(answer)
42
+ ctx.cursor = dict(resumed) if resumed is not None else None