pivot 0.2.1__tar.gz → 0.2.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.
- {pivot-0.2.1 → pivot-0.2.2}/PKG-INFO +1 -1
- {pivot-0.2.1 → pivot-0.2.2}/pyproject.toml +1 -1
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/engine/sinks.py +76 -10
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/executor/worker.py +39 -2
- pivot-0.2.2/src/pivot/loaders.py +888 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/show/data.py +3 -4
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/types.py +5 -0
- pivot-0.2.1/src/pivot/loaders.py +0 -389
- {pivot-0.2.1 → pivot-0.2.2}/LICENSE +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/README.md +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/__init__.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/ast_utils.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/AGENTS.md +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/CLAUDE.md +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/__init__.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/_run_common.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/check_ignore.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/checkout.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/commit.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/completion.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/config.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/console.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/dag.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/data.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/decorators.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/doctor.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/errors.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/fingerprint.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/helpers.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/history.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/import_cmd.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/init.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/list.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/metrics.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/params.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/plots.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/remote.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/repro.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/run.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/status.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/targets.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/track.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/update.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/cli/verify.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/compose.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/config/__init__.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/config/io.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/config/models.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/dag/__init__.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/dag/render.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/decorators.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/discovery.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/engine/__init__.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/engine/agent_rpc.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/engine/engine.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/engine/graph.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/engine/scheduler.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/engine/sources.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/engine/types.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/engine/watch.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/engine/worker_pool.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/exceptions.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/executor/AGENTS.md +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/executor/CLAUDE.md +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/executor/__init__.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/executor/commit.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/executor/core.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/explain.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/fingerprint.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/git.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/ignore.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/import_artifact.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/metrics.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/names.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/outputs.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/parameters.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/path_policy.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/project.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/py.typed +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/registry.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/remote/AGENTS.md +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/remote/__init__.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/remote/config.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/remote/git_archive.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/remote/github.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/remote/storage.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/remote/sync.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/run_history.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/show/__init__.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/show/common.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/show/metrics.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/show/params.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/show/plots.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/skip.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/stage_def.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/status.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/storage/AGENTS.md +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/storage/CLAUDE.md +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/storage/__init__.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/storage/artifact_lock.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/storage/cache.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/storage/lock.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/storage/presentation.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/storage/restore.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/storage/state.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/storage/store.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/storage/track.py +0 -0
- {pivot-0.2.1 → pivot-0.2.2}/src/pivot/yaml_config.py +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import dataclasses
|
|
3
4
|
import sys
|
|
4
5
|
import time
|
|
5
6
|
from typing import TYPE_CHECKING
|
|
@@ -10,8 +11,8 @@ import rich.live
|
|
|
10
11
|
import rich.markup
|
|
11
12
|
import rich.text
|
|
12
13
|
|
|
13
|
-
from pivot.engine.types import StageCompleted
|
|
14
|
-
from pivot.types import DisplayCategory, categorize_stage_result
|
|
14
|
+
from pivot.engine.types import LogLine, StageCompleted
|
|
15
|
+
from pivot.types import LOSSY_OUTPUT_PHRASE, DisplayCategory, categorize_stage_result
|
|
15
16
|
|
|
16
17
|
if TYPE_CHECKING:
|
|
17
18
|
from pivot.engine.types import OutputEvent
|
|
@@ -84,6 +85,20 @@ def _categorize(event: StageCompleted) -> DisplayCategory:
|
|
|
84
85
|
return categorize_stage_result(event["status"])
|
|
85
86
|
|
|
86
87
|
|
|
88
|
+
@dataclasses.dataclass
|
|
89
|
+
class _StageWarnings:
|
|
90
|
+
"""A stage's ``WARNING:`` lines for the report.
|
|
91
|
+
|
|
92
|
+
Pivot's own output-write warnings are always kept and print first. The stage's own
|
|
93
|
+
warnings are counted per distinct line (in first-seen order); the report shows the
|
|
94
|
+
first ``_MAX_LOG_LINES_PER_STAGE`` distinct lines and counts the rest.
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
stage: dict[str, int] = dataclasses.field(default_factory=dict[str, int])
|
|
98
|
+
lossy_outputs: list[str] = dataclasses.field(default_factory=list[str])
|
|
99
|
+
dropped: int = 0
|
|
100
|
+
|
|
101
|
+
|
|
87
102
|
def _print_completions(
|
|
88
103
|
console: rich.console.Console,
|
|
89
104
|
events: list[StageCompleted],
|
|
@@ -91,13 +106,19 @@ def _print_completions(
|
|
|
91
106
|
total: int,
|
|
92
107
|
max_name_width: int,
|
|
93
108
|
stage_logs: dict[str, list[str]] | None = None,
|
|
109
|
+
stage_warnings: dict[str, _StageWarnings] | None = None,
|
|
94
110
|
) -> None:
|
|
95
|
-
"""Print buffered completions sorted by index with skip collapsing.
|
|
111
|
+
"""Print buffered completions sorted by index with skip collapsing.
|
|
112
|
+
|
|
113
|
+
A failed stage shows its captured output; any other stage shows the ``WARNING:``
|
|
114
|
+
lines in ``stage_warnings`` (pass None when those already streamed).
|
|
115
|
+
"""
|
|
96
116
|
if not events:
|
|
97
117
|
return
|
|
98
118
|
|
|
99
119
|
sorted_events = sorted(events, key=lambda e: e["index"])
|
|
100
120
|
logs = stage_logs or {}
|
|
121
|
+
warnings_by_stage = stage_warnings or {}
|
|
101
122
|
|
|
102
123
|
i = 0
|
|
103
124
|
while i < len(sorted_events):
|
|
@@ -152,12 +173,53 @@ def _print_completions(
|
|
|
152
173
|
if event["reason"]:
|
|
153
174
|
for detail in _format_error_detail(event["reason"], total=total):
|
|
154
175
|
console.print(detail)
|
|
176
|
+
elif event["stage"] in warnings_by_stage:
|
|
177
|
+
buffered = warnings_by_stage[event["stage"]]
|
|
178
|
+
stage_lines = [
|
|
179
|
+
line if count == 1 else f"{line} (×{count})"
|
|
180
|
+
for line, count in buffered.stage.items()
|
|
181
|
+
]
|
|
182
|
+
for warning_line in [*buffered.lossy_outputs, *stage_lines]:
|
|
183
|
+
escaped = rich.markup.escape(warning_line)
|
|
184
|
+
console.print(f" [yellow]{escaped}[/yellow]")
|
|
185
|
+
if buffered.dropped:
|
|
186
|
+
console.print(
|
|
187
|
+
f" [yellow]… {buffered.dropped} more warnings "
|
|
188
|
+
+ "(run with --show-output)[/yellow]"
|
|
189
|
+
)
|
|
155
190
|
i += 1
|
|
156
191
|
|
|
157
192
|
|
|
158
193
|
_MAX_LOG_LINES_PER_STAGE = 50
|
|
159
194
|
|
|
160
195
|
|
|
196
|
+
def _buffer_log_line(
|
|
197
|
+
event: LogLine,
|
|
198
|
+
stage_logs: dict[str, list[str]],
|
|
199
|
+
stage_warnings: dict[str, _StageWarnings],
|
|
200
|
+
) -> None:
|
|
201
|
+
"""Keep a stage's output for a failure report and its warnings for every report.
|
|
202
|
+
|
|
203
|
+
Warnings have their own buffer: output writes log them after the stage's own output,
|
|
204
|
+
which can already fill the log buffer.
|
|
205
|
+
"""
|
|
206
|
+
line = event["line"]
|
|
207
|
+
buf = stage_logs.setdefault(event["stage"], [])
|
|
208
|
+
if len(buf) < _MAX_LOG_LINES_PER_STAGE:
|
|
209
|
+
buf.append(line)
|
|
210
|
+
if not line.startswith("WARNING:"):
|
|
211
|
+
return
|
|
212
|
+
buffered = stage_warnings.setdefault(event["stage"], _StageWarnings())
|
|
213
|
+
if LOSSY_OUTPUT_PHRASE in line and line.startswith("WARNING: Stage '"):
|
|
214
|
+
buffered.lossy_outputs.append(line)
|
|
215
|
+
elif line in buffered.stage:
|
|
216
|
+
buffered.stage[line] += 1
|
|
217
|
+
elif len(buffered.stage) < _MAX_LOG_LINES_PER_STAGE:
|
|
218
|
+
buffered.stage[line] = 1
|
|
219
|
+
else:
|
|
220
|
+
buffered.dropped += 1
|
|
221
|
+
|
|
222
|
+
|
|
161
223
|
class StaticConsoleSink:
|
|
162
224
|
"""Pipe/CI sink: buffers completions, prints a sorted report when each run ends."""
|
|
163
225
|
|
|
@@ -166,6 +228,7 @@ class StaticConsoleSink:
|
|
|
166
228
|
_max_name_width: int
|
|
167
229
|
_completion_buffer: list[StageCompleted]
|
|
168
230
|
_stage_logs: dict[str, list[str]]
|
|
231
|
+
_stage_warnings: dict[str, _StageWarnings]
|
|
169
232
|
_total: int
|
|
170
233
|
|
|
171
234
|
def __init__(self, *, console: rich.console.Console, show_output: bool = False) -> None:
|
|
@@ -174,6 +237,7 @@ class StaticConsoleSink:
|
|
|
174
237
|
self._max_name_width = 0
|
|
175
238
|
self._completion_buffer = list[StageCompleted]()
|
|
176
239
|
self._stage_logs = dict[str, list[str]]()
|
|
240
|
+
self._stage_warnings = dict[str, _StageWarnings]()
|
|
177
241
|
self._total = 0
|
|
178
242
|
|
|
179
243
|
async def handle(self, event: OutputEvent) -> None:
|
|
@@ -187,11 +251,9 @@ class StaticConsoleSink:
|
|
|
187
251
|
self._max_name_width = max(self._max_name_width, len(event["stage"]))
|
|
188
252
|
self._completion_buffer.append(event)
|
|
189
253
|
case "log_line":
|
|
190
|
-
#
|
|
254
|
+
# Buffer for the report; stream if --show-output
|
|
191
255
|
stage = event["stage"]
|
|
192
|
-
|
|
193
|
-
if len(buf) < _MAX_LOG_LINES_PER_STAGE:
|
|
194
|
-
buf.append(event["line"])
|
|
256
|
+
_buffer_log_line(event, self._stage_logs, self._stage_warnings)
|
|
195
257
|
if self._show_output:
|
|
196
258
|
line = rich.markup.escape(event["line"])
|
|
197
259
|
if event["is_stderr"]:
|
|
@@ -218,10 +280,12 @@ class StaticConsoleSink:
|
|
|
218
280
|
total=self._total,
|
|
219
281
|
max_name_width=self._max_name_width,
|
|
220
282
|
stage_logs=self._stage_logs,
|
|
283
|
+
stage_warnings=None if self._show_output else self._stage_warnings,
|
|
221
284
|
)
|
|
222
285
|
self._max_name_width = 0
|
|
223
286
|
self._completion_buffer.clear()
|
|
224
287
|
self._stage_logs.clear()
|
|
288
|
+
self._stage_warnings.clear()
|
|
225
289
|
self._total = 0
|
|
226
290
|
|
|
227
291
|
async def close(self) -> None:
|
|
@@ -254,6 +318,7 @@ class LiveConsoleSink:
|
|
|
254
318
|
_max_name_width: int
|
|
255
319
|
_completion_buffer: list[StageCompleted]
|
|
256
320
|
_stage_logs: dict[str, list[str]]
|
|
321
|
+
_stage_warnings: dict[str, _StageWarnings]
|
|
257
322
|
_total: int
|
|
258
323
|
_live: rich.live.Live | None
|
|
259
324
|
|
|
@@ -268,6 +333,7 @@ class LiveConsoleSink:
|
|
|
268
333
|
self._max_name_width = 0
|
|
269
334
|
self._completion_buffer = list[StageCompleted]()
|
|
270
335
|
self._stage_logs = dict[str, list[str]]()
|
|
336
|
+
self._stage_warnings = dict[str, _StageWarnings]()
|
|
271
337
|
self._total = 0
|
|
272
338
|
self._live = None
|
|
273
339
|
|
|
@@ -372,9 +438,7 @@ class LiveConsoleSink:
|
|
|
372
438
|
self._update_live()
|
|
373
439
|
case "log_line":
|
|
374
440
|
stage = event["stage"]
|
|
375
|
-
|
|
376
|
-
if len(buf) < _MAX_LOG_LINES_PER_STAGE:
|
|
377
|
-
buf.append(event["line"])
|
|
441
|
+
_buffer_log_line(event, self._stage_logs, self._stage_warnings)
|
|
378
442
|
if self._show_output:
|
|
379
443
|
line = rich.markup.escape(event["line"])
|
|
380
444
|
if event["is_stderr"]:
|
|
@@ -405,6 +469,7 @@ class LiveConsoleSink:
|
|
|
405
469
|
total=self._total,
|
|
406
470
|
max_name_width=self._max_name_width,
|
|
407
471
|
stage_logs=self._stage_logs,
|
|
472
|
+
stage_warnings=None if self._show_output else self._stage_warnings,
|
|
408
473
|
)
|
|
409
474
|
self._running.clear()
|
|
410
475
|
self._completed_count = 0
|
|
@@ -412,6 +477,7 @@ class LiveConsoleSink:
|
|
|
412
477
|
self._max_name_width = 0
|
|
413
478
|
self._completion_buffer.clear()
|
|
414
479
|
self._stage_logs.clear()
|
|
480
|
+
self._stage_warnings.clear()
|
|
415
481
|
self._total = 0
|
|
416
482
|
|
|
417
483
|
async def close(self) -> None:
|
|
@@ -18,6 +18,7 @@ import random
|
|
|
18
18
|
import sys
|
|
19
19
|
import threading
|
|
20
20
|
import traceback
|
|
21
|
+
import warnings
|
|
21
22
|
from typing import IO, TYPE_CHECKING, Any, Literal, NamedTuple, TypedDict, cast, overload, override
|
|
22
23
|
|
|
23
24
|
import pydantic
|
|
@@ -819,6 +820,42 @@ def _write_output_with_store(
|
|
|
819
820
|
_reject_path_inside_project(ref, value, project_root, dependency_paths)
|
|
820
821
|
output_path = store.prepare_output(ref)
|
|
821
822
|
writer = cast("Any", ref.format)
|
|
823
|
+
|
|
824
|
+
output_label = (
|
|
825
|
+
f"its {type(writer).__name__} output"
|
|
826
|
+
if ref.identity.key is None
|
|
827
|
+
else f"output {ref.identity.key!r}"
|
|
828
|
+
)
|
|
829
|
+
|
|
830
|
+
def save_output(output_value: Any, destination: pathlib.Path) -> None:
|
|
831
|
+
with warnings.catch_warnings(record=True) as caught:
|
|
832
|
+
warnings.simplefilter("always", loaders.LossyOutputWarning)
|
|
833
|
+
try:
|
|
834
|
+
writer.save(output_value, destination)
|
|
835
|
+
except TypeError as e:
|
|
836
|
+
if isinstance(writer, loaders.YAML):
|
|
837
|
+
raise TypeError(
|
|
838
|
+
f"Stage '{ref.identity.producer}' cannot write {output_label}: {e}"
|
|
839
|
+
) from e
|
|
840
|
+
raise
|
|
841
|
+
for caught_warning in caught:
|
|
842
|
+
if issubclass(caught_warning.category, loaders.LossyOutputWarning):
|
|
843
|
+
logger.warning(
|
|
844
|
+
"Stage '%s' wrote %s %s: %s",
|
|
845
|
+
ref.identity.producer,
|
|
846
|
+
output_label,
|
|
847
|
+
types.LOSSY_OUTPUT_PHRASE,
|
|
848
|
+
caught_warning.message,
|
|
849
|
+
)
|
|
850
|
+
else:
|
|
851
|
+
warnings.warn_explicit(
|
|
852
|
+
caught_warning.message,
|
|
853
|
+
caught_warning.category,
|
|
854
|
+
caught_warning.filename,
|
|
855
|
+
caught_warning.lineno,
|
|
856
|
+
source=caught_warning.source,
|
|
857
|
+
)
|
|
858
|
+
|
|
822
859
|
if ref.tag is types.ArtifactTag.DIRECTORY:
|
|
823
860
|
if not isinstance(value, dict):
|
|
824
861
|
raise RuntimeError(
|
|
@@ -845,11 +882,11 @@ def _write_output_with_store(
|
|
|
845
882
|
members.append((output_path / normalized, item_value))
|
|
846
883
|
for full_path, item_value in members:
|
|
847
884
|
full_path.parent.mkdir(parents=True, exist_ok=True)
|
|
848
|
-
|
|
885
|
+
save_output(item_value, full_path)
|
|
849
886
|
return output_path
|
|
850
887
|
|
|
851
888
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
852
|
-
|
|
889
|
+
save_output(value, output_path)
|
|
853
890
|
return output_path
|
|
854
891
|
|
|
855
892
|
|