Skip to content

Enforce @typing.override and missing abstract methods #2244

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/2244.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add in the missing `hikari.api.InteractionMessageBuilder.clear_components`, `hikari.api.InteractionMessageBuilder.clear_embeds` and abstract methods + enforce using `@typing_extensions.override` within the library.
2 changes: 2 additions & 0 deletions hikari/api/event_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

from hikari import iterators
from hikari.events import base_events
from hikari.internal import typing_extensions

if typing.TYPE_CHECKING:
import asyncio
Expand Down Expand Up @@ -108,6 +109,7 @@ def open(self) -> None:
"""

@abc.abstractmethod
@typing_extensions.override
def filter(
self,
*predicates: typing.Union[tuple[str, typing.Any], typing.Callable[[base_events.EventT], bool]],
Expand Down
31 changes: 31 additions & 0 deletions hikari/api/special_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
from hikari import components as components_
from hikari import polls
from hikari import undefined
from hikari.internal import typing_extensions

if typing.TYPE_CHECKING:
import types
Expand Down Expand Up @@ -540,6 +541,7 @@ class InteractionDeferredBuilder(InteractionResponseBuilder, abc.ABC):

@property
@abc.abstractmethod
@typing_extensions.override
def type(self) -> base_interactions.DeferredResponseTypesT:
"""Type of this response."""

Expand Down Expand Up @@ -661,6 +663,7 @@ class InteractionMessageBuilder(InteractionResponseBuilder, abc.ABC):

@property
@abc.abstractmethod
@typing_extensions.override
def type(self) -> base_interactions.MessageResponseTypesT:
"""Type of this response."""

Expand Down Expand Up @@ -782,6 +785,16 @@ def add_component(self, component: ComponentBuilder, /) -> Self:
Object of this builder.
"""

@abc.abstractmethod
def clear_components(self, /) -> Self:
"""Clear the components set for this response.

Returns
-------
InteractionMessageBuilder
Object of this builder to allow for chained calls.
"""

@abc.abstractmethod
def add_embed(self, embed: embeds_.Embed, /) -> Self:
"""Add an embed to this response.
Expand All @@ -797,6 +810,16 @@ def add_embed(self, embed: embeds_.Embed, /) -> Self:
Object of this builder to allow for chained calls.
"""

@abc.abstractmethod
def clear_embeds(self, /) -> Self:
"""Clear the embeds set for this embed.

Returns
-------
InteractionMessageBuilder
Object of this builder to allow for chained calls.
"""

@abc.abstractmethod
def set_content(self, content: undefined.UndefinedOr[str], /) -> Self:
"""Set the response's message content.
Expand Down Expand Up @@ -936,6 +959,7 @@ class InteractionModalBuilder(InteractionResponseBuilder, abc.ABC):

@property
@abc.abstractmethod
@typing_extensions.override
def type(self) -> typing.Literal[base_interactions.ResponseType.MODAL]:
"""Type of this response."""

Expand Down Expand Up @@ -997,6 +1021,7 @@ class InteractionPremiumRequiredBuilder(InteractionResponseBuilder, abc.ABC):

@property
@abc.abstractmethod
@typing_extensions.override
def type(self) -> typing.Literal[base_interactions.ResponseType.PREMIUM_REQUIRED]:
"""Type of this response."""

Expand Down Expand Up @@ -1290,6 +1315,7 @@ def add_option(self, option: commands.CommandOption) -> Self:
"""

