diff --git a/interactions/api/gateway/client.py b/interactions/api/gateway/client.py index bdb56b95d..e02d71b49 100644 --- a/interactions/api/gateway/client.py +++ b/interactions/api/gateway/client.py @@ -264,7 +264,7 @@ async def wait_until_ready(self) -> None: """Waits for the client to become ready according to the Gateway.""" await self.ready.wait() - def _dispatch_event(self, event: str, data: dict) -> None: # sourcery no-metrics + def _dispatch_event(self, event: str, data: dict) -> None: """ Dispatches an event from the Gateway. @@ -273,11 +273,12 @@ def _dispatch_event(self, event: str, data: dict) -> None: # sourcery no-metric :param data: The data for the event. :type data: dict """ + # sourcery no-metrics path: str = "interactions" path += ".models" if event == "INTERACTION_CREATE" else ".api.models" if event == "INTERACTION_CREATE": if data.get("type"): - # sourcery skip: extract-method + # sourcery skip: dict-assign-update-to-union, extract-method, low-code-quality _context = self.__contextualize(data) _name: str = "" __args: list = [_context] diff --git a/interactions/api/gateway/heartbeat.py b/interactions/api/gateway/heartbeat.py index 662f006f9..14731477e 100644 --- a/interactions/api/gateway/heartbeat.py +++ b/interactions/api/gateway/heartbeat.py @@ -1,3 +1,4 @@ +import contextlib from asyncio import AbstractEventLoop, Event from sys import version_info @@ -15,8 +16,6 @@ def __init__(self, loop: AbstractEventLoop) -> None: :param loop: The event loop to base the asynchronous manager. :type loop: AbstractEventLoop """ - try: + with contextlib.suppress(TypeError): self.event = Event(loop=loop) if version_info < (3, 10) else Event() - except TypeError: - pass self.delay = 0.0 diff --git a/interactions/api/http/invite.py b/interactions/api/http/invite.py index 209584f96..2e55f0537 100644 --- a/interactions/api/http/invite.py +++ b/interactions/api/http/invite.py @@ -33,15 +33,16 @@ async def get_invite( """ params_set = { "with_counts=true" if with_counts else None, - "with_expiration=false" if not with_expiration else None, + None if with_expiration else "with_expiration=false", f"guild_scheduled_event_id={guild_scheduled_event_id}" if guild_scheduled_event_id else None, } + final = "&".join([item for item in params_set if item is not None]) return await self._req.request( - Route("GET", f"/invites/{invite_code}{'?' + final if final is not None else ''}") + Route("GET", f"/invites/{invite_code}{f'?{final}' if final is not None else ''}") ) async def delete_invite(self, invite_code: str, reason: Optional[str] = None) -> dict: diff --git a/interactions/api/http/message.py b/interactions/api/http/message.py index 12a71305e..47b8978f7 100644 --- a/interactions/api/http/message.py +++ b/interactions/api/http/message.py @@ -175,7 +175,7 @@ async def edit_message( file._fp, ) part.set_content_disposition( - "form-data", name="files[" + str(id) + "]", filename=file._filename + "form-data", name=f"files[{str(id)}]", filename=file._filename ) return await self._req.request( diff --git a/interactions/api/http/reaction.py b/interactions/api/http/reaction.py index 6701f621a..cd68e2b09 100644 --- a/interactions/api/http/reaction.py +++ b/interactions/api/http/reaction.py @@ -137,8 +137,10 @@ async def get_reactions_of_emoji( return await self._req.request( Route( "GET", - "/channels/{channel_id}/messages/{message_id}/reactions/{emoji}" - + f"{'?' + final if final is not None else ''}", + ( + "/channels/{channel_id}/messages/{message_id}/reactions/{emoji}" + + f"{f'?{final}' if final is not None else ''}" + ), channel_id=channel_id, message_id=message_id, emoji=emoji, diff --git a/interactions/api/http/request.py b/interactions/api/http/request.py index fb0a3dbed..f19a1bce8 100644 --- a/interactions/api/http/request.py +++ b/interactions/api/http/request.py @@ -98,14 +98,14 @@ async def request(self, route: Route, **kwargs) -> Optional[Any]: :return: The contents of the request if any. :rtype: Optional[Any] """ + # sourcery skip: low-code-quality kwargs["headers"] = {**self._headers, **kwargs.get("headers", {})} if kwargs.get("json"): kwargs["headers"]["Content-Type"] = "application/json" - reason = kwargs.pop("reason", None) - if reason: + if reason := kwargs.pop("reason", None): kwargs["headers"]["X-Audit-Log-Reason"] = quote(reason, safe="/ ") # Huge credit and thanks to LordOfPolls for the lock/retry logic. @@ -185,14 +185,7 @@ async def request(self, route: Route, **kwargs) -> Optional[Any]: severity=50, ) if response.status == 429: - if not is_global: - log.warning( - f"The HTTP client has encountered a per-route ratelimit. Locking down future requests for {reset_after} seconds." - ) - _limiter.reset_after = reset_after - await asyncio.sleep(_limiter.reset_after) - continue - else: + if is_global: log.warning( f"The HTTP client has encountered a global ratelimit. Locking down future requests for {reset_after} seconds." ) @@ -200,6 +193,13 @@ async def request(self, route: Route, **kwargs) -> Optional[Any]: self._loop.call_later( self._global_lock.reset_after, self._global_lock.lock.release ) + else: + log.warning( + f"The HTTP client has encountered a per-route ratelimit. Locking down future requests for {reset_after} seconds." + ) + _limiter.reset_after = reset_after + await asyncio.sleep(_limiter.reset_after) + continue if remaining is not None and int(remaining) == 0: log.warning( f"The HTTP client has exhausted a per-route ratelimit. Locking route for {reset_after} seconds." diff --git a/interactions/api/http/scheduledEvent.py b/interactions/api/http/scheduledEvent.py index 3c6238728..2ed3d6917 100644 --- a/interactions/api/http/scheduledEvent.py +++ b/interactions/api/http/scheduledEvent.py @@ -38,8 +38,7 @@ async def create_scheduled_event(self, guild_id: Snowflake, payload: dict) -> di data = {k: v for k, v in payload.items() if k in valid_keys} return await self._req.request( - Route("POST", "/guilds/{guild_id}/scheduled-events", guild_id=int(guild_id)), - json=data, + Route("POST", "/guilds/{guild_id}/scheduled-events", guild_id=guild_id), json=data ) async def get_scheduled_event( diff --git a/interactions/api/models/attrs_utils.py b/interactions/api/models/attrs_utils.py index 2a725113e..9f28c9859 100644 --- a/interactions/api/models/attrs_utils.py +++ b/interactions/api/models/attrs_utils.py @@ -23,6 +23,7 @@ class DictSerializerMixin: """Should the kwargs be deepcopied or not?""" def __init__(self, kwargs_dict: dict = None, /, **other_kwargs): + # sourcery skip: low-code-quality kwargs = kwargs_dict or other_kwargs client = kwargs.pop("_client", None) diff --git a/interactions/api/models/channel.py b/interactions/api/models/channel.py index 4dc91fef3..7c6e09904 100644 --- a/interactions/api/models/channel.py +++ b/interactions/api/models/channel.py @@ -199,7 +199,7 @@ async def send( List["SelectMenu"], ] ] = MISSING, - ) -> "Message": + ) -> "Message": # noqa # sourcery skip: dict-assign-update-to-union """ Sends a message in the channel. @@ -757,7 +757,7 @@ async def purge( before: Optional[int] = MISSING, reason: Optional[str] = None, bulk: Optional[bool] = True, - ) -> List["Message"]: + ) -> List["Message"]: # noqa # sourcery skip: low-code-quality """ Purges a given amount of messages from a channel. You can specify a check function to exclude specific messages. diff --git a/interactions/api/models/guild.py b/interactions/api/models/guild.py index 1abdb5003..f37c76f84 100644 --- a/interactions/api/models/guild.py +++ b/interactions/api/models/guild.py @@ -891,7 +891,7 @@ async def modify_channel( auto_archive_duration: Optional[int] = MISSING, locked: Optional[bool] = MISSING, reason: Optional[str] = None, - ) -> Channel: + ) -> Channel: # sourcery skip: low-code-quality """ Edits a channel of the guild. @@ -1124,7 +1124,7 @@ async def modify( description: Optional[str] = MISSING, premium_progress_bar_enabled: Optional[bool] = MISSING, reason: Optional[str] = None, - ) -> "Guild": + ) -> "Guild": # sourcery skip: low-code-quality """ Modifies the current guild. @@ -2181,7 +2181,7 @@ async def modify_auto_moderation_rule( exempt_roles: Optional[List[int]] = MISSING, exempt_channels: Optional[List[int]] = MISSING, reason: Optional[str] = None, - ) -> "AutoModerationRule": + ) -> "AutoModerationRule": # noqa # sourcery skip: compare-via-equals """ Edits an AutoMod rule diff --git a/interactions/api/models/message.py b/interactions/api/models/message.py index 22d969640..1768822c0 100644 --- a/interactions/api/models/message.py +++ b/interactions/api/models/message.py @@ -1,3 +1,4 @@ +import contextlib from datetime import datetime from enum import IntEnum from typing import TYPE_CHECKING, List, Optional, Union @@ -626,10 +627,8 @@ def remove_author(self) -> None: Removes the embed's author """ - try: + with contextlib.suppress(AttributeError): del self.author - except AttributeError: - pass def set_author( self, @@ -1055,7 +1054,7 @@ async def reply( List["SelectMenu"], ] ] = MISSING, - ) -> "Message": + ) -> "Message": # sourcery skip: dict-assign-update-to-union """ Sends a new message replying to the old. diff --git a/interactions/api/models/webhook.py b/interactions/api/models/webhook.py index a100fda55..743da4b34 100644 --- a/interactions/api/models/webhook.py +++ b/interactions/api/models/webhook.py @@ -131,7 +131,7 @@ async def modify( name: Optional[str] = MISSING, channel_id: int = MISSING, avatar: Optional[Image] = MISSING, - ) -> "Webhook": + ) -> "Webhook": # sourcery skip: compare-via-equals """ Modifies the current webhook. diff --git a/interactions/client/bot.py b/interactions/client/bot.py index f8c01d64b..b82663962 100644 --- a/interactions/client/bot.py +++ b/interactions/client/bot.py @@ -1,3 +1,4 @@ +import contextlib import re import sys from asyncio import AbstractEventLoop, CancelledError, get_event_loop, iscoroutinefunction @@ -187,7 +188,7 @@ async def __compare_sync( _command: dict = {} def __check_options(command, data): - # sourcery skip: none-compare + # sourcery skip: low-code-quality, none-compare # sourcery no-metrics _command_option_names = [option["name"] for option in command.get("options")] _data_option_names = [option["name"] for option in data.get("options")] @@ -266,11 +267,14 @@ def __check_options(command, data): else: continue - for i, __name in enumerate(_command_option_names): - if _data_option_names[i] != __name: - return False, command - - return True, command + return next( + ( + (False, command) + for i, __name in enumerate(_command_option_names) + if _data_option_names[i] != __name + ), + (True, command), + ) for command in pool: if command["name"] == data["name"]: @@ -449,6 +453,7 @@ async def __sync(self) -> None: # sourcery no-metrics .. warning:: This is an internal method. Do not call it unless you know what you are doing! """ + # sourcery skip: low-code-quality log.debug("starting command sync") _guilds = await self._http.get_self_guilds() @@ -479,7 +484,7 @@ async def __sync(self) -> None: # sourcery no-metrics ) except LibraryException as e: if int(e.code) != 50001: - raise LibraryException(code=e.code, message=e.message) + raise LibraryException(code=e.code, message=e.message) from e log.warning( f"Your bot is missing access to guild with corresponding id {_id}! " @@ -1345,23 +1350,17 @@ def remove( if ext_name != "Extension": _extension = self._extensions.get(ext_name) - try: + with contextlib.suppress(AttributeError): self._loop.create_task( _extension.teardown(remove_commands=remove_commands) ) # made for Extension, usable by others - except AttributeError: - pass - del sys.modules[_name] else: - try: + with contextlib.suppress(AttributeError): self._loop.create_task( extension.teardown(remove_commands=remove_commands) ) # made for Extension, usable by others - except AttributeError: - pass - del self._extensions[_name] log.debug(f"Removed extension {name}.") @@ -1539,6 +1538,7 @@ def setup(client): client: Client def __new__(cls, client: Client, *args, **kwargs) -> "Extension": + # sourcery skip: low-code-quality self = super().__new__(cls) diff --git a/interactions/client/context.py b/interactions/client/context.py index 79acc50cf..0cb4cfd51 100644 --- a/interactions/client/context.py +++ b/interactions/client/context.py @@ -336,11 +336,13 @@ def __attrs_post_init__(self) -> None: target = self.data.target_id if self.data.type == 2: - if self.guild_id and str(self.data.target_id) in self.data.resolved.members: - # member id would have potential to exist, and therefore have target def priority. - self.target = self.data.resolved.members[target] - else: - self.target = self.data.resolved.users[target] + self.target = ( + self.data.resolved.members[target] + if self.guild_id and str(self.data.target_id) in self.data.resolved.members + else self.data.resolved.users[target] + ) + # member id would have potential to exist, and therefore have target def priority. + elif self.data.type == 3: self.target = self.data.resolved.messages[target] diff --git a/interactions/client/decor.py b/interactions/client/decor.py index 4cd89482b..e3063fe4b 100644 --- a/interactions/client/decor.py +++ b/interactions/client/decor.py @@ -21,7 +21,7 @@ def command( description_localizations: Optional[Dict[Union[str, Locale], str]] = MISSING, default_member_permissions: Optional[Union[int, Permissions]] = MISSING, dm_permission: Optional[bool] = MISSING -) -> Union[List[dict], dict]: +) -> Union[List[dict], dict]: # sourcery skip: low-code-quality """ A wrapper designed to interpret the client-facing API for how a command is to be created and used. diff --git a/interactions/client/models/component.py b/interactions/client/models/component.py index 0ce07ce7d..b2f55cfa3 100644 --- a/interactions/client/models/component.py +++ b/interactions/client/models/component.py @@ -1,3 +1,4 @@ +import contextlib from typing import List, Optional from ...api.error import LibraryException @@ -30,10 +31,8 @@ def __setattr__(self, key, value) -> None: key not in self._json or value != self._json.get(key) ): if value is not None and value is not MISSING: - try: + with contextlib.suppress(AttributeError): value = [val._json for val in value] if isinstance(value, list) else value._json - except AttributeError: - pass self._json.update({key: value}) elif value is None and key in self._json.keys(): del self._json[key]