splime 0.3.0__tar.gz → 0.4.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.
- {splime-0.3.0/src/splime.egg-info → splime-0.4.0}/PKG-INFO +1 -1
- {splime-0.3.0 → splime-0.4.0}/pyproject.toml +1 -1
- {splime-0.3.0 → splime-0.4.0}/src/spl/_client.py +150 -22
- {splime-0.3.0 → splime-0.4.0}/src/spl/_views.py +66 -4
- splime-0.4.0/src/spl/core/_common.py +1263 -0
- splime-0.4.0/src/spl/core/adapter_compat.py +459 -0
- splime-0.4.0/src/spl/core/entities/adapter.py +426 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/entities/artifact.py +28 -4
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/entities/function.py +6 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/entities/pipeline.py +201 -41
- splime-0.4.0/src/spl/core/fingerprint.py +201 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/ir/utils.py +3 -1
- splime-0.4.0/src/spl/core/manifest.py +1003 -0
- splime-0.4.0/src/spl/core/node_runtime.py +524 -0
- splime-0.4.0/src/spl/core/resume.py +324 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/canonical.py +33 -2
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/cli.py +88 -4
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/doctor.py +67 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/remote_client.py +3 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/repositories/object.py +4 -0
- splime-0.4.0/src/spl/daemon/repositories/run.py +580 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/routes/runs.py +79 -2
- splime-0.4.0/src/spl/daemon/routes/server_connections.py +155 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/run_progress.py +36 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/runtime_dependencies.py +4 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/server.py +210 -28
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/server_connection.py +50 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/spl_free_runner.py +43 -7
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/storage_base.py +44 -12
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/store.py +33 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/worker.py +280 -35
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon_client.py +151 -0
- {splime-0.3.0 → splime-0.4.0/src/splime.egg-info}/PKG-INFO +1 -1
- {splime-0.3.0 → splime-0.4.0}/src/splime.egg-info/SOURCES.txt +5 -0
- splime-0.3.0/src/spl/core/_common.py +0 -331
- splime-0.3.0/src/spl/core/entities/adapter.py +0 -176
- splime-0.3.0/src/spl/daemon/repositories/run.py +0 -295
- splime-0.3.0/src/spl/daemon/routes/server_connections.py +0 -83
- {splime-0.3.0 → splime-0.4.0}/LICENSE +0 -0
- {splime-0.3.0 → splime-0.4.0}/NOTICE +0 -0
- {splime-0.3.0 → splime-0.4.0}/README.md +0 -0
- {splime-0.3.0 → splime-0.4.0}/setup.cfg +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/__init__.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/_deprecate.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/_http.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/client.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/__init__.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/common.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/entities/__init__.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/entities/control.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/entities/distribution.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/entities/local_function.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/entities/misc.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/entities/module.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/entities/node.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/entities/node_function.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/entities/node_remote.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/entities/scalar.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/ir/__init__.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/ir/common.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/ir/parse.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/core/ir/unparse.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/__init__.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/__main__.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/client.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/docker_environment.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/docker_pool.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/environment.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/environment_base.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/heartbeat_service.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/interpreter_visibility.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/metadata.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/repositories/__init__.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/repositories/env.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/repositories/library.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/repositories/server_connection.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/repositories/sync_event.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/routes/__init__.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/routes/_helpers.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/routes/artifacts.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/routes/diagnostics.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/routes/envs.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/routes/libraries.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/routes/objects.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/routes/remote.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/runtime_backend.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/runtime_config.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/secret_store.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/services/__init__.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/services/sync.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/signature.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/spl_free_generator.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/daemon/worker_runtime_marker.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/pipeline_widget.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/py.typed +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/spl/server_client.py +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/splime.egg-info/dependency_links.txt +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/splime.egg-info/entry_points.txt +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/splime.egg-info/requires.txt +0 -0
- {splime-0.3.0 → splime-0.4.0}/src/splime.egg-info/top_level.txt +0 -0
|
@@ -39,6 +39,7 @@ from spl._views import (
|
|
|
39
39
|
SignatureView,
|
|
40
40
|
wrap_action,
|
|
41
41
|
)
|
|
42
|
+
from spl.core import manifest as m_manifest
|
|
42
43
|
from spl.core.entities.node import DEFAULT_PORT
|
|
43
44
|
from spl.daemon_client import (
|
|
44
45
|
DEFAULT_DAEMON_HOST,
|
|
@@ -71,7 +72,8 @@ def _preview(value: Any, *, limit: int = 80) -> str:
|
|
|
71
72
|
|
|
72
73
|
|
|
73
74
|
def _is_missing_server_connection(exc: Exception) -> bool:
|
|
74
|
-
|
|
75
|
+
message = str(exc)
|
|
76
|
+
return isinstance(exc, ClientError) and _NO_SERVER_CONNECTION_MESSAGE in message
|
|
75
77
|
|
|
76
78
|
|
|
77
79
|
def _progress_callback(progress: ProgressOption) -> RunStateCallback | None:
|
|
@@ -767,11 +769,29 @@ class SPLClient:
|
|
|
767
769
|
return ConnectionStatusView(state)
|
|
768
770
|
|
|
769
771
|
def machines(self) -> dict[str, Any]:
|
|
770
|
-
"""Return the user's machines, or an empty listing when not connected.
|
|
772
|
+
"""Return the user's machines, or an empty listing when not connected.
|
|
771
773
|
|
|
772
|
-
|
|
774
|
+
The connection-state endpoint is probed for health only: a missing
|
|
775
|
+
connection maps to an empty listing and any other state failure
|
|
776
|
+
re-raises (0.3.0 contract). A degraded-but-present state (for
|
|
777
|
+
example ``heartbeat_failed``) must not hide the daemon's machine
|
|
778
|
+
payload, so the state content itself does not gate the listing.
|
|
779
|
+
"""
|
|
780
|
+
|
|
781
|
+
if self.server_connection is None:
|
|
782
|
+
try:
|
|
783
|
+
self._daemon.server_connection()
|
|
784
|
+
except Exception as exc:
|
|
785
|
+
if not _is_missing_server_connection(exc):
|
|
786
|
+
raise
|
|
787
|
+
return MachineListView({"current_machine_id": None, "machines": []})
|
|
788
|
+
try:
|
|
789
|
+
machines = self._daemon.server_machines()
|
|
790
|
+
except Exception as exc:
|
|
791
|
+
if not _is_missing_server_connection(exc):
|
|
792
|
+
raise
|
|
773
793
|
return MachineListView({"current_machine_id": None, "machines": []})
|
|
774
|
-
return MachineListView(
|
|
794
|
+
return MachineListView(machines)
|
|
775
795
|
|
|
776
796
|
def libraries(self, *, include_accessible: bool = True) -> list[dict[str, Any]]:
|
|
777
797
|
"""Return visible libraries, or an empty list when not connected."""
|
|
@@ -1368,10 +1388,89 @@ class SPLClient:
|
|
|
1368
1388
|
"environment build",
|
|
1369
1389
|
)
|
|
1370
1390
|
|
|
1371
|
-
def runs(self) -> list[dict[str, Any]]:
|
|
1391
|
+
def runs(self, *, local: bool = False) -> list[dict[str, Any]]:
|
|
1372
1392
|
"""Return known daemon runs, newest first."""
|
|
1373
1393
|
|
|
1374
|
-
return RunListView(self._daemon.list_runs())
|
|
1394
|
+
return RunListView(m_manifest.list_local_runs() if local else self._daemon.list_runs())
|
|
1395
|
+
|
|
1396
|
+
def run_show(self, run_id: str, *, full_inline: bool = False, local: bool = False) -> dict[str, Any]:
|
|
1397
|
+
"""Return one retained run manifest.
|
|
1398
|
+
|
|
1399
|
+
Inline JSON values are summarized by default; pass ``full_inline=True``
|
|
1400
|
+
to include the full manifest values.
|
|
1401
|
+
"""
|
|
1402
|
+
|
|
1403
|
+
payload = (
|
|
1404
|
+
m_manifest.show_local_run(run_id, include_inline_values=full_inline)
|
|
1405
|
+
if local
|
|
1406
|
+
else self._daemon.show_run(run_id, full_inline=full_inline)
|
|
1407
|
+
)
|
|
1408
|
+
return RunRecordView(payload)
|
|
1409
|
+
|
|
1410
|
+
def resume(
|
|
1411
|
+
self,
|
|
1412
|
+
run_id: str,
|
|
1413
|
+
*,
|
|
1414
|
+
from_: Any,
|
|
1415
|
+
kwargs: dict[str, Any] | None = None,
|
|
1416
|
+
output: str | None = None,
|
|
1417
|
+
timeout_seconds: float | None = None,
|
|
1418
|
+
adapters: dict[str, Any] | None = None,
|
|
1419
|
+
runtimes: dict[str, str] | None = None,
|
|
1420
|
+
keep: bool | str | None = None,
|
|
1421
|
+
wait: bool = False,
|
|
1422
|
+
artifacts_dir: str | Path | None = None,
|
|
1423
|
+
progress: ProgressOption = True,
|
|
1424
|
+
) -> RemoteRun | RemoteResult:
|
|
1425
|
+
"""Resume a retained daemon pipeline run from selected recalculation nodes."""
|
|
1426
|
+
|
|
1427
|
+
state = self._daemon.resume_run(
|
|
1428
|
+
run_id,
|
|
1429
|
+
from_=from_,
|
|
1430
|
+
kwargs=kwargs,
|
|
1431
|
+
output=output,
|
|
1432
|
+
timeout_seconds=timeout_seconds,
|
|
1433
|
+
adapters=adapters,
|
|
1434
|
+
runtimes=runtimes,
|
|
1435
|
+
keep=keep,
|
|
1436
|
+
)
|
|
1437
|
+
run = RemoteRun(self, state)
|
|
1438
|
+
if not wait:
|
|
1439
|
+
return run
|
|
1440
|
+
return run.collect(
|
|
1441
|
+
artifacts_dir=artifacts_dir,
|
|
1442
|
+
timeout_seconds=timeout_seconds,
|
|
1443
|
+
progress=progress,
|
|
1444
|
+
)
|
|
1445
|
+
|
|
1446
|
+
def prune_runs(
|
|
1447
|
+
self,
|
|
1448
|
+
*,
|
|
1449
|
+
run_id: str | None = None,
|
|
1450
|
+
status: str | list[str] | None = None,
|
|
1451
|
+
older_than_seconds: float | None = None,
|
|
1452
|
+
dry_run: bool = False,
|
|
1453
|
+
local: bool = False,
|
|
1454
|
+
) -> dict[str, Any]:
|
|
1455
|
+
"""Prune inactive retained runs by id, status, age, or retention TTL."""
|
|
1456
|
+
|
|
1457
|
+
statuses = [status] if isinstance(status, str) else status
|
|
1458
|
+
result = (
|
|
1459
|
+
m_manifest.prune_local_runs(
|
|
1460
|
+
run_id=run_id,
|
|
1461
|
+
statuses=statuses,
|
|
1462
|
+
older_than_seconds=older_than_seconds,
|
|
1463
|
+
dry_run=dry_run,
|
|
1464
|
+
)
|
|
1465
|
+
if local
|
|
1466
|
+
else self._daemon.prune_runs(
|
|
1467
|
+
run_id=run_id,
|
|
1468
|
+
statuses=statuses,
|
|
1469
|
+
older_than_seconds=older_than_seconds,
|
|
1470
|
+
dry_run=dry_run,
|
|
1471
|
+
)
|
|
1472
|
+
)
|
|
1473
|
+
return wrap_action(result, "runs pruned")
|
|
1375
1474
|
|
|
1376
1475
|
def _start_run(
|
|
1377
1476
|
self,
|
|
@@ -1387,24 +1486,37 @@ class SPLClient:
|
|
|
1387
1486
|
offline_policy: OfflinePolicy | None = None,
|
|
1388
1487
|
function: str | None = None,
|
|
1389
1488
|
source: RunSource = "auto",
|
|
1489
|
+
adapters: Any | None = None,
|
|
1490
|
+
runtimes: dict[str, str] | None = None,
|
|
1491
|
+
keep: bool | str | None = None,
|
|
1390
1492
|
) -> RemoteRun:
|
|
1391
1493
|
"""Shared implementation behind ``submit``/``call`` (and legacy aliases)."""
|
|
1392
1494
|
|
|
1495
|
+
if adapters is not None:
|
|
1496
|
+
raise NotImplementedError(
|
|
1497
|
+
"run-level adapter overrides are supported only by local Deployment.run in 0.4.0; "
|
|
1498
|
+
"SPLClient daemon runs cannot serialize Python adapter callables yet"
|
|
1499
|
+
)
|
|
1500
|
+
|
|
1393
1501
|
remote = target_machine is not None or owner is not None or library is not None
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1502
|
+
run_kwargs: dict[str, Any] = {
|
|
1503
|
+
"args": args,
|
|
1504
|
+
"kwargs": kwargs,
|
|
1505
|
+
"output": output,
|
|
1506
|
+
"timeout_seconds": timeout_seconds,
|
|
1507
|
+
"target_machine": target_machine,
|
|
1508
|
+
"object_owner_id": owner,
|
|
1509
|
+
"library": library,
|
|
1510
|
+
"offline_policy": offline_policy,
|
|
1511
|
+
"function": function,
|
|
1512
|
+
"source": source,
|
|
1513
|
+
"remote": remote or None,
|
|
1514
|
+
}
|
|
1515
|
+
if runtimes is not None:
|
|
1516
|
+
run_kwargs["runtimes"] = runtimes
|
|
1517
|
+
if keep is not None:
|
|
1518
|
+
run_kwargs["keep"] = keep
|
|
1519
|
+
state = self._daemon.run(name, **run_kwargs)
|
|
1408
1520
|
return RemoteRun(self, state, server_side=remote)
|
|
1409
1521
|
|
|
1410
1522
|
# ``start()`` warned through 0.1.4/0.1.5 and was removed in 0.2.0 — use
|
|
@@ -1424,12 +1536,17 @@ class SPLClient:
|
|
|
1424
1536
|
offline_policy: OfflinePolicy | None = None,
|
|
1425
1537
|
function: str | None = None,
|
|
1426
1538
|
source: RunSource = "auto",
|
|
1539
|
+
adapters: Any | None = None,
|
|
1540
|
+
runtimes: dict[str, str] | None = None,
|
|
1541
|
+
keep: bool | str | None = None,
|
|
1427
1542
|
) -> RemoteRun:
|
|
1428
1543
|
"""Canonical async entry point: start a run, return a handle immediately.
|
|
1429
1544
|
|
|
1430
1545
|
The default path is local daemon execution. Passing ``target_machine``,
|
|
1431
1546
|
``owner``, or ``library`` intentionally selects central-server remote
|
|
1432
|
-
execution through the connected daemon.
|
|
1547
|
+
execution through the connected daemon. ``adapters`` is reserved for
|
|
1548
|
+
run-level adapter overrides and currently raises because daemon runs do
|
|
1549
|
+
not serialize Python adapter callables.
|
|
1433
1550
|
"""
|
|
1434
1551
|
|
|
1435
1552
|
return self._start_run(
|
|
@@ -1444,6 +1561,9 @@ class SPLClient:
|
|
|
1444
1561
|
offline_policy=offline_policy,
|
|
1445
1562
|
function=function,
|
|
1446
1563
|
source=source,
|
|
1564
|
+
adapters=adapters,
|
|
1565
|
+
runtimes=runtimes,
|
|
1566
|
+
keep=keep,
|
|
1447
1567
|
)
|
|
1448
1568
|
|
|
1449
1569
|
# ``queue()`` warned through 0.1.4/0.1.5 and was removed in 0.2.0 — use
|
|
@@ -1464,6 +1584,9 @@ class SPLClient:
|
|
|
1464
1584
|
offline_policy: OfflinePolicy | None = None,
|
|
1465
1585
|
function: str | None = None,
|
|
1466
1586
|
source: RunSource = "auto",
|
|
1587
|
+
adapters: Any | None = None,
|
|
1588
|
+
runtimes: dict[str, str] | None = None,
|
|
1589
|
+
keep: bool | str | None = None,
|
|
1467
1590
|
progress: ProgressOption = True,
|
|
1468
1591
|
) -> RemoteResult:
|
|
1469
1592
|
"""Run an object, wait for completion, and return result/artifacts.
|
|
@@ -1476,7 +1599,9 @@ class SPLClient:
|
|
|
1476
1599
|
While waiting, slow phases (a first-run environment build, a queued
|
|
1477
1600
|
server-side run) print short progress lines to stderr. Pass
|
|
1478
1601
|
``progress=False`` to wait silently, or a callable to receive every
|
|
1479
|
-
polled run state instead.
|
|
1602
|
+
polled run state instead. ``adapters`` is reserved for run-level
|
|
1603
|
+
adapter overrides and currently raises because daemon runs do not
|
|
1604
|
+
serialize Python adapter callables.
|
|
1480
1605
|
"""
|
|
1481
1606
|
|
|
1482
1607
|
run = self._start_run(
|
|
@@ -1491,6 +1616,9 @@ class SPLClient:
|
|
|
1491
1616
|
offline_policy=offline_policy,
|
|
1492
1617
|
function=function,
|
|
1493
1618
|
source=source,
|
|
1619
|
+
adapters=adapters,
|
|
1620
|
+
runtimes=runtimes,
|
|
1621
|
+
keep=keep,
|
|
1494
1622
|
)
|
|
1495
1623
|
return run.collect(
|
|
1496
1624
|
artifacts_dir=artifacts_dir,
|
|
@@ -136,6 +136,20 @@ def _status(value: Any) -> str:
|
|
|
136
136
|
return _EMPTY if value is None else str(value)
|
|
137
137
|
|
|
138
138
|
|
|
139
|
+
def _mapping_rows(value: Any) -> list[Mapping[str, Any]]:
|
|
140
|
+
if not isinstance(value, list):
|
|
141
|
+
return []
|
|
142
|
+
return [item for item in value if isinstance(item, Mapping)]
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _adapter_label(row: Mapping[str, Any]) -> str:
|
|
146
|
+
save = row.get("save")
|
|
147
|
+
load = row.get("load")
|
|
148
|
+
if save and load and save != load:
|
|
149
|
+
return "{} -> {}".format(save, load)
|
|
150
|
+
return _EMPTY if save is None and load is None else str(save or load)
|
|
151
|
+
|
|
152
|
+
|
|
139
153
|
class CompactDict(dict[str, Any]):
|
|
140
154
|
"""A dict with compact ``repr`` and plain ``.raw`` access."""
|
|
141
155
|
|
|
@@ -516,6 +530,8 @@ class DecompositionView(CompactDict):
|
|
|
516
530
|
|
|
517
531
|
class RunRecordView(CompactDict):
|
|
518
532
|
title = "run"
|
|
533
|
+
runtime_headers = ("node", "runtime", "source")
|
|
534
|
+
edge_headers = ("edge", "tag", "adapter", "source")
|
|
519
535
|
|
|
520
536
|
def _summary_rows(self) -> list[tuple[str, Any]]:
|
|
521
537
|
result = self.get("result")
|
|
@@ -526,9 +542,13 @@ class RunRecordView(CompactDict):
|
|
|
526
542
|
return [
|
|
527
543
|
("id", self.get("id")),
|
|
528
544
|
("status", self.get("status")),
|
|
545
|
+
("keep", self.get("keep")),
|
|
529
546
|
("mode", self.get("mode") or self.get("source")),
|
|
530
547
|
("object", self.get("object") or self.get("object_name")),
|
|
531
548
|
("output", self.get("output")),
|
|
549
|
+
("parent", self.get("parent_run_id")),
|
|
550
|
+
("manifest", self.get("has_manifest")),
|
|
551
|
+
("disk bytes", self.get("disk_size_bytes")),
|
|
532
552
|
("created", self.get("created_at")),
|
|
533
553
|
("started", self.get("started_at")),
|
|
534
554
|
("finished", self.get("finished_at")),
|
|
@@ -536,10 +556,51 @@ class RunRecordView(CompactDict):
|
|
|
536
556
|
("error", self.get("error")),
|
|
537
557
|
]
|
|
538
558
|
|
|
559
|
+
def _runtime_rows(self) -> list[dict[str, Any]]:
|
|
560
|
+
return [
|
|
561
|
+
{
|
|
562
|
+
"node": item.get("alias") or short_id(item.get("node_id")),
|
|
563
|
+
"runtime": item.get("name"),
|
|
564
|
+
"source": item.get("source"),
|
|
565
|
+
}
|
|
566
|
+
for item in _mapping_rows(self.get("node_runtimes"))
|
|
567
|
+
]
|
|
568
|
+
|
|
569
|
+
def _edge_rows(self) -> list[dict[str, Any]]:
|
|
570
|
+
return [
|
|
571
|
+
{
|
|
572
|
+
"edge": "{} -> {}".format(item.get("source") or _EMPTY, item.get("target") or _EMPTY),
|
|
573
|
+
"tag": item.get("tag"),
|
|
574
|
+
"adapter": _adapter_label(item),
|
|
575
|
+
"source": item.get("source_level"),
|
|
576
|
+
}
|
|
577
|
+
for item in _mapping_rows(self.get("edge_adapters"))
|
|
578
|
+
]
|
|
579
|
+
|
|
580
|
+
def __repr__(self) -> str:
|
|
581
|
+
lines = [details_to_text(self._title, self._summary_rows())]
|
|
582
|
+
runtime_rows = self._runtime_rows()
|
|
583
|
+
edge_rows = self._edge_rows()
|
|
584
|
+
if runtime_rows:
|
|
585
|
+
lines.append(table_to_text("node runtimes", self.runtime_headers, runtime_rows))
|
|
586
|
+
if edge_rows:
|
|
587
|
+
lines.append(table_to_text("edge adapters", self.edge_headers, edge_rows))
|
|
588
|
+
return "\n\n".join(lines)
|
|
589
|
+
|
|
590
|
+
def _repr_html_(self) -> str:
|
|
591
|
+
parts = [details_to_html(self._title, self._summary_rows())]
|
|
592
|
+
runtime_rows = self._runtime_rows()
|
|
593
|
+
edge_rows = self._edge_rows()
|
|
594
|
+
if runtime_rows:
|
|
595
|
+
parts.append(table_to_html("node runtimes", self.runtime_headers, runtime_rows))
|
|
596
|
+
if edge_rows:
|
|
597
|
+
parts.append(table_to_html("edge adapters", self.edge_headers, edge_rows))
|
|
598
|
+
return "".join(parts)
|
|
599
|
+
|
|
539
600
|
|
|
540
601
|
class RunListView(CompactList):
|
|
541
602
|
title = "runs"
|
|
542
|
-
headers = ("id", "status", "
|
|
603
|
+
headers = ("id", "status", "keep", "manifest", "parent", "size", "object", "created")
|
|
543
604
|
|
|
544
605
|
def __init__(self, payload: list[Any] | None = None, *, title: str | None = None):
|
|
545
606
|
super().__init__(
|
|
@@ -556,11 +617,12 @@ class RunListView(CompactList):
|
|
|
556
617
|
{
|
|
557
618
|
"id": short_id(item.get("id")),
|
|
558
619
|
"status": _status(item.get("status")),
|
|
559
|
-
"
|
|
620
|
+
"keep": item.get("keep"),
|
|
621
|
+
"manifest": "yes" if item.get("has_manifest") else "no",
|
|
622
|
+
"parent": short_id(item.get("parent_run_id")),
|
|
623
|
+
"size": item.get("disk_size_bytes"),
|
|
560
624
|
"object": item.get("object") or item.get("object_name"),
|
|
561
|
-
"output": item.get("output"),
|
|
562
625
|
"created": item.get("created_at"),
|
|
563
|
-
"error": item.get("error"),
|
|
564
626
|
}
|
|
565
627
|
for item in self
|
|
566
628
|
if isinstance(item, Mapping)
|