@abc.abstractmethod
@typing_extensions.override
async def create(
self,
rest: rest_api.RESTClient,
Expand Down Expand Up @@ -1327,6 +1353,7 @@ class ContextMenuCommandBuilder(CommandBuilder):
__slots__: typing.Sequence[str] = ()

@abc.abstractmethod
@typing_extensions.override
async def create(
self,
rest: rest_api.RESTClient,
Expand Down Expand Up @@ -1387,6 +1414,7 @@ class ButtonBuilder(ComponentBuilder, abc.ABC):

@property
@abc.abstractmethod
@typing_extensions.override
def type(self) -> typing.Literal[components_.ComponentType.BUTTON]:
"""Type of component this builder represents."""

Expand Down Expand Up @@ -1833,6 +1861,7 @@ class TextInputBuilder(ComponentBuilder, abc.ABC):

@property
@abc.abstractmethod
@typing_extensions.override
def type(self) -> typing.Literal[components_.ComponentType.TEXT_INPUT]:
"""Type of component this builder represents."""

Expand Down Expand Up @@ -2009,6 +2038,7 @@ class MessageActionRowBuilder(ComponentBuilder, abc.ABC):

@property
@abc.abstractmethod
@typing_extensions.override
def type(self) -> typing.Literal[components_.ComponentType.ACTION_ROW]:
"""Type of component this builder represents."""

Expand Down Expand Up @@ -2246,6 +2276,7 @@ class ModalActionRowBuilder(ComponentBuilder, abc.ABC):

@property
@abc.abstractmethod
@typing_extensions.override
def type(self) -> typing.Literal[components_.ComponentType.ACTION_ROW]:
"""Type of component this builder represents."""

Expand Down
21 changes: 21 additions & 0 deletions hikari/applications.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
from hikari.internal import attrs_extensions
from hikari.internal import enums
from hikari.internal import routes
from hikari.internal import typing_extensions

if typing.TYPE_CHECKING:
import datetime
Expand Down Expand Up @@ -374,72 +375,90 @@ class TeamMember(users.User):
"""The user representation of this team member."""

@property
@typing_extensions.override
def app(self) -> traits.RESTAware:
"""Return the app that is bound to the user object."""
return self.user.app

@property
@typing_extensions.override
def avatar_hash(self) -> typing.Optional[str]:
return self.user.avatar_hash

@property
@typing_extensions.override
def avatar_url(self) -> typing.Optional[files.URL]:
return self.user.avatar_url

@property
@typing_extensions.override
def default_avatar_url(self) -> files.URL:
return self.user.default_avatar_url

@property
@typing_extensions.override
def banner_hash(self) -> typing.Optional[str]:
return self.user.banner_hash

@property
@typing_extensions.override
def banner_url(self) -> typing.Optional[files.URL]:
return self.user.banner_url

@property
@typing_extensions.override
def accent_color(self) -> typing.Optional[colors.Color]:
return self.user.accent_color

@property
@typing_extensions.override
def discriminator(self) -> str:
return self.user.discriminator

@property
@typing_extensions.override
def flags(self) -> users.UserFlag:
return self.user.flags

@property
@typing_extensions.override
def id(self) -> snowflakes.Snowflake:
return self.user.id

@property
@typing_extensions.override
def is_bot(self) -> bool:
return self.user.is_bot

@property
@typing_extensions.override
def is_system(self) -> bool:
return self.user.is_system

@property
@typing_extensions.override
def mention(self) -> str:
return self.user.mention

@property
@typing_extensions.override
def username(self) -> str:
return self.user.username

@property
@typing_extensions.override
def global_name(self) -> typing.Optional[str]:
return self.user.global_name

@typing_extensions.override
def __str__(self) -> str:
return str(self.user)

@typing_extensions.override
def __hash__(self) -> int:
return hash(self.user)

@typing_extensions.override
def __eq__(self, other: object) -> bool:
return self.user == other

Expand Down Expand Up @@ -476,6 +495,7 @@ class Team(snowflakes.Unique):
owner_id: snowflakes.Snowflake = attrs.field(eq=False, hash=False, repr=True)
"""The ID of this team's owner."""

@typing_extensions.override
def __str__(self) -> str:
return f"Team {self.name} ({self.id})"

Expand Down Expand Up @@ -748,6 +768,7 @@ class PartialOAuth2Token:
scopes: typing.Sequence[typing.Union[OAuth2Scope, str]] = attrs.field(eq=False, hash=False, repr=True)
"""Scopes the access token has access to."""

@typing_extensions.override
def __str__(self) -> str:
return self.access_token

Expand Down
4 changes: 4 additions & 0 deletions hikari/audit_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
from hikari.internal import attrs_extensions
from hikari.internal import collections
from hikari.internal import enums
from hikari.internal import typing_extensions

if typing.TYPE_CHECKING:
import datetime
Expand Down Expand Up @@ -629,13 +630,16 @@ def __getitem__(self, index: int, /) -> AuditLogEntry: ...
@typing.overload
def __getitem__(self, slice_: slice, /) -> typing.Sequence[AuditLogEntry]: ...

@typing_extensions.override
def __getitem__(
self, index_or_slice: typing.Union[int, slice], /
) -> typing.Union[AuditLogEntry, typing.Sequence[AuditLogEntry]]:
return collections.get_index_or_slice(self.entries, index_or_slice)

@typing_extensions.override
def __iter__(self) -> typing.Iterator[AuditLogEntry]:
return iter(self.entries.values())

@typing_extensions.override
def __len__(self) -> int:
return len(self.entries)
4 changes: 4 additions & 0 deletions hikari/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
from hikari.internal import attrs_extensions
from hikari.internal import enums
from hikari.internal import routes
from hikari.internal import typing_extensions

if typing.TYPE_CHECKING:
import datetime
Expand Down Expand Up @@ -367,6 +368,7 @@ def mention(self) -> str:
"""
return f"<#{self.id}>"

@typing_extensions.override
def __str__(self) -> str:
return self.name if self.name is not None else f"Unnamed {self.__class__.__name__} ID {self.id}"

Expand Down Expand Up @@ -853,6 +855,7 @@ def shard_id(self) -> typing.Literal[0]:
"""Return the shard ID for the shard."""
return 0

@typing_extensions.override
def __str__(self) -> str:
return f"{self.__class__.__name__} with: {self.recipient}"

Expand Down Expand Up @@ -885,6 +888,7 @@ class GroupDMChannel(PrivateChannel):
If the group DM was not created by a bot, this will be [`None`][].
"""

@typing_extensions.override
def __str__(self) -> str:
if self.name is None:
return f"{self.__class__.__name__} with: {', '.join(str(user) for user in self.recipients.values())}"
Expand Down
5 changes: 5 additions & 0 deletions hikari/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import string
import typing

from hikari.internal import typing_extensions


def _to_rgb_int(value: str, name: str) -> int:
# Heavy validation that is user-friendly and doesn't allow exploiting overflows, etc easily.
Expand Down Expand Up @@ -171,10 +173,12 @@ def __init__(self, raw_rgb: typing.SupportsInt) -> None:
# than keeping the linter happy.
super().__init__()

@typing_extensions.override
def __repr__(self) -> str:
r, g, b = self.rgb
return f"Color(r={hex(r)}, g={hex(g)}, b={hex(b)})"

@typing_extensions.override
def __str__(self) -> str:
return self.hex_code

Expand Down Expand Up @@ -521,6 +525,7 @@ def of(cls, value: Colorish, /) -> Color:
msg = f"Could not transform {value!r} into a {cls.__qualname__} object"
raise ValueError(msg)

@typing_extensions.override
def to_bytes(
self, length: typing.SupportsIndex, byteorder: typing.Literal["little", "big"], *, signed: bool = True
) -> bytes:
Expand Down
6 changes: 6 additions & 0 deletions hikari/embeds.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
from hikari import files
from hikari import undefined
from hikari.internal import attrs_extensions
from hikari.internal import typing_extensions

if typing.TYPE_CHECKING:
import concurrent.futures
Expand All @@ -64,15 +65,18 @@ class EmbedResource(files.Resource[files.AsyncReader]):

@property
@typing.final
@typing_extensions.override
def url(self) -> str:
"""URL of this embed resource."""
return self.resource.url

@property
@typing_extensions.override
def filename(self) -> str:
"""File name of this embed resource."""
return self.resource.filename

@typing_extensions.override
def stream(
self, *, executor: typing.Optional[concurrent.futures.Executor] = None, head_only: bool = False
) -> files.AsyncReaderContextManager[files.AsyncReader]:
Expand Down Expand Up @@ -902,9 +906,11 @@ def clear_fields(self) -> Embed:
self._fields = None
return self

@typing_extensions.override
def __repr__(self) -> str:
return f"Embed(title={self.title}, color={self.color}, timestamp={self.timestamp})"

@typing_extensions.override
def __eq__(self, other: object) -> bool:
if isinstance(other, type(self)):
for attrsib in self.__slots__:
Expand Down
Loading