Browse Source

Modernize code to use f-strings

This also removes the encoding on the top, since Python 3 does it by
default. It also changes some methods to use `yield from`.
pull/6620/head
Rapptz 4 years ago
parent
commit
9d39b135f4
  1. 2
      discord/__init__.py
  2. 22
      discord/__main__.py
  3. 2
      discord/abc.py
  4. 32
      discord/activity.py
  5. 2
      discord/appinfo.py
  6. 24
      discord/asset.py
  7. 6
      discord/audit_logs.py
  8. 2
      discord/backoff.py
  9. 2
      discord/calls.py
  10. 13
      discord/channel.py
  11. 16
      discord/client.py
  12. 10
      discord/colour.py
  13. 2
      discord/context_managers.py
  14. 9
      discord/embeds.py
  15. 2
      discord/emoji.py
  16. 10
      discord/enums.py
  17. 6
      discord/errors.py
  18. 2
      discord/ext/commands/__init__.py
  19. 2
      discord/ext/commands/_types.py
  20. 10
      discord/ext/commands/bot.py
  21. 6
      discord/ext/commands/cog.py
  22. 2
      discord/ext/commands/context.py
  23. 14
      discord/ext/commands/converter.py
  24. 4
      discord/ext/commands/cooldowns.py
  25. 38
      discord/ext/commands/core.py
  26. 66
      discord/ext/commands/errors.py
  27. 39
      discord/ext/commands/help.py
  28. 2
      discord/ext/commands/view.py
  29. 8
      discord/ext/tasks/__init__.py
  30. 4
      discord/file.py
  31. 14
      discord/flags.py
  32. 6
      discord/gateway.py
  33. 19
      discord/guild.py
  34. 4
      discord/http.py
  35. 2
      discord/integrations.py
  36. 2
      discord/invite.py
  37. 2
      discord/iterators.py
  38. 15
      discord/member.py
  39. 2
      discord/mentions.py
  40. 30
      discord/message.py
  41. 2
      discord/mixins.py
  42. 6
      discord/object.py
  43. 2
      discord/oggparse.py
  44. 8
      discord/opus.py
  45. 8
      discord/partial_emoji.py
  46. 14
      discord/permissions.py
  47. 12
      discord/player.py
  48. 6
      discord/raw_models.py
  49. 2
      discord/reaction.py
  50. 2
      discord/relationship.py
  51. 4
      discord/role.py
  52. 2
      discord/shard.py
  53. 6
      discord/state.py
  54. 2
      discord/sticker.py
  55. 2
      discord/team.py
  56. 4
      discord/template.py
  57. 6
      discord/user.py
  58. 16
      discord/utils.py
  59. 6
      discord/voice_client.py
  60. 18
      discord/webhook.py
  61. 6
      discord/widget.py
  62. 19
      docs/conf.py
  63. 2
      examples/basic_bot.py
  64. 14
      examples/basic_voice.py
  65. 10
      examples/converters.py
  66. 4
      examples/guessing_game.py
  67. 2
      examples/new_member.py

2
discord/__init__.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
Discord API Wrapper
~~~~~~~~~~~~~~~~~~~

22
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)

2
discord/abc.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

32
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 '<Activity %s>' % mapped
inner = ' '.join('%s=%r' % t for t in attrs)
return f'<Activity {inner}>'
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 '<Game name={0.name!r}>'.format(self)
return f'<Game name={self.name!r}>'
def to_dict(self):
timestamps = {}
@ -455,7 +453,7 @@ class Streaming(BaseActivity):
return str(self.name)
def __repr__(self):
return '<Streaming name={0.name!r}>'.format(self)
return f'<Streaming name={self.name!r}>'
@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)

2
discord/appinfo.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

24
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 '<Asset url={0._url!r}>'.format(self)
return f'<Asset url={self._url!r}>'
def __eq__(self, other):
return isinstance(other, Asset) and self._url == other._url

