"""Base class for threads that support graceful termination."""

import threading


class TerminableThread(threading.Thread):
    """A daemon thread that can be stopped via a termination flag.

    Subclasses implement `run` and poll `is_terminating()` to know when to exit.
    """

    def __init__(self, **kwargs) -> None:
        super().__init__(daemon=True, **kwargs)
        self._terminate_event = threading.Event()

    @property
    def _log_name(self) -> str:
        """Thread name used in log messages."""
        return self.name or type(self).__name__

    def _format_log(self, msg: str) -> str:
        """Prefixes *msg* with the thread name bracket."""
        return f"[{self._log_name}] {msg}"

    def is_terminating(self) -> bool:
        """Returns True if termination has been requested."""
        return self._terminate_event.is_set()

    def set_terminating(self) -> None:
        """Signals the thread to stop at the next opportunity."""
        self._terminate_event.set()
