dirigent-client 0.23.4__tar.gz → 0.25.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.
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/PKG-INFO +2 -2
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/pyproject.toml +2 -2
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/pyproject.toml.orig +2 -2
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/__init__.py +24 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/client.py +3 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/enums.py +52 -1
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/pipelines.py +8 -0
- dirigent_client-0.25.0/src/dirigent_client/resources/sources.py +42 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/schemas/__init__.py +22 -5
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/schemas/catalog.py +31 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/schemas/pipelines.py +19 -1
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/schemas/runs.py +16 -0
- dirigent_client-0.25.0/src/dirigent_client/schemas/sources.py +164 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/LICENSE +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/README.md +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/errors.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/messages.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/py.typed +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/__init__.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/alerts.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/auth.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/base.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/blocks.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/connections.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/examples.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/runs.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/schedules.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/schemas.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/system.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/trigger_documents.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/watches.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/webhooks.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/schemas/alerts.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/schemas/auth.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/schemas/common.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/schemas/connections.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/schemas/examples.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/schemas/labels.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/schemas/schemas.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/schemas/system.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/schemas/triggers.py +0 -0
- {dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/transport.py +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dirigent-client
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.25.0
|
|
4
4
|
Summary: The dirigent API contract: typed wire schemas and an async Python client.
|
|
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.
|
|
9
|
+
Requires-Dist: dirigent-common==0.25.0
|
|
10
10
|
Requires-Dist: httpx2>=2.12.0
|
|
11
11
|
Requires-Dist: pydantic>=2.13.5
|
|
12
12
|
Requires-Dist: pyyaml>=6.0.3
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dirigent-client"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.25.0"
|
|
4
4
|
description = "The dirigent API contract: typed wire schemas and an async Python client."
|
|
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.
|
|
14
|
+
"dirigent-common==0.25.0",
|
|
15
15
|
"httpx2>=2.12.0",
|
|
16
16
|
"pydantic>=2.13.5",
|
|
17
17
|
"pyyaml>=6.0.3",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dirigent-client"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.25.0"
|
|
4
4
|
description = "The dirigent API contract: typed wire schemas and an async Python client."
|
|
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.
|
|
14
|
+
"dirigent-common==0.25.0",
|
|
15
15
|
"httpx2>=2.12.0",
|
|
16
16
|
"pydantic>=2.13.5",
|
|
17
17
|
"pyyaml>=6.0.3",
|
|
@@ -6,9 +6,11 @@ from dirigent_client.enums import (
|
|
|
6
6
|
AlertScope,
|
|
7
7
|
AttemptKind,
|
|
8
8
|
AttemptStatus,
|
|
9
|
+
BodyKind,
|
|
9
10
|
DocumentKind,
|
|
10
11
|
FiringOutcome,
|
|
11
12
|
Importance,
|
|
13
|
+
InputOutcome,
|
|
12
14
|
LogLevel,
|
|
13
15
|
NotificationStatus,
|
|
14
16
|
ProvenanceSource,
|
|
@@ -16,6 +18,8 @@ from dirigent_client.enums import (
|
|
|
16
18
|
RunPriority,
|
|
17
19
|
RunStatus,
|
|
18
20
|
ScheduleKind,
|
|
21
|
+
SourceState,
|
|
22
|
+
StepKind,
|
|
19
23
|
TokenKind,
|
|
20
24
|
TriggerKind,
|
|
21
25
|
UserRole,
|
|
@@ -66,12 +70,14 @@ from dirigent_client.schemas import (
|
|
|
66
70
|
DagView,
|
|
67
71
|
DeliveryOut,
|
|
68
72
|
DiffSummary,
|
|
73
|
+
EndpointInput,
|
|
69
74
|
ExampleDetail,
|
|
70
75
|
ExampleOut,
|
|
71
76
|
FiringOut,
|
|
72
77
|
Health,
|
|
73
78
|
HookAccepted,
|
|
74
79
|
Identity,
|
|
80
|
+
InputAccepted,
|
|
75
81
|
IssuedTokenOut,
|
|
76
82
|
ItemOut,
|
|
77
83
|
JsonList,
|
|
@@ -88,6 +94,7 @@ from dirigent_client.schemas import (
|
|
|
88
94
|
PlanAction,
|
|
89
95
|
Problem,
|
|
90
96
|
Readiness,
|
|
97
|
+
RequestFacts,
|
|
91
98
|
Requirements,
|
|
92
99
|
RunAccepted,
|
|
93
100
|
RunDetail,
|
|
@@ -101,6 +108,11 @@ from dirigent_client.schemas import (
|
|
|
101
108
|
SchemaIn,
|
|
102
109
|
SchemaOut,
|
|
103
110
|
SchemaUpdate,
|
|
111
|
+
SourceChanges,
|
|
112
|
+
SourceEntry,
|
|
113
|
+
SourceInputOut,
|
|
114
|
+
SourceOut,
|
|
115
|
+
SourceTokenOut,
|
|
104
116
|
StepReport,
|
|
105
117
|
SurfaceEntry,
|
|
106
118
|
SystemInfo,
|
|
@@ -165,6 +177,17 @@ __all__ = [
|
|
|
165
177
|
"ConnectionOut",
|
|
166
178
|
"ConnectionUpdate",
|
|
167
179
|
"SchemaIn",
|
|
180
|
+
"RequestFacts",
|
|
181
|
+
"EndpointInput",
|
|
182
|
+
"InputAccepted",
|
|
183
|
+
"InputOutcome",
|
|
184
|
+
"SourceChanges",
|
|
185
|
+
"SourceInputOut",
|
|
186
|
+
"SourceOut",
|
|
187
|
+
"SourceState",
|
|
188
|
+
"SourceTokenOut",
|
|
189
|
+
"StepKind",
|
|
190
|
+
"BodyKind",
|
|
168
191
|
"SchemaOut",
|
|
169
192
|
"SchemaUpdate",
|
|
170
193
|
"DagNode",
|
|
@@ -221,6 +244,7 @@ __all__ = [
|
|
|
221
244
|
"SchedulePreviewRequest",
|
|
222
245
|
"ServerError",
|
|
223
246
|
"StepReport",
|
|
247
|
+
"SourceEntry",
|
|
224
248
|
"SurfaceEntry",
|
|
225
249
|
"SystemInfo",
|
|
226
250
|
"TestQueued",
|
|
@@ -16,6 +16,7 @@ from dirigent_client.resources.pipelines import Pipelines
|
|
|
16
16
|
from dirigent_client.resources.runs import Runs
|
|
17
17
|
from dirigent_client.resources.schedules import Schedules
|
|
18
18
|
from dirigent_client.resources.schemas import Schemas
|
|
19
|
+
from dirigent_client.resources.sources import Sources
|
|
19
20
|
from dirigent_client.resources.system import System, Workers
|
|
20
21
|
from dirigent_client.resources.trigger_documents import TriggerDocuments
|
|
21
22
|
from dirigent_client.resources.watches import Watches
|
|
@@ -66,6 +67,7 @@ class Dirigent:
|
|
|
66
67
|
self.schedules = Schedules(self.transport)
|
|
67
68
|
self.webhooks = Webhooks(self.transport)
|
|
68
69
|
self.watches = Watches(self.transport)
|
|
70
|
+
self.sources = Sources(self.transport)
|
|
69
71
|
self.trigger_documents = TriggerDocuments(self.transport)
|
|
70
72
|
self.alerts = Alerts(self.transport)
|
|
71
73
|
self.system = System(self.transport)
|
|
@@ -110,6 +112,7 @@ class BlockingDirigent:
|
|
|
110
112
|
self.schedules = self.client.schedules
|
|
111
113
|
self.webhooks = self.client.webhooks
|
|
112
114
|
self.watches = self.client.watches
|
|
115
|
+
self.sources = self.client.sources
|
|
113
116
|
self.trigger_documents = self.client.trigger_documents
|
|
114
117
|
self.alerts = self.client.alerts
|
|
115
118
|
self.system = self.client.system
|
|
@@ -37,10 +37,23 @@ class AttemptStatus(StrEnum):
|
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
class AttemptKind(StrEnum):
|
|
40
|
-
"""Whether the engine created an attempt
|
|
40
|
+
"""Whether the engine created an attempt, an operator asked for it, or an input arrived as it."""
|
|
41
41
|
|
|
42
42
|
AUTOMATIC = "automatic"
|
|
43
43
|
MANUAL = "manual"
|
|
44
|
+
RECEIVED = "received"
|
|
45
|
+
"""A source node's attempt: written succeeded when the run is created, its output the input."""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class StepKind(StrEnum):
|
|
49
|
+
"""Which of the three forms a step takes: work on a worker, an entry, or an answer."""
|
|
50
|
+
|
|
51
|
+
BLOCK = "block"
|
|
52
|
+
SOURCE = "source"
|
|
53
|
+
"""Where an input enters the pipeline; settled by the server when the run is created."""
|
|
54
|
+
|
|
55
|
+
REPLY = "reply"
|
|
56
|
+
"""A leaf that answers the caller an input arrived from; settled by the server, never claimed."""
|
|
44
57
|
|
|
45
58
|
|
|
46
59
|
class RunItemStatus(StrEnum):
|
|
@@ -102,6 +115,9 @@ class TriggerKind(StrEnum):
|
|
|
102
115
|
WATCH = "watch"
|
|
103
116
|
"""A watch armed this one to wait on its sensor, and ``triggered_by_id`` names the watch."""
|
|
104
117
|
|
|
118
|
+
SOURCE = "source"
|
|
119
|
+
"""An input arrived at a source node, and ``triggered_by_id`` names the source."""
|
|
120
|
+
|
|
105
121
|
|
|
106
122
|
class ScheduleKind(StrEnum):
|
|
107
123
|
"""How a schedule computes its next firing."""
|
|
@@ -175,6 +191,41 @@ class WebhookOutcome(StrEnum):
|
|
|
175
191
|
"""The delivery was refused, and the reason is on the row."""
|
|
176
192
|
|
|
177
193
|
|
|
194
|
+
class SourceState(StrEnum):
|
|
195
|
+
"""Whether a source takes inputs now, read from its row and the runs it has unsettled."""
|
|
196
|
+
|
|
197
|
+
LISTENING = "listening"
|
|
198
|
+
"""It takes inputs."""
|
|
199
|
+
|
|
200
|
+
BACKLOGGED = "backlogged"
|
|
201
|
+
"""As many runs from it are unsettled as ``max_in_flight`` allows; a new input is refused 503."""
|
|
202
|
+
|
|
203
|
+
DRAINING = "draining"
|
|
204
|
+
"""It or its pipeline is paused, and runs it started are still unsettled."""
|
|
205
|
+
|
|
206
|
+
PAUSED = "paused"
|
|
207
|
+
"""It or its pipeline is paused, and nothing it started is unsettled."""
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
class InputOutcome(StrEnum):
|
|
211
|
+
"""What came of one input that reached a source."""
|
|
212
|
+
|
|
213
|
+
ACCEPTED = "accepted"
|
|
214
|
+
"""It became a run, and the caller was answered with where to read it."""
|
|
215
|
+
|
|
216
|
+
REFUSED = "refused"
|
|
217
|
+
"""It was refused before any run existed, and the reason is on the row."""
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
class BodyKind(StrEnum):
|
|
221
|
+
"""How an inbound request's body was read."""
|
|
222
|
+
|
|
223
|
+
NONE = "none"
|
|
224
|
+
JSON = "json"
|
|
225
|
+
FORM = "form"
|
|
226
|
+
TEXT = "text"
|
|
227
|
+
|
|
228
|
+
|
|
178
229
|
class LogLevel(StrEnum):
|
|
179
230
|
"""Severity of a product log entry, which is separate from process logging."""
|
|
180
231
|
|
{dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/pipelines.py
RENAMED
|
@@ -7,6 +7,7 @@ from pathlib import Path
|
|
|
7
7
|
from typing import cast
|
|
8
8
|
|
|
9
9
|
import yaml
|
|
10
|
+
from pydantic import JsonValue
|
|
10
11
|
|
|
11
12
|
from dirigent_client.enums import LogLevel, ProvenanceSource, RunPriority
|
|
12
13
|
from dirigent_client.errors import DirigentError
|
|
@@ -137,6 +138,8 @@ class Pipelines(Resource):
|
|
|
137
138
|
window: tuple[datetime, datetime] | None = None,
|
|
138
139
|
log_levels: dict[str, LogLevel] | None = None,
|
|
139
140
|
priority: RunPriority | None = None,
|
|
141
|
+
source: str | None = None,
|
|
142
|
+
input: JsonValue = None,
|
|
140
143
|
) -> RunAccepted:
|
|
141
144
|
"""Start an ad hoc run, with parameters validated against the pipeline's own schema.
|
|
142
145
|
|
|
@@ -151,9 +154,14 @@ class Pipelines(Resource):
|
|
|
151
154
|
|
|
152
155
|
``priority`` is how far ahead of other runs this one's attempts are claimed; omitted
|
|
153
156
|
takes the pipeline's own.
|
|
157
|
+
|
|
158
|
+
``source`` is the source a run of a pipeline with sources enters at, omitted for its only
|
|
159
|
+
one, and ``input`` is what arrives there, omitted for the source's sample.
|
|
154
160
|
"""
|
|
155
161
|
payload = RunRequest(
|
|
156
162
|
params=params or {},
|
|
163
|
+
source=source,
|
|
164
|
+
input=input,
|
|
157
165
|
window_start=window[0] if window else None,
|
|
158
166
|
window_end=window[1] if window else None,
|
|
159
167
|
log_levels=log_levels,
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""A pipeline's sources: what each listens to, its state, what has arrived, and its token."""
|
|
2
|
+
|
|
3
|
+
from dirigent_client.resources.base import Resource, query
|
|
4
|
+
from dirigent_client.schemas import Page, SourceInputOut, SourceOut, SourceTokenOut
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Sources(Resource):
|
|
8
|
+
"""Read, pause, resume and rotate the sources a pipeline's document declares."""
|
|
9
|
+
|
|
10
|
+
async def list(
|
|
11
|
+
self, pipeline: str | None = None, *, after: str | None = None, limit: int | None = None
|
|
12
|
+
) -> Page[SourceOut]:
|
|
13
|
+
"""List one pipeline's sources, or every pipeline's, never their tokens."""
|
|
14
|
+
path = f"/pipelines/{pipeline}/sources" if pipeline is not None else "/sources"
|
|
15
|
+
return await self._many(SourceOut, "GET", path, params=query(after=after, limit=limit))
|
|
16
|
+
|
|
17
|
+
async def get(self, pipeline: str, code: str) -> SourceOut:
|
|
18
|
+
"""Read one source by its step code, never its token."""
|
|
19
|
+
return await self._one(SourceOut, "GET", f"/pipelines/{pipeline}/sources/{code}")
|
|
20
|
+
|
|
21
|
+
async def pause(self, pipeline: str, code: str) -> SourceOut:
|
|
22
|
+
"""Refuse new inputs with 503, keeping the token and the counts."""
|
|
23
|
+
return await self._one(SourceOut, "POST", f"/pipelines/{pipeline}/sources/{code}/$pause")
|
|
24
|
+
|
|
25
|
+
async def resume(self, pipeline: str, code: str) -> SourceOut:
|
|
26
|
+
"""Take inputs again on the token that was already issued."""
|
|
27
|
+
return await self._one(SourceOut, "POST", f"/pipelines/{pipeline}/sources/{code}/$resume")
|
|
28
|
+
|
|
29
|
+
async def rotate_token(self, pipeline: str, code: str) -> SourceTokenOut:
|
|
30
|
+
"""Mint a new token and forget the old one immediately; every caller has to be given it."""
|
|
31
|
+
return await self._one(SourceTokenOut, "POST", f"/pipelines/{pipeline}/sources/{code}/$rotate-token")
|
|
32
|
+
|
|
33
|
+
async def inputs(
|
|
34
|
+
self, pipeline: str, code: str, *, after: str | None = None, limit: int | None = None
|
|
35
|
+
) -> Page[SourceInputOut]:
|
|
36
|
+
"""Read what has arrived, newest first, refusals included."""
|
|
37
|
+
return await self._many(
|
|
38
|
+
SourceInputOut,
|
|
39
|
+
"GET",
|
|
40
|
+
f"/pipelines/{pipeline}/sources/{code}/inputs",
|
|
41
|
+
params=query(after=after, limit=limit),
|
|
42
|
+
)
|
|
@@ -23,7 +23,7 @@ from dirigent_client.schemas.auth import (
|
|
|
23
23
|
UserOut,
|
|
24
24
|
UserUpdate,
|
|
25
25
|
)
|
|
26
|
-
from dirigent_client.schemas.catalog import BlockEntry, BlockKind, Catalog, SurfaceEntry
|
|
26
|
+
from dirigent_client.schemas.catalog import BlockEntry, BlockKind, Catalog, SourceEntry, SurfaceEntry
|
|
27
27
|
from dirigent_client.schemas.common import Page, Problem
|
|
28
28
|
from dirigent_client.schemas.connections import ConnectionIn, ConnectionOut, ConnectionUpdate
|
|
29
29
|
from dirigent_client.schemas.examples import ExampleDetail, ExampleOut
|
|
@@ -64,6 +64,15 @@ from dirigent_client.schemas.runs import (
|
|
|
64
64
|
StepReport,
|
|
65
65
|
)
|
|
66
66
|
from dirigent_client.schemas.schemas import SchemaIn, SchemaOut, SchemaUpdate
|
|
67
|
+
from dirigent_client.schemas.sources import (
|
|
68
|
+
EndpointInput,
|
|
69
|
+
InputAccepted,
|
|
70
|
+
RequestFacts,
|
|
71
|
+
SourceChanges,
|
|
72
|
+
SourceInputOut,
|
|
73
|
+
SourceOut,
|
|
74
|
+
SourceTokenOut,
|
|
75
|
+
)
|
|
67
76
|
from dirigent_client.schemas.system import (
|
|
68
77
|
CheckResult,
|
|
69
78
|
CheckStatus,
|
|
@@ -100,8 +109,8 @@ __all__ = [
|
|
|
100
109
|
"AttemptEvent",
|
|
101
110
|
"AttemptOut",
|
|
102
111
|
"BackfillAccepted",
|
|
103
|
-
"BackfilledRun",
|
|
104
112
|
"BackfillRequest",
|
|
113
|
+
"BackfilledRun",
|
|
105
114
|
"BlockEntry",
|
|
106
115
|
"BlockKind",
|
|
107
116
|
"Catalog",
|
|
@@ -115,6 +124,8 @@ __all__ = [
|
|
|
115
124
|
"DagView",
|
|
116
125
|
"DeliveryOut",
|
|
117
126
|
"DiffSummary",
|
|
127
|
+
"EndpointInput",
|
|
128
|
+
"InputAccepted",
|
|
118
129
|
"ExampleDetail",
|
|
119
130
|
"ExampleOut",
|
|
120
131
|
"FiringOut",
|
|
@@ -125,11 +136,9 @@ __all__ = [
|
|
|
125
136
|
"ItemOut",
|
|
126
137
|
"JsonList",
|
|
127
138
|
"JsonMap",
|
|
139
|
+
"LOG_NOTIFIER",
|
|
128
140
|
"Labels",
|
|
129
141
|
"LastRun",
|
|
130
|
-
"LOG_NOTIFIER",
|
|
131
|
-
"TEST_BODY",
|
|
132
|
-
"TEST_SUBJECT",
|
|
133
142
|
"LogEntryOut",
|
|
134
143
|
"LoginRequest",
|
|
135
144
|
"Materialized",
|
|
@@ -146,6 +155,11 @@ __all__ = [
|
|
|
146
155
|
"PruneRequest",
|
|
147
156
|
"PruneResult",
|
|
148
157
|
"Readiness",
|
|
158
|
+
"RequestFacts",
|
|
159
|
+
"SourceChanges",
|
|
160
|
+
"SourceInputOut",
|
|
161
|
+
"SourceOut",
|
|
162
|
+
"SourceTokenOut",
|
|
149
163
|
"Requirements",
|
|
150
164
|
"RunAccepted",
|
|
151
165
|
"RunDetail",
|
|
@@ -159,10 +173,13 @@ __all__ = [
|
|
|
159
173
|
"SchemaIn",
|
|
160
174
|
"SchemaOut",
|
|
161
175
|
"SchemaUpdate",
|
|
176
|
+
"SourceEntry",
|
|
162
177
|
"StepReport",
|
|
163
178
|
"SurfaceEntry",
|
|
164
179
|
"SystemInfo",
|
|
165
180
|
"TERMINAL_RUN_STATUSES",
|
|
181
|
+
"TEST_BODY",
|
|
182
|
+
"TEST_SUBJECT",
|
|
166
183
|
"TestQueued",
|
|
167
184
|
"TestRequest",
|
|
168
185
|
"TokenOut",
|
|
@@ -49,6 +49,31 @@ class SurfaceEntry(BaseModel):
|
|
|
49
49
|
declares one. Monochrome: a screen fills it in the ink it draws every other mark in."""
|
|
50
50
|
|
|
51
51
|
|
|
52
|
+
class SourceEntry(BaseModel):
|
|
53
|
+
"""One source kind in the catalog: where an input enters a pipeline, and what it hands on."""
|
|
54
|
+
|
|
55
|
+
kind: str
|
|
56
|
+
"""What a document writes as ``source.kind``."""
|
|
57
|
+
|
|
58
|
+
plugin: str
|
|
59
|
+
summary: str
|
|
60
|
+
hosting: str
|
|
61
|
+
"""Who takes the kind's inputs: ``received`` by the server, ``polled`` or ``held`` by a worker."""
|
|
62
|
+
|
|
63
|
+
replies: bool = False
|
|
64
|
+
"""Whether a reply node may answer an input of this kind."""
|
|
65
|
+
|
|
66
|
+
config_schema: JsonMap = Field(default_factory=dict)
|
|
67
|
+
"""The fields a source node of this kind writes beside ``kind``."""
|
|
68
|
+
|
|
69
|
+
output_schema: JsonMap = Field(default_factory=dict)
|
|
70
|
+
"""The input a source node of this kind hands the step after it."""
|
|
71
|
+
|
|
72
|
+
secret_fields: list[str] = Field(default_factory=list[str])
|
|
73
|
+
mark: str | None = None
|
|
74
|
+
"""The ``d`` of one SVG path on a 24-unit grid this kind is drawn by, where it declares one."""
|
|
75
|
+
|
|
76
|
+
|
|
52
77
|
class Catalog(BaseModel):
|
|
53
78
|
"""The host's merged view of every contribution."""
|
|
54
79
|
|
|
@@ -58,11 +83,17 @@ class Catalog(BaseModel):
|
|
|
58
83
|
storage_schemes: list[SurfaceEntry] = Field(default_factory=list[SurfaceEntry])
|
|
59
84
|
notifiers: list[SurfaceEntry] = Field(default_factory=list[SurfaceEntry])
|
|
60
85
|
connection_kinds: list[SurfaceEntry] = Field(default_factory=list[SurfaceEntry])
|
|
86
|
+
sources: list[SourceEntry] = Field(default_factory=list[SourceEntry])
|
|
87
|
+
"""The source kinds a source node may write."""
|
|
61
88
|
|
|
62
89
|
def block(self, block_id: str) -> BlockEntry | None:
|
|
63
90
|
"""Find one catalog entry by block id."""
|
|
64
91
|
return next((entry for entry in self.blocks if entry.id == block_id), None)
|
|
65
92
|
|
|
93
|
+
def source(self, kind: str) -> SourceEntry | None:
|
|
94
|
+
"""Find one source kind by the ``kind`` a document writes."""
|
|
95
|
+
return next((entry for entry in self.sources if entry.kind == kind), None)
|
|
96
|
+
|
|
66
97
|
@property
|
|
67
98
|
def digest(self) -> str:
|
|
68
99
|
"""Hash the catalog, so a worker registry row can prove code parity across nodes."""
|
|
@@ -5,7 +5,7 @@ from enum import StrEnum
|
|
|
5
5
|
from typing import Any
|
|
6
6
|
from uuid import UUID
|
|
7
7
|
|
|
8
|
-
from pydantic import AliasChoices, BaseModel, ConfigDict, Field, field_validator, model_validator
|
|
8
|
+
from pydantic import AliasChoices, BaseModel, ConfigDict, Field, JsonValue, field_validator, model_validator
|
|
9
9
|
|
|
10
10
|
from dirigent_client.enums import DocumentKind, Importance, LogLevel, ProvenanceSource, RunPriority, RunStatus
|
|
11
11
|
from dirigent_client.messages import (
|
|
@@ -15,6 +15,7 @@ from dirigent_client.messages import (
|
|
|
15
15
|
WINDOW_RUNS_FORWARDS,
|
|
16
16
|
)
|
|
17
17
|
from dirigent_client.schemas.common import WireModel
|
|
18
|
+
from dirigent_client.schemas.sources import SourceChanges
|
|
18
19
|
from dirigent_common import EntityName, Issue, JsonMap, Message
|
|
19
20
|
|
|
20
21
|
|
|
@@ -141,6 +142,20 @@ class RunRequest(BaseModel):
|
|
|
141
142
|
"""Ad hoc run parameters, validated against the pipeline's own schema."""
|
|
142
143
|
|
|
143
144
|
params: JsonMap = Field(default_factory=dict)
|
|
145
|
+
source: str | None = Field(
|
|
146
|
+
default=None,
|
|
147
|
+
description=(
|
|
148
|
+
"The source node a run of a pipeline with sources enters at. Omitted names the "
|
|
149
|
+
"pipeline's only source, and a pipeline with several refuses the run."
|
|
150
|
+
),
|
|
151
|
+
)
|
|
152
|
+
input: JsonValue = Field(
|
|
153
|
+
default=None,
|
|
154
|
+
description=(
|
|
155
|
+
"What arrives at that source, in the shape of its output; what it omits the kind "
|
|
156
|
+
"fills in. Omitted takes the source's sample."
|
|
157
|
+
),
|
|
158
|
+
)
|
|
144
159
|
priority: RunPriority | None = Field(
|
|
145
160
|
default=None,
|
|
146
161
|
description=(
|
|
@@ -381,3 +396,6 @@ class ApplyResult(WireModel):
|
|
|
381
396
|
dry_run: bool = False
|
|
382
397
|
triggers: Materialized = Field(default_factory=Materialized)
|
|
383
398
|
"""Which schedules, webhooks and watches the document's ``triggers:`` section created, changed, or retired."""
|
|
399
|
+
|
|
400
|
+
sources: SourceChanges = Field(default_factory=SourceChanges)
|
|
401
|
+
"""Which source rows the apply created, changed, or retired, and the tokens it minted."""
|
|
@@ -12,6 +12,7 @@ from dirigent_client.enums import (
|
|
|
12
12
|
RunItemStatus,
|
|
13
13
|
RunPriority,
|
|
14
14
|
RunStatus,
|
|
15
|
+
StepKind,
|
|
15
16
|
TriggerKind,
|
|
16
17
|
)
|
|
17
18
|
from dirigent_client.schemas.common import WireModel
|
|
@@ -42,7 +43,13 @@ class RunOut(WireModel):
|
|
|
42
43
|
triggered_by_kind: TriggerKind
|
|
43
44
|
parent_run_id: UUID | None = None
|
|
44
45
|
"""The run whose step started this one, when a step of another run did."""
|
|
46
|
+
triggered_by_id: UUID | None = None
|
|
47
|
+
"""What started the run: the source, schedule, webhook, watch, token or user, as its id."""
|
|
48
|
+
|
|
45
49
|
triggered_by_label: str | None = None
|
|
50
|
+
source: str | None = None
|
|
51
|
+
"""The source node a run of a pipeline with sources entered at, by its step code."""
|
|
52
|
+
|
|
46
53
|
trace_id: str | None = None
|
|
47
54
|
error: str | None = None
|
|
48
55
|
"""What went wrong: the reason a cancel gave, else what the first failed attempt said."""
|
|
@@ -158,7 +165,12 @@ class DagNode(WireModel):
|
|
|
158
165
|
name: str | None = None
|
|
159
166
|
"""The step's human title, when the document gave it one."""
|
|
160
167
|
|
|
168
|
+
kind: StepKind = StepKind.BLOCK
|
|
169
|
+
"""Which form the step takes: a block, a source an input enters at, or a reply."""
|
|
170
|
+
|
|
161
171
|
block: str
|
|
172
|
+
"""The block a block step runs, the kind of a source, or ``reply``."""
|
|
173
|
+
|
|
162
174
|
outcome: str
|
|
163
175
|
depends_on: list[str] = Field(default_factory=list[str])
|
|
164
176
|
rule: str
|
|
@@ -166,6 +178,10 @@ class DagNode(WireModel):
|
|
|
166
178
|
grid_source: str | None = None
|
|
167
179
|
"""The step a late grid waits for before it expands, or null for a grid fixed at creation."""
|
|
168
180
|
|
|
181
|
+
item_wise_parent: str | None = None
|
|
182
|
+
"""The fan-out whose matching item each of this step's items waits for, one by one, or null
|
|
183
|
+
when the step waits for its prerequisites whole."""
|
|
184
|
+
|
|
169
185
|
items_total: int = 0
|
|
170
186
|
items_failed: int = 0
|
|
171
187
|
attempts: int = 0
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""Sources: what an input arrives as, the source rows that take inputs, and their journal."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from uuid import UUID
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field, JsonValue
|
|
7
|
+
|
|
8
|
+
from dirigent_client.enums import BodyKind, InputOutcome, SourceState
|
|
9
|
+
from dirigent_client.schemas.common import WireModel
|
|
10
|
+
from dirigent_common import JsonMap
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class RequestFacts(BaseModel):
|
|
14
|
+
"""What an HTTP request arrived as, read once: the shape the playground and an endpoint share."""
|
|
15
|
+
|
|
16
|
+
model_config = ConfigDict(use_attribute_docstrings=True)
|
|
17
|
+
|
|
18
|
+
method: str
|
|
19
|
+
"""The HTTP method the call was made with."""
|
|
20
|
+
|
|
21
|
+
path: str
|
|
22
|
+
"""The concrete path, without the query."""
|
|
23
|
+
|
|
24
|
+
query: dict[str, JsonValue] = Field(default_factory=dict[str, JsonValue])
|
|
25
|
+
"""The query arguments as strings, with a repeated name arriving as a list."""
|
|
26
|
+
|
|
27
|
+
headers: dict[str, str] = Field(default_factory=dict[str, str])
|
|
28
|
+
"""The request headers, lowercased."""
|
|
29
|
+
|
|
30
|
+
content_type: str | None = None
|
|
31
|
+
"""The content type the body arrived under, as the header spelled it."""
|
|
32
|
+
|
|
33
|
+
body_kind: BodyKind = BodyKind.NONE
|
|
34
|
+
"""How the body was read. A body appears once, in ``body``."""
|
|
35
|
+
|
|
36
|
+
body: JsonValue = None
|
|
37
|
+
"""The body, decoded the way ``body_kind`` says. Null when there was none."""
|
|
38
|
+
|
|
39
|
+
body_bytes: int = 0
|
|
40
|
+
"""How large the body was, in bytes."""
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class EndpointInput(RequestFacts):
|
|
44
|
+
"""The output of an endpoint source, which is the input its pipeline's next steps read.
|
|
45
|
+
|
|
46
|
+
``headers`` never carries the credential the caller presented: ``authorization``, the
|
|
47
|
+
cookie and the signature header are removed before the input is written.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
route: str
|
|
51
|
+
"""The template the source declares, which the concrete path matched."""
|
|
52
|
+
|
|
53
|
+
path_params: dict[str, str] = Field(default_factory=dict[str, str])
|
|
54
|
+
"""What each ``{name}`` in the template matched, as a string."""
|
|
55
|
+
|
|
56
|
+
received_at: datetime
|
|
57
|
+
"""When the input arrived, or when a hand run supplied it."""
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class SourceOut(WireModel):
|
|
61
|
+
"""A source as a listing shows it: what it listens to, its state, and what it has taken, never its token."""
|
|
62
|
+
|
|
63
|
+
model_config = ConfigDict(use_attribute_docstrings=True)
|
|
64
|
+
|
|
65
|
+
id: UUID
|
|
66
|
+
pipeline: str
|
|
67
|
+
"""The code of the pipeline the source belongs to."""
|
|
68
|
+
|
|
69
|
+
code: str
|
|
70
|
+
"""The source's step key."""
|
|
71
|
+
|
|
72
|
+
name: str | None = None
|
|
73
|
+
description: str | None = None
|
|
74
|
+
kind: str
|
|
75
|
+
state: SourceState
|
|
76
|
+
methods: list[str] = Field(default_factory=list[str])
|
|
77
|
+
"""The methods a received source answers; empty for a kind the server does not receive."""
|
|
78
|
+
|
|
79
|
+
route: str | None = None
|
|
80
|
+
"""The template a received source answers, under the instance's endpoint prefix."""
|
|
81
|
+
|
|
82
|
+
url_path: str | None = None
|
|
83
|
+
"""Where a received source is called: the endpoint prefix and the template."""
|
|
84
|
+
|
|
85
|
+
auth: str | None = None
|
|
86
|
+
"""How a caller of a received source authenticates: ``token`` or ``public``."""
|
|
87
|
+
|
|
88
|
+
token_prefix: str | None = None
|
|
89
|
+
"""The leading characters of the token, so a caller's copy can be told apart from another."""
|
|
90
|
+
|
|
91
|
+
in_flight: int = 0
|
|
92
|
+
"""How many runs it started are unsettled."""
|
|
93
|
+
|
|
94
|
+
max_in_flight: int | None = None
|
|
95
|
+
"""How many unsettled runs it allows before refusing an input, or null for no bound."""
|
|
96
|
+
|
|
97
|
+
accepted: int = 0
|
|
98
|
+
"""How many inputs became runs."""
|
|
99
|
+
|
|
100
|
+
refused: int = 0
|
|
101
|
+
"""How many inputs were refused once their caller was let in."""
|
|
102
|
+
|
|
103
|
+
last_input_at: datetime | None = None
|
|
104
|
+
created_at: datetime
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class SourceTokenOut(WireModel):
|
|
108
|
+
"""A token freshly minted for a source, returned once and never readable again."""
|
|
109
|
+
|
|
110
|
+
source_id: UUID
|
|
111
|
+
pipeline: str
|
|
112
|
+
code: str
|
|
113
|
+
token: str
|
|
114
|
+
prefix: str
|
|
115
|
+
url_path: str
|
|
116
|
+
"""Where the source is called, so a caller can be configured without assembling the path by hand."""
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class SourceChanges(WireModel):
|
|
120
|
+
"""What applying a document did to the source rows its pipeline holds."""
|
|
121
|
+
|
|
122
|
+
created: list[str] = Field(default_factory=list[str])
|
|
123
|
+
updated: list[str] = Field(default_factory=list[str])
|
|
124
|
+
removed: list[str] = Field(default_factory=list[str])
|
|
125
|
+
tokens: list[SourceTokenOut] = Field(default_factory=list[SourceTokenOut])
|
|
126
|
+
"""The tokens minted for the sources this apply created, each shown here and nowhere else again."""
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def empty(self) -> bool:
|
|
130
|
+
"""Report whether the apply left every source row exactly as it was."""
|
|
131
|
+
return not (self.created or self.updated or self.removed)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class SourceInputOut(WireModel):
|
|
135
|
+
"""One input that reached a source, and the run or the refusal it became."""
|
|
136
|
+
|
|
137
|
+
id: int
|
|
138
|
+
created_at: datetime
|
|
139
|
+
outcome: InputOutcome
|
|
140
|
+
status: int
|
|
141
|
+
"""The HTTP status the caller was answered with."""
|
|
142
|
+
|
|
143
|
+
run_id: UUID | None = None
|
|
144
|
+
code: str | None = None
|
|
145
|
+
"""The refusal's message code, or null for an accepted input."""
|
|
146
|
+
|
|
147
|
+
reason: str | None = None
|
|
148
|
+
params: JsonMap | None = None
|
|
149
|
+
method: str
|
|
150
|
+
path: str
|
|
151
|
+
body_bytes: int = 0
|
|
152
|
+
duration_ms: int = 0
|
|
153
|
+
caller: str | None = None
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class InputAccepted(WireModel):
|
|
157
|
+
"""What a caller of a source is answered with when its input became a run."""
|
|
158
|
+
|
|
159
|
+
run_id: UUID
|
|
160
|
+
status: str
|
|
161
|
+
"""The status the run was created in."""
|
|
162
|
+
|
|
163
|
+
run_url: str
|
|
164
|
+
"""Where the run is read, under the versioned API."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/connections.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/schedules.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/resources/trigger_documents.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dirigent_client-0.23.4 → dirigent_client-0.25.0}/src/dirigent_client/schemas/connections.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|