diff --git a/bot_bottle/backend/docker/__init__.py b/bot_bottle/backend/docker/__init__.py index dc2340b..8da7dc8 100644 --- a/bot_bottle/backend/docker/__init__.py +++ b/bot_bottle/backend/docker/__init__.py @@ -11,18 +11,42 @@ The bulk of the implementation lives in sibling modules: - launch: bring-up + teardown context manager - cleanup: orphan enumeration, removal, active listing - backend: DockerBottleBackend façade wiring the above + - infra: DockerInfraService (the per-host infra container) -This file only re-exports the public names so -`from bot_bottle.backend.docker import DockerBottleBackend` keeps -working. +Thin by design: the public names are re-exported lazily via `__getattr__`, so +importing a leaf like `backend.docker.util` doesn't drag `DockerBottleBackend` +(and the whole framework it pulls) into memory. """ from __future__ import annotations -from .backend import DockerBottleBackend -from .bottle import DockerBottle -from .bottle_cleanup_plan import DockerBottleCleanupPlan -from .bottle_plan import DockerBottlePlan +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from .backend import DockerBottleBackend + from .bottle import DockerBottle + from .bottle_cleanup_plan import DockerBottleCleanupPlan + from .bottle_plan import DockerBottlePlan + + +_LAZY_MODULES: dict[str, str] = { + "DockerBottleBackend": "backend", + "DockerBottle": "bottle", + "DockerBottleCleanupPlan": "bottle_cleanup_plan", + "DockerBottlePlan": "bottle_plan", +} + + +def __getattr__(name: str) -> Any: + mod = _LAZY_MODULES.get(name) + if mod is None: + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + from importlib import import_module + + value = getattr(import_module(f"{__name__}.{mod}"), name) + globals()[name] = value + return value + __all__ = [ "DockerBottle", diff --git a/bot_bottle/backend/firecracker/__init__.py b/bot_bottle/backend/firecracker/__init__.py index 57b5840..cae1248 100644 --- a/bot_bottle/backend/firecracker/__init__.py +++ b/bot_bottle/backend/firecracker/__init__.py @@ -1,7 +1,25 @@ -"""Firecracker backend: Linux KVM microVM isolation (issue #342).""" +"""Firecracker backend: Linux KVM microVM isolation (issue #342). + +Thin by design: `FirecrackerBottleBackend` is re-exported lazily via +`__getattr__`, so importing a leaf module under this package doesn't drag the +backend (and the framework it pulls) into memory. +""" from __future__ import annotations -from .backend import FirecrackerBottleBackend +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from .backend import FirecrackerBottleBackend + + +def __getattr__(name: str) -> Any: + if name == "FirecrackerBottleBackend": + from .backend import FirecrackerBottleBackend + + globals()[name] = FirecrackerBottleBackend + return FirecrackerBottleBackend + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + __all__ = ["FirecrackerBottleBackend"] diff --git a/bot_bottle/backend/macos_container/__init__.py b/bot_bottle/backend/macos_container/__init__.py index 6d56f95..c655d15 100644 --- a/bot_bottle/backend/macos_container/__init__.py +++ b/bot_bottle/backend/macos_container/__init__.py @@ -1,10 +1,29 @@ """macOS Apple Container backend. -Selectable via `BOT_BOTTLE_BACKEND=macos-container`. This package owns -the Apple `container` CLI integration; launch remains gated until the -gateway network enforcement shape is implemented. +Selectable via `BOT_BOTTLE_BACKEND=macos-container`. This package owns the Apple +`container` CLI integration; launch remains gated until the gateway network +enforcement shape is implemented. + +Thin by design: `MacosContainerBottleBackend` is re-exported lazily via +`__getattr__`, so importing a leaf module under this package doesn't drag the +backend (and the framework it pulls) into memory. """ -from .backend import MacosContainerBottleBackend +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from .backend import MacosContainerBottleBackend + + +def __getattr__(name: str) -> Any: + if name == "MacosContainerBottleBackend": + from .backend import MacosContainerBottleBackend + + globals()[name] = MacosContainerBottleBackend + return MacosContainerBottleBackend + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + __all__ = ["MacosContainerBottleBackend"]