dirigent-core 0.16.1__tar.gz → 0.16.2__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 (56) hide show
  1. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/PKG-INFO +4 -4
  2. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/pyproject.toml +4 -4
  3. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/pyproject.toml.orig +4 -4
  4. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/pipelines.py +19 -5
  5. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/protocol.py +11 -1
  6. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/LICENSE +0 -0
  7. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/README.md +0 -0
  8. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/__init__.py +0 -0
  9. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/alembic/env.py +0 -0
  10. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/alembic/script.py.mako +0 -0
  11. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/alembic/versions/0001_baseline_schema.py +0 -0
  12. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/alerting.py +0 -0
  13. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/artifacts.py +0 -0
  14. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/auth.py +0 -0
  15. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/blockdocs.py +0 -0
  16. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/config.py +0 -0
  17. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/configdocs.py +0 -0
  18. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/database.py +0 -0
  19. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/directory.py +0 -0
  20. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/documents.py +0 -0
  21. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/documentschema.py +0 -0
  22. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/engine/__init__.py +0 -0
  23. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/engine/claim.py +0 -0
  24. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/engine/context.py +0 -0
  25. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/engine/definition.py +0 -0
  26. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/engine/executor.py +0 -0
  27. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/engine/failure.py +0 -0
  28. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/engine/recovery.py +0 -0
  29. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/engine/references.py +0 -0
  30. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/engine/runs.py +0 -0
  31. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/engine/services.py +0 -0
  32. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/engine/state.py +0 -0
  33. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/examples.py +0 -0
  34. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/ids.py +0 -0
  35. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/logging.py +0 -0
  36. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/migrations.py +0 -0
  37. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/models.py +0 -0
  38. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/plugins.py +0 -0
  39. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/py.typed +0 -0
  40. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/ratelimit.py +0 -0
  41. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/registry.py +0 -0
  42. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/reporting.py +0 -0
  43. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/retention.py +0 -0
  44. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/scheduler.py +0 -0
  45. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/schemas.py +0 -0
  46. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/secrets.py +0 -0
  47. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/storage.py +0 -0
  48. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/telemetry.py +0 -0
  49. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/trigger_documents.py +0 -0
  50. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/triggers/__init__.py +0 -0
  51. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/triggers/backfill.py +0 -0
  52. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/triggers/materialize.py +0 -0
  53. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/triggers/schedules.py +0 -0
  54. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/triggers/webhooks.py +0 -0
  55. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/types.py +0 -0
  56. {dirigent_core-0.16.1 → dirigent_core-0.16.2}/src/dirigent_core/worker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dirigent-core
3
- Version: 0.16.1
3
+ Version: 0.16.2
4
4
  Summary: Dirigent engine core: schema, configuration, and plugin host.
5
5
  License-Expression: LicenseRef-Proprietary
6
6
  License-File: LICENSE
@@ -10,9 +10,9 @@ Requires-Dist: argon2-cffi>=25.1.0
10
10
  Requires-Dist: asyncpg>=0.31.0
11
11
  Requires-Dist: cronsim>=2.7
12
12
  Requires-Dist: cryptography>=46.0.5
13
- Requires-Dist: dirigent-client
14
- Requires-Dist: dirigent-common
15
- Requires-Dist: dirigent-plugin
13
+ Requires-Dist: dirigent-client==0.16.2
14
+ Requires-Dist: dirigent-common==0.16.2
15
+ Requires-Dist: dirigent-plugin==0.16.2
16
16
  Requires-Dist: jsonschema>=4.26.0
17
17
  Requires-Dist: opentelemetry-api>=1.44.0
18
18
  Requires-Dist: pydantic-settings>=2.15.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dirigent-core"