6
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 '<AuditLogDiff %s>' % values
return f'<AuditLogDiff {values}>'
class AuditLogChanges:
TRANSFORMERS = {
@ -166,7 +164,7 @@ class AuditLogChanges:
self.before.color = self.before.colour
def __repr__(self):
return '<AuditLogChanges before=%r after=%r>' % (self.before, self.after)
return f'<AuditLogChanges before={self.before!r} after={self.after!r}>'
def _handle_role(self, first, second, entry, elem):
if not hasattr(first, 'roles'):

2
discord/backoff.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

2
discord/calls.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

13
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 '<DMChannel id={0.id} recipient={0.recipient!r}>'.format(self)

16
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

10
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 '<Colour value=%s>' % self.value
return f'<Colour value={self.value}>'
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
"""

2
discord/context_managers.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

9
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):

2
discord/emoji.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

10
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 '<enum %r>' % cls.__name__
return f'<enum {cls.__name__}>'
@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]

6
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

2
discord/ext/commands/__init__.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
discord.ext.commands
~~~~~~~~~~~~~~~~~~~~~

2
discord/ext/commands/_types.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

10
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):

6
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

2
discord/ext/commands/context.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

14
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)

4
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)

38
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.
"""

66
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.')

39
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):
# <description> 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)

2
discord/ext/commands/view.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

8
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):

4
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

14
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 '<flag_value flag={.flag!r}>'.format(self)
return f'<flag_value flag={self.flag!r}>'
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

6
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:

19
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 '<Guild %s>' % ' '.join(resolved)
inner = ' '.join('%s=%r' % t for t in attrs)
return f'<Guild {inner}>'
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)

4
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'

2
discord/integrations.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

2
discord/invite.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

2
discord/iterators.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

15
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 '<Member id={1.id} name={1.name!r} discriminator={1.discriminator!r}' \
' bot={1.bot} nick={0.nick!r} guild={0.guild!r}>'.format(self, self._user)
return f'<Member id={self._user.id} name={self._user.name!r} discriminator={self._user.discriminator!r}' \
f' bot={self._user.bot} nick={self.nick!r} guild={self.guild!r}>'
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):

2
discord/mentions.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

30
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

2
discord/mixins.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

6
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 '<Object id=%r>' % self.id
return f'<Object id={self.id!r}>'
@property
def created_at(self):

2
discord/oggparse.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

8
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)

8
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 '<a:%s:%s>' % (self.name, self.id)
return '<:%s:%s>' % (self.name, self.id)
return f'<a:{self.name}:{self.id}>'
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):

14
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)

12
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__)

6
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.

2
discord/reaction.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

2
discord/relationship.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

4
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):

2
discord/shard.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

6
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)

2
discord/sticker.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

2
discord/team.py

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
The MIT License (MIT)

4
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.

6
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`.

16
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]*((?<!\{0})\{0})))'.format(
_MARKDOWN_ESCAPE_COMMON = r'^>(?:>>)?\s|\[.+\]\(.+\)'
_MARKDOWN_ESCAPE_REGEX = re.compile(r'(?P<markdown>%s|%s)' % (_MARKDOWN_ESCAPE_SUBREGEX, _MARKDOWN_ESCAPE_COMMON), re.MULTILINE)
_MARKDOWN_ESCAPE_REGEX = re.compile(fr'(?P<markdown>{_MARKDOWN_ESCAPE_SUBREGEX}|{_MARKDOWN_ESCAPE_COMMON})', re.MULTILINE)
_URL_REGEX = r'(?P<url><[^: >]+:\/[^ >]+>|(?:https?|steam):\/\/[^\s<]+[^<.,:;\"\'\]\s])'
_MARKDOWN_STOCK_REGEX = r'(?P<markdown>[_\\~|\*`]|%s)' % _MARKDOWN_ESCAPE_COMMON
_MARKDOWN_STOCK_REGEX = fr'(?P<markdown>[_\\~|\*`]|{_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)

6
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.')

18
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 '<Webhook id=%r>' % self.id
return f'<Webhook id={self.id!r}>'
@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,

6
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):

19
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'),
]

2
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):

14
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):

10
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()

4
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')

2
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)

Loading…
Cancel
Save