dirigent-cli 0.16.1__tar.gz → 0.16.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.
Files changed (35) hide show
  1. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/PKG-INFO +8 -8
  2. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/pyproject.toml +8 -8
  3. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/pyproject.toml.orig +8 -8
  4. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/commands.py +18 -6
  5. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/LICENSE +0 -0
  6. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/README.md +0 -0
  7. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/__init__.py +0 -0
  8. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/aliases.py +0 -0
  9. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/context.py +0 -0
  10. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/formatters.py +0 -0
  11. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/graph.py +0 -0
  12. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/health.py +0 -0
  13. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/init_form.py +0 -0
  14. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/local.py +0 -0
  15. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/main.py +0 -0
  16. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/output.py +0 -0
  17. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/params.py +0 -0
  18. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/profiles.py +0 -0
  19. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/project.py +0 -0
  20. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/py.typed +0 -0
  21. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/reaper.py +0 -0
  22. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/scaffold.py +0 -0
  23. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/schemas.py +0 -0
  24. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/seeding.py +0 -0
  25. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/sources.py +0 -0
  26. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/starters.py +0 -0
  27. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/stream.py +0 -0
  28. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/summaries.py +0 -0
  29. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/templates/pack/README.md.tmpl +0 -0
  30. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/templates/pack/__init__.py.tmpl +0 -0
  31. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/templates/pack/operator.py.tmpl +0 -0
  32. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/templates/pack/pyproject.toml.tmpl +0 -0
  33. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/templates/pack/test_plugin.py.tmpl +0 -0
  34. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/timing.py +0 -0
  35. {dirigent_cli-0.16.1 → dirigent_cli-0.16.3}/src/dirigent_cli/triggers.py +0 -0
@@ -1,16 +1,16 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dirigent-cli
3
- Version: 0.16.1
3
+ Version: 0.16.3
4
4
  Summary: The dirigent command line interface (dirigent / dg).
5
5
  License-Expression: LicenseRef-Proprietary
6
6
  License-File: LICENSE
7
- Requires-Dist: dirigent-blocks
8
- Requires-Dist: dirigent-client
9
- Requires-Dist: dirigent-common
10
- Requires-Dist: dirigent-core
11
- Requires-Dist: dirigent-examples
12
- Requires-Dist: dirigent-plugin
13
- Requires-Dist: dirigent-server
7
+ Requires-Dist: dirigent-blocks==0.16.3
8
+ Requires-Dist: dirigent-client==0.16.3
9
+ Requires-Dist: dirigent-common==0.16.3
10
+ Requires-Dist: dirigent-core==0.16.3
11
+ Requires-Dist: dirigent-examples==0.16.3
12
+ Requires-Dist: dirigent-plugin==0.16.3
13
+ Requires-Dist: dirigent-server==0.16.3
14
14
  Requires-Dist: httpx2>=2.12.0
15
15
  Requires-Dist: python-dotenv>=1.1.0
16
16
  Requires-Dist: pyyaml>=6.0.3
@@ -1,19 +1,19 @@
1
1
  [project]
2
2
  name = "dirigent-cli"
3
- version = "0.16.1"
3
+ version = "0.16.3"
4
4
  description = "The dirigent command line interface (dirigent / dg)."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
7
7
  license = "LicenseRef-Proprietary"
8
8
  license-files = ["LICENSE"]
