From 09c99a96ab435cd9cf31c4004076fa92bf21e75f Mon Sep 17 00:00:00 2001 From: Sourcery AI <> Date: Wed, 24 May 2023 09:24:11 +0000 Subject: [PATCH] 'Refactored by Sourcery' --- discord/__main__.py | 23 +- discord/abc.py | 54 ++- discord/activity.py | 24 +- discord/application_commands.py | 194 +++++------ discord/asset.py | 40 ++- discord/audit_logs.py | 36 +- discord/auto_updater.py | 35 +- discord/automod.py | 29 +- discord/channel.py | 88 ++--- discord/client.py | 60 ++-- discord/colour.py | 6 +- discord/components.py | 76 ++--- discord/embeds.py | 12 +- discord/emoji.py | 3 +- discord/enums.py | 57 ++-- discord/errors.py | 10 +- discord/ext/commands/bot.py | 113 +++---- discord/ext/commands/cog.py | 16 +- discord/ext/commands/context.py | 9 +- discord/ext/commands/converter.py | 55 ++- discord/ext/commands/cooldowns.py | 11 +- discord/ext/commands/core.py | 96 +++--- discord/ext/commands/errors.py | 64 ++-- discord/ext/commands/help.py | 58 ++-- discord/ext/commands/view.py | 19 +- discord/ext/tasks/__init__.py | 2 +- discord/file.py | 2 +- discord/flags.py | 18 +- discord/gateway.py | 9 +- discord/guild.py | 49 ++- discord/http.py | 48 +-- discord/interactions.py | 66 ++-- discord/invite.py | 7 +- discord/iterators.py | 125 +++---- discord/member.py | 31 +- discord/message.py | 31 +- discord/mixins.py | 4 +- discord/oauth2/client.py | 76 ++--- discord/oauth2/models.py | 12 +- discord/oauth2/server.py | 2 +- discord/oggparse.py | 4 +- discord/opus.py | 2 +- discord/partial_emoji.py | 22 +- discord/permissions.py | 12 +- discord/player.py | 91 ++--- discord/raw_models.py | 2 +- discord/reaction.py | 4 +- discord/role.py | 22 +- discord/scheduled_event.py | 25 +- discord/shard.py | 8 +- discord/sink.py | 11 +- discord/state.py | 123 +++---- discord/user.py | 18 +- discord/utils.py | 102 +++--- discord/voice_client.py | 21 +- discord/webhook.py | 39 +-- discord/welcome_screen.py | 13 +- discord/widget.py | 2 +- docs/conf.py | 8 +- docs/extensions/attributetable.py | 26 +- docs/extensions/builder.py | 12 +- examples/buttons/calculator.py | 21 +- examples/buttons/calculator_ansi.py | 21 +- examples/modals/suggestions.py | 404 ++++++++++++----------- examples/slash-commands/clear_command.py | 15 +- examples/slash-commands/help_command.py | 28 +- setup.py | 4 +- 67 files changed, 1239 insertions(+), 1491 deletions(-) diff --git a/discord/__main__.py b/discord/__main__.py index 41f25c69..598f5334 100644 --- a/discord/__main__.py +++ b/discord/__main__.py @@ -42,8 +42,9 @@ def show_version(): version_info = discord.version_info entries.append('- discord.py-message-components v{0.major}.{0.minor}.{0.micro}-{0.releaselevel}'.format(version_info)) if version_info.releaselevel != 'final': - version = importlib_metadata.version('discord.py-message-components') - if version: + if version := importlib_metadata.version( + 'discord.py-message-components' + ): entries.append(' - discord.py.message-components metadata: v{0}'.format(version)) entries.append('- aiohttp v{0.__version__}'.format(aiohttp)) @@ -177,7 +178,7 @@ async def cog_after_invoke(self, ctx): } # NUL (0) and 1-31 are disallowed -_base_table.update((chr(i), None) for i in range(32)) +_base_table |= ((chr(i), None) for i in range(32)) translation_table = str.maketrans(_base_table) @@ -206,7 +207,7 @@ def newbot(parser, args): try: new_directory.mkdir(exist_ok=True, parents=True) except OSError as exc: - parser.error('could not create our bot directory ({})'.format(exc)) + parser.error(f'could not create our bot directory ({exc})') cogs = new_directory / 'cogs' @@ -215,27 +216,27 @@ def newbot(parser, args): init = cogs / '__init__.py' init.touch() except OSError as exc: - print('warning: could not create cogs directory ({})'.format(exc)) + print(f'warning: could not create cogs directory ({exc})') try: with open(str(new_directory / 'config.py'), 'w', encoding='utf-8') as fp: fp.write('token = "place your token here"\ncogs = []\n') except OSError as exc: - parser.error('could not create config file ({})'.format(exc)) + parser.error(f'could not create config file ({exc})') try: with open(str(new_directory / 'bot.py'), 'w', encoding='utf-8') as fp: base = 'Bot' if not args.sharded else 'AutoShardedBot' fp.write(bot_template.format(base=base, prefix=args.prefix)) except OSError as exc: - parser.error('could not create bot file ({})'.format(exc)) + parser.error(f'could not create bot file ({exc})') if not args.no_git: try: with open(str(new_directory / '.gitignore'), 'w', encoding='utf-8') as fp: fp.write(gitignore_template) except OSError as exc: - print('warning: could not create .gitignore file ({})'.format(exc)) + print(f'warning: could not create .gitignore file ({exc})') print('successfully made bot at', new_directory) @@ -245,7 +246,7 @@ def newcog(parser, args): try: cog_dir.mkdir(exist_ok=True) except OSError as exc: - print('warning: could not create cogs directory ({})'.format(exc)) + print(f'warning: could not create cogs directory ({exc})') directory = cog_dir / to_path(parser, args.name) directory = directory.with_suffix('.py') @@ -264,12 +265,12 @@ def newcog(parser, args): name = name.title() if args.display_name: - attrs += ', name="{}"'.format(args.display_name) + attrs += f', name="{args.display_name}"' if args.hide_commands: attrs += ', command_attrs=dict(hidden=True)' fp.write(cog_template.format(name=name, extra=extra, attrs=attrs)) except OSError as exc: - parser.error('could not create cog file ({})'.format(exc)) + parser.error(f'could not create cog file ({exc})') else: print('successfully made cog at', directory) diff --git a/discord/abc.py b/discord/abc.py index b4923e1a..9dac5472 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -147,19 +147,19 @@ def mention(self): @classmethod def __subclasshook__(cls, C): - if cls is User: - if Snowflake.__subclasshook__(C) is NotImplemented: - return NotImplemented + if cls is not User: + return NotImplemented + if Snowflake.__subclasshook__(C) is NotImplemented: + return NotImplemented - mro = C.__mro__ - for attr in ('display_name', 'mention', 'name', 'avatar', 'discriminator', 'bot'): - for base in mro: - if attr in base.__dict__: - break - else: - return NotImplemented - return True - return NotImplemented + mro = C.__mro__ + for attr in ('display_name', 'mention', 'name', 'avatar', 'discriminator', 'bot'): + for base in mro: + if attr in base.__dict__: + break + else: + return NotImplemented + return True class PrivateChannel(metaclass=abc.ABCMeta): @@ -186,10 +186,7 @@ def __subclasshook__(cls, C): return NotImplemented mro = C.__mro__ - for base in mro: - if 'me' in base.__dict__: - return True - return NotImplemented + return next((True for base in mro if 'me' in base.__dict__), NotImplemented) return NotImplemented @@ -324,14 +321,10 @@ async def _edit(self, options, reason): payload = { 'allow': allow.value, 'deny': deny.value, - 'id': target.id + 'id': target.id, + 'type': 'role' if isinstance(target, Role) else 'member', } - if isinstance(target, Role): - payload['type'] = 'role' - else: - payload['type'] = 'member' - perms.append(payload) options['permission_overwrites'] = perms @@ -356,7 +349,9 @@ def _fill_overwrites(self, data): for index, overridden in enumerate(data.get('permission_overwrites', [])): overridden_type = try_enum(PermissionType, overridden.pop('type')) if not isinstance(overridden_type, PermissionType): - raise AttributeError('Type type should be 0 - member, or 1 - role not %s' % overridden_type) + raise AttributeError( + f'Type type should be 0 - member, or 1 - role not {overridden_type}' + ) overridden_id = int(overridden.pop('id')) self._overwrites.append(_Overwrites(id=overridden_id, type=overridden_type.name, **overridden)) @@ -371,9 +366,7 @@ def _fill_overwrites(self, data): # swap it to be the first one. everyone_index = index - # do the swap - tmp = self._overwrites - if tmp: + if tmp := self._overwrites: tmp[everyone_index], tmp[0] = tmp[0], tmp[everyone_index] @property @@ -395,7 +388,7 @@ def changed_roles(self): @property def mention(self): """:class:`str`: The string that allows you to mention the channel.""" - return '<#%s>' % self.id + return f'<#{self.id}>' @property def jump_url(self): @@ -694,15 +687,14 @@ async def set_permissions( raise InvalidArgument(f'target parameter must be either Member or Role, not {target.__class__.__name__}') if isinstance(overwrite, _Undefined): - if len(permissions) == 0: + if not permissions: raise InvalidArgument('No overwrite provided.') try: overwrite = PermissionOverwrite(**permissions) except (ValueError, TypeError): raise InvalidArgument('Invalid permissions given to keyword arguments.') - else: - if len(permissions) > 0: - raise InvalidArgument('Cannot mix overwrite and keyword arguments.') + elif permissions: + raise InvalidArgument('Cannot mix overwrite and keyword arguments.') # TODO: wait for event diff --git a/discord/activity.py b/discord/activity.py index 88c2e7e1..cc418e38 100644 --- a/discord/activity.py +++ b/discord/activity.py @@ -194,10 +194,7 @@ def __init__(self, **kwargs): self.session_id = kwargs.pop('session_id', None) self.type = try_enum(ActivityType, kwargs.pop('type', -1)) emoji = kwargs.pop('emoji', None) - if emoji is not None: - self.emoji = PartialEmoji.from_dict(emoji) - else: - self.emoji = None + self.emoji = PartialEmoji.from_dict(emoji) if emoji is not None else None def __repr__(self): attrs = ( @@ -210,7 +207,7 @@ def __repr__(self): 'emoji', ) mapped = ' '.join('%s=%r' % (attr, getattr(self, attr)) for attr in attrs) - return '' % mapped + return f'' def to_dict(self): ret = {} @@ -338,9 +335,9 @@ def _extract_timestamp(self, data, key): try: dt = data[key] except KeyError: - setattr(self, '_' + key, 0) + setattr(self, f'_{key}', 0) else: - setattr(self, '_' + key, dt.timestamp() * 1000.0) + setattr(self, f'_{key}', dt.timestamp() * 1000.0) @property def type(self): @@ -632,7 +629,7 @@ def album_cover_url(self): if large_image[:8] != 'spotify:': return '' album_image_id = large_image[8:] - return 'https://i.scdn.co/image/' + album_image_id + return f'https://i.scdn.co/image/{album_image_id}' @property def track_id(self): @@ -751,12 +748,9 @@ def __hash__(self): return hash((self.name, str(self.emoji))) def __str__(self): - if self.emoji: - if self.name: - return '%s %s' % (self.emoji, self.name) - return str(self.emoji) - else: + if not self.emoji: return str(self.name) + return f'{self.emoji} {self.name}' if self.name else str(self.emoji) def __repr__(self): return ''.format(self) @@ -779,9 +773,7 @@ def create_activity(data): else: return CustomActivity(name=name, **data) elif game_type is ActivityType.streaming: - if 'url' in data: - return Streaming(**data) - return Activity(**data) + return Streaming(**data) if 'url' in data else Activity(**data) elif game_type is ActivityType.listening and 'sync_id' in data and 'session_id' in data: return Spotify(**data) return Activity(**data) diff --git a/discord/application_commands.py b/discord/application_commands.py index 3a4a88a5..67c2db43 100644 --- a/discord/application_commands.py +++ b/discord/application_commands.py @@ -238,14 +238,14 @@ def from_target(self, target: Union[Guild, BaseInteraction], *, default: Any = N except KeyError: if default is None: return self.__languages_dict__.get('en-US', self.__languages_dict__.get('en-GB', None)) - else: - if (default.value if default is Locale else default) not in self.__slots__: - return default - else: - try: - self[default.value if default is Locale else default] - except KeyError: # not a locale so return it - return default + if ( + default.value if default is Locale else default + ) not in self.__slots__: + return default + try: + self[default.value if default is Locale else default] + except KeyError: # not a locale so return it + return default class ApplicationCommand: @@ -311,7 +311,7 @@ def __call__(self, *args, **kwargs): return super().__init__(self, *args, **kwargs) def __repr__(self) -> str: - return '<%s name=%s, id=%s, disabled=%s>' % (self.__class__.__name__, self.name, self.id, self.disabled) + return f'<{self.__class__.__name__} name={self.name}, id={self.id}, disabled={self.disabled}>' def __eq__(self, other) -> bool: if isinstance(other, self.__class__): @@ -380,10 +380,14 @@ async def can_run(self, *args, **kwargs) -> bool: # if self.cog: # args = (self.cog, *args) check_func = kwargs.pop('__func', self) - checks = getattr(check_func, '__commands_checks__', getattr(self.func, '__commands_checks__', [])) - if not checks: + if checks := getattr( + check_func, + '__commands_checks__', + getattr(self.func, '__commands_checks__', []), + ): + return await async_all(check(args[0]) for check in checks) + else: return True - return await async_all(check(args[0]) for check in checks) async def invoke(self, interaction, *args, **kwargs): if not self.func: @@ -491,10 +495,7 @@ async def delete(self) -> None: Deletes the application command """ - if self.guild_id != 0: - guild_id = self.guild_id - else: - guild_id = None + guild_id = self.guild_id if self.guild_id != 0 else None await self._state.http.delete_application_command(self.application_id, self.id, guild_id) if guild_id: self._state._get_client()._remove_application_command(self, from_cache=True) @@ -527,21 +528,22 @@ def __init__( ): if 100 < len(str(name)) < 1: - raise ValueError('The name of a choice must bee between 1 and 100 characters long, got %s.' % len(name)) + raise ValueError( + f'The name of a choice must bee between 1 and 100 characters long, got {len(name)}.' + ) self.name: str = str(name) self.value: Union[str, int, float] = value if value is not None else name self.name_localizations: Optional[Localizations] = name_localizations def __repr__(self): - return '' % (self.name, self.value) + return f'' def to_dict(self) -> Dict[str, Any]: - base = { + return { 'name': str(self.name), 'value': self.value, - 'name_localizations': self.name_localizations.to_dict() + 'name_localizations': self.name_localizations.to_dict(), } - return base @classmethod def from_dict(cls, data) -> SlashCommandOptionChoice: @@ -658,7 +660,9 @@ def __init__( self.name: str = name self.name_localizations: Localizations = name_localizations if 100 < len(description) < 1: - raise ValueError('The description must be between 1 and 100 characters long, got %s.' % len(description)) + raise ValueError( + f'The description must be between 1 and 100 characters long, got {len(description)}.' + ) self.description: str = description self.description_localizations: Localizations = description_localizations self.required: bool = required @@ -681,12 +685,7 @@ def __init__( self.ignore_conversion_failures: bool = ignore_conversion_failures def __repr__(self) -> str: - return '' \ - % (self.type, - self.name, - self.description, - self.required, - self.choices) + return f'' @property def autocomplete(self) -> bool: @@ -705,12 +704,12 @@ def autocomplete(self) -> bool: @autocomplete.setter def autocomplete(self, value: bool) -> None: - if bool(value) is True: + if value: if self.type not in (OptionType.string, OptionType.integer, OptionType.number): raise TypeError('Only Options of type string, integer or number could have autocomplete.') elif self.choices: raise TypeError('Options with choices could not have autocomplete.') - self._autocomplete = bool(value) + self._autocomplete = value @property def choices(self) -> Optional[List[SlashCommandOptionChoice]]: @@ -791,7 +790,7 @@ def channel_types(self, value) -> None: for index, c in enumerate(value): if not isinstance(c, ChannelType): value[index] = ChannelType.from_type(c) - if not any([isinstance(c, ChannelType) for c in value]): + if not any(isinstance(c, ChannelType) for c in value): raise ValueError('Only ChannelType Enums, integers or Channel classes allowed.') self._channel_types = value @@ -803,7 +802,7 @@ def to_dict(self) -> dict: 'description': str(self.description), 'description_localizations': self.description_localizations.to_dict() } - if bool(self.required) is True: + if bool(self.required): base['required'] = bool(self.required) if self.choices: base['choices'] = [c.to_dict() for c in self.choices] @@ -816,9 +815,8 @@ def to_dict(self) -> dict: if self.max_value is not None: base['max_value'] = self.max_value if self.type.string: - min_length = self.min_length max_length = self.max_length - if min_length: + if min_length := self.min_length: base['min_length'] = min_length if max_length: base['max_length'] = max_length @@ -870,10 +868,12 @@ def __init__( self.name = name if 100 < len(description) < 1: raise ValueError( - 'The description of the Sub-Command must be 1-100 characters long, got %s.' % len(description) - ) + f'The description of the Sub-Command must be 1-100 characters long, got {len(description)}.' + ) if len(options) > 25: - raise ValueError('The maximum of options per Sub-Command is 25, got %s.' % len(options)) + raise ValueError( + f'The maximum of options per Sub-Command is 25, got {len(options)}.' + ) self.options = options self.func = kwargs.get('func', None) self.cog = kwargs.get('cog', None) @@ -899,11 +899,7 @@ def disabled(self, value: bool) -> None: self._disabled = value def __repr__(self): - return '' \ - % (self.parent.name, - self.name, - self.description, - self.options) + return f'' @property def base_command(self) -> SlashCommand: @@ -983,24 +979,27 @@ def qualified_name(self) -> str: return full_name def to_dict(self): - base = { + return { 'type': 1, 'name': str(self.name), 'name_localizations': self.name_localizations.to_dict(), 'description': str(self.description), 'description_localizations': self.description_localizations.to_dict(), - 'options': [c.to_dict() for c in self.options] + 'options': [c.to_dict() for c in self.options], } - return base async def can_run(self, *args, **kwargs): # if self.cog is not None: # args = (self.cog, *args) check_func = kwargs.pop('__func', self) - checks = getattr(check_func, '__commands_checks__', getattr(self.func, '__commands_checks__', [])) - if not checks: + if checks := getattr( + check_func, + '__commands_checks__', + getattr(self.func, '__commands_checks__', []), + ): + return await async_all(check(args[0]) for check in checks) + else: return True - return await async_all(check(args[0]) for check in checks) async def invoke(self, interaction, *args, **kwargs): if not self.func: @@ -1099,13 +1098,7 @@ def disabled(self, value: bool) -> None: cmd.disabled = value def __repr__(self): - return '' \ - % (self.parent.name, - self.name, - self.description, - self.options, - ', '.join([str(g) for g in self.guild_ids]) - ) + return f"" def autocomplete_callback(self, coro: Coroutine[Any, Any, Awaitable]): """ @@ -1204,10 +1197,14 @@ def __init__( ) self.name = name if 100 < len(description) < 1: - raise ValueError('The description must be between 1 and 100 characters long, got %s.' % len(description)) + raise ValueError( + f'The description must be between 1 and 100 characters long, got {len(description)}.' + ) self.description = description if len(options) > 25: - raise ValueError('The maximum of options per command is 25, got %s' % len(options)) + raise ValueError( + f'The maximum of options per command is 25, got {len(options)}' + ) self.connector: Dict[str, str] = connector self._sub_commands = {command.name: command for command in options if OptionType.try_value(command.type) in ( OptionType.sub_command, OptionType.sub_command_group)} @@ -1217,14 +1214,7 @@ def __init__( sc.parent = self def __repr__(self): - return '' \ - % (self.name, - self.description, - self.default_member_permissions, - self.options or self.sub_commands, - self.guild_id or 'None', - self.disabled, - self.id) + return f"" @property def _state(self): @@ -1408,8 +1398,7 @@ async def _parse_arguments(self, interaction: ApplicationCommandInteraction): name = connector.get(option.name) or option.name.replace('-', '_') if option.type in (OptionType.string, OptionType.integer, OptionType.boolean, OptionType.number): origin_option = get(to_invoke.options, name=option.name) - converter = origin_option.converter - if converter: + if converter := origin_option.converter: try: params[name] = await transform(interaction, origin_option, converter, str(option.value)) except Exception as exc: @@ -1427,7 +1416,7 @@ async def _parse_arguments(self, interaction: ApplicationCommandInteraction): params[name] = resolved.roles[_id] or _id elif option.type == OptionType.channel: params[name] = interaction.guild.get_channel(_id) or resolved.channels[_id] or interaction._state.get_channel(_id)\ - or PartialMessageable(interaction._state, _id, guild_id=interaction.guild) + or PartialMessageable(interaction._state, _id, guild_id=interaction.guild) elif option.type == OptionType.mentionable: try: params[name] = resolved.roles[_id] @@ -1465,25 +1454,22 @@ async def _actual_conversion(ctx, converter, argument, param): pass else: if module is not None: - if module.startswith('discord.') and module.endswith('converter'): - pass - else: - converter = getattr(converters, converter.__name__ + 'Converter', converter) + if not module.startswith('discord.') or not module.endswith( + 'converter' + ): + converter = getattr(converters, f'{converter.__name__}Converter', converter) try: if inspect.isclass(converter): if issubclass(converter, converters.Converter): instance = converter() - ret = await instance.convert(ctx, argument) - return ret + return await instance.convert(ctx, argument) else: method = getattr(converter, 'convert', None) if method is not None and inspect.ismethod(method): - ret = await method(ctx, argument) - return ret + return await method(ctx, argument) elif isinstance(converter, converters.Converter): - ret = await converter.convert(ctx, argument) - return ret + return await converter.convert(ctx, argument) except CommandError: raise except Exception as exc: @@ -1499,7 +1485,9 @@ async def _actual_conversion(ctx, converter, argument, param): except AttributeError: name = converter.__class__.__name__ - raise BadArgument('Converting to "{}" failed for parameter "{}".'.format(name, param.name)) from exc + raise BadArgument( + f'Converting to "{name}" failed for parameter "{param.name}".' + ) from exc async def do_conversion(interaction, converter, argument, param): @@ -1551,9 +1539,7 @@ async def _transform_greedy_pos(ctx, param, required, converter, value): else: result.append(value) - if not result and not required: - return param.default - return result + return param.default if not result and not required else result async def transform(interaction: ApplicationCommandInteraction, param: SlashCommandOption, converter, value: Any) -> Any: @@ -1579,13 +1565,7 @@ def disabled(self, value: bool): cmd.disabled = value def __repr__(self): - return '' \ - % (self.name, - self.description, - self.default_member_permissions, - self.options, - ', '.join([str(g) for g in self.guild_ids]) - ) + return f"" def autocomplete_callback(self, coro: 'Coroutine[Any, Any, Awaitable]'): """ @@ -1642,7 +1622,9 @@ def __init__( **kwargs ): if 32 < len(name) < 1: - raise ValueError('The name of the User-Command has to be 1-32 characters long, got %s.' % len(name)) + raise ValueError( + f'The name of the User-Command has to be 1-32 characters long, got {len(name)}.' + ) super().__init__(2, name=name, name_localizations=name_localizations, default_member_permissions=default_member_permissions, allow_dm=allow_dm, **kwargs ) @@ -1693,7 +1675,9 @@ def __init__( **kwargs ): if 32 < len(name) < 1: - raise ValueError('The name of the Message-Command has to be 1-32 characters long, got %s.' % len(name)) + raise ValueError( + f'The name of the Message-Command has to be 1-32 characters long, got {len(name)}.' + ) super().__init__(3, name=name, name_localizations=name_localizations, default_member_permissions=default_member_permissions, allow_dm=allow_dm, **kwargs ) @@ -1736,10 +1720,12 @@ def __init__( self.name = name if 100 < len(description) < 1: raise ValueError( - 'The description of the Sub-Command-Group must be 1-100 characters long, got %s.' % len(description) - ) + f'The description of the Sub-Command-Group must be 1-100 characters long, got {len(description)}.' + ) if 25 < len(commands) < 1: - raise ValueError('A Sub-Command-Group needs 1-25 sub-sub_commands, got %s.' % len(commands)) + raise ValueError( + f'A Sub-Command-Group needs 1-25 sub-sub_commands, got {len(commands)}.' + ) self.guild_ids = kwargs.get('guild_ids', parent.guild_ids) self.guild_id = kwargs.get('guild_id', parent.guild_id) self.func = kwargs.get('func', None) @@ -1755,12 +1741,7 @@ def __init__( self.parent = parent def __repr__(self): - return '' % \ - (self.parent.name, - self.name, - self.description, - ', '.join([sub_cmd.name for sub_cmd in self.sub_commands]) - ) + return f"" @property def parent(self) -> SlashCommand: @@ -1792,15 +1773,14 @@ def sub_commands(self) -> List[SubCommand]: return list(self._sub_commands.values()) def to_dict(self): - base = { + return { 'type': 2, 'name': str(self.name), 'name_localizations': self.name_localizations.to_dict(), 'description': str(self.description), 'description_localizations': self.description_localizations.to_dict(), - 'options': [c.to_dict() for c in self.sub_commands] + 'options': [c.to_dict() for c in self.sub_commands], } - return base @classmethod def from_dict(cls, data): @@ -1820,13 +1800,7 @@ def __init__(self, *args, guild_ids: List[int] = None, **kwargs): super().__init__(*args, **kwargs, guild_ids=guild_ids) def __repr__(self): - return '' % \ - (self.parent.name, - self.name, - self.description, - ', '.join([sub_cmd.name for sub_cmd in self.sub_commands]), - ', '.join([str(g) for g in self.guild_ids]) - ) + return f"" def generate_options( diff --git a/discord/asset.py b/discord/asset.py index 94fca9f8..bdd7858d 100644 --- a/discord/asset.py +++ b/discord/asset.py @@ -120,11 +120,11 @@ def _from_avatar( if not utils.valid_icon_size(size): raise InvalidArgument("size must be a power of 2 between 16 and 4096") if format is not None and format not in VALID_AVATAR_FORMATS: - raise InvalidArgument("format must be None or one of {}".format(VALID_AVATAR_FORMATS)) + raise InvalidArgument(f"format must be None or one of {VALID_AVATAR_FORMATS}") if format == "gif" and not user.is_avatar_animated(): raise InvalidArgument("non animated avatars do not support gif format") if static_format not in VALID_STATIC_FORMATS: - raise InvalidArgument("static_format must be one of {}".format(VALID_STATIC_FORMATS)) + raise InvalidArgument(f"static_format must be one of {VALID_STATIC_FORMATS}") if user.avatar is None: return user.default_avatar_url @@ -147,11 +147,11 @@ def _from_guild_avatar( if not utils.valid_icon_size(size): raise InvalidArgument("size must be a power of 2 between 16 and 4096") if format is not None and format not in VALID_AVATAR_FORMATS: - raise InvalidArgument("format must be None or one of {}".format(VALID_AVATAR_FORMATS)) + raise InvalidArgument(f"format must be None or one of {VALID_AVATAR_FORMATS}") if format == "gif" and not member.is_guild_avatar_animated(): raise InvalidArgument("non animated avatars do not support gif format") if static_format not in VALID_STATIC_FORMATS: - raise InvalidArgument("static_format must be one of {}".format(VALID_STATIC_FORMATS)) + raise InvalidArgument(f"static_format must be one of {VALID_STATIC_FORMATS}") if member.guild_avatar is None: return member.avatar_url @@ -179,11 +179,11 @@ def _from_banner( if not utils.valid_icon_size(size): raise InvalidArgument("size must be a power of 2 between 16 and 4096") if format is not None and format not in VALID_AVATAR_FORMATS: - raise InvalidArgument("format must be None or one of {}".format(VALID_AVATAR_FORMATS)) + raise InvalidArgument(f"format must be None or one of {VALID_AVATAR_FORMATS}") if format == "gif" and not user.is_banner_animated(): raise InvalidArgument("non animated avatars do not support gif format") if static_format not in VALID_STATIC_FORMATS: - raise InvalidArgument("static_format must be one of {}".format(VALID_STATIC_FORMATS)) + raise InvalidArgument(f"static_format must be one of {VALID_STATIC_FORMATS}") if format is None: format = 'gif' if user.is_banner_animated() else static_format @@ -205,11 +205,11 @@ def _from_guild_banner( if not utils.valid_icon_size(size): raise InvalidArgument("size must be a power of 2 between 16 and 4096") if format is not None and format not in VALID_AVATAR_FORMATS: - raise InvalidArgument("format must be None or one of {}".format(VALID_AVATAR_FORMATS)) + raise InvalidArgument(f"format must be None or one of {VALID_AVATAR_FORMATS}") if format == "gif" and not member.is_banner_animated(): raise InvalidArgument("non animated avatars do not support gif format") if static_format not in VALID_STATIC_FORMATS: - raise InvalidArgument("static_format must be one of {}".format(VALID_STATIC_FORMATS)) + raise InvalidArgument(f"static_format must be one of {VALID_STATIC_FORMATS}") if format is None: format = 'gif' if member.is_banner_animated() else static_format @@ -235,7 +235,7 @@ def _from_icon( if not utils.valid_icon_size(size): raise InvalidArgument("size must be a power of 2 between 16 and 4096") if format not in VALID_STATIC_FORMATS: - raise InvalidArgument("format must be None or one of {}".format(VALID_STATIC_FORMATS)) + raise InvalidArgument(f"format must be None or one of {VALID_STATIC_FORMATS}") url = '/{0}-icons/{1.id}/{1.icon}.{2}?size={3}'.format(path, object, format, size) return cls(state, url) @@ -255,7 +255,7 @@ def _from_cover_image( if not utils.valid_icon_size(size): raise InvalidArgument("size must be a power of 2 between 16 and 4096") if format not in VALID_STATIC_FORMATS: - raise InvalidArgument("format must be None or one of {}".format(VALID_STATIC_FORMATS)) + raise InvalidArgument(f"format must be None or one of {VALID_STATIC_FORMATS}") url = '/app-assets/{0.id}/store/{0.cover_image}.{1}?size={2}'.format(obj, format, size) return cls(state, url) @@ -274,7 +274,7 @@ def _from_guild_image( if not utils.valid_icon_size(size): raise InvalidArgument("size must be a power of 2 between 16 and 4096") if format not in VALID_STATIC_FORMATS: - raise InvalidArgument("format must be one of {}".format(VALID_STATIC_FORMATS)) + raise InvalidArgument(f"format must be one of {VALID_STATIC_FORMATS}") if hash is None: return cls(state) @@ -295,11 +295,11 @@ def _from_guild_icon( if not utils.valid_icon_size(size): raise InvalidArgument("size must be a power of 2 between 16 and 4096") if format is not None and format not in VALID_AVATAR_FORMATS: - raise InvalidArgument("format must be one of {}".format(VALID_AVATAR_FORMATS)) + raise InvalidArgument(f"format must be one of {VALID_AVATAR_FORMATS}") if format == "gif" and not guild.is_icon_animated(): raise InvalidArgument("non animated guild icons do not support gif format") if static_format not in VALID_STATIC_FORMATS: - raise InvalidArgument("static_format must be one of {}".format(VALID_STATIC_FORMATS)) + raise InvalidArgument(f"static_format must be one of {VALID_STATIC_FORMATS}") if guild.icon is None: return cls(state) @@ -330,7 +330,7 @@ def _from_sticker_pack( if not utils.valid_icon_size(size): raise InvalidArgument("size must be a power of 2 between 16 and 4096") if format is not None and format not in VALID_STATIC_FORMATS: - raise InvalidArgument("format must be None or one of {}".format(VALID_AVATAR_FORMATS)) + raise InvalidArgument(f"format must be None or one of {VALID_AVATAR_FORMATS}") return cls(state, f'/app-assets/710982414301790216/store/{sticker_pack.banner_asset_id}.{format}?size={size}') @classmethod @@ -343,11 +343,11 @@ def _from_emoji( static_format='png' ): if format is not None and format not in VALID_AVATAR_FORMATS: - raise InvalidArgument("format must be None or one of {}".format(VALID_AVATAR_FORMATS)) + raise InvalidArgument(f"format must be None or one of {VALID_AVATAR_FORMATS}") if format == "gif" and not emoji.animated: raise InvalidArgument("non animated emoji's do not support gif format") if static_format not in VALID_STATIC_FORMATS: - raise InvalidArgument("static_format must be one of {}".format(VALID_STATIC_FORMATS)) + raise InvalidArgument(f"static_format must be one of {VALID_STATIC_FORMATS}") if format is None: format = 'gif' if emoji.animated else static_format return cls(state, '/emojis/{0.id}.{1}'.format(emoji, format)) @@ -365,18 +365,16 @@ def _from_guild_event( if not utils.valid_icon_size(size): raise InvalidArgument("size must be a power of 2 between 16 and 4096") if format is not None and format not in VALID_AVATAR_FORMATS: - raise InvalidArgument("format must be None or one of {}".format(VALID_AVATAR_FORMATS)) + raise InvalidArgument(f"format must be None or one of {VALID_AVATAR_FORMATS}") if static_format not in VALID_STATIC_FORMATS: - raise InvalidArgument("static_format must be one of {}".format(VALID_STATIC_FORMATS)) + raise InvalidArgument(f"static_format must be one of {VALID_STATIC_FORMATS}") return cls(state, '/guild-events/{0.id}/{0.image}.{1}?size={2}'.format(event, format, size)) def __str__(self): return self.BASE + self._url if self._url is not None else '' def __len__(self): - if self._url: - return len(self.BASE + self._url) - return 0 + return len(self.BASE + self._url) if self._url else 0 def __bool__(self): return self._url is not None diff --git a/discord/audit_logs.py b/discord/audit_logs.py index e458fc21..8677cd8f 100644 --- a/discord/audit_logs.py +++ b/discord/audit_logs.py @@ -55,14 +55,10 @@ def _transform_channel(entry, data): return entry.guild.get_channel(int(data)) or Object(id=data) def _transform_owner_id(entry, data): - if data is None: - return None - return entry._get_member(int(data)) + return None if data is None else entry._get_member(int(data)) def _transform_inviter_id(entry, data): - if data is None: - return None - return entry._get_member(int(data)) + return None if data is None else entry._get_member(int(data)) def _transform_overwrites(entry, data): overwrites = [] @@ -93,7 +89,7 @@ def __iter__(self): def __repr__(self): values = ' '.join('%s=%r' % item for item in self.__dict__.items()) - return '' % values + return f'' class AuditLogChanges: # TODO: Add ad transformers for all the other keys @@ -309,7 +305,7 @@ def created_at(self): @utils.cached_property def target(self): try: - converter = getattr(self, '_convert_target_' + self.action.target_type) + converter = getattr(self, f'_convert_target_{self.action.target_type}') except AttributeError: return Object(id=self._target_id) else: @@ -342,18 +338,14 @@ def _convert_target_guild(self, target_id): def _convert_target_channel(self, target_id): ch = self.guild.get_channel(target_id) - if ch is None: - return Object(id=target_id) - return ch + return Object(id=target_id) if ch is None else ch def _convert_target_user(self, target_id): return self._get_member(target_id) def _convert_target_role(self, target_id): role = self.guild.get_role(target_id) - if role is None: - return Object(id=target_id) - return role + return Object(id=target_id) if role is None else role def _convert_target_invite(self, target_id): # invites have target_id set to null @@ -385,27 +377,19 @@ def _convert_target_message(self, target_id): def _convert_target_stage(self, target_id): stage = self.guild.get_channel(target_id) - if stage is None: - return Object(id=target_id) - return stage + return Object(id=target_id) if stage is None else stage def _convert_target_sticker(self, target_id): sticker = self.guild.get_sticker(target_id) - if sticker is None: - return Object(id=target_id) - return sticker + return Object(id=target_id) if sticker is None else sticker def _convert_target_scheduled_event(self, target_id): event = self.guild.get_event(target_id) - if event is None: - return Object(id=target_id) - return event + return Object(id=target_id) if event is None else event def _convert_target_thread(self, target_id): thread = self.guild.get_channel(target_id) - if thread is None: - return Object(id=target_id) - return thread + return Object(id=target_id) if thread is None else thread def _convert_target_application_command(self, target_id): cmd = self.guild.get_application_command(target_id) diff --git a/discord/auto_updater.py b/discord/auto_updater.py index 3c5a5bf7..ce4b1515 100644 --- a/discord/auto_updater.py +++ b/discord/auto_updater.py @@ -134,24 +134,22 @@ async def request( async def get_current_release(self) -> Union[MinimalReleaseInfo, GitReleaseInfo]: dist = importlib_metadata.distribution('discord.py-message-components') version, release = VERSION_REGEX.match(dist.version).groups() - if release: - direct_url_file = dist.read_text('direct_url.json') - if direct_url_file: - direct_url = json.loads(direct_url_file) - self._vcs_url = vcs_url = direct_url['url'] - url_is_valid = await self.validate_vcs_url(vcs_url) - vcs_info = direct_url['vcs_info'] - branch = vcs_info.get('requested_revision', None) - commit_id = vcs_info.get('commit_id', None) - return GitReleaseInfo(branch, version, release, commit_id, url_is_valid, MISSING) - else: - info = await self.find_release(version, release) - if info is not None: - return GitReleaseInfo(info['branch'], version, release, info['commit'], True, MISSING) - else: - log.warning('Unknown release used. Version checks will not be performed') - else: + if not release: return MinimalReleaseInfo(version, release, True, MISSING) + if direct_url_file := dist.read_text('direct_url.json'): + direct_url = json.loads(direct_url_file) + self._vcs_url = vcs_url = direct_url['url'] + url_is_valid = await self.validate_vcs_url(vcs_url) + vcs_info = direct_url['vcs_info'] + branch = vcs_info.get('requested_revision', None) + commit_id = vcs_info.get('commit_id', None) + return GitReleaseInfo(branch, version, release, commit_id, url_is_valid, MISSING) + else: + info = await self.find_release(version, release) + if info is not None: + return GitReleaseInfo(info['branch'], version, release, info['commit'], True, MISSING) + else: + log.warning('Unknown release used. Version checks will not be performed') async def validate_vcs_url(self, url: str) -> bool: d = await self.request('POST', '/is-valid-vcs-url', data={'url': url}) @@ -192,8 +190,7 @@ async def run_check(self) -> None: self.current_release.use_instead = use_instead = data.get("use_instead", None) log.warning( - f'You are using a branch of the library that has been deleted and will no longer receive updates!' - f'Consider updating to {use_instead + "branch instead" if use_instead else "an other branch"}.' + f'You are using a branch of the library that has been deleted and will no longer receive updates!Consider updating to {f"{use_instead}branch instead" if use_instead else "an other branch"}.' ) self.dispatch('used_branch_deleted', use_instead) log.info('Stopped update checker task') diff --git a/discord/automod.py b/discord/automod.py index 3d4fdce4..fa1c8167 100644 --- a/discord/automod.py +++ b/discord/automod.py @@ -164,9 +164,6 @@ def __init__(self, type: AutoModActionType, **metadata): self.timeout_duration: Optional[datetime.timedelta] = timeout_duration def to_dict(self) -> Dict[str, Any]: - base = { - 'type': int(self.type) - } metadata = {} if self.type.block_message: custom_message = getattr(self, 'custom_message', None) @@ -176,8 +173,7 @@ def to_dict(self) -> Dict[str, Any]: metadata['channel_id'] = self.channel_id elif self.type.timeout_user: metadata['duration_seconds'] = self.timeout_duration - base['metadata'] = metadata - return base + return {'type': int(self.type), 'metadata': metadata} @classmethod def from_dict(cls, data: Dict[str, Any]) -> Self: @@ -287,7 +283,7 @@ def __init__( raise TypeError('regex_patterns can only be used with AutoModRule\'s of type keyword') self.regex_patterns: List[Pattern] = [_re_compile(pattern) for pattern in regex_patterns if not isinstance(pattern, Pattern)] self.presets: List[AutoModKeywordPresetType] = presets or [] - if exempt_words and not (presets or keyword_filter): + if exempt_words and not presets and not keyword_filter: raise TypeError('exempt_words can only be used with keyword_filter or preset') self.exempt_words: Optional[List[str]] = exempt_words self.total_mentions_limit: Optional[int] = total_mentions_limit @@ -411,8 +407,7 @@ def to_dict(self) -> Dict[str, Any]: @classmethod def from_dict(cls, data: Dict[str, Any]) -> Self: self = cls.__new__(cls) - presets = data.get('presets', None) - if presets: + if presets := data.get('presets', None): self.presets = data['presets'] self.exempt_words = data.get('allow_list', []) else: @@ -542,11 +537,12 @@ def creator(self) -> Optional[Member]: Optional[Member] The member, that created the rule. """ - creator = self.guild.get_member(self.creator_id) - # If the member is not found and the members intent is disabled, then raise - if not creator and not self._state.intents.members: + if creator := self.guild.get_member(self.creator_id): + return creator + elif self._state.intents.members: + return creator + else: raise ClientException('Intents.members must be enabled to use this') - return creator @property def created_at(self) -> datetime.datetime: @@ -786,8 +782,9 @@ def member(self) -> Optional[Member]: Optional[Member]: The guild member """ - member = self.guild.get_member(self.user_id) - # If the member is not found and the members intent is disabled, then raise - if not member and not self._state.intents.members: + if member := self.guild.get_member(self.user_id): + return member + elif self._state.intents.members: + return member + else: raise ClientException('Intents.members must be enabled to use this') - return member diff --git a/discord/channel.py b/discord/channel.py index 26be33ca..0876677b 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -154,7 +154,7 @@ def __repr__(self): ('news', self.is_news()), ('category_id', self.category_id) ] - return '<%s %s>' % (self.__class__.__name__, ' '.join('%s=%r' % t for t in attrs)) + return f"<{self.__class__.__name__} {' '.join('%s=%r' % t for t in attrs)}>" def __del__(self): if getattr(self, '_TextChannel__deleted', None) is True: @@ -665,8 +665,10 @@ async def create_thread( :class:`ThreadChannel` The created thread on success """ - if len(name) > 100 or len(name) < 1: - raise ValueError('The name of the thread must bee between 1-100 characters; got %s' % len(name)) + if len(name) > 100 or not name: + raise ValueError( + f'The name of the thread must bee between 1-100 characters; got {len(name)}' + ) payload = { 'name': name @@ -754,15 +756,15 @@ def permissions_in(self, channel: abc.GuildChannel) -> Permissions: TypeError The associated guild member is not cached """ - member = self.as_guild_member - if not member: + if member := self.as_guild_member: + return member.permissions_in(channel) + else: raise TypeError('The guild member of this thread member is not cached') - return member.permissions_in(channel) @property def mention(self) -> str: """Returns a string the client renders as a mention of the user""" - return '<@%s>' % self.id + return f'<@{self.id}>' class ThreadChannel(abc.Messageable, Hashable): @@ -805,8 +807,7 @@ def _update(self, guild: Guild, data: Dict[str, Any]): self.last_message_id: int = utils._get_as_snowflake(data, 'last_message_id') self.slowmode_delay: int = int(data.get('rate_limit_per_user', 0)) self._thread_meta = data.get('thread_metadata', {}) - me = data.get('member', None) - if me: + if me := data.get('member', None): self._members[self._state.self_id] = ThreadMember._from_thread(thread=self, data=me) return self @@ -833,8 +834,7 @@ def _sync_from_members_update(self, data: Dict[str, Any]) -> None: self.guild._add_member(Member(data=new_member, guild=self.guild, state=self._state)) self._add_member(ThreadMember(state=self._state, guild=self.guild, data=new_member)) for removed_id in data.get('removed_member_ids', []): - member = self.get_member(int(removed_id)) - if member: + if member := self.get_member(int(removed_id)): self._remove_member(member) def _add_self(self, data: Dict[str, Any]) -> None: @@ -912,8 +912,7 @@ def archive_time(self) -> Optional[datetime.datetime]: """ Optional[:class:`datetime.datetime`]: When the thread's archive status was last changed, used for calculating recent activity """ - archive_timestamp = self._thread_meta.get('archive_timestamp', None) - if archive_timestamp: + if archive_timestamp := self._thread_meta.get('archive_timestamp', None): return datetime.datetime.fromisoformat(archive_timestamp) @property @@ -939,8 +938,7 @@ def created_at(self) -> Optional[datetime.datetime]: This timestamp only exists for threads created after 9 January 2022, otherwise returns ``None``. """ - create_timestamp = self._thread_meta.get('create_timestamp', None) - if create_timestamp: + if create_timestamp := self._thread_meta.get('create_timestamp', None): return datetime.datetime.fromisoformat(create_timestamp) @property @@ -1042,7 +1040,7 @@ async def add_member(self, member: Union[Member, int]): raise ThreadIsArchived(self.add_member) member_id = member if isinstance(member, int) else member.id if self.get_member(member_id): - raise ClientException('The user %s is already a Member of this thread.' % member) + raise ClientException(f'The user {member} is already a Member of this thread.') return await self._state.http.add_thread_member(channel_id=self.id, member_id=member_id) @@ -1067,7 +1065,9 @@ async def remove_member(self, member: Union[Member, int]): raise ThreadIsArchived(self.remove_member) member_id = member if isinstance(member, int) else member.id if not self.get_member(member_id): - raise ClientException('The user %s is not a member of this thread yet, so you could not remove him.' % member) + raise ClientException( + f'The user {member} is not a member of this thread yet, so you could not remove him.' + ) return await self._state.http.remove_thread_member(channel_id=self.id, member_id=member_id) @@ -1276,7 +1276,9 @@ async def edit( if auto_archive_duration is not MISSING: auto_archive_duration = try_enum(AutoArchiveDuration, auto_archive_duration) if not isinstance(auto_archive_duration, AutoArchiveDuration): - raise InvalidArgument('%s is not a valid auto_archive_duration' % auto_archive_duration) + raise InvalidArgument( + f'{auto_archive_duration} is not a valid auto_archive_duration' + ) else: payload['auto_archive_duration'] = auto_archive_duration.value @@ -1429,7 +1431,7 @@ def __repr__(self): ('user_limit', self.user_limit), ('category_id', self.category_id) ] - return '<%s %s>' % (self.__class__.__name__, ' '.join('%s=%r' % t for t in attrs)) + return f"<{self.__class__.__name__} {' '.join('%s=%r' % t for t in attrs)}>" @staticmethod def channel_type(): @@ -1560,7 +1562,7 @@ def __repr__(self): ('user_limit', self.user_limit), ('category_id', self.category_id) ] - return '<%s %s>' % (self.__class__.__name__, ' '.join('%s=%r' % t for t in attrs)) + return f"<{self.__class__.__name__} {' '.join('%s=%r' % t for t in attrs)}>" def _update(self, guild, data): super()._update(guild, data) @@ -1925,7 +1927,7 @@ async def _get_channel(self): return self def __str__(self): - return 'Direct Message with %s' % self.recipient + return f'Direct Message with {self.recipient}' def __repr__(self): return ''.format(self) @@ -2290,10 +2292,7 @@ def _update(self, guild, data) -> ForumPost: @property def applied_tags(self) -> List[ForumTag]: """List[:class:`ForumTag`]: Returns a list of tags applied to this post.""" - tags = [] - for tag_id in self._applied_tags: - tags.append(self.parent_channel.get_tag(tag_id)) - return tags + return [self.parent_channel.get_tag(tag_id) for tag_id in self._applied_tags] async def edit_tags(self, *tags: ForumTag) -> ForumPost: """|coro| @@ -2371,13 +2370,15 @@ async def edit( if auto_archive_duration is not MISSING: auto_archive_duration = try_enum(AutoArchiveDuration, auto_archive_duration) if not isinstance(auto_archive_duration, AutoArchiveDuration): - raise InvalidArgument('%s is not a valid auto_archive_duration' % auto_archive_duration) + raise InvalidArgument( + f'{auto_archive_duration} is not a valid auto_archive_duration' + ) else: payload['auto_archive_duration'] = auto_archive_duration.value - + if archived is not MISSING: payload['archived'] = archived - + if locked is not MISSING: payload['locked'] = locked @@ -2436,7 +2437,7 @@ def __repr__(self) -> str: ('emoji_name', self.emoji_name), ('moderated', self.moderated) ] - return '<%s %s>' % (self.__class__.__name__, ' '.join('%s=%r' % t for t in attrs)) + return f"<{self.__class__.__name__} {' '.join('%s=%r' % t for t in attrs)}>" def __str__(self) -> str: return self.name @@ -2444,9 +2445,10 @@ def __str__(self) -> str: @property def emoji(self) -> Optional[PartialEmoji]: """Optional[:class:`PartialEmoji`]: The emoji that is set for this post, if any""" - if not (self.emoji_name or self.emoji_id): + if self.emoji_name or self.emoji_id: + return PartialEmoji(name=self.emoji_name, id=self.emoji_id) + else: return None - return PartialEmoji(name=self.emoji_name, id=self.emoji_id) @classmethod def _with_state(cls, state: ConnectionState, guild: Guild, data: Dict[str, Any]) -> ForumTag: @@ -2545,7 +2547,7 @@ def __repr__(self): ('nsfw', self.nsfw), ('category_id', self.category_id) ] - return '<%s %s>' % (self.__class__.__name__, ' '.join('%s=%r' % t for t in attrs)) + return f"<{self.__class__.__name__} {' '.join('%s=%r' % t for t in attrs)}>" def __del__(self): if getattr(self, '_ForumChannel__deleted', None) is True: @@ -2559,15 +2561,13 @@ def _update(self, guild, data): self.category_id: int = utils._get_as_snowflake(data, 'parent_id') self.topic: str = data.get('topic') self.flags: ChannelFlags = ChannelFlags._from_value(data['flags']) - emoji = data.get('default_reaction_emoji', None) - if not emoji: - if not hasattr(self, 'default_reaction_emoji'): - self.default_reaction_emoji = None - else: + if emoji := data.get('default_reaction_emoji', None): self.default_reaction_emoji: Optional[PartialEmoji] = PartialEmoji( name=emoji['emoji_name'], id=utils._get_as_snowflake(emoji, 'id') or None ) + elif not hasattr(self, 'default_reaction_emoji'): + self.default_reaction_emoji = None self.position: int = data['position'] self.nsfw: bool = data.get('nsfw', False) # Does this need coercion into `int`? No idea yet. @@ -2613,7 +2613,7 @@ def _remove_post(self, post: ForumPost) -> Optional[ForumPost]: def get_post(self, id: int) -> Optional[ForumPost]: """Optional[:class:`ForumPost`]: Returns a post in the forum with the given ID. or None when not found.""" - return self._posts.get(int(id), None) + return self._posts.get(id, None) @property def posts(self) -> List[ForumPost]: @@ -2921,12 +2921,16 @@ async def create_post( else: flags = MISSING - if len(name) > 100 or len(name) < 1: - raise InvalidArgument('The name of the post must bee between 1-100 characters; got %s' % len(name)) + if len(name) > 100 or not name: + raise InvalidArgument( + f'The name of the post must bee between 1-100 characters; got {len(name)}' + ) if auto_archive_duration: auto_archive_duration = try_enum(AutoArchiveDuration, auto_archive_duration) if not isinstance(auto_archive_duration, AutoArchiveDuration): - raise InvalidArgument('%s is not a valid auto_archive_duration' % auto_archive_duration) + raise InvalidArgument( + f'{auto_archive_duration} is not a valid auto_archive_duration' + ) else: auto_archive_duration = auto_archive_duration.value @@ -3078,5 +3082,5 @@ def _channel_factory(channel_type): def _check_channel_type(obj, types) -> bool: """Just something to check channel instances without circular imports.""" - types = tuple([_channel_factory(t)[0] for t in types]) + types = tuple(_channel_factory(t)[0] for t in types) return isinstance(obj, types) diff --git a/discord/client.py b/discord/client.py index c93eb091..b66010c8 100644 --- a/discord/client.py +++ b/discord/client.py @@ -167,7 +167,7 @@ def __repr__(self): ] if self._exception is not None: info.append(('exception', repr(self._exception))) - return ''.format(' '.join('%s=%s' % t for t in info)) + return f"" class Client: @@ -391,9 +391,7 @@ def is_ws_ratelimited(self) -> bool: .. versionadded:: 1.6 """ - if self.ws: - return self.ws.is_ratelimited() - return False + return self.ws.is_ratelimited() if self.ws else False @property def user(self) -> ClientUser: @@ -464,10 +462,9 @@ def _schedule_event(self, coro: Coro, event_name: str, *args, **kwargs) -> _Clie def dispatch(self, event: str, *args, **kwargs) -> None: log.debug('Dispatching event %s', event) - method = 'on_' + event + method = f'on_{event}' - listeners = self._listeners.get(event) - if listeners: + if listeners := self._listeners.get(event): removed = [] for i, (future, condition) in enumerate(listeners): if isinstance(future, asyncio.Future): @@ -482,7 +479,7 @@ def dispatch(self, event: str, *args, **kwargs) -> None: removed.append(i) else: if result: - if len(args) == 0: + if not args: future.set_result(None) elif len(args) == 1: future.set_result(args[0]) @@ -495,10 +492,8 @@ def dispatch(self, event: str, *args, **kwargs) -> None: else: for idx in reversed(removed): del listeners[idx] - else: - result = condition(*args) - if result: - self._schedule_event(future, method, *args, **kwargs) + elif result := condition(*args): + self._schedule_event(future, method, *args, **kwargs) try: coro = getattr(self, method) @@ -516,7 +511,7 @@ async def on_error(self, event_method: str, *args, **kwargs) -> None: overridden to have a different implementation. Check :func:`~discord.on_error` for more details. """ - print('Ignoring exception in {}'.format(event_method), file=sys.stderr) + print(f'Ignoring exception in {event_method}', file=sys.stderr) traceback.print_exc() async def on_application_command_error( @@ -557,17 +552,20 @@ async def _request_sync_commands(self, is_cog_reload: bool = False, *, reload_fa """ if not hasattr(self, 'app'): await self.application_info() - if (is_cog_reload and not reload_failed and getattr(self, 'sync_commands_on_cog_reload', False) is True) or ( - not is_cog_reload and self.sync_commands is True + if ( + is_cog_reload + and not reload_failed + and getattr(self, 'sync_commands_on_cog_reload', False) + or (not is_cog_reload and self.sync_commands is True) ): return await self._sync_commands() state = self._connection # Speedup attribute access - app_id = self.app.id - get_commands = self.http.get_application_commands if not is_cog_reload: + app_id = self.app.id log.info('Collecting global application-commands for application %s (%s)', self.app.name, self.app.id) self._minimal_registered_global_commands_raw = minimal_registered_global_commands_raw = [] + get_commands = self.http.get_application_commands global_registered_raw = await get_commands(app_id) for raw_command in global_registered_raw: @@ -584,7 +582,13 @@ async def _request_sync_commands(self, is_cog_reload: bool = False, *, reload_fa command._state = state self._application_commands[command.id] = command - log.info('Done! Cached %s global application-commands', sum([len(cmds) for cmds in self._application_commands_by_type.values()])) + log.info( + 'Done! Cached %s global application-commands', + sum( + len(cmds) + for cmds in self._application_commands_by_type.values() + ), + ) log.info('Collecting guild-specific application-commands for application %s (%s)', self.app.name, app_id) self._minimal_registered_guild_commands_raw = minimal_registered_guild_commands_raw = {} @@ -619,7 +623,16 @@ async def _request_sync_commands(self, is_cog_reload: bool = False, *, reload_fa command._state = state self._application_commands[command.id] = guild._application_commands[command.id] = command - log.info('Done! Cached %s commands for %s guilds', sum([len(commands) for commands in list(minimal_registered_guild_commands_raw.values())]), len(minimal_registered_guild_commands_raw.keys())) + log.info( + 'Done! Cached %s commands for %s guilds', + sum( + len(commands) + for commands in list( + minimal_registered_guild_commands_raw.values() + ) + ), + len(minimal_registered_guild_commands_raw.keys()), + ) else: # re-assign metadata to the commands (for commands added from cogs) @@ -662,7 +675,6 @@ async def _request_sync_commands(self, is_cog_reload: bool = False, *, reload_fa no_longer_in_code_guilds.add(guild_id) no_longer_in_code_guild_specific += 1 self._application_commands[raw_command['id']].func = None - pass # Should already be cached in self._application_commands so skip that part here another once again else: if command.disabled: no_longer_in_code_guild_specific += 1 @@ -867,7 +879,7 @@ async def connect(self, *, reconnect: bool = True) -> None: sys.stderr.write(str(PrivilegedIntentsRequired(exc.shard_id))) if exc.code != 1000: await self.close() - if not exc.code == 4014: + if exc.code != 4014: raise retry = backoff.delay() @@ -1207,8 +1219,7 @@ def get_all_channels(self) -> Iterator[GuildChannel]: """ for guild in self.guilds: - for channel in guild.channels: - yield channel + yield from guild.channels def get_all_members(self) -> Iterator[Member]: """Returns a generator with every :class:`.Member` the client can see. @@ -1225,8 +1236,7 @@ def get_all_members(self) -> Iterator[Member]: A member the client can see. """ for guild in self.guilds: - for member in guild.members: - yield member + yield from guild.members # listeners/waiters diff --git a/discord/colour.py b/discord/colour.py index aefd7041..596f4d51 100644 --- a/discord/colour.py +++ b/discord/colour.py @@ -61,7 +61,9 @@ class Colour: def __init__(self, value): if not isinstance(value, int): - raise TypeError('Expected int parameter, received %s instead.' % value.__class__.__name__) + raise TypeError( + f'Expected int parameter, received {value.__class__.__name__} instead.' + ) self.value = value @@ -78,7 +80,7 @@ def __str__(self): return '#{:0>6x}'.format(self.value) def __repr__(self): - return '' % self.value + return f'' def __hash__(self): return hash(self.value) diff --git a/discord/components.py b/discord/components.py index b407462b..f85aa4cd 100644 --- a/discord/components.py +++ b/discord/components.py @@ -131,7 +131,9 @@ def custom_id(self) -> Union[str, int]: def custom_id(self, value: Union[str, int]): length = len(str(value)) if 1 > length > 100: - raise ValueError('The custom_id must be between 1 and 100 in length; got %s' % length) + raise ValueError( + f'The custom_id must be between 1 and 100 in length; got {length}' + ) self._custom_id = value @property @@ -141,7 +143,7 @@ def disabled(self) -> bool: @disabled.setter def disabled(self, value: bool): - self._disabled = bool(value) + self._disabled = value def to_dict(self) -> Dict[str, Any]: raise NotImplementedError() @@ -197,12 +199,10 @@ def __init__( self.emoji = emoji def __repr__(self) -> str: - return f'