"""
Provide tools to build core application components.
"""
from abc import ABC, abstractmethod
from collections.abc import Callable, MutableSequence, Awaitable
from types import TracebackType
from typing import Self, Any, final, TypedDict, Unpack, TypeAlias
from warnings import warn
from typing_extensions import override
from betty.typing import internal, public
[docs]
@internal
class Bootstrapped:
"""
A component that can be in a bootstrapped state.
"""
@final
@property
def bootstrapped(self) -> bool:
"""
Whether the component has been bootstrapped.
"""
return self._bootstrapped
[docs]
@final
def assert_bootstrapped(self) -> None:
"""
Assert that the component has been bootstrapped.
"""
if not self.bootstrapped:
message = f"{self} was not bootstrapped yet."
warn(message, stacklevel=2)
raise RuntimeError(message)
[docs]
@final
def assert_not_bootstrapped(self) -> None:
"""
Assert that the component was not bootstrapped.
"""
if self.bootstrapped:
message = f"{self} was bootstrapped already."
warn(message, stacklevel=2)
raise RuntimeError(message)
[docs]
class Shutdownable(ABC):
"""
A component that can be shut down.
"""
[docs]
class ShutdownCallbackKwargs(TypedDict):
"""
The keyword arguments to a shutdown callback.
"""
#: ``True`` to wait for the component to shut down gracefully, or ``False`` to attempt an immediate forced shutdown.
wait: bool
[docs]
def append(self, callback: ShutdownCallback | Shutdownable) -> None:
"""
Append a callback or another component to the stack.
"""
self._callbacks.append(
callback.shutdown if isinstance(callback, Shutdownable) else callback
)
[docs]
@internal
class CoreComponent(Bootstrapped, Shutdownable, ABC): # noqa B024
"""
A core component.
Core components can manage their resources by being bootstrapped and shut down.
"""