From 2989fba99c6a955515d784d2c496ac80223732f9 Mon Sep 17 00:00:00 2001 From: DCCONSTRUCTIONS Date: Mon, 31 Aug 2026 19:58:20 +0300 Subject: [PATCH] fix(lab): support legacy Python 3.9 adapters --- .../Install-LabV1ComponentAdapterImages.ps1 | 4 ++-- .../portable_lab_v1_component_adapter.py | 18 +++++++++--------- .../run_portable_lab_v1_ddrnet_component.py | 2 +- ...lab_v1_component_adapter_image_installer.py | 4 ++-- ...atory_portable_lab_v1_component_adapters.py | 13 +++++++++++++ 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/experiments/perception/worker/observatory_portable/Install-LabV1ComponentAdapterImages.ps1 b/experiments/perception/worker/observatory_portable/Install-LabV1ComponentAdapterImages.ps1 index 854ad5a..3a58782 100644 --- a/experiments/perception/worker/observatory_portable/Install-LabV1ComponentAdapterImages.ps1 +++ b/experiments/perception/worker/observatory_portable/Install-LabV1ComponentAdapterImages.ps1 @@ -11,7 +11,7 @@ $ProgressPreference = "SilentlyContinue" $RuntimeRoot = [IO.Path]::GetFullPath("D:\NDC_MISSIONCORE\runtime").TrimEnd("\") $BuildRoot = Join-Path $RuntimeRoot "staging\observatory-lab-v1-build-$SourceRevision" -$SharedAdapterSha256 = "fb208c6cd337153827147006cd26bf4c1c00963f91eb801280485dbc7213d08b" +$SharedAdapterSha256 = "91c1878a58acf3ac35ce894f4de9b63cba3b7f29a65548e28df176063a2953c9" $BuildMethod = "docker-commit-exact-layer-v1" $MaximumLayerBytes = [int64](16MB) @@ -34,7 +34,7 @@ $Components = [ordered]@{ "ddrnet" = [pscustomobject]@{ base_image_sha256 = "591cb382c099eeb05e7ec16e2371e0b2da54d2bb5c49ec0f4ac88dbf72b0f0cd" adapter_name = "run_portable_lab_v1_ddrnet_component.py" - adapter_sha256 = "d2af887b065b0f63890768d59247114e49b70ad490c027f20eefd98682636c3c" + adapter_sha256 = "a398a43fe4069bf1b1fc2ec61b44df53dad6072cccb6d10a2627e76a96a94056" python_check = "conda run --no-capture-output --name goose python -B -m py_compile" entrypoint = '["conda","run","--no-capture-output","--name","goose","python"]' command = '["/opt/nodedc/adapter/run_portable_lab_v1_ddrnet_component.py"]' diff --git a/experiments/perception/worker/observatory_portable/portable_lab_v1_component_adapter.py b/experiments/perception/worker/observatory_portable/portable_lab_v1_component_adapter.py index 6d6e1ca..c1d5aa9 100644 --- a/experiments/perception/worker/observatory_portable/portable_lab_v1_component_adapter.py +++ b/experiments/perception/worker/observatory_portable/portable_lab_v1_component_adapter.py @@ -70,17 +70,17 @@ _SAFE_COMPONENT = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$") _OBSERVATORY_JOB_ID = re.compile(r"^observatory-run-[a-f0-9]{32}$") _CAMERA_JOB_ID = re.compile(r"^recorded-camera-[a-f0-9]{24}$") -type Component = Literal["eomt", "ddrnet"] -type AssetKind = Literal["file", "tree"] -type AssetVerification = Literal["sha256", "identity-sha256"] -type CommandRunner = Callable[[Sequence[str], Mapping[str, str] | None], None] +Component = Literal["eomt", "ddrnet"] +AssetKind = Literal["file", "tree"] +AssetVerification = Literal["sha256", "identity-sha256"] +CommandRunner = Callable[[Sequence[str], Mapping[str, str] | None], None] class ComponentAdapterError(RuntimeError): """A sealed request, mounted input, or component output changed.""" -@dataclass(frozen=True, slots=True) +@dataclass(frozen=True) class AssetExpectation: asset_id: str path: str @@ -102,7 +102,7 @@ class AssetExpectation: raise ValueError("asset expectation byte length is invalid") -@dataclass(frozen=True, slots=True) +@dataclass(frozen=True) class AssetBinding: asset_id: str path: str @@ -112,7 +112,7 @@ class AssetBinding: byte_length: int | None -@dataclass(frozen=True, slots=True) +@dataclass(frozen=True) class SourceBinding: observatory_job_id: str source_session_id: str @@ -126,7 +126,7 @@ class SourceBinding: timeline_end_seconds: float -@dataclass(frozen=True, slots=True) +@dataclass(frozen=True) class ComponentRequest: component: Component component_image_sha256: str @@ -139,7 +139,7 @@ class ComponentRequest: assets: Mapping[str, AssetBinding] -@dataclass(frozen=True, slots=True) +@dataclass(frozen=True) class RuntimeLayout: """Runtime-only test seam; production entrypoints use ``fixed()`` only.""" diff --git a/experiments/perception/worker/observatory_portable/run_portable_lab_v1_ddrnet_component.py b/experiments/perception/worker/observatory_portable/run_portable_lab_v1_ddrnet_component.py index 2d16642..63a83aa 100644 --- a/experiments/perception/worker/observatory_portable/run_portable_lab_v1_ddrnet_component.py +++ b/experiments/perception/worker/observatory_portable/run_portable_lab_v1_ddrnet_component.py @@ -65,7 +65,7 @@ EOMT_MODEL_ARCHITECTURE: Final = "EomtForUniversalSegmentation" SOURCE_FRAME_MANIFEST_SCHEMA: Final = "missioncore.recorded-perception-source-frames/v1" -@dataclass(frozen=True, slots=True) +@dataclass(frozen=True) class SourceFrameRow: sequence: int path: str diff --git a/tests/test_lab_v1_component_adapter_image_installer.py b/tests/test_lab_v1_component_adapter_image_installer.py index 94f97f1..962c6c5 100644 --- a/tests/test_lab_v1_component_adapter_image_installer.py +++ b/tests/test_lab_v1_component_adapter_image_installer.py @@ -41,9 +41,9 @@ def test_component_image_installer_binds_bases_and_adapter_sources() -> None: for digest in ( "58df7489c3f2276f9591d500a012dee03e23d35543ce3c390b4c001e6bf90794", "591cb382c099eeb05e7ec16e2371e0b2da54d2bb5c49ec0f4ac88dbf72b0f0cd", - "fb208c6cd337153827147006cd26bf4c1c00963f91eb801280485dbc7213d08b", + "91c1878a58acf3ac35ce894f4de9b63cba3b7f29a65548e28df176063a2953c9", "b48ef255403abcfd177a6550688410a52b0fbd29d2a54c8417cb5a0daa330ad5", - "d2af887b065b0f63890768d59247114e49b70ad490c027f20eefd98682636c3c", + "a398a43fe4069bf1b1fc2ec61b44df53dad6072cccb6d10a2627e76a96a94056", ): assert digest in script assert 'entrypoint = \'["python3"]\'' in script diff --git a/tests/test_observatory_portable_lab_v1_component_adapters.py b/tests/test_observatory_portable_lab_v1_component_adapters.py index f789d95..cdefa86 100644 --- a/tests/test_observatory_portable_lab_v1_component_adapters.py +++ b/tests/test_observatory_portable_lab_v1_component_adapters.py @@ -26,6 +26,19 @@ import run_portable_lab_v1_ddrnet_component as ddrnet # noqa: E402 import run_portable_lab_v1_eomt_component as eomt # noqa: E402 +def test_component_entrypoints_keep_the_legacy_python39_syntax_floor() -> None: + paths = ( + ADAPTER_ROOT / "portable_lab_v1_component_adapter.py", + ADAPTER_ROOT / "run_portable_lab_v1_eomt_component.py", + ADAPTER_ROOT / "run_portable_lab_v1_ddrnet_component.py", + ) + for path in paths: + source = path.read_text(encoding="utf-8") + assert "\ntype " not in source + assert "slots=True" not in paths[0].read_text(encoding="utf-8") + assert "slots=True" not in paths[2].read_text(encoding="utf-8") + + def _write_canonical(path: Path, value: object) -> None: path.parent.mkdir(parents=True, exist_ok=True) path.write_bytes(contract.canonical_json(value))