Repository: hikari-py/hikari
Pull request #820 (2021-10-05 15:25:36)

Remove Unique pattern and hashing from Overwrites
### Summary
Remove Unique pattern and hashing from Overwrites

### Checklist
<!-- Make sure to tick all the following boxes by putting an `x` in between (like this `[x]`) -->
- [x] I have run `nox` and all the pipelines have passed.
- [x] I have made unittests according to the code I have added/modified/deleted.

### Related issues
<!--
To mention an issue use `#issue-id` and to mention a merge request use `!merge-request-id`
To close/fix an issue use `Close #issue-id` or `Fix #issue-id` (depending on the merge request)
-->



Patch:
diff --git a/changes/816.breaking.md b/changes/816.breaking.md
new file mode 100644
index 00000000..6a5dd694
--- /dev/null
+++ b/changes/816.breaking.md
@@ -0,0 +1,2 @@
+Remove `hikari.errors.RESTErrorCode` enum
+- The message that is sent with the error code is the info that the enum contained
diff --git a/changes/820.breaking.md b/changes/820.breaking.md
new file mode 100644
index 00000000..48c04e87
--- /dev/null
+++ b/changes/820.breaking.md
@@ -0,0 +1,1 @@
+PermissionOverwrite doesn't inherit from Unique anymore and isn't hashable. Equality checks now consider all its fields.
diff --git a/hikari/channels.py b/hikari/channels.py
index a942b7e2..2fe57550 100644
--- a/hikari/channels.py
+++ b/hikari/channels.py
@@ -259,8 +259,8 @@ class PermissionOverwriteType(int, enums.Enum):
 
 
 @attr_extensions.with_copy
-@attr.define(hash=True, kw_only=True, weakref_slot=False)
-class PermissionOverwrite(snowflakes.Unique):
+@attr.define(kw_only=True, weakref_slot=False)
+class PermissionOverwrite:
     """Represents permission overwrites for a channel or role in a channel.
 
     You may sometimes need to make instances of this object to add/edit
@@ -286,29 +286,21 @@ class PermissionOverwrite(snowflakes.Unique):
     ```
     """
 
-    id: snowflakes.Snowflake = attr.field(
-        converter=snowflakes.Snowflake,
-        hash=True,
-        repr=True,
-    )
+    id: snowflakes.Snowflake = attr.field(converter=snowflakes.Snowflake, repr=True)
     """The ID of this entity."""
 
-    type: typing.Union[PermissionOverwriteType, int] = attr.field(
-        converter=PermissionOverwriteType, hash=True, repr=True
-    )
+    type: typing.Union[PermissionOverwriteType, int] = attr.field(converter=PermissionOverwriteType, repr=True)
     """The type of entity this overwrite targets."""
 
     allow: permissions.Permissions = attr.field(
         converter=permissions.Permissions,
         default=permissions.Permissions.NONE,
-        eq=False,
-        hash=False,
         repr=False,
     )
     """The permissions this overwrite allows."""
 
     deny: permissions.Permissions = attr.field(
-        converter=permissions.Permissions, default=permissions.Permissions.NONE, eq=False, hash=False, repr=False
+        converter=permissions.Permissions, default=permissions.Permissions.NONE, repr=False
     )
     """The permissions this overwrite denies."""
 
diff --git a/hikari/errors.py b/hikari/errors.py
index e5f68ae5..aaa6da05 100644
--- a/hikari/errors.py
+++ b/hikari/errors.py
@@ -36,7 +36,6 @@
     "UnauthorizedError",
     "ForbiddenError",
     "BadRequestError",
-    "RESTErrorCode",
     "HTTPError",
     "HTTPResponseError",
     "ClientHTTPResponseError",
@@ -223,221 +222,6 @@ class HTTPError(HikariError):
     """The error message."""
 
 
