refactor(bottles): BottlePlatform becomes ABC; DockerBottlePlatform in docker.py
test / run tests/run_tests.py (pull_request) Successful in 18s
test / run tests/run_tests.py (pull_request) Successful in 18s
Mirror the BottlePlan -> DockerBottlePlan hierarchy at the platform layer. BottlePlatform is now an abstract base with abstract `prepare` and `launch` methods; DockerBottlePlatform lives alongside the rest of the Docker code in bottles/docker.py and supplies the concrete impls. The registry in bottles/__init__.py now holds an instance of each concrete platform class. Future per-platform state (region, api token, cleanup primitives) has a natural home on the subclass rather than being stitched onto a dataclass struct. No behavior change. Tests pass; dry-run output unchanged.
This commit is contained in:
@@ -22,7 +22,7 @@ from __future__ import annotations
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from contextlib import contextmanager
|
||||
from contextlib import AbstractContextManager, contextmanager
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Iterator
|
||||
@@ -34,7 +34,7 @@ from .. import skills as skills_mod
|
||||
from .. import ssh as ssh_mod
|
||||
from ..env_resolve import env_resolve
|
||||
from ..log import die, info
|
||||
from . import BottlePlan, BottleSpec
|
||||
from . import BottlePlan, BottlePlatform, BottleSpec
|
||||
|
||||
|
||||
# --- Runtime detection -----------------------------------------------------
|
||||
@@ -434,3 +434,24 @@ def _provision_container(plan: DockerBottlePlan, container: str) -> str | None:
|
||||
)
|
||||
|
||||
return in_container_prompt_path if agent.prompt else None
|
||||
|
||||
|
||||
# --- Platform --------------------------------------------------------------
|
||||
|
||||
|
||||
class DockerBottlePlatform(BottlePlatform):
|
||||
"""Docker platform implementation. Selected by CLAUDE_BOTTLE_PLATFORM
|
||||
(default). The methods delegate to the module-level prepare/launch
|
||||
functions so the platform class itself stays a thin dispatch layer."""
|
||||
|
||||
name = "docker"
|
||||
|
||||
def prepare(self, spec: BottleSpec, *, stage_dir: Path) -> BottlePlan:
|
||||
return prepare_docker_bottle(spec, stage_dir=stage_dir)
|
||||
|
||||
def launch(self, plan: BottlePlan) -> AbstractContextManager[_DockerBottle]:
|
||||
assert isinstance(plan, DockerBottlePlan), (
|
||||
f"DockerBottlePlatform.launch expects DockerBottlePlan, "
|
||||
f"got {type(plan).__name__}"
|
||||
)
|
||||
return launch_docker_bottle(plan)
|
||||
|
||||
Reference in New Issue
Block a user