3
- version = "0.16.1"
3
+ version = "0.16.2"
4
4
  description = "Dirigent engine core: schema, configuration, and plugin host."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -13,9 +13,9 @@ dependencies = [
13
13
  "asyncpg>=0.31.0",
14
14
  "cronsim>=2.7",
15
15
  "cryptography>=46.0.5",
16
- "dirigent-client",
17
- "dirigent-common",
18
- "dirigent-plugin",
16
+ "dirigent-client==0.16.2",
17
+ "dirigent-common==0.16.2",
18
+ "dirigent-plugin==0.16.2",
19
19
  "jsonschema>=4.26.0",
20
20
  "opentelemetry-api>=1.44.0",
21
21
  "pydantic-settings>=2.15.0",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dirigent-core"
3
- version = "0.16.1"
3
+ version = "0.16.2"
4
4
  description = "Dirigent engine core: schema, configuration, and plugin host."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -13,9 +13,9 @@ dependencies = [
13
13
  "asyncpg>=0.31.0",
14
14
  "cronsim>=2.7",
15
15
  "cryptography>=46.0.5",
16
- "dirigent-client",
17
- "dirigent-common",
18
- "dirigent-plugin",
16
+ "dirigent-client==0.16.2",
17
+ "dirigent-common==0.16.2",
18
+ "dirigent-plugin==0.16.2",
19
19
  "jsonschema>=4.26.0",
20
20
  "opentelemetry-api>=1.44.0",
21
21
  "pydantic-settings>=2.15.0",
@@ -471,24 +471,38 @@ async def last_runs(session: AsyncSession, pipeline_ids: Sequence[UUID]) -> dict
471
471
  status=row.status,
472
472
  started_at=row.started_at,
473
473
  finished_at=row.finished_at,
474
- failed_step=failing.get(row.id),
474
+ failed_step=failing[row.id].step if row.id in failing else None,
475
475
  )
476
476
  for row in rows
477
477
  }
478
478
 
479
479
 
480
- async def failing_steps(session: AsyncSession, run_ids: Sequence[UUID]) -> dict[UUID, str]:
481
- """Name the step each run's first failed attempt was of."""
480
+ class FailedStep(NamedTuple):
481
+ """A run's first failed attempt, as a listing names it: which step, and what it said."""
482
+
483
+ step: str
484
+ error: str | None
485
+
486
+
487
+ async def failing_steps(session: AsyncSession, run_ids: Sequence[UUID]) -> dict[UUID, FailedStep]:
488
+ """Name the step each run's first failed attempt was of, and what that attempt said.
489
+
490
+ A run row carries no error of its own unless it was cancelled: what went wrong is written
491
+ on the attempt, so a listing that names the step reads its message from the same row.
492
+ """
482
493
  if not run_ids:
483
494
  return {}
484
495
  ranked = (
485
496
  sa.select(
486
497
  StepAttempt.run_id,
487
498
  StepAttempt.step_name,
499
+ StepAttempt.error,
488
500
  sa.func.row_number().over(partition_by=StepAttempt.run_id, order_by=StepAttempt.id).label("rank"),
489
501
  )
490
502
  .where(StepAttempt.run_id.in_(run_ids), StepAttempt.status == AttemptStatus.FAILED)
491
503
  .subquery()
492
504
  )
493
- rows = await session.execute(sa.select(ranked.c.run_id, ranked.c.step_name).where(ranked.c.rank == 1))
494
- return {run_id: step for run_id, step in rows.all()}
505
+ rows = await session.execute(
506
+ sa.select(ranked.c.run_id, ranked.c.step_name, ranked.c.error).where(ranked.c.rank == 1)
507
+ )
508
+ return {run_id: FailedStep(step, error) for run_id, step, error in rows.all()}
@@ -33,6 +33,10 @@ ABSENT: Final = "-"
33
33
  LEVEL_WIDTH: Final = 8
34
34
  MESSAGE_WIDTH: Final = 30
35
35
 
36
+ #: The first year a zone's offset is a whole-minute standard one everywhere. Before it, a
37
+ #: conversion into the reader's zone spells local mean time rather than a time.
38
+ STANDARD_TIME_YEAR: Final = 1900
39
+
36
40
  #: Nested values are spread into ``prefix.key`` fields for the flat spellings.
37
41
  NESTED_PREFIXES: Final[Mapping[str, str]] = {"output": "output.", "fields": ""}
38
42
 
@@ -173,13 +177,19 @@ def _pad(text: str, width: int) -> str:
173
177
 
174
178
 
175
179
  def _stamp(at: str, *, local: bool) -> str:
176
- """Render an instant for a person: the same moment, in the reader's own offset."""
180
+ """Render an instant for a person: the same moment, in the reader's own offset.
181
+
182
+ A moment from before standard time is left in the spelling it arrived in: a zone's offset
183
+ that far back is its local mean time, and a line reading ``+00:53:28`` says nothing.
184
+ """
177
185
  if not local:
178
186
  return at
179
187
  try:
180
188
  parsed = datetime.fromisoformat(at)
181
189
  except ValueError:
182
190
  return at
191
+ if parsed.year < STANDARD_TIME_YEAR:
192
+ return at
183
193
  return parsed.astimezone().isoformat(timespec="milliseconds")
184
194
 
185
195
 
File without changes
File without changes