diff --git a/discord/__init__.py b/discord/__init__.py index 2523a493c..446d127c3 100644 --- a/discord/__init__.py +++ b/discord/__init__.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ Discord API Wrapper ~~~~~~~~~~~~~~~~~~~ diff --git a/discord/__main__.py b/discord/__main__.py index 925283543..e80f7ec17 100644 --- a/discord/__main__.py +++ b/discord/__main__.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -42,9 +40,9 @@ def show_version(): if version_info.releaselevel != 'final': pkg = pkg_resources.get_distribution('discord.py') if pkg: - entries.append(' - discord.py pkg_resources: v{0}'.format(pkg.version)) + entries.append(f' - discord.py pkg_resources: v{pkg.version}') - entries.append('- aiohttp v{0.__version__}'.format(aiohttp)) + entries.append(f'- aiohttp v{aiohttp.__version__}') uname = platform.uname() entries.append('- system info: {0.system} {0.release} {0.version}'.format(uname)) print('\n'.join(entries)) @@ -200,7 +198,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' @@ -209,27 +207,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) @@ -238,7 +236,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') @@ -257,12 +255,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 54cb6e80a..e0f0802ff 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/activity.py b/discord/activity.py index cf5192adf..afdc2dd2a 100644 --- a/discord/activity.py +++ b/discord/activity.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -196,16 +194,16 @@ class Activity(BaseActivity): def __repr__(self): attrs = ( - 'type', - 'name', - 'url', - 'details', - 'application_id', - 'session_id', - 'emoji', + ('type', self.type), + ('name', self.name), + ('url', self.url), + ('details', self.details), + ('application_id', self.application_id), + ('session_id', self.session_id), + ('emoji', self.emoji), ) - mapped = ' '.join('%s=%r' % (attr, getattr(self, attr)) for attr in attrs) - return '' % mapped + inner = ' '.join('%s=%r' % t for t in attrs) + return f'' def to_dict(self): ret = {} @@ -250,7 +248,7 @@ class Activity(BaseActivity): except KeyError: return None else: - return Asset.BASE + '/app-assets/{0}/{1}.png'.format(self.application_id, large_image) + return Asset.BASE + f'/app-assets/{self.application_id}/{large_image}.png' @property def small_image_url(self): @@ -263,7 +261,7 @@ class Activity(BaseActivity): except KeyError: return None else: - return Asset.BASE + '/app-assets/{0}/{1}.png'.format(self.application_id, small_image) + return Asset.BASE + f'/app-assets/{self.application_id}/{small_image}.png' @property def large_image_text(self): """Optional[:class:`str`]: Returns the large image asset hover text of this activity if applicable.""" @@ -362,7 +360,7 @@ class Game(BaseActivity): return str(self.name) def __repr__(self): - return ''.format(self) + return f'' def to_dict(self): timestamps = {} @@ -455,7 +453,7 @@ class Streaming(BaseActivity): return str(self.name) def __repr__(self): - return ''.format(self) + return f'' @property def twitch_name(self): @@ -700,7 +698,7 @@ class CustomActivity(BaseActivity): elif isinstance(emoji, PartialEmoji): self.emoji = emoji else: - raise TypeError('Expected str, PartialEmoji, or None, received {0!r} instead.'.format(type(emoji))) + raise TypeError(f'Expected str, PartialEmoji, or None, received {type(emoji)!r} instead.') @property def type(self): @@ -739,7 +737,7 @@ class CustomActivity(BaseActivity): def __str__(self): if self.emoji: if self.name: - return '%s %s' % (self.emoji, self.name) + return f'{self.emoji} {self.name}' return str(self.emoji) else: return str(self.name) diff --git a/discord/appinfo.py b/discord/appinfo.py index 97337b916..9af4a373d 100644 --- a/discord/appinfo.py +++ b/discord/appinfo.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/asset.py b/discord/asset.py index ea4572972..01e22c8b0 100644 --- a/discord/asset.py +++ b/discord/asset.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -74,11 +72,11 @@ class Asset: 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 @@ -96,7 +94,7 @@ class Asset: 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) @@ -109,7 +107,7 @@ class Asset: 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) @@ -119,7 +117,7 @@ class Asset: 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) @@ -132,11 +130,11 @@ class Asset: 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) @@ -156,15 +154,15 @@ class Asset: @classmethod def _from_emoji(cls, state, emoji, *, format=None, 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)) + return cls(state, f'/emojis/{emoji.id}.{format}') def __str__(self): return self.BASE + self._url if self._url is not None else '' @@ -178,7 +176,7 @@ class Asset: return self._url is not None def __repr__(self): - return ''.format(self) + return f'' def __eq__(self, other): return isinstance(other, Asset) and self._url == other._url diff --git a/discord/audit_logs.py b/discord/audit_logs.py index 7d70a93bc..ee52dcd77 100644 --- a/discord/audit_logs.py +++ b/discord/audit_logs.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -94,7 +92,7 @@ class AuditLogDiff: def __repr__(self): values = ' '.join('%s=%r' % item for item in self.__dict__.items()) - return '' % values + return f'' class AuditLogChanges: TRANSFORMERS = { @@ -166,7 +164,7 @@ class AuditLogChanges: self.before.color = self.before.colour def __repr__(self): - return '' % (self.before, self.after) + return f'' def _handle_role(self, first, second, entry, elem): if not hasattr(first, 'roles'): diff --git a/discord/backoff.py b/discord/backoff.py index 0f49d155a..22c15bcd0 100644 --- a/discord/backoff.py +++ b/discord/backoff.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/calls.py b/discord/calls.py index 2006b30a8..bd3a1b893 100644 --- a/discord/calls.py +++ b/discord/calls.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/channel.py b/discord/channel.py index bd4a39dca..00f77db09 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -115,7 +113,8 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable): ('news', self.is_news()), ('category_id', self.category_id) ] - return '<%s %s>' % (self.__class__.__name__, ' '.join('%s=%r' % t for t in attrs)) + joined = ' '.join('%s=%r' % t for t in attrs) + return f'<{self.__class__.__name__} {joined}>' def _update(self, guild, data): self.guild = guild @@ -668,7 +667,8 @@ class VoiceChannel(VocalGuildChannel): ('user_limit', self.user_limit), ('category_id', self.category_id) ] - return '<%s %s>' % (self.__class__.__name__, ' '.join('%s=%r' % t for t in attrs)) + joined = ' '.join('%s=%r' % t for t in attrs) + return f'<{self.__class__.__name__} {joined}>' @property def type(self): @@ -791,7 +791,8 @@ class StageChannel(VocalGuildChannel): ('user_limit', self.user_limit), ('category_id', self.category_id) ] - return '<%s %s>' % (self.__class__.__name__, ' '.join('%s=%r' % t for t in attrs)) + joined = ' '.join('%s=%r' % t for t in attrs) + return f'<{self.__class__.__name__} {joined}>' def _update(self, guild, data): super()._update(guild, data) @@ -1219,7 +1220,7 @@ class DMChannel(discord.abc.Messageable, Hashable): 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) diff --git a/discord/client.py b/discord/client.py index 0daf011b7..cf15bfed8 100644 --- a/discord/client.py +++ b/discord/client.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -403,7 +401,7 @@ class Client: 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() @utils.deprecated('Guild.chunk') @@ -516,7 +514,7 @@ class Client: """|coro| Logs out of Discord and closes all connections. - + .. deprecated:: 1.7 .. note:: @@ -660,7 +658,7 @@ class Client: reconnect = kwargs.pop('reconnect', True) if kwargs: - raise TypeError("unexpected keyword argument(s) %s" % list(kwargs.keys())) + raise TypeError(f"unexpected keyword argument(s) {list(kwargs.keys())}") await self.login(*args, bot=bot) await self.connect(reconnect=reconnect) @@ -760,7 +758,7 @@ class Client: if value is None or isinstance(value, AllowedMentions): self._connection.allowed_mentions = value else: - raise TypeError('allowed_mentions must be AllowedMentions not {0.__class__!r}'.format(value)) + raise TypeError(f'allowed_mentions must be AllowedMentions not {value.__class__!r}') @property def intents(self): @@ -859,8 +857,7 @@ class Client: """ for guild in self.guilds: - for channel in guild.channels: - yield channel + yield from guild.channels def get_all_members(self): """Returns a generator with every :class:`.Member` the client can see. @@ -877,8 +874,7 @@ class Client: 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 fbf9aaef6..3296afb7d 100644 --- a/discord/colour.py +++ b/discord/colour.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -61,7 +59,7 @@ 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 @@ -75,10 +73,10 @@ class Colour: return not self.__eq__(other) def __str__(self): - return '#{:0>6x}'.format(self.value) + return f'#{self.value:0>6x}' def __repr__(self): - return '' % self.value + return f'' def __hash__(self): return hash(self.value) @@ -132,7 +130,7 @@ class Colour: Parameters ------------ seed: Optional[Union[:class:`int`, :class:`str`, :class:`float`, :class:`bytes`, :class:`bytearray`]] - The seed to initialize the RNG with. If ``None`` is passed the default RNG is used. + The seed to initialize the RNG with. If ``None`` is passed the default RNG is used. .. versionadded:: 1.7 """ diff --git a/discord/context_managers.py b/discord/context_managers.py index e4fde6b3c..4cb51c1bf 100644 --- a/discord/context_managers.py +++ b/discord/context_managers.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/embeds.py b/discord/embeds.py index 95470e184..91d2a6d3f 100644 --- a/discord/embeds.py +++ b/discord/embeds.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -49,7 +47,8 @@ class EmbedProxy: return len(self.__dict__) def __repr__(self): - return 'EmbedProxy(%s)' % ', '.join(('%s=%r' % (k, v) for k, v in self.__dict__.items() if not k.startswith('_'))) + inner = ', '.join((f'{k}={v!r}' for k, v in self.__dict__.items() if not k.startswith('_'))) + return f'EmbedProxy({inner})' def __getattr__(self, attr): return EmptyEmbed @@ -225,7 +224,7 @@ class Embed: elif isinstance(value, int): self._colour = Colour(value=value) else: - raise TypeError('Expected discord.Colour, int, or Embed.Empty but received %s instead.' % value.__class__.__name__) + raise TypeError(f'Expected discord.Colour, int, or Embed.Empty but received {value.__class__.__name__} instead.') color = colour @@ -238,7 +237,7 @@ class Embed: if isinstance(value, (datetime.datetime, _EmptyEmbed)): self._timestamp = value else: - raise TypeError("Expected datetime.datetime or Embed.Empty received %s instead" % value.__class__.__name__) + raise TypeError(f"Expected datetime.datetime or Embed.Empty received {value.__class__.__name__} instead") @property def footer(self): diff --git a/discord/emoji.py b/discord/emoji.py index 735d508c0..798edc44e 100644 --- a/discord/emoji.py +++ b/discord/emoji.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/enums.py b/discord/enums.py index 38ff285fe..d77dcd918 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -57,8 +55,8 @@ __all__ = ( def _create_value_cls(name): cls = namedtuple('_EnumValue_' + name, 'name value') - cls.__repr__ = lambda self: '<%s.%s: %r>' % (name, self.name, self.value) - cls.__str__ = lambda self: '%s.%s' % (name, self.name) + cls.__repr__ = lambda self: f'<{name}.{self.name}: {self.value!r}>' + cls.__str__ = lambda self: f'{name}.{self.name}' return cls def _is_descriptor(obj): @@ -112,7 +110,7 @@ class EnumMeta(type): return len(cls._enum_member_names_) def __repr__(cls): - return '' % cls.__name__ + return f'' @property def __members__(cls): @@ -122,7 +120,7 @@ class EnumMeta(type): try: return cls._enum_value_map_[value] except (KeyError, TypeError): - raise ValueError("%r is not a valid %s" % (value, cls.__name__)) + raise ValueError(f"{value!r} is not a valid {cls.__name__}") def __getitem__(cls, key): return cls._enum_member_map_[key] diff --git a/discord/errors.py b/discord/errors.py index 72470510f..6e95010ef 100644 --- a/discord/errors.py +++ b/discord/errors.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -48,7 +46,7 @@ class GatewayNotFound(DiscordException): for the :class:`Client` websocket is not found.""" def __init__(self): message = 'The gateway to connect to discord was not found.' - super(GatewayNotFound, self).__init__(message) + super().__init__(message) def flatten_error_dict(d, key=''): items = [] @@ -174,7 +172,7 @@ class ConnectionClosed(ClientException): # aiohttp doesn't seem to consistently provide close reason self.reason = '' self.shard_id = shard_id - super().__init__('Shard ID %s WebSocket closed with %s' % (self.shard_id, self.code)) + super().__init__(f'Shard ID {self.shard_id} WebSocket closed with {self.code}') class PrivilegedIntentsRequired(ClientException): """Exception that's thrown when the gateway is requesting privileged intents diff --git a/discord/ext/commands/__init__.py b/discord/ext/commands/__init__.py index 6f356c5d5..bfb0814a7 100644 --- a/discord/ext/commands/__init__.py +++ b/discord/ext/commands/__init__.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ discord.ext.commands ~~~~~~~~~~~~~~~~~~~~~ diff --git a/discord/ext/commands/_types.py b/discord/ext/commands/_types.py index 36d0efc9e..8c3c53a28 100644 --- a/discord/ext/commands/_types.py +++ b/discord/ext/commands/_types.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/ext/commands/bot.py b/discord/ext/commands/bot.py index ee0308e28..503aa2667 100644 --- a/discord/ext/commands/bot.py +++ b/discord/ext/commands/bot.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -46,7 +44,7 @@ def when_mentioned(bot, msg): These are meant to be passed into the :attr:`.Bot.command_prefix` attribute. """ - return [bot.user.mention + ' ', '<@!%s> ' % bot.user.id] + return [f'<@{bot.user.id}> ', f'<@!{bot.user.id}> '] def when_mentioned_or(*prefixes): """A callable that implements when mentioned or other prefixes provided. @@ -114,7 +112,7 @@ class BotBase(GroupMixin): raise TypeError('Both owner_id and owner_ids are set.') if self.owner_ids and not isinstance(self.owner_ids, collections.abc.Collection): - raise TypeError('owner_ids must be a collection not {0.__class__!r}'.format(self.owner_ids)) + raise TypeError(f'owner_ids must be a collection not {self.owner_ids.__class__!r}') if options.pop('self_bot', False): self._skip_check = lambda x, y: x != y @@ -169,7 +167,7 @@ class BotBase(GroupMixin): if cog and Cog._get_overridden_method(cog.cog_command_error) is not None: return - print('Ignoring exception in command {}:'.format(context.command), file=sys.stderr) + print(f'Ignoring exception in command {context.command}:', file=sys.stderr) traceback.print_exception(type(exception), exception, exception.__traceback__, file=sys.stderr) # global check registration @@ -944,7 +942,7 @@ class BotBase(GroupMixin): else: self.dispatch('command_completion', ctx) elif ctx.invoked_with: - exc = errors.CommandNotFound('Command "{}" is not found'.format(ctx.invoked_with)) + exc = errors.CommandNotFound(f'Command "{ctx.invoked_with}" is not found') self.dispatch('command_error', ctx, exc) async def process_commands(self, message): diff --git a/discord/ext/commands/cog.py b/discord/ext/commands/cog.py index 8cb3e4d2f..dcaa9cdcb 100644 --- a/discord/ext/commands/cog.py +++ b/discord/ext/commands/cog.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -120,7 +118,7 @@ class CogMeta(type): value = value.__func__ if isinstance(value, _BaseCommand): if is_static_method: - raise TypeError('Command in method {0}.{1!r} must not be staticmethod.'.format(base, elem)) + raise TypeError(f'Command in method {base}.{elem!r} must not be staticmethod.') if elem.startswith(('cog_', 'bot_')): raise TypeError(no_bot_cog.format(base, elem)) commands[elem] = value @@ -275,7 +273,7 @@ class Cog(metaclass=CogMeta): """ if name is not None and not isinstance(name, str): - raise TypeError('Cog.listener expected str but received {0.__class__.__name__!r} instead.'.format(name)) + raise TypeError(f'Cog.listener expected str but received {name.__class__.__name__!r} instead.') def decorator(func): actual = func diff --git a/discord/ext/commands/context.py b/discord/ext/commands/context.py index 8df4f7301..e0eb7a5ca 100644 --- a/discord/ext/commands/context.py +++ b/discord/ext/commands/context.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/ext/commands/converter.py b/discord/ext/commands/converter.py index 730b34417..010acca90 100644 --- a/discord/ext/commands/converter.py +++ b/discord/ext/commands/converter.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -777,7 +775,7 @@ class clean_content(Converter): if self.fix_channel_mentions and ctx.guild: def resolve_channel(id, *, _get=ctx.guild.get_channel): ch = _get(id) - return ('<#%s>' % id), ('#' + ch.name if ch else '#deleted-channel') + return (f'<#{id}>'), ('#' + ch.name if ch else '#deleted-channel') transformations.update(resolve_channel(channel) for channel in message.raw_channel_mentions) @@ -792,12 +790,12 @@ class clean_content(Converter): transformations.update( - ('<@%s>' % member_id, resolve_member(member_id)) + (f'<@{member_id}>', resolve_member(member_id)) for member_id in message.raw_mentions ) transformations.update( - ('<@!%s>' % member_id, resolve_member(member_id)) + (f'<@!{member_id}>', resolve_member(member_id)) for member_id in message.raw_mentions ) @@ -807,7 +805,7 @@ class clean_content(Converter): return '@' + r.name if r else '@deleted-role' transformations.update( - ('<@&%s>' % role_id, resolve_role(role_id)) + (f'<@&{role_id}>', resolve_role(role_id)) for role_id in message.raw_role_mentions ) @@ -842,10 +840,10 @@ class _Greedy: raise TypeError('Greedy[...] expects a type or a Converter instance.') if converter is str or converter is type(None) or converter is _Greedy: - raise TypeError('Greedy[%s] is invalid.' % converter.__name__) + raise TypeError(f'Greedy[{converter.__name__}] is invalid.') if getattr(converter, '__origin__', None) is typing.Union and type(None) in converter.__args__: - raise TypeError('Greedy[%r] is invalid.' % converter) + raise TypeError(f'Greedy[{converter!r}] is invalid.') return self.__class__(converter=converter) diff --git a/discord/ext/commands/cooldowns.py b/discord/ext/commands/cooldowns.py index 54a533961..7cfc9fd74 100644 --- a/discord/ext/commands/cooldowns.py +++ b/discord/ext/commands/cooldowns.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -255,7 +253,7 @@ class MaxConcurrency: raise ValueError('max_concurrency \'number\' cannot be less than 1') if not isinstance(per, BucketType): - raise TypeError('max_concurrency \'per\' must be of type BucketType not %r' % type(per)) + raise TypeError(f'max_concurrency \'per\' must be of type BucketType not {type(per)!r}') def copy(self): return self.__class__(self.number, per=self.per, wait=self.wait) diff --git a/discord/ext/commands/core.py b/discord/ext/commands/core.py index 1c22ec0a1..d3badff47 100644 --- a/discord/ext/commands/core.py +++ b/discord/ext/commands/core.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -473,7 +471,7 @@ class Command(_BaseCommand): 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(self, ctx, converter, argument, param): try: @@ -775,7 +773,7 @@ class Command(_BaseCommand): ctx.command = self if not await self.can_run(ctx): - raise CheckFailure('The check functions for command {0.qualified_name} failed.'.format(self)) + raise CheckFailure(f'The check functions for command {self.qualified_name} failed.') if self._max_concurrency is not None: await self._max_concurrency.acquire(ctx) @@ -1014,23 +1012,23 @@ class Command(_BaseCommand): # do [name] since [name=None] or [name=] are not exactly useful for the user. should_print = param.default if isinstance(param.default, str) else param.default is not None if should_print: - result.append('[%s=%s]' % (name, param.default) if not greedy else - '[%s=%s]...' % (name, param.default)) + result.append(f'[{name}={param.default}]' if not greedy else + f'[{name}={param.default}]...') continue else: - result.append('[%s]' % name) + result.append(f'[{name}]') elif param.kind == param.VAR_POSITIONAL: if self.require_var_positional: - result.append('<%s...>' % name) + result.append(f'<{name}...>') else: - result.append('[%s...]' % name) + result.append(f'[{name}...]') elif greedy: - result.append('[%s]...' % name) + result.append(f'[{name}]...') elif self._is_typing_optional(param.annotation): - result.append('[%s]' % name) + result.append(f'[{name}]') else: - result.append('<%s>' % name) + result.append(f'<{name}>') return ' '.join(result) @@ -1062,14 +1060,14 @@ class Command(_BaseCommand): """ if not self.enabled: - raise DisabledCommand('{0.name} command is disabled'.format(self)) + raise DisabledCommand(f'{self.name} command is disabled') original = ctx.command ctx.command = self try: if not await ctx.bot.can_run(ctx): - raise CheckFailure('The global check functions for command {0.qualified_name} failed.'.format(self)) + raise CheckFailure(f'The global check functions for command {self.qualified_name} failed.') cog = self.cog if cog is not None: @@ -1588,7 +1586,7 @@ def check_any(*checks): try: pred = wrapped.predicate except AttributeError: - raise TypeError('%r must be wrapped by commands.check decorator' % wrapped) from None + raise TypeError(f'{wrapped!r} must be wrapped by commands.check decorator') from None else: unwrapped.append(pred) @@ -1776,7 +1774,7 @@ def has_permissions(**perms): invalid = set(perms) - set(discord.Permissions.VALID_FLAGS) if invalid: - raise TypeError('Invalid permission(s): %s' % (', '.join(invalid))) + raise TypeError(f"Invalid permission(s): {', '.join(invalid)}") def predicate(ctx): ch = ctx.channel @@ -1801,7 +1799,7 @@ def bot_has_permissions(**perms): invalid = set(perms) - set(discord.Permissions.VALID_FLAGS) if invalid: - raise TypeError('Invalid permission(s): %s' % (', '.join(invalid))) + raise TypeError(f"Invalid permission(s): {', '.join(invalid)}") def predicate(ctx): guild = ctx.guild @@ -1829,7 +1827,7 @@ def has_guild_permissions(**perms): invalid = set(perms) - set(discord.Permissions.VALID_FLAGS) if invalid: - raise TypeError('Invalid permission(s): %s' % (', '.join(invalid))) + raise TypeError(f"Invalid permission(s): {', '.join(invalid)}") def predicate(ctx): if not ctx.guild: @@ -1854,7 +1852,7 @@ def bot_has_guild_permissions(**perms): invalid = set(perms) - set(discord.Permissions.VALID_FLAGS) if invalid: - raise TypeError('Invalid permission(s): %s' % (', '.join(invalid))) + raise TypeError(f"Invalid permission(s): {', '.join(invalid)}") def predicate(ctx): if not ctx.guild: @@ -1961,7 +1959,7 @@ def cooldown(rate, per, type=BucketType.default): The amount of seconds to wait for a cooldown when it's been triggered. type: Union[:class:`.BucketType`, Callable[[:class:`.Message`], Any]] The type of cooldown to have. If callable, should return a key for the mapping. - + .. versionchanged:: 1.7 Callables are now supported for custom bucket types. """ diff --git a/discord/ext/commands/errors.py b/discord/ext/commands/errors.py index d533d96a7..f9fbba0f3 100644 --- a/discord/ext/commands/errors.py +++ b/discord/ext/commands/errors.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -143,7 +141,7 @@ class MissingRequiredArgument(UserInputError): """ def __init__(self, param): self.param = param - super().__init__('{0.name} is a required argument that is missing.'.format(param)) + super().__init__(f'{param.name} is a required argument that is missing.') class TooManyArguments(UserInputError): """Exception raised when the command was passed too many arguments and its @@ -229,7 +227,7 @@ class MemberNotFound(BadArgument): """ def __init__(self, argument): self.argument = argument - super().__init__('Member "{}" not found.'.format(argument)) + super().__init__(f'Member "{argument}" not found.') class GuildNotFound(BadArgument): """Exception raised when the guild provided was not found in the bot's cache. @@ -245,7 +243,7 @@ class GuildNotFound(BadArgument): """ def __init__(self, argument): self.argument = argument - super().__init__('Guild "{}" not found.'.format(argument)) + super().__init__(f'Guild "{argument}" not found.') class UserNotFound(BadArgument): """Exception raised when the user provided was not found in the bot's @@ -262,7 +260,7 @@ class UserNotFound(BadArgument): """ def __init__(self, argument): self.argument = argument - super().__init__('User "{}" not found.'.format(argument)) + super().__init__(f'User "{argument}" not found.') class MessageNotFound(BadArgument): """Exception raised when the message provided was not found in the channel. @@ -278,7 +276,7 @@ class MessageNotFound(BadArgument): """ def __init__(self, argument): self.argument = argument - super().__init__('Message "{}" not found.'.format(argument)) + super().__init__(f'Message "{argument}" not found.') class ChannelNotReadable(BadArgument): """Exception raised when the bot does not have permission to read messages @@ -295,7 +293,7 @@ class ChannelNotReadable(BadArgument): """ def __init__(self, argument): self.argument = argument - super().__init__("Can't read messages in {}.".format(argument.mention)) + super().__init__(f"Can't read messages in {argument.mention}.") class ChannelNotFound(BadArgument): """Exception raised when the bot can not find the channel. @@ -311,7 +309,7 @@ class ChannelNotFound(BadArgument): """ def __init__(self, argument): self.argument = argument - super().__init__('Channel "{}" not found.'.format(argument)) + super().__init__(f'Channel "{argument}" not found.') class BadColourArgument(BadArgument): """Exception raised when the colour is not valid. @@ -327,7 +325,7 @@ class BadColourArgument(BadArgument): """ def __init__(self, argument): self.argument = argument - super().__init__('Colour "{}" is invalid.'.format(argument)) + super().__init__(f'Colour "{argument}" is invalid.') BadColorArgument = BadColourArgument @@ -345,7 +343,7 @@ class RoleNotFound(BadArgument): """ def __init__(self, argument): self.argument = argument - super().__init__('Role "{}" not found.'.format(argument)) + super().__init__(f'Role "{argument}" not found.') class BadInviteArgument(BadArgument): """Exception raised when the invite is invalid or expired. @@ -371,7 +369,7 @@ class EmojiNotFound(BadArgument): """ def __init__(self, argument): self.argument = argument - super().__init__('Emoji "{}" not found.'.format(argument)) + super().__init__(f'Emoji "{argument}" not found.') class PartialEmojiConversionFailure(BadArgument): """Exception raised when the emoji provided does not match the correct @@ -388,7 +386,7 @@ class PartialEmojiConversionFailure(BadArgument): """ def __init__(self, argument): self.argument = argument - super().__init__('Couldn\'t convert "{}" to PartialEmoji.'.format(argument)) + super().__init__(f'Couldn\'t convert "{argument}" to PartialEmoji.') class BadBoolArgument(BadArgument): """Exception raised when a boolean argument was not convertable. @@ -404,7 +402,7 @@ class BadBoolArgument(BadArgument): """ def __init__(self, argument): self.argument = argument - super().__init__('{} is not a recognised boolean option'.format(argument)) + super().__init__(f'{argument} is not a recognised boolean option') class DisabledCommand(CommandError): """Exception raised when the command being invoked is disabled. @@ -444,7 +442,7 @@ class CommandOnCooldown(CommandError): def __init__(self, cooldown, retry_after): self.cooldown = cooldown self.retry_after = retry_after - super().__init__('You are on cooldown. Try again in {:.2f}s'.format(retry_after)) + super().__init__(f'You are on cooldown. Try again in {retry_after:.2f}s') class MaxConcurrencyReached(CommandError): """Exception raised when the command being invoked has reached its maximum concurrency. @@ -466,7 +464,7 @@ class MaxConcurrencyReached(CommandError): suffix = 'per %s' % name if per.name != 'default' else 'globally' plural = '%s times %s' if number > 1 else '%s time %s' fmt = plural % (number, suffix) - super().__init__('Too many people using this command. It can only be used {} concurrently.'.format(fmt)) + super().__init__(f'Too many people using this command. It can only be used {fmt} concurrently.') class MissingRole(CheckFailure): """Exception raised when the command invoker lacks a role to run a command. @@ -483,7 +481,7 @@ class MissingRole(CheckFailure): """ def __init__(self, missing_role): self.missing_role = missing_role - message = 'Role {0!r} is required to run this command.'.format(missing_role) + message = f'Role {missing_role!r} is required to run this command.' super().__init__(message) class BotMissingRole(CheckFailure): @@ -501,7 +499,7 @@ class BotMissingRole(CheckFailure): """ def __init__(self, missing_role): self.missing_role = missing_role - message = 'Bot requires the role {0!r} to run this command'.format(missing_role) + message = f'Bot requires the role {missing_role!r} to run this command' super().__init__(message) class MissingAnyRole(CheckFailure): @@ -521,14 +519,14 @@ class MissingAnyRole(CheckFailure): def __init__(self, missing_roles): self.missing_roles = missing_roles - missing = ["'{}'".format(role) for role in missing_roles] + missing = [f"'{role}'" for role in missing_roles] if len(missing) > 2: fmt = '{}, or {}'.format(", ".join(missing[:-1]), missing[-1]) else: fmt = ' or '.join(missing) - message = "You are missing at least one of the required roles: {}".format(fmt) + message = f"You are missing at least one of the required roles: {fmt}" super().__init__(message) @@ -550,14 +548,14 @@ class BotMissingAnyRole(CheckFailure): def __init__(self, missing_roles): self.missing_roles = missing_roles - missing = ["'{}'".format(role) for role in missing_roles] + missing = [f"'{role}'" for role in missing_roles] if len(missing) > 2: fmt = '{}, or {}'.format(", ".join(missing[:-1]), missing[-1]) else: fmt = ' or '.join(missing) - message = "Bot is missing at least one of the required roles: {}".format(fmt) + message = f"Bot is missing at least one of the required roles: {fmt}" super().__init__(message) class NSFWChannelRequired(CheckFailure): @@ -574,7 +572,7 @@ class NSFWChannelRequired(CheckFailure): """ def __init__(self, channel): self.channel = channel - super().__init__("Channel '{}' needs to be NSFW for this command to work.".format(channel)) + super().__init__(f"Channel '{channel}' needs to be NSFW for this command to work.") class MissingPermissions(CheckFailure): """Exception raised when the command invoker lacks permissions to run a @@ -596,7 +594,7 @@ class MissingPermissions(CheckFailure): fmt = '{}, and {}'.format(", ".join(missing[:-1]), missing[-1]) else: fmt = ' and '.join(missing) - message = 'You are missing {} permission(s) to run this command.'.format(fmt) + message = f'You are missing {fmt} permission(s) to run this command.' super().__init__(message, *args) class BotMissingPermissions(CheckFailure): @@ -619,7 +617,7 @@ class BotMissingPermissions(CheckFailure): fmt = '{}, and {}'.format(", ".join(missing[:-1]), missing[-1]) else: fmt = ' and '.join(missing) - message = 'Bot requires {} permission(s) to run this command.'.format(fmt) + message = f'Bot requires {fmt} permission(s) to run this command.' super().__init__(message, *args) class BadUnionArgument(UserInputError): @@ -654,7 +652,7 @@ class BadUnionArgument(UserInputError): else: fmt = ' or '.join(to_string) - super().__init__('Could not convert "{0.name}" into {1}.'.format(param, fmt)) + super().__init__(f'Could not convert "{param.name}" into {fmt}.') class ArgumentParsingError(UserInputError): """An exception raised when the parser fails to parse a user's input. @@ -678,7 +676,7 @@ class UnexpectedQuoteError(ArgumentParsingError): """ def __init__(self, quote): self.quote = quote - super().__init__('Unexpected quote mark, {0!r}, in non-quoted string'.format(quote)) + super().__init__(f'Unexpected quote mark, {quote!r}, in non-quoted string') class InvalidEndOfQuotedStringError(ArgumentParsingError): """An exception raised when a space is expected after the closing quote in a string @@ -693,7 +691,7 @@ class InvalidEndOfQuotedStringError(ArgumentParsingError): """ def __init__(self, char): self.char = char - super().__init__('Expected space after closing quotation but received {0!r}'.format(char)) + super().__init__(f'Expected space after closing quotation but received {char!r}') class ExpectedClosingQuoteError(ArgumentParsingError): """An exception raised when a quote character is expected but not found. @@ -708,7 +706,7 @@ class ExpectedClosingQuoteError(ArgumentParsingError): def __init__(self, close_quote): self.close_quote = close_quote - super().__init__('Expected closing {}.'.format(close_quote)) + super().__init__(f'Expected closing {close_quote}.') class ExtensionError(DiscordException): """Base exception for extension related errors. @@ -722,7 +720,7 @@ class ExtensionError(DiscordException): """ def __init__(self, message=None, *args, name): self.name = name - message = message or 'Extension {!r} had an error.'.format(name) + message = message or f'Extension {name!r} had an error.' # clean-up @everyone and @here mentions m = message.replace('@everyone', '@\u200beveryone').replace('@here', '@\u200bhere') super().__init__(m, *args) @@ -733,7 +731,7 @@ class ExtensionAlreadyLoaded(ExtensionError): This inherits from :exc:`ExtensionError` """ def __init__(self, name): - super().__init__('Extension {!r} is already loaded.'.format(name), name=name) + super().__init__(f'Extension {name!r} is already loaded.', name=name) class ExtensionNotLoaded(ExtensionError): """An exception raised when an extension was not loaded. @@ -741,7 +739,7 @@ class ExtensionNotLoaded(ExtensionError): This inherits from :exc:`ExtensionError` """ def __init__(self, name): - super().__init__('Extension {!r} has not been loaded.'.format(name), name=name) + super().__init__(f'Extension {name!r} has not been loaded.', name=name) class NoEntryPointError(ExtensionError): """An exception raised when an extension does not have a ``setup`` entry point function. @@ -749,7 +747,7 @@ class NoEntryPointError(ExtensionError): This inherits from :exc:`ExtensionError` """ def __init__(self, name): - super().__init__("Extension {!r} has no 'setup' function.".format(name), name=name) + super().__init__(f"Extension {name!r} has no 'setup' function.", name=name) class ExtensionFailed(ExtensionError): """An exception raised when an extension failed to load during execution of the module or ``setup`` entry point. @@ -808,4 +806,4 @@ class CommandRegistrationError(ClientException): self.name = name self.alias_conflict = alias_conflict type_ = 'alias' if alias_conflict else 'command' - super().__init__('The {} {} is already an existing command or alias.'.format(type_, name)) + super().__init__(f'The {type_} {name} is already an existing command or alias.') diff --git a/discord/ext/commands/help.py b/discord/ext/commands/help.py index a00b79f74..117da5906 100644 --- a/discord/ext/commands/help.py +++ b/discord/ext/commands/help.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -132,7 +130,7 @@ class Paginator: """ max_page_size = self.max_size - self._prefix_len - self._suffix_len - 2 * self._linesep_len if len(line) > max_page_size: - raise RuntimeError('Line exceeds maximum page size %s' % (max_page_size)) + raise RuntimeError(f'Line exceeds maximum page size {max_page_size}') if self._count + len(line) + self._linesep_len > self.max_size - self._suffix_len: self.close_page() @@ -386,8 +384,9 @@ class HelpCommand: # consider this to be an *incredibly* strange use case. I'd rather go # for this common use case rather than waste performance for the # odd one. - pattern = re.compile(r"<@!?%s>" % user.id) - return pattern.sub("@%s" % user.display_name.replace('\\', r'\\'), self.context.prefix) + pattern = re.compile(fr"<@!?{user.id}>") + display_name = user.display_name.replace('\\', r'\\') + return pattern.sub('@' + display_name, self.context.prefix) @property def invoked_with(self): @@ -436,14 +435,14 @@ class HelpCommand: if len(command.aliases) > 0: aliases = '|'.join(command.aliases) - fmt = '[%s|%s]' % (command.name, aliases) + fmt = f'[{command.name}|{aliases}]' if parent_sig: fmt = parent_sig + ' ' + fmt alias = fmt else: alias = command.name if not parent_sig else parent_sig + ' ' + command.name - return '%s%s %s' % (self.clean_prefix, alias, command.signature) + return f'{self.clean_prefix}{alias} {command.signature}' def remove_mentions(self, string): """Removes mentions from the string to prevent abuse. @@ -506,7 +505,7 @@ class HelpCommand: :class:`str` The string to use when a command has not been found. """ - return 'No command called "{}" found.'.format(string) + return f'No command called "{string}" found.' def subcommand_not_found(self, command, string): """|maybecoro| @@ -535,8 +534,8 @@ class HelpCommand: The string to use when the command did not have the subcommand requested. """ if isinstance(command, Group) and len(command.all_commands) > 0: - return 'Command "{0.qualified_name}" has no subcommand named {1}'.format(command, string) - return 'Command "{0.qualified_name}" has no subcommands.'.format(command) + return f'Command "{command.qualified_name}" has no subcommand named {string}' + return f'Command "{command.qualified_name}" has no subcommands.' async def filter_commands(self, commands, *, sort=False, key=None): """|coro| @@ -941,8 +940,8 @@ class DefaultHelpCommand(HelpCommand): def get_ending_note(self): """:class:`str`: Returns help command's ending note. This is mainly useful to override for i18n purposes.""" command_name = self.invoked_with - return "Type {0}{1} command for more info on a command.\n" \ - "You can also type {0}{1} category for more info on a category.".format(self.clean_prefix, command_name) + return f"Type {self.clean_prefix}{command_name} command for more info on a command.\n" \ + f"You can also type {self.clean_prefix}{command_name} category for more info on a category." def add_indented_commands(self, commands, *, heading, max_size=None): """Indents a list of commands after the specified heading. @@ -977,7 +976,7 @@ class DefaultHelpCommand(HelpCommand): for command in commands: name = command.name width = max_size - (get_width(name) - len(name)) - entry = '{0}{1:<{width}} {2}'.format(self.indent * ' ', name, command.short_doc, width=width) + entry = f'{self.indent * " "}{name:<{width}} {command.short_doc}' self.paginator.add_line(self.shorten_text(entry)) async def send_pages(self): @@ -1030,7 +1029,7 @@ class DefaultHelpCommand(HelpCommand): # portion self.paginator.add_line(bot.description, empty=True) - no_category = '\u200b{0.no_category}:'.format(self) + no_category = f'\u200b{self.no_category}:' def get_category(command, *, no_category=no_category): cog = command.cog return cog.qualified_name + ':' if cog is not None else no_category @@ -1154,7 +1153,7 @@ class MinimalHelpCommand(HelpCommand): "You can also use `{0}{1} [category]` for more info on a category.".format(self.clean_prefix, command_name) def get_command_signature(self, command): - return '%s%s %s' % (self.clean_prefix, command.qualified_name, command.signature) + return f'{self.clean_prefix}{command.qualified_name} {command.signature}' def get_ending_note(self): """Return the help command's ending note. This is mainly useful to override for i18n purposes. @@ -1186,7 +1185,7 @@ class MinimalHelpCommand(HelpCommand): if commands: # U+2002 Middle Dot joined = '\u2002'.join(c.name for c in commands) - self.paginator.add_line('__**%s**__' % heading) + self.paginator.add_line(f'__**{heading}**__') self.paginator.add_line(joined) def add_subcommand_formatting(self, command): @@ -1220,7 +1219,7 @@ class MinimalHelpCommand(HelpCommand): aliases: Sequence[:class:`str`] A list of aliases to format. """ - self.paginator.add_line('**%s** %s' % (self.aliases_heading, ', '.join(aliases)), empty=True) + self.paginator.add_line(f'**{self.aliases_heading}** {", ".join(aliases)}', empty=True) def add_command_formatting(self, command): """A utility function to format commands and groups. @@ -1273,7 +1272,7 @@ class MinimalHelpCommand(HelpCommand): if note: self.paginator.add_line(note, empty=True) - no_category = '\u200b{0.no_category}'.format(self) + no_category = f'\u200b{self.no_category}' def get_category(command, *, no_category=no_category): cog = command.cog return cog.qualified_name if cog is not None else no_category @@ -1306,7 +1305,7 @@ class MinimalHelpCommand(HelpCommand): filtered = await self.filter_commands(cog.get_commands(), sort=self.sort_commands) if filtered: - self.paginator.add_line('**%s %s**' % (cog.qualified_name, self.commands_heading)) + self.paginator.add_line(f'**{cog.qualified_name} {self.commands_heading}**') for command in filtered: self.add_subcommand_formatting(command) @@ -1326,7 +1325,7 @@ class MinimalHelpCommand(HelpCommand): if note: self.paginator.add_line(note, empty=True) - self.paginator.add_line('**%s**' % self.commands_heading) + self.paginator.add_line(f'**{self.commands_heading}**') for command in filtered: self.add_subcommand_formatting(command) diff --git a/discord/ext/commands/view.py b/discord/ext/commands/view.py index 7f74c7007..763cf73e5 100644 --- a/discord/ext/commands/view.py +++ b/discord/ext/commands/view.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/ext/tasks/__init__.py b/discord/ext/tasks/__init__.py index 818f38ad6..57724be7c 100644 --- a/discord/ext/tasks/__init__.py +++ b/discord/ext/tasks/__init__.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -289,9 +287,9 @@ class Loop: for exc in exceptions: if not inspect.isclass(exc): - raise TypeError('{0!r} must be a class.'.format(exc)) + raise TypeError(f'{exc!r} must be a class.') if not issubclass(exc, BaseException): - raise TypeError('{0!r} must inherit from BaseException.'.format(exc)) + raise TypeError(f'{exc!r} must inherit from BaseException.') self._valid_exception = (*self._valid_exception, *exceptions) @@ -345,7 +343,7 @@ class Loop: async def _error(self, *args): exception = args[-1] - print('Unhandled exception in internal background task {0.__name__!r}.'.format(self.coro), file=sys.stderr) + print(f'Unhandled exception in internal background task {self.coro.__name__!r}.', file=sys.stderr) traceback.print_exception(type(exception), exception, exception.__traceback__, file=sys.stderr) def before_loop(self, coro): diff --git a/discord/file.py b/discord/file.py index 442931c34..df83f32e7 100644 --- a/discord/file.py +++ b/discord/file.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -65,7 +63,7 @@ class File: if isinstance(fp, io.IOBase): if not (fp.seekable() and fp.readable()): - raise ValueError('File buffer {!r} must be seekable and readable'.format(fp)) + raise ValueError(f'File buffer {fp!r} must be seekable and readable') self.fp = fp self._original_pos = fp.tell() self._owner = False diff --git a/discord/flags.py b/discord/flags.py index 9681be8a4..d7ceb9076 100644 --- a/discord/flags.py +++ b/discord/flags.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -48,7 +46,7 @@ class flag_value: instance._set_flag(self.flag, value) def __repr__(self): - return ''.format(self) + return f'' class alias_flag_value(flag_value): pass @@ -78,7 +76,7 @@ class BaseFlags: self.value = self.DEFAULT_VALUE for key, value in kwargs.items(): if key not in self.VALID_FLAGS: - raise TypeError('%r is not a valid flag name.' % key) + raise TypeError(f'{key!r} is not a valid flag name.') setattr(self, key, value) @classmethod @@ -97,7 +95,7 @@ class BaseFlags: return hash(self.value) def __repr__(self): - return '<%s value=%s>' % (self.__class__.__name__, self.value) + return f'<{self.__class__.__name__} value={self.value}>' def __iter__(self): for name, value in self.__class__.__dict__.items(): @@ -116,7 +114,7 @@ class BaseFlags: elif toggle is False: self.value &= ~o else: - raise TypeError('Value to set for %s must be a bool.' % self.__class__.__name__) + raise TypeError(f'Value to set for {self.__class__.__name__} must be a bool.') @fill_with_flags(inverted=True) class SystemChannelFlags(BaseFlags): @@ -399,7 +397,7 @@ class Intents(BaseFlags): self.value = self.DEFAULT_VALUE for key, value in kwargs.items(): if key not in self.VALID_FLAGS: - raise TypeError('%r is not a valid flag name.' % key) + raise TypeError(f'{key!r} is not a valid flag name.') setattr(self, key, value) @classmethod @@ -832,7 +830,7 @@ class MemberCacheFlags(BaseFlags): self.value = (1 << bits) - 1 for key, value in kwargs.items(): if key not in self.VALID_FLAGS: - raise TypeError('%r is not a valid flag name.' % key) + raise TypeError(f'{key!r} is not a valid flag name.') setattr(self, key, value) @classmethod diff --git a/discord/gateway.py b/discord/gateway.py index 210a88225..17801ee11 100644 --- a/discord/gateway.py +++ b/discord/gateway.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -162,8 +160,8 @@ class KeepAliveHandler(threading.Thread): except KeyError: msg = self.block_msg else: - stack = traceback.format_stack(frame) - msg = '%s\nLoop thread traceback (most recent call last):\n%s' % (self.block_msg, ''.join(stack)) + stack = ''.join(traceback.format_stack(frame)) + msg = f'{self.block_msg}\nLoop thread traceback (most recent call last):\n{stack}' log.warning(msg, self.shard_id, total) except Exception: diff --git a/discord/guild.py b/discord/guild.py index 2cc5679f0..b7a1b690f 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -209,11 +207,14 @@ class Guild(Hashable): def __repr__(self): attrs = ( - 'id', 'name', 'shard_id', 'chunked' + ('id', self.id), + ('name', self.name), + ('shard_id', self.shard_id), + ('chunked', self.chunked), + ('member_count', getattr(self, '_member_count', None)), ) - resolved = ['%s=%r' % (attr, getattr(self, attr)) for attr in attrs] - resolved.append('member_count=%r' % getattr(self, '_member_count', None)) - return '' % ' '.join(resolved) + inner = ' '.join('%s=%r' % t for t in attrs) + return f'' def _update_voice_state(self, data, channel_id): user_id = int(data['user_id']) @@ -1507,7 +1508,7 @@ class Guild(Hashable): """ if not isinstance(days, int): - raise InvalidArgument('Expected int for ``days``, received {0.__class__.__name__} instead.'.format(days)) + raise InvalidArgument(f'Expected int for ``days``, received {days.__class__.__name__} instead.') if roles: roles = [str(role.id) for role in roles] @@ -1593,7 +1594,7 @@ class Guild(Hashable): """ if not isinstance(days, int): - raise InvalidArgument('Expected int for ``days``, received {0.__class__.__name__} instead.'.format(days)) + raise InvalidArgument(f'Expected int for ``days``, received {days.__class__.__name__} instead.') if roles: roles = [str(role.id) for role in roles] @@ -1896,7 +1897,7 @@ class Guild(Hashable): valid_keys = ('name', 'permissions', 'color', 'hoist', 'mentionable') for key in fields: if key not in valid_keys: - raise InvalidArgument('%r is not a valid field.' % key) + raise InvalidArgument(f'{key!r} is not a valid field.') data = await self._state.http.create_role(self.id, reason=reason, **fields) role = Role(guild=self, data=data, state=self._state) diff --git a/discord/http.py b/discord/http.py index 3f63a75dc..a61d0696a 100644 --- a/discord/http.py +++ b/discord/http.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -404,7 +402,7 @@ class HTTPClient: else: for index, file in enumerate(files): form.append({ - 'name': 'file%s' % index, + 'name': f'file{index}', 'value': file.fp, 'filename': file.filename, 'content_type': 'application/octet-stream' diff --git a/discord/integrations.py b/discord/integrations.py index e2d05575e..bd58d4101 100644 --- a/discord/integrations.py +++ b/discord/integrations.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/invite.py b/discord/invite.py index a1d794b08..2543f766e 100644 --- a/discord/invite.py +++ b/discord/invite.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/iterators.py b/discord/iterators.py index d18437caa..2b6fcb5aa 100644 --- a/discord/iterators.py +++ b/discord/iterators.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/member.py b/discord/member.py index d0e969bd4..e15a9d20d 100644 --- a/discord/member.py +++ b/discord/member.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -113,7 +111,8 @@ class VoiceState: ('requested_to_speak_at', self.requested_to_speak_at), ('channel', self.channel) ] - return '<%s %s>' % (self.__class__.__name__, ' '.join('%s=%r' % t for t in attrs)) + inner = ' '.join('%s=%r' % t for t in attrs) + return f'<{self.__class__.__name__} {inner}>' def flatten_user(cls): for attr, value in itertools.chain(BaseUser.__dict__.items(), User.__dict__.items()): @@ -129,7 +128,7 @@ def flatten_user(cls): # slotted members are implemented as member_descriptors in Type.__dict__ if not hasattr(value, '__annotations__'): getter = attrgetter('_user.' + attr) - setattr(cls, attr, property(getter, doc='Equivalent to :attr:`User.%s`' % attr)) + setattr(cls, attr, property(getter, doc=f'Equivalent to :attr:`User.{attr}`')) else: # Technically, this can also use attrgetter # However I'm not sure how I feel about "functions" returning properties @@ -222,8 +221,8 @@ class Member(discord.abc.Messageable, _BaseUser): return str(self._user) def __repr__(self): - return ''.format(self, self._user) + return f'' def __eq__(self, other): return isinstance(other, _BaseUser) and other.id == self.id @@ -422,8 +421,8 @@ class Member(discord.abc.Messageable, _BaseUser): def mention(self): """:class:`str`: Returns a string that allows you to mention the member.""" if self.nick: - return '<@!%s>' % self.id - return '<@%s>' % self.id + return f'<@!{self._user.id}>' + return f'<@{self._user.id}>' @property def display_name(self): diff --git a/discord/mentions.py b/discord/mentions.py index 2cabc4c61..b100b925a 100644 --- a/discord/mentions.py +++ b/discord/mentions.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/message.py b/discord/message.py index cebbb3bbe..f558b8f61 100644 --- a/discord/message.py +++ b/discord/message.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -58,7 +56,7 @@ def convert_emoji_reaction(emoji): emoji = emoji.emoji if isinstance(emoji, Emoji): - return '%s:%s' % (emoji.name, emoji.id) + return f'{emoji.name}:{emoji.id}' if isinstance(emoji, PartialEmoji): return emoji._as_reaction() if isinstance(emoji, str): @@ -66,7 +64,7 @@ def convert_emoji_reaction(emoji): # No existing emojis have <> in them, so this should be okay. return emoji.strip('<>') - raise InvalidArgument('emoji argument must be str, Emoji, or Reaction not {.__class__.__name__}.'.format(emoji)) + raise InvalidArgument(f'emoji argument must be str, Emoji, or Reaction not {emoji.__class__.__name__}.') class Attachment(Hashable): """Represents an attachment from Discord. @@ -585,7 +583,7 @@ class Message(Hashable): for handler in ('author', 'member', 'mentions', 'mention_roles', 'call', 'flags'): try: - getattr(self, '_handle_%s' % handler)(data[handler]) + getattr(self, f'_handle_{handler}')(data[handler]) except KeyError: continue @@ -828,23 +826,23 @@ class Message(Hashable): .. note:: This *does not* affect markdown. If you want to escape - or remove markdown then use :func:`utils.escape_markdown` or :func:`utils.remove_markdown` + or remove markdown then use :func:`utils.escape_markdown` or :func:`utils.remove_markdown` respectively, along with this function. """ transformations = { - re.escape('<#%s>' % channel.id): '#' + channel.name + re.escape(f'<#{channel.id}>'): '#' + channel.name for channel in self.channel_mentions } mention_transforms = { - re.escape('<@%s>' % member.id): '@' + member.display_name + re.escape(f'<@{member.id}>'): '@' + member.display_name for member in self.mentions } # add the <@!user_id> cases as well.. second_mention_transforms = { - re.escape('<@!%s>' % member.id): '@' + member.display_name + re.escape(f'<@!{member.id}>'): '@' + member.display_name for member in self.mentions } @@ -853,7 +851,7 @@ class Message(Hashable): if self.guild is not None: role_transforms = { - re.escape('<@&%s>' % role.id): '@' + role.name + re.escape(f'<@&{role.id}>'): '@' + role.name for role in self.role_mentions } transformations.update(role_transforms) @@ -902,7 +900,7 @@ class Message(Hashable): return self.content if self.type is MessageType.pins_add: - return '{0.name} pinned a message to this channel.'.format(self.author) + return f'{self.author.name} pinned a message to this channel.' if self.type is MessageType.recipient_add: return '{0.name} added {1.name} to the group.'.format(self.author, self.mentions[0]) @@ -914,7 +912,7 @@ class Message(Hashable): return '{0.author.name} changed the channel name: {0.content}'.format(self) if self.type is MessageType.channel_icon_change: - return '{0.author.name} changed the channel icon.'.format(self) + return f'{self.author.name} changed the channel icon.' if self.type is MessageType.new_member: formats = [ @@ -946,14 +944,14 @@ class Message(Hashable): call_ended = self.call.ended_timestamp is not None if self.channel.me in self.call.participants: - return '{0.author.name} started a call.'.format(self) + return f'{self.author.name} started a call.' elif call_ended: - return 'You missed a call from {0.author.name}'.format(self) + return f'You missed a call from {self.author.name}' else: return '{0.author.name} started a call \N{EM DASH} Join the call.'.format(self) if self.type is MessageType.premium_guild_subscription: - return '{0.author.name} just boosted the server!'.format(self) + return f'{self.author.name} just boosted the server!' if self.type is MessageType.premium_guild_tier_1: return '{0.author.name} just boosted the server! {0.guild} has achieved **Level 1!**'.format(self) @@ -1447,7 +1445,7 @@ class PartialMessage(Hashable): def __init__(self, *, channel, id): if channel.type not in (ChannelType.text, ChannelType.news, ChannelType.private): - raise TypeError('Expected TextChannel or DMChannel not %r' % type(channel)) + raise TypeError(f'Expected TextChannel or DMChannel not {type(channel)!r}') self.channel = channel self._state = channel._state diff --git a/discord/mixins.py b/discord/mixins.py index afdbc1d0c..4413a0eef 100644 --- a/discord/mixins.py +++ b/discord/mixins.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/object.py b/discord/object.py index d349caa31..a2ceeddb1 100644 --- a/discord/object.py +++ b/discord/object.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -65,12 +63,12 @@ class Object(Hashable): try: id = int(id) except ValueError: - raise TypeError('id parameter must be convertable to int not {0.__class__!r}'.format(id)) from None + raise TypeError(f'id parameter must be convertable to int not {id.__class__!r}') from None else: self.id = id def __repr__(self): - return '' % self.id + return f'' @property def created_at(self): diff --git a/discord/oggparse.py b/discord/oggparse.py index a7b9dcd7c..a360ad90d 100644 --- a/discord/oggparse.py +++ b/discord/oggparse.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/opus.py b/discord/opus.py index 94adf3381..afc551750 100644 --- a/discord/opus.py +++ b/discord/opus.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -185,7 +183,7 @@ def _load_default(): _basedir = os.path.dirname(os.path.abspath(__file__)) _bitness = struct.calcsize('P') * 8 _target = 'x64' if _bitness > 32 else 'x86' - _filename = os.path.join(_basedir, 'bin', 'libopus-0.{}.dll'.format(_target)) + _filename = os.path.join(_basedir, 'bin', f'libopus-0.{_target}.dll') _lib = libopus_loader(_filename) else: _lib = libopus_loader(ctypes.util.find_library('opus')) @@ -310,14 +308,14 @@ class Encoder(_OpusStruct): def set_bandwidth(self, req): if req not in band_ctl: - raise KeyError('%r is not a valid bandwidth setting. Try one of: %s' % (req, ','.join(band_ctl))) + raise KeyError(f'{req!r} is not a valid bandwidth setting. Try one of: {",".join(band_ctl)}') k = band_ctl[req] _lib.opus_encoder_ctl(self._state, CTL_SET_BANDWIDTH, k) def set_signal_type(self, req): if req not in signal_ctl: - raise KeyError('%r is not a valid signal setting. Try one of: %s' % (req, ','.join(signal_ctl))) + raise KeyError(f'{req!r} is not a valid bandwidth setting. Try one of: {",".join(signal_ctl)}') k = signal_ctl[req] _lib.opus_encoder_ctl(self._state, CTL_SET_SIGNAL, k) diff --git a/discord/partial_emoji.py b/discord/partial_emoji.py index a9b9eae97..fed70db35 100644 --- a/discord/partial_emoji.py +++ b/discord/partial_emoji.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -103,8 +101,8 @@ class PartialEmoji(_EmojiTag): if self.id is None: return self.name if self.animated: - return '' % (self.name, self.id) - return '<:%s:%s>' % (self.name, self.id) + return f'' + return f'<:{self.name}:{self.id}>' def __repr__(self): return '<{0.__class__.__name__} animated={0.animated} name={0.name!r} id={0.id}>'.format(self) @@ -134,7 +132,7 @@ class PartialEmoji(_EmojiTag): def _as_reaction(self): if self.id is None: return self.name - return '%s:%s' % (self.name, self.id) + return f'{self.name}:{self.id}' @property def created_at(self): diff --git a/discord/permissions.py b/discord/permissions.py index 3fd0dacf0..fe6cabf53 100644 --- a/discord/permissions.py +++ b/discord/permissions.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -96,12 +94,12 @@ class Permissions(BaseFlags): def __init__(self, permissions=0, **kwargs): if not isinstance(permissions, int): - raise TypeError('Expected int parameter, received %s instead.' % permissions.__class__.__name__) + raise TypeError(f'Expected int parameter, received {permissions.__class__.__name__} instead.') self.value = permissions for key, value in kwargs.items(): if key not in self.VALID_FLAGS: - raise TypeError('%r is not a valid permission name.' % key) + raise TypeError(f'{key!r} is not a valid permission name.') setattr(self, key, value) def is_subset(self, other): @@ -109,14 +107,14 @@ class Permissions(BaseFlags): if isinstance(other, Permissions): return (self.value & other.value) == self.value else: - raise TypeError("cannot compare {} with {}".format(self.__class__.__name__, other.__class__.__name__)) + raise TypeError(f"cannot compare {self.__class__.__name__} with {other.__class__.__name__}") def is_superset(self, other): """Returns ``True`` if self has the same or more permissions as other.""" if isinstance(other, Permissions): return (self.value | other.value) == self.value else: - raise TypeError("cannot compare {} with {}".format(self.__class__.__name__, other.__class__.__name__)) + raise TypeError(f"cannot compare {self.__class__.__name__} with {other.__class__.__name__}") def is_strict_subset(self, other): """Returns ``True`` if the permissions on other are a strict subset of those on self.""" @@ -539,7 +537,7 @@ class PermissionOverwrite: for key, value in kwargs.items(): if key not in self.VALID_NAMES: - raise ValueError('no permission called {0}.'.format(key)) + raise ValueError(f'no permission called {key}.') setattr(self, key, value) @@ -548,7 +546,7 @@ class PermissionOverwrite: def _set(self, key, value): if value not in (True, None, False): - raise TypeError('Expected bool or NoneType, received {0.__class__.__name__}'.format(value)) + raise TypeError(f'Expected bool or NoneType, received {value.__class__.__name__}') if value is None: self._values.pop(key, None) diff --git a/discord/player.py b/discord/player.py index 413e5de66..fd4271932 100644 --- a/discord/player.py +++ b/discord/player.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -313,7 +311,7 @@ class FFmpegOpusAudio(FFmpegAudio): '-c:a', codec, '-ar', '48000', '-ac', '2', - '-b:a', '%sk' % bitrate, + '-b:a', f'{bitrate}k', '-loglevel', 'warning')) if isinstance(options, str): @@ -421,7 +419,7 @@ class FFmpegOpusAudio(FFmpegAudio): if isinstance(method, str): probefunc = getattr(cls, '_probe_codec_' + method, None) if probefunc is None: - raise AttributeError("Invalid probe method '%s'" % method) + raise AttributeError(f"Invalid probe method {method!r}") if probefunc is cls._probe_codec_native: fallback = cls._probe_codec_fallback @@ -431,7 +429,7 @@ class FFmpegOpusAudio(FFmpegAudio): fallback = cls._probe_codec_fallback else: raise TypeError("Expected str or callable for parameter 'probe', " \ - "not '{0.__class__.__name__}'" .format(method)) + f"not '{method.__class__.__name__}'") codec = bitrate = None loop = asyncio.get_event_loop() @@ -519,7 +517,7 @@ class PCMVolumeTransformer(AudioSource): def __init__(self, original, volume=1.0): if not isinstance(original, AudioSource): - raise TypeError('expected AudioSource not {0.__class__.__name__}.'.format(original)) + raise TypeError(f'expected AudioSource not {original.__class__.__name__}.') if original.is_opus(): raise ClientException('AudioSource must not be Opus encoded.') @@ -619,7 +617,7 @@ class AudioPlayer(threading.Thread): exc.__context__ = error traceback.print_exception(type(exc), exc, exc.__traceback__) elif error: - msg = 'Exception in voice thread {}'.format(self.name) + msg = f'Exception in voice thread {self.name}' log.exception(msg, exc_info=error) print(msg, file=sys.stderr) traceback.print_exception(type(error), error, error.__traceback__) diff --git a/discord/raw_models.py b/discord/raw_models.py index 9be268ef4..535a4fc83 100644 --- a/discord/raw_models.py +++ b/discord/raw_models.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -26,8 +24,8 @@ DEALINGS IN THE SOFTWARE. class _RawReprMixin: def __repr__(self): - value = ' '.join('%s=%r' % (attr, getattr(self, attr)) for attr in self.__slots__) - return '<%s %s>' % (self.__class__.__name__, value) + value = ' '.join(f'{attr}={getattr(self, attr)!r}' for attr in self.__slots__) + return f'<{self.__class__.__name__} {value}>' class RawMessageDeleteEvent(_RawReprMixin): """Represents the event payload for a :func:`on_raw_message_delete` event. diff --git a/discord/reaction.py b/discord/reaction.py index 437c0fe9d..c1db4415a 100644 --- a/discord/reaction.py +++ b/discord/reaction.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/relationship.py b/discord/relationship.py index 0a9fffda8..f7a1c66d9 100644 --- a/discord/relationship.py +++ b/discord/relationship.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/role.py b/discord/role.py index 735ad12b7..46f1ba39b 100644 --- a/discord/role.py +++ b/discord/role.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -248,7 +246,7 @@ class Role(Hashable): @property def mention(self): """:class:`str`: Returns a string that allows you to mention a role.""" - return '<@&%s>' % self.id + return f'<@&{self.id}>' @property def members(self): diff --git a/discord/shard.py b/discord/shard.py index 1ef9e923e..ce2174aca 100644 --- a/discord/shard.py +++ b/discord/shard.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/state.py b/discord/state.py index 00ccb83db..93b4f7270 100644 --- a/discord/state.py +++ b/discord/state.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -149,7 +147,7 @@ class ConnectionState: intents = options.get('intents', None) if intents is not None: if not isinstance(intents, Intents): - raise TypeError('intents parameter must be Intent not %r' % type(intents)) + raise TypeError(f'intents parameter must be Intent not {type(intents)!r}') else: intents = Intents.default() @@ -175,7 +173,7 @@ class ConnectionState: cache_flags = MemberCacheFlags.from_intents(intents) else: if not isinstance(cache_flags, MemberCacheFlags): - raise TypeError('member_cache_flags parameter must be MemberCacheFlags not %r' % type(cache_flags)) + raise TypeError(f'member_cache_flags parameter must be MemberCacheFlags not {type(cache_flags)!r}') cache_flags._verify_intents(intents) diff --git a/discord/sticker.py b/discord/sticker.py index d94d16444..22897be30 100644 --- a/discord/sticker.py +++ b/discord/sticker.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/team.py b/discord/team.py index 63cd0c075..d0f62f9e8 100644 --- a/discord/team.py +++ b/discord/team.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) diff --git a/discord/template.py b/discord/template.py index 2e9573464..a5869a88f 100644 --- a/discord/template.py +++ b/discord/template.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -76,7 +74,7 @@ class _PartialTemplateState: return [] def __getattr__(self, attr): - raise AttributeError('PartialTemplateState does not support {0!r}.'.format(attr)) + raise AttributeError(f'PartialTemplateState does not support {attr!r}.') class Template: """Represents a Discord template. diff --git a/discord/user.py b/discord/user.py index 3cddf99cc..25377b789 100644 --- a/discord/user.py +++ b/discord/user.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -199,7 +197,7 @@ class BaseUser(_BaseUser): @property def default_avatar_url(self): """:class:`Asset`: Returns a URL for a user's default avatar.""" - return Asset(self._state, '/embed/avatars/{}.png'.format(self.default_avatar.value)) + return Asset(self._state, f'/embed/avatars/{self.default_avatar.value}.png') @property def colour(self): @@ -222,7 +220,7 @@ class BaseUser(_BaseUser): @property def mention(self): """:class:`str`: Returns a string that allows you to mention the given user.""" - return '<@{0.id}>'.format(self) + return f'<@{self.id}>' def permissions_in(self, channel): """An alias for :meth:`abc.GuildChannel.permissions_for`. diff --git a/discord/utils.py b/discord/utils.py index b15f1c7b3..dc8e39f24 100644 --- a/discord/utils.py +++ b/discord/utils.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -158,7 +156,7 @@ def oauth_url(client_id, permissions=None, guild=None, redirect_uri=None, scopes :class:`str` The OAuth2 URL for inviting the bot into guilds. """ - url = 'https://discord.com/oauth2/authorize?client_id={}'.format(client_id) + url = f'https://discord.com/oauth2/authorize?client_id={client_id}' url = url + '&scope=' + '+'.join(scopes or ('bot',)) if permissions is not None: url = url + '&permissions=' + str(permissions.value) @@ -489,21 +487,21 @@ _MARKDOWN_ESCAPE_SUBREGEX = '|'.join(r'\{0}(?=([\s\S]*((?(?:>>)?\s|\[.+\]\(.+\)' -_MARKDOWN_ESCAPE_REGEX = re.compile(r'(?P%s|%s)' % (_MARKDOWN_ESCAPE_SUBREGEX, _MARKDOWN_ESCAPE_COMMON), re.MULTILINE) +_MARKDOWN_ESCAPE_REGEX = re.compile(fr'(?P{_MARKDOWN_ESCAPE_SUBREGEX}|{_MARKDOWN_ESCAPE_COMMON})', re.MULTILINE) _URL_REGEX = r'(?P<[^: >]+:\/[^ >]+>|(?:https?|steam):\/\/[^\s<]+[^<.,:;\"\'\]\s])' -_MARKDOWN_STOCK_REGEX = r'(?P[_\\~|\*`]|%s)' % _MARKDOWN_ESCAPE_COMMON +_MARKDOWN_STOCK_REGEX = fr'(?P[_\\~|\*`]|{_MARKDOWN_ESCAPE_COMMON})' def remove_markdown(text, *, ignore_links=True): """A helper function that removes markdown characters. .. versionadded:: 1.7 - + .. note:: This function is not markdown aware and may remove meaning from the original text. For example, if the input contains ``10 * 5`` then it will be converted into ``10 5``. - + Parameters ----------- text: :class:`str` @@ -525,7 +523,7 @@ def remove_markdown(text, *, ignore_links=True): regex = _MARKDOWN_STOCK_REGEX if ignore_links: - regex = '(?:%s|%s)' % (_URL_REGEX, regex) + regex = f'(?:{_URL_REGEX}|{regex})' return re.sub(regex, replacement, text, 0, re.MULTILINE) def escape_markdown(text, *, as_needed=False, ignore_links=True): @@ -563,7 +561,7 @@ def escape_markdown(text, *, as_needed=False, ignore_links=True): regex = _MARKDOWN_STOCK_REGEX if ignore_links: - regex = '(?:%s|%s)' % (_URL_REGEX, regex) + regex = f'(?:{_URL_REGEX}|{regex})' return re.sub(regex, replacement, text, 0, re.MULTILINE) else: text = re.sub(r'\\', r'\\\\', text) diff --git a/discord/voice_client.py b/discord/voice_client.py index c276c3e45..9a1701989 100644 --- a/discord/voice_client.py +++ b/discord/voice_client.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -558,7 +556,7 @@ class VoiceClient(VoiceProtocol): raise ClientException('Already playing audio.') if not isinstance(source, AudioSource): - raise TypeError('source must an AudioSource not {0.__class__.__name__}'.format(source)) + raise TypeError(f'source must an AudioSource not {source.__class__.__name__}') if not self.encoder and not source.is_opus(): self.encoder = opus.Encoder() @@ -601,7 +599,7 @@ class VoiceClient(VoiceProtocol): @source.setter def source(self, value): if not isinstance(value, AudioSource): - raise TypeError('expected AudioSource not {0.__class__.__name__}.'.format(value)) + raise TypeError(f'expected AudioSource not {value.__class__.__name__}.') if self._player is None: raise ValueError('Not playing anything.') diff --git a/discord/webhook.py b/discord/webhook.py index 0b0195b23..a68be12a0 100644 --- a/discord/webhook.py +++ b/discord/webhook.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -65,7 +63,7 @@ class WebhookAdapter: def _prepare(self, webhook): self._webhook_id = webhook.id self._webhook_token = webhook.token - self._request_url = '{0.BASE}/webhooks/{1}/{2}'.format(self, webhook.id, webhook.token) + self._request_url = f'{self.BASE}/webhooks/{webhook.id}/{webhook.token}' self.webhook = webhook def is_async(self): @@ -100,10 +98,10 @@ class WebhookAdapter: return self.request('PATCH', self._request_url, payload=payload, reason=reason) def edit_webhook_message(self, message_id, payload): - return self.request('PATCH', '{}/messages/{}'.format(self._request_url, message_id), payload=payload) + return self.request('PATCH', f'{self._request_url}/messages/{message_id}', payload=payload) def delete_webhook_message(self, message_id): - return self.request('DELETE', '{}/messages/{}'.format(self._request_url, message_id)) + return self.request('DELETE', f'{self._request_url}/messages/{message_id}') def handle_execution_response(self, data, *, wait): """Transforms the webhook execution response into something @@ -158,7 +156,7 @@ class WebhookAdapter: multipart = None files_to_pass = None - url = '%s?wait=%d' % (self._request_url, wait) + url = f'{self._request_url}?wait={int(wait)}' maybe_coro = None try: maybe_coro = self.request('POST', url, multipart=multipart, payload=data, files=files_to_pass) @@ -422,7 +420,7 @@ class _PartialWebhookState: if self.parent is not None: return getattr(self.parent, attr) - raise AttributeError('PartialWebhookState does not support {0!r}.'.format(attr)) + raise AttributeError(f'PartialWebhookState does not support {attr!r}.') class WebhookMessage(Message): """Represents a message sent from your webhook. @@ -623,12 +621,12 @@ class Webhook(Hashable): self.user = User(state=state, data=user) def __repr__(self): - return '' % self.id + return f'' @property def url(self): """:class:`str` : Returns the webhook's url.""" - return 'https://discord.com/api/webhooks/{}/{}'.format(self.id, self.token) + return f'https://discord.com/api/webhooks/{self.id}/{self.token}' @classmethod def partial(cls, id, token, *, adapter): @@ -697,7 +695,7 @@ class Webhook(Hashable): @classmethod def _as_follower(cls, data, *, channel, user): - name = "{} #{}".format(channel.guild, channel) + name = f"{channel.guild} #{channel}" feed = { 'id': data['webhook_id'], 'type': 2, diff --git a/discord/widget.py b/discord/widget.py index 252cebe25..7f3ed4c8f 100644 --- a/discord/widget.py +++ b/discord/widget.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ The MIT License (MIT) @@ -77,7 +75,7 @@ class WidgetChannel: @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 created_at(self): @@ -236,7 +234,7 @@ class Widget: @property def json_url(self): """:class:`str`: The JSON URL of the widget.""" - return "https://discord.com/api/guilds/{0.id}/widget.json".format(self) + return f"https://discord.com/api/guilds/{self.id}/widget.json" @property def invite_url(self): diff --git a/docs/conf.py b/docs/conf.py index 35cd2d8ec..b353bd8a3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # discord.py documentation build configuration file, created by # sphinx-quickstart on Fri Aug 21 05:43:30 2015. @@ -76,8 +75,8 @@ source_suffix = '.rst' master_doc = 'index' # General information about the project. -project = u'discord.py' -copyright = u'2015-present, Rapptz' +project = 'discord.py' +copyright = '2015-present, Rapptz' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -160,7 +159,7 @@ resource_links = { 'discord': 'https://discord.gg/r3sSKJJ', 'issues': 'https://github.com/Rapptz/discord.py/issues', 'discussions': 'https://github.com/Rapptz/discord.py/discussions', - 'examples': 'https://github.com/Rapptz/discord.py/tree/%s/examples' % branch, + 'examples': f'https://github.com/Rapptz/discord.py/tree/{branch}/examples', } # Theme options are theme-specific and customize the look and feel of a theme @@ -283,8 +282,8 @@ latex_elements = { # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'discord.py.tex', u'discord.py Documentation', - u'Rapptz', 'manual'), + ('index', 'discord.py.tex', 'discord.py Documentation', + 'Rapptz', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -313,8 +312,8 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'discord.py', u'discord.py Documentation', - [u'Rapptz'], 1) + ('index', 'discord.py', 'discord.py Documentation', + ['Rapptz'], 1) ] # If true, show URL addresses after external links. @@ -327,8 +326,8 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'discord.py', u'discord.py Documentation', - u'Rapptz', 'discord.py', 'One line description of project.', + ('index', 'discord.py', 'discord.py Documentation', + 'Rapptz', 'discord.py', 'One line description of project.', 'Miscellaneous'), ] diff --git a/examples/basic_bot.py b/examples/basic_bot.py index 409d4c4a3..1d8928bfc 100644 --- a/examples/basic_bot.py +++ b/examples/basic_bot.py @@ -61,7 +61,7 @@ async def cool(ctx): In reality this just checks if a subcommand is being invoked. """ if ctx.invoked_subcommand is None: - await ctx.send('No, {0.subcommand_passed} is not cool'.format(ctx)) + await ctx.send(f'No, {ctx.subcommand_passed} is not cool') @cool.command(name='bot') async def _bot(ctx): diff --git a/examples/basic_voice.py b/examples/basic_voice.py index 42cea2c87..45387911f 100644 --- a/examples/basic_voice.py +++ b/examples/basic_voice.py @@ -70,9 +70,9 @@ class Music(commands.Cog): """Plays a file from the local filesystem""" source = discord.PCMVolumeTransformer(discord.FFmpegPCMAudio(query)) - ctx.voice_client.play(source, after=lambda e: print('Player error: %s' % e) if e else None) + ctx.voice_client.play(source, after=lambda e: print(f'Player error: {e}') if e else None) - await ctx.send('Now playing: {}'.format(query)) + await ctx.send(f'Now playing: {query}') @commands.command() async def yt(self, ctx, *, url): @@ -80,9 +80,9 @@ class Music(commands.Cog): async with ctx.typing(): player = await YTDLSource.from_url(url, loop=self.bot.loop) - ctx.voice_client.play(player, after=lambda e: print('Player error: %s' % e) if e else None) + ctx.voice_client.play(player, after=lambda e: print(f'Player error: {e}') if e else None) - await ctx.send('Now playing: {}'.format(player.title)) + await ctx.send(f'Now playing: {player.title}') @commands.command() async def stream(self, ctx, *, url): @@ -90,9 +90,9 @@ class Music(commands.Cog): async with ctx.typing(): player = await YTDLSource.from_url(url, loop=self.bot.loop, stream=True) - ctx.voice_client.play(player, after=lambda e: print('Player error: %s' % e) if e else None) + ctx.voice_client.play(player, after=lambda e: print(f'Player error: {e}') if e else None) - await ctx.send('Now playing: {}'.format(player.title)) + await ctx.send(f'Now playing: {player.title}') @commands.command() async def volume(self, ctx, volume: int): @@ -102,7 +102,7 @@ class Music(commands.Cog): return await ctx.send("Not connected to a voice channel.") ctx.voice_client.source.volume = volume / 100 - await ctx.send("Changed volume to {}%".format(volume)) + await ctx.send(f"Changed volume to {volume}%") @commands.command() async def stop(self, ctx): diff --git a/examples/converters.py b/examples/converters.py index 74b9c3c46..41aba4987 100644 --- a/examples/converters.py +++ b/examples/converters.py @@ -29,7 +29,7 @@ async def userinfo(ctx: commands.Context, user: discord.User): user_id = user.id username = user.name avatar = user.avatar_url - await ctx.send('User found: {} -- {}\n{}'.format(user_id, username, avatar)) + await ctx.send(f'User found: {user_id} -- {username}\n{avatar}') @userinfo.error async def userinfo_error(ctx: commands.Context, error: commands.CommandError): @@ -70,7 +70,7 @@ class ChannelOrMemberConverter(commands.Converter): # If the value could not be converted we can raise an error # so our error handlers can deal with it in one place. # The error has to be CommandError derived, so BadArgument works fine here. - raise commands.BadArgument('No Member or TextChannel could be converted from "{}"'.format(argument)) + raise commands.BadArgument(f'No Member or TextChannel could be converted from "{argument}"') @@ -81,7 +81,7 @@ async def notify(ctx: commands.Context, target: ChannelOrMemberConverter): # the `argument` parameter of the `ChannelOrMemberConverter.convert` method and # the conversion will go through the process defined there. - await target.send('Hello, {}!'.format(target.name)) + await target.send(f'Hello, {target.name}!') @bot.command() async def ignore(ctx: commands.Context, target: typing.Union[discord.Member, discord.TextChannel]): @@ -95,9 +95,9 @@ async def ignore(ctx: commands.Context, target: typing.Union[discord.Member, dis # To check the resulting type, `isinstance` is used if isinstance(target, discord.Member): - await ctx.send('Member found: {}, adding them to the ignore list.'.format(target.mention)) + await ctx.send(f'Member found: {target.mention}, adding them to the ignore list.') elif isinstance(target, discord.TextChannel): # this could be an `else` but for completeness' sake. - await ctx.send('Channel found: {}, adding it to the ignore list.'.format(target.mention)) + await ctx.send(f'Channel found: {target.mention}, adding it to the ignore list.') # Built-in type converters. @bot.command() diff --git a/examples/guessing_game.py b/examples/guessing_game.py index a8f09c637..7620d7af1 100644 --- a/examples/guessing_game.py +++ b/examples/guessing_game.py @@ -25,12 +25,12 @@ class MyClient(discord.Client): try: guess = await self.wait_for('message', check=is_correct, timeout=5.0) except asyncio.TimeoutError: - return await message.channel.send('Sorry, you took too long it was {}.'.format(answer)) + return await message.channel.send(f'Sorry, you took too long it was {answer}.') if int(guess.content) == answer: await message.channel.send('You are right!') else: - await message.channel.send('Oops. It is actually {}.'.format(answer)) + await message.channel.send(f'Oops. It is actually {answer}.') client = MyClient() client.run('token') diff --git a/examples/new_member.py b/examples/new_member.py index aa67c46ed..6a9a530f3 100644 --- a/examples/new_member.py +++ b/examples/new_member.py @@ -12,7 +12,7 @@ class MyClient(discord.Client): async def on_member_join(self, member): guild = member.guild if guild.system_channel is not None: - to_send = 'Welcome {0.mention} to {1.name}!'.format(member, guild) + to_send = f'Welcome {member.mention} to {guild.name}!' await guild.system_channel.send(to_send)