-@typing.final
-class RESTErrorCode(int, enums.Enum):
-    """Non-exhaustive enum of error codes provided as further info on errors returned by the REST API."""
-
-    GENERAL_ERROR = 0
-    """A general error, no further info provided."""
-
-    UNKNOWN_APPLICATION = 10_002
-    """Unknown application provided."""
-
-    UNKNOWN_CHANNEL = 10_003
-    """Unknown channel provided."""
-
-    UNKNOWN_GUILD = 10_004
-    """Unknown guild provided."""
-
-    UNKNOWN_INTEGRATION = 10_005
-    """Unknown integration provided."""
-
-    UNKNOWN_INVITE = 10_006
-    """Unknown invite provided."""
-
-    UNKNOWN_MEMBER = 10_007
-    """Unknown member provided."""
-
-    UNKNOWN_MESSAGE = 10_008
-    """Unknown message provided."""
-
-    UNKNOWN_PERMISSION_OVERWRITE = 10_009
-    """Unknown permission overwrite provided."""
-
-    UNKNOWN_ROLE = 10_011
-    """Unknown role provided."""
-
-    UNKNOWN_USER = 10_013
-    """Unknown user provided."""
-
-    UNKNOWN_EMOJI = 10_014
-    """Unknown emoji provided."""
-
-    UNKNOWN_WEBHOOK = 10_015
-    """Unknown webhook provided."""
-
-    UNKNOWN_BAN = 10_026
-    """Unknown ban provided."""
-
-    UNKNOWN_GUILD_TEMPLATE = 10_057
-    """Unknown guild template provided."""
-
-    UNKNOWN_STICKER = 10_060
-    """Unknown sticker provided."""
-
-    UNKNOWN_INTERACTION = 10_062
-    """Unknown interaction provided."""
-
-    UNKNOWN_APPLICATION_COMMAND = 10_063
-    """Unknown application command provided."""
-
-    UNKNOWN_APPLICATION_COMMAND_PERMISSIONS = 10_066
-    """Unknown application command permissions provided."""
-
-    UNKNOWN_STAGE_INSTANCE = 10_067
-    """Unknown stage instance provided."""
-
-    UNKNOWN_GUILD_WELCOME_SCREEN = 10_069
-    """Unknown guild welcome screen provided."""
-
-    EXPLICIT_CONTENT_BLOCKED = 20_009
-    """Explicit content cannot be sent to the desired recipient(s)."""
-
-    ANNOUNCEMENT_LIMIT_HIT = 20_022
-    """Message can not be edited due to announcement rate limits."""
-
-    WRITE_LIMIT_HIT = 20_028
-    """The global write limit on a channel has been hit."""
-
-    DISALLOWED_WORDS_FOR_PUBLIC_STAGES = 20_031
-    """The guild contains disallowed words for public stages.
-
-    This may include guild name, guild description or channel names.
-    """
-
-    GUILD_PREMIUM_LEVEL_TOO_LOW = 20_035
-    """The guilds premium level is too low."""
-
-    MAXIMUM_GUILDS = 30_001
-    """Maximum number of guilds reached (100)."""
-
-    MAXIMUM_PINS = 30_003
-    """Maximum number of pins reached for the channel (50)."""
-
-    MAXIMUM_RECIPIENTS = 30_004
-    """Maximum number of recipients reached (10)."""
-
-    MAXIMUM_ROLES = 30_005
-    """Maximum number of guild roles reached (250)."""
-
-    MAXIMUM_WEBHOOKS = 30_007
-    """Maximum number of webhooks in a channel reached (10)."""
-
-    MAXIMUM_EMOJIS = 30_008
-    """Maximum number of emojis reached."""
-
-    MAXIMUM_REACTIONS = 30_010
-    """Maximum number of reactions on a message reached (20)."""
-
-    MAXIMUM_CHANNELS = 30_013
-    """Maximum number of guild channels reached (500)."""
-
-    MAXIMUM_INVITES = 30_016
-    """Maximum number of invites reached (1000)."""
-
-    MAXIMUM_ANIMATED_EMOJIS = 30_018
-    """Maximum number of animated emojis reached."""
-
-    MAXIMUM_NUMBER_OF_GUILD_MEMBERS_REACHED = 30_019
-    """Maximum number of guild members reached."""
-
-    GUILD_ALREADY_HAS_TEMPLATE = 30_031
-    """Guild already has a template."""
-
-    MAXIMUM_NUMBER_OF_THREAD_PARTICIPANTS_REACHED = 30_033
-    """Maximum number of thread participants reached."""
-
-    MAXIMUM_BANS_FOR_NON_GUILD_MEMBERS = 30_035
-    """Maximum number of bans for non-guild members reached."""
-
-    MAXIMUM_NUMBER_OF_STICKERS_REACHED = 30_037
-    """Maximum number of stickers reached."""
-
-    MAXIMUM_PRUNE_REQUESTS_REACHED = 30_040
-    """Maximum number of prune requests has been reached. Try again later."""
-
-    REQUEST_TOO_LARGE = 40_005
-    """Request too large. Try sending something smaller in size."""
-
-    TEMPORARILY_DISABLED = 40_006
-    """This feature has been temporarily disabled server-side."""
-
-    USER_BANNED = 40_003
-    """The user is banned from this guild."""
-
-    ALREADY_CROSSPOSTED = 40_033
-    """This message has already been crossposted."""
-
-    APPLICATION_COMMAND_ALREADY_EXISTS = 40_041
-    """An application command with that name already exists."""
-
-    INVALID_ACCOUNT_TYPE = 50_002
-    """Invalid account type."""
-
-    PROHIBITED_ON_DM = 50_003
-    """Cannot execute action on a DM channel."""
-
-    GUILD_WIDGET_DISABLED = 50_004
-    """Guild widget disabled."""
-
-    NOT_MESSAGE_AUTHOR = 50_005
-    """Cannot edit a message created by another user."""
-
-    EMPTY_MESSAGE = 50_006
-    """Cannot send an empty message."""
-
-    USER_DM_CLOSED = 50_007
-    """Cannot send messages to this user."""
-
-    MESSAGE_IN_VC = 50_008
-    """Cannot send messages in a voice channel."""
-
-    PINS_ONLY_ON_ORIGIN_CHANNEL = 50_019
-    """A message can only be pinned to the channel it was sent in."""
-
-    INVALID_INVITE_CODE = 50_020
-    """Invite code was either invalid or taken."""
-
-    PROHIBITED_ON_SYSTEM_MESSAGE = 50_021
-    """Cannot execute action on a system message."""
-
-    PROHIBITED_ON_CHANNEL_TYPE = 50_024
-    """Cannot execute action on this channel type."""
-
-    INVALID_OAUTH2_TOKEN = 50_025
-    """Invalid OAuth2 access token provided."""
-
-    MISSING_REQUIRED_OAUTH2_SCOPE = 50_026
-    """Missing required OAuth2 scope."""
-
-    INVALID_ROLE = 50_028
-    """Invalid role."""
-
-    INVALID_RECIPIENTS = 50_033
-    """Invalid recipients."""
-
-    MESSAGE_TOO_OLD = 50_034
-    """A message provided was too old to bulk delete."""
-
-    REQUIRED_CHANNEL = 50_074
-    """Cannot delete a channel required for community guilds."""
-
-    NO_USERS_WITH_TAG = 80_004
-    """No users with this tag exist."""
-
-    REACTION_BLOCKED = 90_001
-    """The reaction was blocked."""
-
-    TWO_FACTOR_AUTHENTICATION_REQUIRED = 60_003
-    """2FA is required to use this endpoint."""
-
-    SYSTEM_OVERLOADED = 130_000
-    """API resource is currently overloaded. Try again a little later."""
-
-    STAGE_ALREADY_OPEN = 150_006
-    """The stage channel is already open."""
-
-
 @attr.define(auto_exc=True, repr=False, weakref_slot=False)
 class HTTPResponseError(HTTPError):
     """Base exception for an erroneous HTTP response."""
