Made dataclasses frozen and slotted for immutability and lower memory usage.
CI / Formatting (push) Successful in 5s
CI / Linting (push) Successful in 5s
CI / Tests (Python 3.12) (push) Successful in 20s
CI / Tests (Python 3.13) (push) Successful in 22s
CI / Tests (Python 3.14) (push) Successful in 50s
CI / Type Checking (push) Successful in 25s
CI / Spelling (push) Has been cancelled

This commit is contained in:
2026-03-26 13:33:20 -04:00
parent 0ddffe5e09
commit 8a45ba1f91
8 changed files with 29 additions and 29 deletions
+3 -3
View File
@@ -43,7 +43,7 @@ class CommandMark(TypedDict):
cooldown: int | float
@dataclass
@dataclass(frozen=True, slots=True)
class CommandEvent:
"""Parsed command information from a chat message."""
@@ -57,7 +57,7 @@ class CommandEvent:
type CommandHandler = "Callable[[CommandContext], Awaitable[None]]"
@dataclass
@dataclass(frozen=True, slots=True)
class CommandInfo:
"""Metadata about a registered command."""
@@ -72,7 +72,7 @@ class CommandInfo:
def __post_init__(self) -> None:
"""Compute derived fields."""
self.all_triggers = frozenset({self.name}) | self.aliases
object.__setattr__(self, "all_triggers", frozenset({self.name}) | self.aliases)
def on_command(
+5 -5
View File
@@ -43,7 +43,7 @@ if TYPE_CHECKING:
from .templates import ModuleTemplates
@dataclass
@dataclass(slots=True)
class ModuleContext:
"""Shared services available to all module handlers.
@@ -97,7 +97,7 @@ class ModuleContext:
self.logger = logging.getLogger(f"owlbot.modules.{self.module_name}")
@dataclass
@dataclass(slots=True)
class PropagationState:
"""Mutable state for controlling event propagation across handlers."""
@@ -105,7 +105,7 @@ class PropagationState:
reason: str = ""
@dataclass
@dataclass(slots=True)
class EventContext[E]:
"""Context passed to event handlers.
@@ -200,7 +200,7 @@ class EventContext[E]:
self._propagation.reason = reason
@dataclass
@dataclass(slots=True)
class CommandContext:
"""Context passed to command handlers.
@@ -304,7 +304,7 @@ class CommandContext:
return self.module.admin_client
@dataclass
@dataclass(slots=True)
class RouteContext:
"""Context passed to HTTP route handlers.
+10 -10
View File
@@ -76,7 +76,7 @@ def _parse_timestamp(ts: str | None) -> datetime | None:
return None
@dataclass
@dataclass(frozen=True, slots=True)
class User:
"""Represents a chat user's identity and metadata."""
@@ -118,7 +118,7 @@ class User:
return "MODERATOR" in self.scopes
@dataclass
@dataclass(frozen=True, slots=True)
class ChatEvent:
"""Represents a chat message sent by a user."""
@@ -155,7 +155,7 @@ class ChatEvent:
)
@dataclass
@dataclass(frozen=True, slots=True)
class UserJoinedEvent:
"""Fired when a user joins the chat."""
@@ -179,7 +179,7 @@ class UserJoinedEvent:
)
@dataclass
@dataclass(frozen=True, slots=True)
class UserPartedEvent:
"""Fired when a user disconnects from chat."""
@@ -203,7 +203,7 @@ class UserPartedEvent:
)
@dataclass
@dataclass(frozen=True, slots=True)
class NameChangedEvent:
"""Fired when a user changes their display name."""
@@ -231,7 +231,7 @@ class NameChangedEvent:
)
@dataclass
@dataclass(frozen=True, slots=True)
class StreamStartedEvent:
"""Fired when the stream goes live."""
@@ -257,7 +257,7 @@ class StreamStartedEvent:
)
@dataclass
@dataclass(frozen=True, slots=True)
class StreamStoppedEvent:
"""Fired when the stream goes offline."""
@@ -283,7 +283,7 @@ class StreamStoppedEvent:
)
@dataclass
@dataclass(frozen=True, slots=True)
class StreamStatus:
"""Current stream status snapshot included in some events."""
@@ -315,7 +315,7 @@ class StreamStatus:
)
@dataclass
@dataclass(frozen=True, slots=True)
class StreamTitleUpdatedEvent:
"""Fired when the stream title is changed."""
@@ -344,7 +344,7 @@ class StreamTitleUpdatedEvent:
)
@dataclass
@dataclass(frozen=True, slots=True)
class VisibilityUpdateEvent:
"""Fired when message visibility changes (moderation action)."""
+4 -4
View File
@@ -28,7 +28,7 @@ if TYPE_CHECKING:
from .http_client import HttpClient
@dataclass
@dataclass(frozen=True, slots=True)
class StreamKey:
"""A stream key for ingest authentication.
@@ -49,7 +49,7 @@ class StreamKey:
return {"key": self.key, "comment": self.comment}
@dataclass
@dataclass(frozen=True, slots=True)
class VideoVariant:
"""A video output variant (quality level) for transcoding.
@@ -113,7 +113,7 @@ class VideoVariant:
}
@dataclass
@dataclass(frozen=True, slots=True)
class SocialHandle:
"""A social media handle displayed on the server page.
@@ -134,7 +134,7 @@ class SocialHandle:
return {"platform": self.platform, "url": self.url}
@dataclass
@dataclass(frozen=True, slots=True)
class ExternalAction:
"""An external action button displayed in the player UI.
+1 -1
View File
@@ -46,7 +46,7 @@ type RouteHandler = (
)
@dataclass
@dataclass(frozen=True, slots=True)
class RouteInfo:
"""Metadata about a registered route."""
+2 -2
View File
@@ -29,7 +29,7 @@ if TYPE_CHECKING:
from .processing import ProcessingManager
@dataclass
@dataclass(slots=True)
class EditorSession:
"""A clip editor session."""
@@ -40,7 +40,7 @@ class EditorSession:
expiry_task: asyncio.Task[None] | None = None
@dataclass
@dataclass(slots=True)
class ModuleState:
"""Runtime state for the clips module."""
@@ -53,7 +53,7 @@ from .placeholder_handlers import HANDLERS, PlaceholderError
DEFAULT_MAX_DEPTH: int = 4
@dataclass
@dataclass(slots=True)
class TextNode:
"""A span of literal text that needs no further processing.
@@ -63,7 +63,7 @@ class TextNode:
text: str
@dataclass
@dataclass(slots=True)
class PlaceholderNode:
"""A ``$(name ...)`` placeholder expression.
@@ -82,7 +82,7 @@ class PlaceholderNode:
type Node = TextNode | PlaceholderNode
@dataclass
@dataclass(slots=True)
class PlaceholderContext:
"""Bundles the runtime state needed to resolve placeholders.
+1 -1
View File
@@ -41,7 +41,7 @@ if TYPE_CHECKING:
logger = logging.getLogger("owlbot.web")
@dataclass
@dataclass(slots=True)
class _RouteGroup:
"""Groups route handlers that share the same path pattern.