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