@@ -457,15 +241,15 @@ class HTTPResponseError(HTTPError):
     message: str = attr.field(default="")
     """The error message."""
 
-    code: typing.Union[RESTErrorCode, int] = attr.field(default=RESTErrorCode.GENERAL_ERROR)
+    code: int = attr.field(default=0)
     """The error code."""
 
     def __str__(self) -> str:
         name = self.status.name.replace("_", " ").title()
         name_value = f"{name} {self.status.value}"
 
-        if isinstance(self.code, RESTErrorCode) and self.code != RESTErrorCode.GENERAL_ERROR:
-            code_str = f" ({self.code.name})"
+        if self.code:
+            code_str = f" ({self.code})"
         else:
             code_str = ""
 
diff --git a/hikari/impl/rest.py b/hikari/impl/rest.py
index 3e4f89e5..098ab63e 100644
--- a/hikari/impl/rest.py
+++ b/hikari/impl/rest.py
@@ -1067,6 +1067,7 @@ async def edit_permission_overwrites(
                     "Cannot determine the type of the target to update. Try specifying 'target_type' manually."
                 )
 
+        target = target.id if isinstance(target, channels_.PermissionOverwrite) else target
         route = routes.PUT_CHANNEL_PERMISSIONS.compile(channel=channel, overwrite=target)
         body = data_binding.JSONObjectBuilder()
         body.put("type", target_type)
