fix(backend): fix pyright errors in lazy-load implementation
lint / lint (push) Successful in 2m13s
test / unit (pull_request) Successful in 1m6s
test / integration (pull_request) Successful in 24s
test / coverage (pull_request) Successful in 1m18s

- Rename _BACKENDS → _backends: pyright treats uppercase module-level
  names as constants and flags the reassignment in _get_backends() as
  reportConstantRedefinition; lowercase avoids this.
- Add TYPE_CHECKING guard importing CommitCancelled/Freezer/get_freezer
  from .freeze: pyright cannot see module-level __getattr__ bindings, so
  reportUnsupportedDunderAll fired for those three __all__ entries; the
  guard makes them visible to the type checker without running at import
  time.
- Update test_backend_selection.py to patch _backends (lowercase).
This commit is contained in:
2026-07-14 09:07:21 +00:00
parent 2a2669b69f
commit b05775b581
2 changed files with 22 additions and 19 deletions
+14 -11
View File
@@ -40,7 +40,7 @@ from abc import ABC, abstractmethod
from contextlib import AbstractContextManager
from dataclasses import dataclass
from pathlib import Path
from typing import Any, Generic, Sequence, TypeVar
from typing import TYPE_CHECKING, Any, Generic, Sequence, TypeVar
from ..agent_provider import AgentProvisionPlan, get_provider, build_agent_provision_plan
from ..egress import EgressPlan
@@ -54,6 +54,9 @@ from ..workspace import WorkspacePlan, workspace_plan
from .print_util import print_multi, visible_agent_env_names
from .util import host_skill_dir
if TYPE_CHECKING:
from .freeze import CommitCancelled, Freezer, get_freezer
@dataclass(frozen=True)
class BottleSpec:
@@ -572,31 +575,31 @@ class BottleBackend(ABC, Generic[PlanT, CleanupT]):
Not called by the launch path or the test suite."""
# _BACKENDS is None until the first call to _get_backends(), at which
# _backends is None until the first call to _get_backends(), at which
# point all three concrete backend classes are imported and instantiated.
# Keeping the imports out of module scope means that importing any
# backend sub-module (e.g. `backend.docker.util`) no longer drags the
# firecracker and macos-container implementations into memory.
#
# Tests may replace _BACKENDS with a {name: fake} dict via patch.object;
# Tests may replace _backends with a {name: fake} dict via patch.object;
# _get_backends() returns the current module-level value as-is when it
# is not None, so test fakes take effect without triggering real imports.
_BACKENDS: dict[str, BottleBackend[Any, Any]] | None = None
_backends: dict[str, BottleBackend[Any, Any]] | None = None
def _get_backends() -> dict[str, BottleBackend[Any, Any]]:
"""Return the registry of all backend instances, loading lazily on first call."""
global _BACKENDS # pylint: disable=global-statement
if _BACKENDS is None:
global _backends # pylint: disable=global-statement
if _backends is None:
from .docker import DockerBottleBackend
from .firecracker import FirecrackerBottleBackend
from .macos_container import MacosContainerBottleBackend
_BACKENDS = {
_backends = {
"docker": DockerBottleBackend(),
"firecracker": FirecrackerBottleBackend(),
"macos-container": MacosContainerBottleBackend(),
}
return _BACKENDS
return _backends
def __getattr__(name: str) -> Any:
@@ -717,12 +720,12 @@ __all__ = [
"BottleCleanupPlan",
"BottlePlan",
"BottleSpec",
"CommitCancelled", # pylint: disable=undefined-all-variable
"CommitCancelled",
"ExecResult",
"Freezer", # pylint: disable=undefined-all-variable
"Freezer",
"enumerate_active_agents",
"get_bottle_backend",
"get_freezer", # pylint: disable=undefined-all-variable
"get_freezer",
"has_backend",
"known_backend_names",
]