diff options
Diffstat (limited to 'discord')
31 files changed, 213 insertions, 136 deletions
diff --git a/discord/abc.py b/discord/abc.py index 18e8a062..7f895b52 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -279,7 +279,7 @@ class GuildChannel(Protocol): perms = [] for target, perm in overwrites.items(): if not isinstance(perm, PermissionOverwrite): - raise InvalidArgument('Expected PermissionOverwrite received {0.__name__}'.format(type(perm))) + raise InvalidArgument(f'Expected PermissionOverwrite received {perm.__class__.__name__}') allow, deny = perm.pair() payload = { diff --git a/discord/activity.py b/discord/activity.py index 7c46a660..f9128817 100644 --- a/discord/activity.py +++ b/discord/activity.py @@ -584,7 +584,7 @@ class Spotify: return 'Spotify' def __repr__(self): - return '<Spotify title={0.title!r} artist={0.artist!r} track_id={0.track_id!r}>'.format(self) + return f'<Spotify title={self.title!r} artist={self.artist!r} track_id={self.track_id!r}>' @property def title(self): @@ -738,7 +738,7 @@ class CustomActivity(BaseActivity): return str(self.name) def __repr__(self): - return '<CustomActivity name={0.name!r} emoji={0.emoji!r}>'.format(self) + return f'<CustomActivity name={self.name!r} emoji={self.emoji!r}>' def create_activity(data): diff --git a/discord/appinfo.py b/discord/appinfo.py index 066cf6f0..6f1754ff 100644 --- a/discord/appinfo.py +++ b/discord/appinfo.py @@ -31,6 +31,7 @@ __all__ = ( 'AppInfo', ) + class AppInfo: """Represents the application info for the bot provided by Discord. @@ -95,10 +96,25 @@ class AppInfo: .. versionadded:: 1.3 """ - __slots__ = ('_state', 'description', 'id', 'name', 'rpc_origins', - 'bot_public', 'bot_require_code_grant', 'owner', 'icon', - 'summary', 'verify_key', 'team', 'guild_id', 'primary_sku_id', - 'slug', 'cover_image') + + __slots__ = ( + '_state', + 'description', + 'id', + 'name', + 'rpc_origins', + 'bot_public', + 'bot_require_code_grant', + 'owner', + 'icon', + 'summary', + 'verify_key', + 'team', + 'guild_id', + 'primary_sku_id', + 'slug', + 'cover_image', + ) def __init__(self, state, data): self._state = state @@ -125,8 +141,11 @@ class AppInfo: self.cover_image = data.get('cover_image') def __repr__(self): - return '<{0.__class__.__name__} id={0.id} name={0.name!r} description={0.description!r} public={0.bot_public} ' \ - 'owner={0.owner!r}>'.format(self) + return ( + f'<{self.__class__.__name__} id={self.id} name={self.name!r} ' + f'description={self.description!r} public={self.bot_public} ' + f'owner={self.owner!r}>' + ) @property def icon_url(self): @@ -166,7 +185,6 @@ class AppInfo: """ return Asset._from_icon(self._state, self, 'app', format=format, size=size) - @property def cover_image_url(self): """:class:`.Asset`: Retrieves the cover image on a store embed. diff --git a/discord/asset.py b/discord/asset.py index db3b8967..da1788d1 100644 --- a/discord/asset.py +++ b/discord/asset.py @@ -88,7 +88,7 @@ class Asset: if format is None: format = 'gif' if user.is_avatar_animated() else static_format - return cls(state, '/avatars/{0.id}/{0.avatar}.{1}?size={2}'.format(user, format, size)) + return cls(state, f'/avatars/{user.id}/{user.avatar}.{format}?size={size}') @classmethod def _from_icon(cls, state, object, path, *, format='webp', size=1024): @@ -100,7 +100,7 @@ class Asset: if format not in 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) + url = f'/{path}-icons/{object.id}/{object.icon}.{format}?size={size}' return cls(state, url) @classmethod @@ -113,7 +113,7 @@ class Asset: if format not in 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) + url = f'/app-assets/{obj.id}/store/{obj.cover_image}.{format}?size={size}' return cls(state, url) @classmethod @@ -126,8 +126,7 @@ class Asset: if hash is None: return cls(state) - url = '/{key}/{0}/{1}.{2}?size={3}' - return cls(state, url.format(id, hash, format, size, key=key)) + return cls(state, f'/{key}/{id}/{hash}.{format}?size={size}') @classmethod def _from_guild_icon(cls, state, guild, *, format=None, static_format='webp', size=1024): @@ -146,14 +145,14 @@ class Asset: if format is None: format = 'gif' if guild.is_icon_animated() else static_format - return cls(state, '/icons/{0.id}/{0.icon}.{1}?size={2}'.format(guild, format, size)) + return cls(state, f'/icons/{guild.id}/{guild.icon}.{format}?size={size}') @classmethod def _from_sticker_url(cls, state, sticker, *, size=1024): if not utils.valid_icon_size(size): raise InvalidArgument("size must be a power of 2 between 16 and 4096") - return cls(state, '/stickers/{0.id}/{0.image}.png?size={2}'.format(sticker, format, size)) + return cls(state, f'/stickers/{sticker.id}/{sticker.image}.png?size={size}') @classmethod def _from_emoji(cls, state, emoji, *, format=None, static_format='png'): diff --git a/discord/audit_logs.py b/discord/audit_logs.py index 745f89d1..ea97eb74 100644 --- a/discord/audit_logs.py +++ b/discord/audit_logs.py @@ -301,7 +301,7 @@ class AuditLogEntry(Hashable): return self.guild.get_member(user_id) or self._users.get(user_id) def __repr__(self): - return '<AuditLogEntry id={0.id} action={0.action} user={0.user!r}>'.format(self) + return f'<AuditLogEntry id={self.id} action={self.action} user={self.user!r}>' @utils.cached_property def created_at(self): diff --git a/discord/channel.py b/discord/channel.py index 5c6eed1e..314485d6 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -320,7 +320,7 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable): return m.author == client.user deleted = await channel.purge(limit=100, check=is_me) - await channel.send('Deleted {} message(s)'.format(len(deleted))) + await channel.send(f'Deleted {len(deleted)} message(s)') Parameters ----------- @@ -504,7 +504,7 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable): raise ClientException('The channel must be a news channel.') if not isinstance(destination, TextChannel): - raise InvalidArgument('Expected TextChannel received {0.__name__}'.format(type(destination))) + raise InvalidArgument(f'Expected TextChannel received {destination.__class__.__name__}') from .webhook import Webhook data = await self._state.http.follow_webhook(self.id, webhook_channel_id=destination.id, reason=reason) @@ -896,7 +896,7 @@ class CategoryChannel(discord.abc.GuildChannel, Hashable): self._update(guild, data) def __repr__(self): - return '<CategoryChannel id={0.id} name={0.name!r} position={0.position} nsfw={0.nsfw}>'.format(self) + return f'<CategoryChannel id={self.id} name={self.name!r} position={self.position} nsfw={self.nsfw}>' def _update(self, guild, data): self.guild = guild @@ -1092,7 +1092,7 @@ class StoreChannel(discord.abc.GuildChannel, Hashable): self._update(guild, data) def __repr__(self): - return '<StoreChannel id={0.id} name={0.name!r} position={0.position} nsfw={0.nsfw}>'.format(self) + return f'<StoreChannel id={self.id} name={self.name!r} position={self.position} nsfw={self.nsfw}>' def _update(self, guild, data): self.guild = guild @@ -1218,7 +1218,7 @@ class DMChannel(discord.abc.Messageable, Hashable): return f'Direct Message with {self.recipient}' def __repr__(self): - return '<DMChannel id={0.id} recipient={0.recipient!r}>'.format(self) + return f'<DMChannel id={self.id} recipient={self.recipient!r}>' @property def type(self): @@ -1354,7 +1354,7 @@ class GroupChannel(discord.abc.Messageable, Hashable): return ', '.join(map(lambda x: x.name, self.recipients)) def __repr__(self): - return '<GroupChannel id={0.id} name={0.name!r}>'.format(self) + return f'<GroupChannel id={self.id} name={self.name!r}>' @property def type(self): diff --git a/discord/client.py b/discord/client.py index 32560099..cae978f1 100644 --- a/discord/client.py +++ b/discord/client.py @@ -849,7 +849,7 @@ class Client: return m.content == 'hello' and m.channel == channel msg = await client.wait_for('message', check=check) - await channel.send('Hello {.author}!'.format(msg)) + await channel.send(f'Hello {msg.author}!') Waiting for a thumbs up reaction from the message author: :: diff --git a/discord/emoji.py b/discord/emoji.py index 02c0ddc8..bf7982ab 100644 --- a/discord/emoji.py +++ b/discord/emoji.py @@ -111,11 +111,11 @@ class Emoji(_EmojiTag): def __str__(self): if self.animated: - return '<a:{0.name}:{0.id}>'.format(self) - return "<:{0.name}:{0.id}>".format(self) + return f'<a:{self.name}:{self.id}>' + return f'<:{self.name}:{self.id}>' def __repr__(self): - return '<Emoji id={0.id} name={0.name!r} animated={0.animated} managed={0.managed}>'.format(self) + return f'<Emoji id={self.id} name={self.name!r} animated={self.animated} managed={self.managed}>' def __eq__(self, other): return isinstance(other, _EmojiTag) and self.id == other.id diff --git a/discord/ext/commands/bot.py b/discord/ext/commands/bot.py index 59f11c74..dabe1439 100644 --- a/discord/ext/commands/bot.py +++ b/discord/ext/commands/bot.py @@ -846,7 +846,7 @@ class BotBase(GroupMixin): raise raise TypeError("command_prefix must be plain string, iterable of strings, or callable " - "returning either of these, not {}".format(ret.__class__.__name__)) + f"returning either of these, not {ret.__class__.__name__}") if not ret: raise ValueError("Iterable command_prefix must contain at least one prefix") @@ -907,13 +907,13 @@ class BotBase(GroupMixin): except TypeError: if not isinstance(prefix, list): raise TypeError("get_prefix must return either a string or a list of string, " - "not {}".format(prefix.__class__.__name__)) + f"not {prefix.__class__.__name__}") # It's possible a bad command_prefix got us here. for value in prefix: if not isinstance(value, str): raise TypeError("Iterable command_prefix or list returned from get_prefix must " - "contain only strings, not {}".format(value.__class__.__name__)) + f"contain only strings, not {value.__class__.__name__}") # Getting here shouldn't happen raise diff --git a/discord/ext/commands/cooldowns.py b/discord/ext/commands/cooldowns.py index 7cfc9fd7..fc438c9f 100644 --- a/discord/ext/commands/cooldowns.py +++ b/discord/ext/commands/cooldowns.py @@ -131,7 +131,7 @@ class Cooldown: return Cooldown(self.rate, self.per, self.type) def __repr__(self): - return '<Cooldown rate: {0.rate} per: {0.per} window: {0._window} tokens: {0._tokens}>'.format(self) + return f'<Cooldown rate: {self.rate} per: {self.per} window: {self._window} tokens: {self._tokens}>' class CooldownMapping: def __init__(self, original): @@ -202,7 +202,7 @@ class _Semaphore: self._waiters = deque() def __repr__(self): - return '<_Semaphore value={0.value} waiters={1}>'.format(self, len(self._waiters)) + return f'<_Semaphore value={self.value} waiters={len(self._waiters)}>' def locked(self): return self.value == 0 @@ -259,7 +259,7 @@ class MaxConcurrency: return self.__class__(self.number, per=self.per, wait=self.wait) def __repr__(self): - return '<MaxConcurrency per={0.per!r} number={0.number} wait={0.wait}>'.format(self) + return f'<MaxConcurrency per={self.per!r} number={self.number} wait={self.wait}>' def get_key(self, message): return self.per.get_key(message) diff --git a/discord/ext/commands/core.py b/discord/ext/commands/core.py index 0de14b45..a570ee48 100644 --- a/discord/ext/commands/core.py +++ b/discord/ext/commands/core.py @@ -695,15 +695,13 @@ class Command(_BaseCommand): try: next(iterator) except StopIteration: - fmt = 'Callback for {0.name} command is missing "self" parameter.' - raise discord.ClientException(fmt.format(self)) + raise discord.ClientException(f'Callback for {self.name} command is missing "self" parameter.') # next we have the 'ctx' as the next parameter try: next(iterator) except StopIteration: - fmt = 'Callback for {0.name} command is missing "ctx" parameter.' - raise discord.ClientException(fmt.format(self)) + raise discord.ClientException(f'Callback for {self.name} command is missing "ctx" parameter.') for name, param in iterator: if param.kind == param.POSITIONAL_OR_KEYWORD or param.kind == param.POSITIONAL_ONLY: @@ -2046,7 +2044,7 @@ def before_invoke(coro): @commands.before_invoke(record_usage) @commands.command() async def when(self, ctx): # Output: <User> used when at <Time> - await ctx.send('and i have existed since {}'.format(ctx.bot.user.created_at)) + await ctx.send(f'and i have existed since {ctx.bot.user.created_at}') @commands.command() async def where(self, ctx): # Output: <Nothing> diff --git a/discord/ext/commands/errors.py b/discord/ext/commands/errors.py index f9fbba0f..f8a2724d 100644 --- a/discord/ext/commands/errors.py +++ b/discord/ext/commands/errors.py @@ -424,7 +424,7 @@ class CommandInvokeError(CommandError): """ def __init__(self, e): self.original = e - super().__init__('Command raised an exception: {0.__class__.__name__}: {0}'.format(e)) + super().__init__(f'Command raised an exception: {e.__class__.__name__}: {e}') class CommandOnCooldown(CommandError): """Exception raised when the command being invoked is on cooldown. @@ -764,8 +764,8 @@ class ExtensionFailed(ExtensionError): """ def __init__(self, name, original): self.original = original - fmt = 'Extension {0!r} raised an error: {1.__class__.__name__}: {1}' - super().__init__(fmt.format(name, original), name=name) + msg = f'Extension {name!r} raised an error: {original.__class__.__name__}: {original}' + super().__init__(msg, name=name) class ExtensionNotFound(ExtensionError): """An exception raised when an extension is not found. @@ -784,8 +784,8 @@ class ExtensionNotFound(ExtensionError): """ def __init__(self, name, original=None): self.original = None - fmt = 'Extension {0!r} could not be loaded.' - super().__init__(fmt.format(name), name=name) + msg = f'Extension {name!r} could not be loaded.' + super().__init__(msg, name=name) class CommandRegistrationError(ClientException): """An exception raised when the command can't be added diff --git a/discord/ext/commands/help.py b/discord/ext/commands/help.py index 117da590..177d3b9b 100644 --- a/discord/ext/commands/help.py +++ b/discord/ext/commands/help.py @@ -60,6 +60,7 @@ __all__ = ( # Type <prefix>help command for more info on a command. # You can also type <prefix>help category for more info on a category. + class Paginator: """A class that aids in paginating code blocks for Discord messages. @@ -81,6 +82,7 @@ class Paginator: The character string inserted between lines. e.g. a newline character. .. versionadded:: 1.7 """ + def __init__(self, prefix='```', suffix='```', max_size=2000, linesep='\n'): self.prefix = prefix self.suffix = suffix @@ -92,7 +94,7 @@ class Paginator: """Clears the paginator to have no pages.""" if self.prefix is not None: self._current_page = [self.prefix] - self._count = len(self.prefix) + self._linesep_len # prefix + newline + self._count = len(self.prefix) + self._linesep_len # prefix + newline else: self._current_page = [] self._count = 0 @@ -150,7 +152,7 @@ class Paginator: if self.prefix is not None: self._current_page = [self.prefix] - self._count = len(self.prefix) + self._linesep_len # prefix + linesep + self._count = len(self.prefix) + self._linesep_len # prefix + linesep else: self._current_page = [] self._count = 0 @@ -171,10 +173,12 @@ class Paginator: fmt = '<Paginator prefix: {0.prefix!r} suffix: {0.suffix!r} linesep: {0.linesep!r} max_size: {0.max_size} count: {0._count}>' return fmt.format(self) + def _not_overriden(f): f.__help_command_not_overriden__ = True return f + class _HelpCommandImpl(Command): def __init__(self, inject, *args, **kwargs): super().__init__(inject.command_callback, *args, **kwargs) @@ -250,6 +254,7 @@ class _HelpCommandImpl(Command): cog.walk_commands = cog.walk_commands.__wrapped__ self.cog = None + class HelpCommand: r"""The base implementation for help command formatting. @@ -288,7 +293,7 @@ class HelpCommand: '@everyone': '@\u200beveryone', '@here': '@\u200bhere', r'<@!?[0-9]{17,22}>': '@deleted-user', - r'<@&[0-9]{17,22}>': '@deleted-role' + r'<@&[0-9]{17,22}>': '@deleted-role', } MENTION_PATTERN = re.compile('|'.join(MENTION_TRANSFORMS.keys())) @@ -305,10 +310,7 @@ class HelpCommand: # The keys can be safely copied as-is since they're 99.99% certain of being # string keys deepcopy = copy.deepcopy - self.__original_kwargs__ = { - k: deepcopy(v) - for k, v in kwargs.items() - } + self.__original_kwargs__ = {k: deepcopy(v) for k, v in kwargs.items()} self.__original_args__ = deepcopy(args) return self @@ -369,10 +371,7 @@ class HelpCommand: def get_bot_mapping(self): """Retrieves the bot mapping passed to :meth:`send_bot_help`.""" bot = self.context.bot - mapping = { - cog: cog.get_commands() - for cog in bot.cogs.values() - } + mapping = {cog: cog.get_commands() for cog in bot.cogs.values()} mapping[None] = [c for c in bot.commands if c.cog is None] return mapping @@ -607,10 +606,7 @@ class HelpCommand: The maximum width of the commands. """ - as_lengths = ( - discord.utils._string_width(c.name) - for c in commands - ) + as_lengths = (discord.utils._string_width(c.name) for c in commands) return max(as_lengths, default=0) def get_destination(self): @@ -880,6 +876,7 @@ class HelpCommand: else: return await self.send_command_help(cmd) + class DefaultHelpCommand(HelpCommand): """The implementation of the default help command. @@ -940,8 +937,10 @@ 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 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." + 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. @@ -1030,6 +1029,7 @@ class DefaultHelpCommand(HelpCommand): self.paginator.add_line(bot.description, empty=True) 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 @@ -1083,6 +1083,7 @@ class DefaultHelpCommand(HelpCommand): await self.send_pages() + class MinimalHelpCommand(HelpCommand): """An implementation of a help command with minimal output. @@ -1149,8 +1150,10 @@ class MinimalHelpCommand(HelpCommand): The help command opening note. """ command_name = self.invoked_with - return "Use `{0}{1} [command]` for more info on a command.\n" \ - "You can also use `{0}{1} [category]` for more info on a category.".format(self.clean_prefix, command_name) + return ( + f"Use `{self.clean_prefix}{command_name} [command]` for more info on a command.\n" + f"You can also use `{self.clean_prefix}{command_name} [category]` for more info on a category." + ) def get_command_signature(self, command): return f'{self.clean_prefix}{command.qualified_name} {command.signature}' @@ -1273,6 +1276,7 @@ class MinimalHelpCommand(HelpCommand): self.paginator.add_line(note, empty=True) 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 diff --git a/discord/ext/commands/view.py b/discord/ext/commands/view.py index 763cf73e..a7dc7236 100644 --- a/discord/ext/commands/view.py +++ b/discord/ext/commands/view.py @@ -189,4 +189,4 @@ class StringView: def __repr__(self): - return '<StringView pos: {0.index} prev: {0.previous} end: {0.end} eof: {0.eof}>'.format(self) + return f'<StringView pos: {self.index} prev: {self.previous} end: {self.end} eof: {self.eof}>' diff --git a/discord/ext/tasks/__init__.py b/discord/ext/tasks/__init__.py index 4c587e86..240fc42e 100644 --- a/discord/ext/tasks/__init__.py +++ b/discord/ext/tasks/__init__.py @@ -75,7 +75,7 @@ class Loop: self._next_iteration = None if not inspect.iscoroutinefunction(self.coro): - raise TypeError('Expected coroutine function, not {0.__name__!r}.'.format(type(self.coro))) + raise TypeError(f'Expected coroutine function, not {type(self.coro).__name__!r}.') async def _call_loop_function(self, name, *args, **kwargs): coro = getattr(self, '_' + name) @@ -370,7 +370,7 @@ class Loop: """ if not inspect.iscoroutinefunction(coro): - raise TypeError('Expected coroutine function, received {0.__name__!r}.'.format(type(coro))) + raise TypeError(f'Expected coroutine function, received {coro.__class__.__name__!r}.') self._before_loop = coro return coro @@ -398,7 +398,7 @@ class Loop: """ if not inspect.iscoroutinefunction(coro): - raise TypeError('Expected coroutine function, received {0.__name__!r}.'.format(type(coro))) + raise TypeError(f'Expected coroutine function, received {coro.__class__.__name__!r}.') self._after_loop = coro return coro @@ -424,7 +424,7 @@ class Loop: The function was not a coroutine. """ if not inspect.iscoroutinefunction(coro): - raise TypeError('Expected coroutine function, received {0.__name__!r}.'.format(type(coro))) + raise TypeError(f'Expected coroutine function, received {coro.__class__.__name__!r}.') self._error = coro return coro diff --git a/discord/guild.py b/discord/guild.py index 51d2004f..a3343686 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -839,7 +839,7 @@ class Guild(Hashable): perms = [] for target, perm in overwrites.items(): if not isinstance(perm, PermissionOverwrite): - raise InvalidArgument('Expected PermissionOverwrite received {0.__name__}'.format(type(perm))) + raise InvalidArgument(f'Expected PermissionOverwrite received {perm.__class__.__name__}') allow, deny = perm.pair() payload = { @@ -2105,17 +2105,17 @@ class Guild(Hashable): Getting the first 100 entries: :: async for entry in guild.audit_logs(limit=100): - print('{0.user} did {0.action} to {0.target}'.format(entry)) + print(f'{entry.user} did {entry.action} to {entry.target}') Getting entries for a specific action: :: async for entry in guild.audit_logs(action=discord.AuditLogAction.ban): - print('{0.user} banned {0.target}'.format(entry)) + print(f'{entry.user} banned {entry.target}') Getting entries made by a specific user: :: entries = await guild.audit_logs(limit=None, user=guild.me).flatten() - await channel.send('I made {} moderation actions.'.format(len(entries))) + await channel.send(f'I made {len(entries)} moderation actions.') Parameters ----------- diff --git a/discord/http.py b/discord/http.py index 353410e4..1c7030f2 100644 --- a/discord/http.py +++ b/discord/http.py @@ -587,7 +587,7 @@ class HTTPClient: r = Route('DELETE', '/guilds/{guild_id}/members/{user_id}', guild_id=guild_id, user_id=user_id) if reason: # thanks aiohttp - r.url = '{0.url}?reason={1}'.format(r, _uriquote(reason)) + r.url = f'{r.url}?reason={_uriquote(reason)}' return self.request(r) @@ -599,7 +599,7 @@ class HTTPClient: if reason: # thanks aiohttp - r.url = '{0.url}?reason={1}'.format(r, _uriquote(reason)) + r.url = f'{r.url}?reason={_uriquote(reason)}' return self.request(r, params=params) diff --git a/discord/integrations.py b/discord/integrations.py index 6784f3f9..34458adc 100644 --- a/discord/integrations.py +++ b/discord/integrations.py @@ -53,7 +53,7 @@ class IntegrationAccount: self.name = kwargs.pop('name') def __repr__(self): - return '<IntegrationAccount id={0.id} name={0.name!r}>'.format(self) + return f'<IntegrationAccount id={self.id} name={self.name!r}>' class Integration: """Represents a guild integration. @@ -101,7 +101,7 @@ class Integration: self._from_data(data) def __repr__(self): - return '<Integration id={0.id} name={0.name!r} type={0.type!r}>'.format(self) + return f'<Integration id={self.id} name={self.name!r} type={self.type!r}>' def _from_data(self, integ): self.id = _get_as_snowflake(integ, 'id') diff --git a/discord/invite.py b/discord/invite.py index 697c62d0..3c061750 100644 --- a/discord/invite.py +++ b/discord/invite.py @@ -34,6 +34,7 @@ __all__ = ( 'Invite', ) + class PartialInviteChannel: """Represents a "partial" invite channel. @@ -79,7 +80,7 @@ class PartialInviteChannel: return self.name def __repr__(self): - return '<PartialInviteChannel id={0.id} name={0.name} type={0.type!r}>'.format(self) + return f'<PartialInviteChannel id={self.id} name={self.name} type={self.type!r}>' @property def mention(self): @@ -91,6 +92,7 @@ class PartialInviteChannel: """:class:`datetime.datetime`: Returns the channel's creation time in UTC.""" return snowflake_time(self.id) + class PartialInviteGuild: """Represents a "partial" invite guild. @@ -135,8 +137,7 @@ class PartialInviteGuild: The partial guild's description. """ - __slots__ = ('_state', 'features', 'icon', 'banner', 'id', 'name', 'splash', - 'verification_level', 'description') + __slots__ = ('_state', 'features', 'icon', 'banner', 'id', 'name', 'splash', 'verification_level', 'description') def __init__(self, state, data, id): self._state = state @@ -153,8 +154,10 @@ class PartialInviteGuild: return self.name def __repr__(self): - return '<{0.__class__.__name__} id={0.id} name={0.name!r} features={0.features} ' \ - 'description={0.description!r}>'.format(self) + return ( + f'<{self.__class__.__name__} id={self.id} name={self.name!r} features={self.features} ' + f'description={self.description!r}>' + ) @property def created_at(self): @@ -213,6 +216,7 @@ class PartialInviteGuild: """ return Asset._from_guild_image(self._state, self.id, self.splash, 'splashes', format=format, size=size) + class Invite(Hashable): r"""Represents a Discord :class:`Guild` or :class:`abc.GuildChannel` invite. @@ -291,9 +295,21 @@ class Invite(Hashable): The channel the invite is for. """ - __slots__ = ('max_age', 'code', 'guild', 'revoked', 'created_at', 'uses', - 'temporary', 'max_uses', 'inviter', 'channel', '_state', - 'approximate_member_count', 'approximate_presence_count' ) + __slots__ = ( + 'max_age', + 'code', + 'guild', + 'revoked', + 'created_at', + 'uses', + 'temporary', + 'max_uses', + 'inviter', + 'channel', + '_state', + 'approximate_member_count', + 'approximate_presence_count', + ) BASE = 'https://discord.gg' @@ -361,9 +377,11 @@ class Invite(Hashable): return self.url def __repr__(self): - return '<Invite code={0.code!r} guild={0.guild!r} ' \ - 'online={0.approximate_presence_count} ' \ - 'members={0.approximate_member_count}>'.format(self) + return ( + f'<Invite code={self.code!r} guild={self.guild!r} ' + f'online={self.approximate_presence_count} ' + f'members={self.approximate_member_count}>' + ) def __hash__(self): return hash(self.code) diff --git a/discord/mentions.py b/discord/mentions.py index 5b2a32e1..57b1e3fc 100644 --- a/discord/mentions.py +++ b/discord/mentions.py @@ -26,6 +26,7 @@ __all__ = ( 'AllowedMentions', ) + class _FakeBool: def __repr__(self): return 'True' @@ -36,8 +37,10 @@ class _FakeBool: def __bool__(self): return True + default = _FakeBool() + class AllowedMentions: """A class that represents what mentions are allowed in a message. @@ -126,4 +129,7 @@ class AllowedMentions: return AllowedMentions(everyone=everyone, roles=roles, users=users, replied_user=replied_user) def __repr__(self): - return '{0.__class__.__qualname__}(everyone={0.everyone}, users={0.users}, roles={0.roles}, replied_user={0.replied_user})'.format(self) + return ( + f'{self.__class__.__name__}(everyone={self.everyone}, ' + f'users={self.users}, roles={self.roles}, replied_user={self.replied_user})' + ) diff --git a/discord/message.py b/discord/message.py index a19f44ab..9796983d 100644 --- a/discord/message.py +++ b/discord/message.py @@ -132,7 +132,7 @@ class Attachment(Hashable): return self.filename.startswith('SPOILER_') def __repr__(self): - return '<Attachment id={0.id} filename={0.filename!r} url={0.url!r}>'.format(self) + return f'<Attachment id={self.id} filename={self.filename!r} url={self.url!r}>' def __str__(self): return self.url or '' @@ -380,10 +380,10 @@ class MessageReference: .. versionadded:: 1.7 """ guild_id = self.guild_id if self.guild_id is not None else '@me' - return 'https://discord.com/channels/{0}/{1.channel_id}/{1.message_id}'.format(guild_id, self) + return f'https://discord.com/channels/{guild_id}/{self.channel_id}/{self.message_id}' def __repr__(self): - return '<MessageReference message_id={0.message_id!r} channel_id={0.channel_id!r} guild_id={0.guild_id!r}>'.format(self) + return f'<MessageReference message_id={self.message_id!r} channel_id={self.channel_id!r} guild_id={self.guild_id!r}>' def to_dict(self): result = {'message_id': self.message_id} if self.message_id is not None else {} @@ -580,7 +580,7 @@ class Message(Hashable): continue def __repr__(self): - return '<Message id={0.id} channel={0.channel!r} type={0.type!r} author={0.author!r} flags={0.flags!r}>'.format(self) + return f'<Message id={self.id} channel={self.channel!r} type={self.type!r} author={self.author!r} flags={self.flags!r}>' def _try_patch(self, data, key, transform=None): try: @@ -849,7 +849,7 @@ class Message(Hashable): def jump_url(self): """:class:`str`: Returns a URL that allows the client to jump to this message.""" guild_id = getattr(self.guild, 'id', '@me') - return 'https://discord.com/channels/{0}/{1.channel.id}/{1.id}'.format(guild_id, self) + return f'https://discord.com/channels/{guild_id}/{self.channel.id}/{self.id}' def is_system(self): """:class:`bool`: Whether the message is a system message. @@ -875,13 +875,13 @@ class Message(Hashable): 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]) + return f'{self.author.name} added {self.mentions[0].name} to the group.' if self.type is MessageType.recipient_remove: - return '{0.name} removed {1.name} from the group.'.format(self.author, self.mentions[0]) + return f'{self.author.name} removed {self.mentions[0].name} from the group.' if self.type is MessageType.channel_name_change: - return '{0.author.name} changed the channel name: {0.content}'.format(self) + return f'{self.author.name} changed the channel name: {self.content}' if self.type is MessageType.channel_icon_change: return f'{self.author.name} changed the channel icon.' @@ -910,19 +910,19 @@ class Message(Hashable): 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) + return f'{self.author.name} just boosted the server! {self.guild} has achieved **Level 1!**' if self.type is MessageType.premium_guild_tier_2: - return '{0.author.name} just boosted the server! {0.guild} has achieved **Level 2!**'.format(self) + return f'{self.author.name} just boosted the server! {self.guild} has achieved **Level 2!**' if self.type is MessageType.premium_guild_tier_3: - return '{0.author.name} just boosted the server! {0.guild} has achieved **Level 3!**'.format(self) + return f'{self.author.name} just boosted the server! {self.guild} has achieved **Level 3!**' if self.type is MessageType.channel_follow_add: - return '{0.author.name} has added {0.content} to this channel'.format(self) + return f'{self.author.name} has added {self.content} to this channel' if self.type is MessageType.guild_stream: - return '{0.author.name} is live! Now streaming {0.author.activity.name}'.format(self) + return f'{self.author.name} is live! Now streaming {self.author.activity.name}' if self.type is MessageType.guild_discovery_disqualified: return 'This server has been removed from Server Discovery because it no longer passes all the requirements. Check Server Settings for more details.' @@ -1394,7 +1394,7 @@ class PartialMessage(Hashable): pinned = property(None, lambda x, y: ...) def __repr__(self): - return '<PartialMessage id={0.id} channel={0.channel!r}>'.format(self) + return f'<PartialMessage id={self.id} channel={self.channel!r}>' @property def created_at(self): diff --git a/discord/partial_emoji.py b/discord/partial_emoji.py index 698feeab..c84da4bf 100644 --- a/discord/partial_emoji.py +++ b/discord/partial_emoji.py @@ -108,7 +108,7 @@ class PartialEmoji(_EmojiTag): 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) + return f'<{self.__class__.__name__} animated={self.animated} name={self.name!r} id={self.id}>' def __eq__(self, other): if self.is_unicode_emoji(): diff --git a/discord/player.py b/discord/player.py index fd427193..48b702e6 100644 --- a/discord/player.py +++ b/discord/player.py @@ -144,7 +144,7 @@ class FFmpegAudio(AudioSource): executable = args.partition(' ')[0] if isinstance(args, str) else args[0] raise ClientException(executable + ' was not found.') from None except subprocess.SubprocessError as exc: - raise ClientException('Popen failed: {0.__class__.__name__}: {0}'.format(exc)) from exc + raise ClientException(f'Popen failed: {exc.__class__.__name__}: {exc}') from exc else: return process diff --git a/discord/reaction.py b/discord/reaction.py index 34ef5333..d8829590 100644 --- a/discord/reaction.py +++ b/discord/reaction.py @@ -93,7 +93,7 @@ class Reaction: return str(self.emoji) def __repr__(self): - return '<Reaction emoji={0.emoji!r} me={0.me} count={0.count}>'.format(self) + return f'<Reaction emoji={self.emoji!r} me={self.me} count={self.count}>' async def remove(self, user): """|coro| @@ -158,14 +158,14 @@ class Reaction: # I do not actually recommend doing this. async for user in reaction.users(): - await channel.send('{0} has reacted with {1.emoji}!'.format(user, reaction)) + await channel.send(f'{user} has reacted with {reaction.emoji}!') Flattening into a list: :: users = await reaction.users().flatten() # users is now a list of User... winner = random.choice(users) - await channel.send('{} has won the raffle.'.format(winner)) + await channel.send(f'{winner} has won the raffle.') Parameters ------------ @@ -191,7 +191,7 @@ class Reaction: """ if self.custom_emoji: - emoji = '{0.name}:{0.id}'.format(self.emoji) + emoji = f'{self.emoji.name}:{self.emoji.id}' else: emoji = self.emoji diff --git a/discord/role.py b/discord/role.py index 37fa8f8b..c1060ace 100644 --- a/discord/role.py +++ b/discord/role.py @@ -33,6 +33,7 @@ __all__ = ( 'Role', ) + class RoleTags: """Represents tags on a role. @@ -52,7 +53,11 @@ class RoleTags: The integration ID that manages the role. """ - __slots__ = ('bot_id', 'integration_id', '_premium_subscriber',) + __slots__ = ( + 'bot_id', + 'integration_id', + '_premium_subscriber', + ) def __init__(self, data): self.bot_id = _get_as_snowflake(data, 'bot_id') @@ -76,8 +81,11 @@ class RoleTags: return self.integration_id is not None def __repr__(self): - return '<RoleTags bot_id={0.bot_id} integration_id={0.integration_id} ' \ - 'premium_subscriber={1}>'.format(self, self.is_premium_subscriber()) + return ( + f'<RoleTags bot_id={self.bot_id} integration_id={self.integration_id} ' + f'premium_subscriber={self.is_premium_subscriber()}>' + ) + class Role(Hashable): """Represents a Discord role in a :class:`Guild`. @@ -138,8 +146,19 @@ class Role(Hashable): The role tags associated with this role. """ - __slots__ = ('id', 'name', '_permissions', '_colour', 'position', - 'managed', 'mentionable', 'hoist', 'guild', 'tags', '_state') + __slots__ = ( + 'id', + 'name', + '_permissions', + '_colour', + 'position', + 'managed', + 'mentionable', + 'hoist', + 'guild', + 'tags', + '_state', + ) def __init__(self, *, guild, state, data): self.guild = guild @@ -151,7 +170,7 @@ class Role(Hashable): return self.name def __repr__(self): - return '<Role id={0.id} name={0.name!r}>'.format(self) + return f'<Role id={self.id} name={self.name!r}>' def __lt__(self, other): if not isinstance(other, Role) or not isinstance(self, Role): @@ -346,7 +365,7 @@ class Role(Hashable): 'permissions': str(fields.get('permissions', self.permissions).value), 'color': colour.value, 'hoist': fields.get('hoist', self.hoist), - 'mentionable': fields.get('mentionable', self.mentionable) + 'mentionable': fields.get('mentionable', self.mentionable), } data = await self._state.http.edit_role(self.guild.id, self.id, reason=reason, **payload) diff --git a/discord/sticker.py b/discord/sticker.py index 1240e357..48701f62 100644 --- a/discord/sticker.py +++ b/discord/sticker.py @@ -88,7 +88,7 @@ class Sticker(Hashable): self.preview_image = data.get('preview_asset') def __repr__(self): - return '<{0.__class__.__name__} id={0.id} name={0.name!r}>'.format(self) + return f'<{self.__class__.__name__} id={self.id} name={self.name!r}>' def __str__(self): return self.name diff --git a/discord/team.py b/discord/team.py index d0f62f9e..3278433a 100644 --- a/discord/team.py +++ b/discord/team.py @@ -32,6 +32,7 @@ __all__ = ( 'TeamMember', ) + class Team: """Represents an application team for a bot provided by Discord. @@ -50,6 +51,7 @@ class Team: .. versionadded:: 1.3 """ + __slots__ = ('_state', 'id', 'name', 'icon', 'owner_id', 'members') def __init__(self, state, data): @@ -62,7 +64,7 @@ class Team: self.members = [TeamMember(self, self._state, member) for member in data['members']] def __repr__(self): - return '<{0.__class__.__name__} id={0.id} name={0.name}>'.format(self) + return f'<{self.__class__.__name__} id={self.id} name={self.name}>' @property def icon_url(self): @@ -105,6 +107,7 @@ class Team: """Optional[:class:`TeamMember`]: The team's owner.""" return utils.get(self.members, id=self.owner_id) + class TeamMember(BaseUser): """Represents a team member in a team. @@ -145,6 +148,7 @@ class TeamMember(BaseUser): membership_state: :class:`TeamMembershipState` The membership state of the member (e.g. invited or accepted) """ + __slots__ = BaseUser.__slots__ + ('team', 'membership_state', 'permissions') def __init__(self, team, state, data): @@ -154,5 +158,7 @@ class TeamMember(BaseUser): super().__init__(state=state, data=data['user']) def __repr__(self): - return '<{0.__class__.__name__} id={0.id} name={0.name!r} ' \ - 'discriminator={0.discriminator!r} membership_state={0.membership_state!r}>'.format(self) + return ( + f'<{self.__class__.__name__} id={self.id} name={self.name!r} ' + f'discriminator={self.discriminator!r} membership_state={self.membership_state!r}>' + ) diff --git a/discord/template.py b/discord/template.py index fd412bb7..af2d0dc4 100644 --- a/discord/template.py +++ b/discord/template.py @@ -30,12 +30,14 @@ __all__ = ( 'Template', ) + class _FriendlyHttpAttributeErrorHelper: __slots__ = () def __getattr__(self, attr): raise AttributeError('PartialTemplateState does not support http methods.') + class _PartialTemplateState: def __init__(self, *, state): self.__state = state @@ -72,6 +74,7 @@ class _PartialTemplateState: def __getattr__(self, attr): raise AttributeError(f'PartialTemplateState does not support {attr!r}.') + class Template: """Represents a Discord template. @@ -105,7 +108,7 @@ class Template: def _store(self, data): self.code = data['code'] self.uses = data['usage_count'] - self.name = data['name'] + self.name = data['name'] self.description = data['description'] creator_data = data.get('creator') self.creator = None if creator_data is None else self._state.store_user(creator_data) @@ -126,8 +129,10 @@ class Template: self.source_guild = guild def __repr__(self): - return '<Template code={0.code!r} uses={0.uses} name={0.name!r}' \ - ' creator={0.creator!r} source_guild={0.source_guild!r}>'.format(self) + return ( + f'<Template code={self.code!r} uses={self.uses} name={self.name!r}' + f' creator={self.creator!r} source_guild={self.source_guild!r}>' + ) async def create_guild(self, name, region=None, icon=None): """|coro| diff --git a/discord/user.py b/discord/user.py index 8b134b40..d5541112 100644 --- a/discord/user.py +++ b/discord/user.py @@ -36,6 +36,7 @@ __all__ = ( _BaseUser = discord.abc.User + class BaseUser(_BaseUser): __slots__ = ('name', 'id', 'discriminator', 'avatar', 'bot', 'system', '_public_flags', '_state') @@ -44,7 +45,7 @@ class BaseUser(_BaseUser): self._update(data) def __str__(self): - return '{0.name}#{0.discriminator}'.format(self) + return f'{self.name}#{self.discriminator}' def __eq__(self, other): return isinstance(other, _BaseUser) and other.id == self.id @@ -66,7 +67,7 @@ class BaseUser(_BaseUser): @classmethod def _copy(cls, user): - self = cls.__new__(cls) # bypass __init__ + self = cls.__new__(cls) # bypass __init__ self.name = user.name self.id = user.id @@ -230,6 +231,7 @@ class BaseUser(_BaseUser): return any(user.id == self.id for user in message.mentions) + class ClientUser(BaseUser): """Represents your Discord user. @@ -275,15 +277,17 @@ class ClientUser(BaseUser): mfa_enabled: :class:`bool` Specifies if the user has MFA turned on and working. """ - __slots__ = BaseUser.__slots__ + \ - ('locale', '_flags', 'verified', 'mfa_enabled', '__weakref__') + + __slots__ = BaseUser.__slots__ + ('locale', '_flags', 'verified', 'mfa_enabled', '__weakref__') def __init__(self, *, state, data): super().__init__(state=state, data=data) def __repr__(self): - return '<ClientUser id={0.id} name={0.name!r} discriminator={0.discriminator!r}' \ - ' bot={0.bot} verified={0.verified} mfa_enabled={0.mfa_enabled}>'.format(self) + return ( + f'<ClientUser id={self.id} name={self.name!r} discriminator={self.discriminator!r}' + f' bot={self.bot} verified={self.verified} mfa_enabled={self.mfa_enabled}>' + ) def _update(self, data): super()._update(data) @@ -293,7 +297,6 @@ class ClientUser(BaseUser): self._flags = data.get('flags', 0) self.mfa_enabled = data.get('mfa_enabled', False) - async def edit(self, *, username=None, avatar=None): """|coro| @@ -330,6 +333,7 @@ class ClientUser(BaseUser): data = await self._state.http.edit_profile(username=username, avatar=avatar) self._update(data) + class User(BaseUser, discord.abc.Messageable): """Represents a Discord user. @@ -370,7 +374,7 @@ class User(BaseUser, discord.abc.Messageable): __slots__ = BaseUser.__slots__ + ('__weakref__',) def __repr__(self): - return '<User id={0.id} name={0.name!r} discriminator={0.discriminator!r} bot={0.bot}>'.format(self) + return f'<User id={self.id} name={self.name!r} discriminator={self.discriminator!r} bot={self.bot}>' async def _get_channel(self): ch = await self.create_dm() diff --git a/discord/webhook.py b/discord/webhook.py index dd646b33..43d56319 100644 --- a/discord/webhook.py +++ b/discord/webhook.py @@ -106,7 +106,7 @@ class PartialWebhookGuild(Hashable): @property def icon_url(self): """:class:`Asset`: Returns the guild's icon asset.""" - return self.icon_url_as() + return self.icon_url_as() def is_icon_animated(self): """:class:`bool`: Returns True if the guild has an animated icon.""" @@ -724,13 +724,13 @@ class Webhook(Hashable): source_channel = data.get('source_channel') if source_channel: source_channel = PartialWebhookChannel(data=source_channel) - + self.source_channel = source_channel source_guild = data.get('source_guild') if source_guild: source_guild = PartialWebhookGuild(data=source_guild, state=state) - + self.source_guild = source_guild def __repr__(self): @@ -904,7 +904,7 @@ class Webhook(Hashable): if format not in ('png', 'jpg', 'jpeg'): raise InvalidArgument("format must be one of 'png', 'jpg', or 'jpeg'.") - url = '/avatars/{0.id}/{0.avatar}.{1}?size={2}'.format(self, format, size) + url = f'/avatars/{self.id}/{self.avatar}.{format}?size={size}' return Asset(self._state, url) def delete(self, *, reason=None): diff --git a/discord/widget.py b/discord/widget.py index 6a7a8adf..93a46be7 100644 --- a/discord/widget.py +++ b/discord/widget.py @@ -76,7 +76,7 @@ class WidgetChannel: return self.name def __repr__(self): - return '<WidgetChannel id={0.id} name={0.name!r} position={0.position!r}>'.format(self) + return f'<WidgetChannel id={self.id} name={self.name!r} position={self.position!r}>' @property def mention(self): @@ -230,7 +230,7 @@ class Widget: return self.id == other.id def __repr__(self): - return '<Widget id={0.id} name={0.name!r} invite_url={0.invite_url!r}>'.format(self) + return f'<Widget id={self.id} name={self.name!r} invite_url={self.invite_url!r}>' @property def created_at(self): |