diff --git a/hikari/interactions/base_interactions.py b/hikari/interactions/base_interactions.py
index 8fd4c416..1d6d0576 100644
--- a/hikari/interactions/base_interactions.py
+++ b/hikari/interactions/base_interactions.py
@@ -127,12 +127,7 @@ class ResponseType(int, enums.Enum):
 * `ResponseType.MESSAGE_UPDATE`
 """
 
-MessageResponseTypesT = typing.Union[
-    typing.Literal[ResponseType.MESSAGE_CREATE],
-    typing.Literal[4],
-    typing.Literal[ResponseType.MESSAGE_UPDATE],
-    typing.Literal[7],
-]
+MessageResponseTypesT = typing.Literal[ResponseType.MESSAGE_CREATE, 4, ResponseType.MESSAGE_UPDATE, 7]
 """Type-hint of the response types which are valid for message responses.
 
 The following are valid for this:
@@ -152,12 +147,10 @@ class ResponseType(int, enums.Enum):
 * `ResponseType.DEFERRED_MESSAGE_UPDATE`
 """
 
-DeferredResponseTypesT = typing.Union[
-    typing.Literal[ResponseType.DEFERRED_MESSAGE_CREATE],
-    typing.Literal[5],
-    typing.Literal[ResponseType.DEFERRED_MESSAGE_UPDATE],
-    typing.Literal[6],
+DeferredResponseTypesT = typing.Literal[
+    ResponseType.DEFERRED_MESSAGE_CREATE, 5, ResponseType.DEFERRED_MESSAGE_UPDATE, 6
 ]
+
 """Type-hint of the response types which are valid for deferred messages responses.
 
 The following are valid for this:
diff --git a/hikari/interactions/command_interactions.py b/hikari/interactions/command_interactions.py
index ca5c6beb..1ec913b6 100644
--- a/hikari/interactions/command_interactions.py
+++ b/hikari/interactions/command_interactions.py
@@ -62,11 +62,8 @@
 * `hikari.interactions.base_interactions.ResponseType.DEFERRED_MESSAGE_CREATE`
 """
 
-CommandResponseTypesT = typing.Union[
-    typing.Literal[base_interactions.ResponseType.MESSAGE_CREATE],
-    typing.Literal[4],
-    typing.Literal[base_interactions.ResponseType.DEFERRED_MESSAGE_CREATE],
-    typing.Literal[5],
+CommandResponseTypesT = typing.Literal[
+    base_interactions.ResponseType.MESSAGE_CREATE, 4, base_interactions.ResponseType.DEFERRED_MESSAGE_CREATE, 5
 ]
 """Type-hint of the response types which are valid for a command interaction.
 
diff --git a/hikari/interactions/component_interactions.py b/hikari/interactions/component_interactions.py
index 9dd10160..8fb78c4a 100644
--- a/hikari/interactions/component_interactions.py
+++ b/hikari/interactions/component_interactions.py
@@ -44,20 +44,14 @@
 _DEFERRED_TYPES: typing.AbstractSet[_DeferredTypesT] = frozenset(
     [base_interactions.ResponseType.DEFERRED_MESSAGE_CREATE, base_interactions.ResponseType.DEFERRED_MESSAGE_UPDATE]
 )