9
9
  dependencies = [
10
- "dirigent-blocks",
11
- "dirigent-client",
12
- "dirigent-common",
13
- "dirigent-core",
14
- "dirigent-examples",
15
- "dirigent-plugin",
16
- "dirigent-server",
10
+ "dirigent-blocks==0.16.3",
11
+ "dirigent-client==0.16.3",
12
+ "dirigent-common==0.16.3",
13
+ "dirigent-core==0.16.3",
14
+ "dirigent-examples==0.16.3",
15
+ "dirigent-plugin==0.16.3",
16
+ "dirigent-server==0.16.3",
17
17
  "httpx2>=2.12.0",
18
18
  "python-dotenv>=1.1.0",
19
19
  "pyyaml>=6.0.3",
@@ -1,19 +1,19 @@
1
1
  [project]
2
2
  name = "dirigent-cli"
3
- version = "0.16.1"
3
+ version = "0.16.3"
4
4
  description = "The dirigent command line interface (dirigent / dg)."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
7
7
  license = "LicenseRef-Proprietary"
8
8
  license-files = ["LICENSE"]
9
9
  dependencies = [
10
- "dirigent-blocks",
11
- "dirigent-client",
12
- "dirigent-common",
13
- "dirigent-core",
14
- "dirigent-examples",
15
- "dirigent-plugin",
16
- "dirigent-server",
10
+ "dirigent-blocks==0.16.3",
11
+ "dirigent-client==0.16.3",
12
+ "dirigent-common==0.16.3",
13
+ "dirigent-core==0.16.3",
14
+ "dirigent-examples==0.16.3",
15
+ "dirigent-plugin==0.16.3",
16
+ "dirigent-server==0.16.3",
17
17
  "httpx2>=2.12.0",
18
18
  "python-dotenv>=1.1.0",
19
19
  "pyyaml>=6.0.3",
@@ -1467,20 +1467,29 @@ _LOG_SECOND = 1
1467
1467
  #: One thing that happened, in the order it happened: when, its tie-break rank, and what.
1468
1468
  type WatchEvent = tuple[datetime, int, AttemptOut | LogEntryOut, str | None]
1469
1469
 
1470
+ #: The sort key of something the server put no clock on at all, which orders before every
1471
+ #: real instant. It is an ordering device: no record is stamped with it.
1472
+ UNTIMED: Final = datetime.min.replace(tzinfo=UTC)
1473
+
1470
1474
 
1471
1475
  def moment_of(value: object) -> datetime:
1472
1476
  """Read a server timestamp for ordering, treating a missing one as the beginning of time."""
1473
1477
  if isinstance(value, datetime):
1474
1478
  return value if value.tzinfo is not None else value.replace(tzinfo=UTC)
1475
1479
  if not isinstance(value, str):
1476
- return datetime.min.replace(tzinfo=UTC)
1480
+ return UNTIMED
1477
1481
  try:
1478
1482
  parsed = datetime.fromisoformat(value)
1479
1483
  except ValueError: # pragma: no cover - the server writes ISO instants
1480
- return datetime.min.replace(tzinfo=UTC)
1484
+ return UNTIMED
1481
1485
  return parsed if parsed.tzinfo is not None else parsed.replace(tzinfo=UTC)
1482
1486
 
1483
1487
 
1488
+ def stamped(when: datetime) -> datetime:
1489
+ """Read the instant a record carries: the one it was ordered by, or now when it has none."""
1490
+ return datetime.now(UTC) if when == UNTIMED else when
1491
+
1492
+
1484
1493
  def item_labels(items: Sequence[ItemOut], attempts: Sequence[AttemptOut]) -> dict[UUID, str]:
1485
1494
  """Map each attempt of a fan-out step to the element it was created for."""
1486
1495
  keys = {item.id: item.item_key.strip() or str(item.item_index) for item in items}
@@ -1531,13 +1540,16 @@ def transition_event(attempt: AttemptEvent, seen: dict[str, str]) -> list[WatchE
1531
1540
  """Report one streamed attempt when it has moved since the stream last named it.
1532
1541
 
1533
1542
  The server replays every attempt on connect and after a reconnection, so an attempt in a
1534
- state already printed is nothing to say.
1543
+ state already printed is nothing to say. A queued attempt has neither started nor
1544
+ finished, so the moment it reached the state it is being announced in is when it was
1545
+ written down.
1535
1546
  """
1536
1547
  key = f"{attempt.step_name}#{attempt.item or ''}#{attempt.attempt}"
1537
1548
  if seen.get(key) == attempt.status.value or attempt.status is AttemptStatus.PENDING:
1538
1549
  return []
1539
1550
  seen[key] = attempt.status.value
1540
- return [(moment_of(attempt.finished_at or attempt.started_at), _TRANSITION_FIRST, attempt, attempt.item)]
1551
+ when = attempt.finished_at or attempt.started_at or attempt.created_at
1552
+ return [(moment_of(when), _TRANSITION_FIRST, attempt, attempt.item)]
1541
1553
 
1542
1554
 
1543
1555
  def log_events(entries: list[LogEntryOut], labels: dict[UUID, str] | None = None) -> list[WatchEvent]:
@@ -1568,7 +1580,7 @@ def print_events(events: list[WatchEvent], level: Detail = Detail.SUMMARY, *, ou
1568
1580
  continue
1569
1581
  writer.event(
1570
1582
  "step",
1571
- at=when,
1583
+ at=stamped(when),
1572
1584
  step=subject.step_name,
1573
1585
  item=label,
1574
1586
  message=subject.status.value,
@@ -1582,7 +1594,7 @@ def print_events(events: list[WatchEvent], level: Detail = Detail.SUMMARY, *, ou
1582
1594
  continue
1583
1595
  writer.event(
1584
1596
  "output",
1585
- at=when,
1597
+ at=stamped(when),
1586
1598
  step=subject.step_name,
1587
1599
  item=label,
1588
1600
  message=subject.status.value,
File without changes
File without changes