-_DeferredTypesT = typing.Union[
-    typing.Literal[base_interactions.ResponseType.DEFERRED_MESSAGE_CREATE],
-    typing.Literal[5],
-    typing.Literal[base_interactions.ResponseType.DEFERRED_MESSAGE_UPDATE],
-    typing.Literal[6],
+_DeferredTypesT = typing.Literal[
+    base_interactions.ResponseType.DEFERRED_MESSAGE_CREATE, 5, base_interactions.ResponseType.DEFERRED_MESSAGE_UPDATE, 6
 ]
 _IMMEDIATE_TYPES: typing.AbstractSet[_ImmediateTypesT] = frozenset(
     [base_interactions.ResponseType.MESSAGE_CREATE, base_interactions.ResponseType.MESSAGE_UPDATE]
 )
-_ImmediateTypesT = typing.Union[
-    typing.Literal[base_interactions.ResponseType.MESSAGE_CREATE],
-    typing.Literal[4],
-    typing.Literal[base_interactions.ResponseType.MESSAGE_UPDATE],
-    typing.Literal[7],
+_ImmediateTypesT = typing.Literal[
+    base_interactions.ResponseType.MESSAGE_CREATE, 4, base_interactions.ResponseType.MESSAGE_UPDATE, 7
 ]
 
 
diff --git a/hikari/internal/net.py b/hikari/internal/net.py
index 1dfc2283..d60aac3e 100644
--- a/hikari/internal/net.py
+++ b/hikari/internal/net.py
@@ -48,7 +48,7 @@ async def generate_error_response(response: aiohttp.ClientResponse) -> errors.HT
     try:
         json_body = await response.json()
         args.append(json_body.get("message", ""))
-        args.append(errors.RESTErrorCode(json_body.get("code", 0)))
+        args.append(json_body.get("code", 0))
         raw_error_array: typing.Optional[data_binding.JSONObject] = json_body.get("errors")
     except aiohttp.ContentTypeError:
         raw_error_array = None
diff --git a/hikari/messages.py b/hikari/messages.py
index 4bc194c3..3c679c8f 100644
--- a/hikari/messages.py
+++ b/hikari/messages.py
@@ -1419,16 +1419,20 @@ async def remove_reaction(
             # reaction.
             await message.remove_reaction("\N{OK HAND SIGN}")
 
+            # Using a custom emoji's name and ID to remove a specific user's
+            # reaction from this reaction.
+            await message.remove_reaction("a:Distraction", 745991233939439616, user=some_user)
+
             # Using a unicode emoji and removing a specific user from this
             # reaction.
-            await message.remove_reaction("\N{OK HAND SIGN}", some_user)
+            await message.remove_reaction("\N{OK HAND SIGN}", user=some_user)
 
             # Using the name and id.
             await message.add_reaction("rooAYAYA", 705837374319493284)
 
             # Using an Emoji object and removing a specific user from this
             # reaction.
-            await message.remove_reaction(some_emoji_object, some_user)
+            await message.remove_reaction(some_emoji_object, user=some_user)
 
         Raises
         ------


Test patch:
diff --git a/tests/hikari/test_errors.py b/tests/hikari/test_errors.py
index 875dfcee..99bf71c2 100644
--- a/tests/hikari/test_errors.py
+++ b/tests/hikari/test_errors.py
@@ -81,23 +81,23 @@ def error(self):
             {},
             "raw body",
             "message",
-            errors.RESTErrorCode.UNKNOWN_GUILD,
+            12345,
         )
 
     def test_str(self, error):
-        assert str(error) == "Bad Request 400: (UNKNOWN_GUILD) 'message' for https://some.url"
+        assert str(error) == "Bad Request 400: (12345) 'message' for https://some.url"
 
     def test_str_when_message_is_None(self, error):
         error.message = None
-        assert str(error) == "Bad Request 400: (UNKNOWN_GUILD) 'raw body' for https://some.url"
+        assert str(error) == "Bad Request 400: (12345) 'raw body' for https://some.url"
 
-    def test_str_when_code_is_GENERAL_ERROR(self, error):
-        error.code = errors.RESTErrorCode.GENERAL_ERROR
+    def test_str_when_code_is_zero(self, error):
+        error.code = 0
         assert str(error) == "Bad Request 400: 'message' for https://some.url"
 
-    def test_str_when_code_is_int(self, error):
+    def test_str_when_code_is_not_zero(self, error):
         error.code = 100
-        assert str(error) == "Bad Request 400: 'message' for https://some.url"
+        assert str(error) == "Bad Request 400: (100) 'message' for https://some.url"
 
 
 class TestBadRequestError: