Skip to content

Commit 33e93b0

Browse files
committed
Merge branch 'master' into viewless-components
2 parents 23c2632 + c3e7453 commit 33e93b0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+290
-303
lines changed

discord/abc.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@
9999
from .types.channel import PermissionOverwrite as PermissionOverwritePayload
100100
from .user import ClientUser
101101

102-
PartialMessageableChannel = Union[TextChannel, VoiceChannel, StageChannel, Thread, DMChannel, PartialMessageable]
103-
MessageableChannel = Union[PartialMessageableChannel, GroupChannel]
104-
SnowflakeTime = Union["Snowflake", datetime]
102+
PartialMessageableChannel = TextChannel | VoiceChannel | StageChannel | Thread | DMChannel | PartialMessageable
103+
MessageableChannel = PartialMessageableChannel | GroupChannel
104+
SnowflakeTime = "Snowflake" | datetime
105105

106106
MISSING = utils.MISSING
107107

@@ -912,8 +912,8 @@ async def set_permissions(self, target, *, overwrite=MISSING, reason=None, **per
912912
raise InvalidArgument("No overwrite provided.")
913913
try:
914914
overwrite = PermissionOverwrite(**permissions)
915-
except (ValueError, TypeError):
916-
raise InvalidArgument("Invalid permissions given to keyword arguments.")
915+
except (ValueError, TypeError) as e:
916+
raise InvalidArgument("Invalid permissions given to keyword arguments.") from e
917917
elif len(permissions) > 0:
918918
raise InvalidArgument("Cannot mix overwrite and keyword arguments.")
919919

@@ -1748,8 +1748,8 @@ def can_send(self, *objects) -> bool:
17481748
if obj.guild_id == channel.guild.id:
17491749
continue
17501750

1751-
except (KeyError, AttributeError):
1752-
raise TypeError(f"The object {obj} is of an invalid type.")
1751+
except (KeyError, AttributeError) as e:
1752+
raise TypeError(f"The object {obj} is of an invalid type.") from e
17531753

17541754
if not getattr(channel.permissions_for(channel.guild.me), permission):
17551755
return False

discord/activity.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ def __repr__(self) -> str:
805805
return f"<CustomActivity name={self.name!r} emoji={self.emoji!r}>"
806806

807807

808-
ActivityTypes = Union[Activity, Game, CustomActivity, Streaming, Spotify]
808+
ActivityTypes = Activity | Game | CustomActivity | Streaming | Spotify
809809

810810

811811
@overload

discord/audit_logs.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ def _handle_role(
383383
elem: list[RolePayload],
384384
) -> None:
385385
if not hasattr(first, "roles"):
386-
setattr(first, "roles", [])
386+
first.roles = []
387387

388388
data = []
389389
g: Guild = entry.guild # type: ignore
@@ -398,7 +398,7 @@ def _handle_role(
398398

399399
data.append(role)
400400

401-
setattr(second, "roles", data)
401+
second.roles = data
402402

403403
def _handle_trigger_metadata(
404404
self,
@@ -409,13 +409,13 @@ def _handle_trigger_metadata(
409409
attr: str,
410410
) -> None:
411411
if not hasattr(first, "trigger_metadata"):
412-
setattr(first, "trigger_metadata", None)
412+
first.trigger_metadata = None
413413

414414
key = attr.split("_", 1)[-1]
415415
data = {key: elem}
416416
tm = AutoModTriggerMetadata.from_dict(data)
417417

418-
setattr(second, "trigger_metadata", tm)
418+
second.trigger_metadata = tm
419419

420420

421421
class _AuditLogProxyMemberPrune:

discord/bot.py

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def pending_application_commands(self):
113113
def commands(self) -> list[ApplicationCommand | Any]:
114114
commands = self.application_commands
115115
if self._bot._supports_prefixed_commands and hasattr(self._bot, "prefixed_commands"):
116-
commands += getattr(self._bot, "prefixed_commands")
116+
commands += self._bot.prefixed_commands
117117
return commands
118118

119119
@property
@@ -267,7 +267,7 @@ def _check_command(cmd: ApplicationCommand, match: Mapping[str, Any]) -> bool:
267267
if isinstance(cmd, SlashCommandGroup):
268268
if len(cmd.subcommands) != len(match.get("options", [])):
269269
return True
270-
for i, subcommand in enumerate(cmd.subcommands):
270+
for subcommand in cmd.subcommands:
271271
match_ = next(
272272
(data for data in match["options"] if data["name"] == subcommand.name),
273273
MISSING,
@@ -359,8 +359,9 @@ def _check_command(cmd: ApplicationCommand, match: Mapping[str, Any]) -> bool:
359359
return_value.append({"command": cmd, "action": None, "id": int(match["id"])})
360360

361361
# Now let's see if there are any commands on discord that we need to delete
362-
for cmd, value_ in registered_commands_dict.items():
363-
match = find(lambda c: c.name == value_["name"], pending)
362+
for _, value_ in registered_commands_dict.items():
363+
# name default arg is used because loop variables leak in surrounding scope
364+
match = find(lambda c, name=value_["name"]: c.name == name, pending)
364365
if match is None:
365366
# We have this command registered but not in our list
366367
return_value.append(
@@ -519,7 +520,11 @@ def register(
519520
)
520521
continue
521522
# We can assume the command item is a command, since it's only a string if action is delete
522-
match = find(lambda c: c.name == cmd["command"].name and c.type == cmd["command"].type, pending)
523+
wanted = cmd["command"]
524+
name = wanted.name
525+
type_ = wanted.type
526+
527+
match = next((c for c in pending if c.name == name and c.type == type_), None)
523528
if match is None:
524529
continue
525530
if cmd["action"] == "edit":
@@ -608,8 +613,10 @@ def register(
608613
registered = await register("bulk", data, guild_id=guild_id)
609614

610615
for i in registered:
616+
type_ = i.get("type")
617+
# name, type_ default args are used because loop variables leak in surrounding scope
611618
cmd = find(
612-
lambda c: c.name == i["name"] and c.type == i.get("type"),
619+
lambda c, name=i["name"], type_=type_: c.name == name and c.type == type_,
613620
self.pending_application_commands,
614621
)
615622
if not cmd:
@@ -626,7 +633,7 @@ async def sync_commands(
626633
force: bool = False,
627634
guild_ids: list[int] | None = None,
628635
register_guild_commands: bool = True,
629-
check_guilds: list[int] | None = [],
636+
check_guilds: list[int] | None = None,
630637
delete_existing: bool = True,
631638
) -> None:
632639
"""|coro|
@@ -713,25 +720,37 @@ async def on_connect():
713720
)
714721
registered_guild_commands[guild_id] = app_cmds
715722

716-
for i in registered_commands:
723+
for item in registered_commands:
724+
type_ = item.get("type")
725+
# name, type_ default args are used because loop variables leak in surrounding scope
717726
cmd = find(
718-
lambda c: c.name == i["name"] and c.guild_ids is None and c.type == i.get("type"),
727+
lambda c, name=item["name"], type_=type_: (c.name == name and c.guild_ids is None and c.type == type_),
719728
self.pending_application_commands,
720729
)
721730
if cmd:
722-
cmd.id = i["id"]
731+
cmd.id = item["id"]
723732
self._application_commands[cmd.id] = cmd
724733

725734
if register_guild_commands and registered_guild_commands:
726735
for guild_id, guild_cmds in registered_guild_commands.items():
727736
for i in guild_cmds:
728-
cmd = find(
729-
lambda cmd: cmd.name == i["name"]
730-
and cmd.type == i.get("type")
731-
and cmd.guild_ids is not None
732-
and (guild_id := i.get("guild_id"))
733-
and guild_id in cmd.guild_ids,
734-
self.pending_application_commands,
737+
name = i["name"]
738+
type_ = i.get("type")
739+
target_gid = i.get("guild_id")
740+
if target_gid is None:
741+
continue
742+
743+
cmd = next(
744+
(
745+
c
746+
for c in self.pending_application_commands
747+
if c.name == name
748+
and c.type == type_
749+
and c.guild_ids is not None
750+
and target_gid == guild_id
751+
and target_gid in c.guild_ids
752+
),
753+
None,
735754
)
736755
if not cmd:
737756
# command has not been added yet

discord/cog.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -186,14 +186,12 @@ def __new__(cls: type[CogMeta], *args: Any, **kwargs: Any) -> CogMeta:
186186
commands[f"ext_{cmd.ext_variant.qualified_name}"] = cmd.ext_variant
187187

188188
if inspect.iscoroutinefunction(value):
189-
try:
190-
getattr(value, "__cog_listener__")
191-
except AttributeError:
192-
continue
193-
else:
189+
if hasattr(value, "__cog_listener__"):
194190
if elem.startswith(("cog_", "bot_")):
195191
raise TypeError(no_bot_cog.format(base, elem))
196192
listeners[elem] = value
193+
else:
194+
continue
197195

198196
new_cls.__cog_commands__ = list(commands.values())
199197

@@ -711,7 +709,7 @@ def _remove_module_references(self, name: str) -> None:
711709

712710
def _call_module_finalizers(self, lib: types.ModuleType, key: str) -> None:
713711
try:
714-
func = getattr(lib, "teardown")
712+
func = lib.teardown
715713
except AttributeError:
716714
pass
717715
else:
@@ -738,10 +736,10 @@ def _load_from_module_spec(self, spec: importlib.machinery.ModuleSpec, key: str)
738736
raise errors.ExtensionFailed(key, e) from e
739737

740738
try:
741-
setup = getattr(lib, "setup")
742-
except AttributeError:
739+
setup = lib.setup
740+
except AttributeError as e:
743741
del sys.modules[key]
744-
raise errors.NoEntryPointError(key)
742+
raise errors.NoEntryPointError(key) from e
745743

746744
try:
747745
setup(self)
@@ -756,8 +754,8 @@ def _load_from_module_spec(self, spec: importlib.machinery.ModuleSpec, key: str)
756754
def _resolve_name(self, name: str, package: str | None) -> str:
757755
try:
758756
return importlib.util.resolve_name(name, package)
759-
except ImportError:
760-
raise errors.ExtensionNotFound(name)
757+
except ImportError as e:
758+
raise errors.ExtensionNotFound(name) from e
761759

762760
@overload
763761
def load_extension(

discord/commands/core.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -763,8 +763,8 @@ def _check_required_params(self, params):
763763
for p in required_params:
764764
try:
765765
next(params)
766-
except StopIteration:
767-
raise ClientException(f'Callback for {self.name} command is missing "{p}" parameter.')
766+
except StopIteration as e:
767+
raise ClientException(f'Callback for {self.name} command is missing "{p}" parameter.') from e
768768

769769
return params
770770

@@ -849,7 +849,7 @@ def _match_option_param_names(self, params, options):
849849
lambda o, a: o.input_type == SlashCommandOptionType.string
850850
and o.converter is not None, # pass on converters
851851
lambda o, a: isinstance(o.input_type, SlashCommandOptionType), # pass on slash cmd option type enums
852-
lambda o, a: isinstance(o._raw_type, tuple) and a == Union[o._raw_type], # type: ignore # union types
852+
lambda o, a: isinstance(o._raw_type, tuple) and a == Union[o._raw_type], # type: ignore # union types # noqa: UP007
853853
lambda o, a: self._is_typing_optional(a) and not o.required and o._raw_type in a.__args__, # optional
854854
lambda o, a: isinstance(a, type) and issubclass(a, o._raw_type), # 'normal' types
855855
]
@@ -858,8 +858,8 @@ def _match_option_param_names(self, params, options):
858858
_validate_descriptions(o)
859859
try:
860860
p_name, p_obj = next(params)
861-
except StopIteration: # not enough params for all the options
862-
raise ClientException("Too many arguments passed to the options kwarg.")
861+
except StopIteration as e: # not enough params for all the options
862+
raise ClientException("Too many arguments passed to the options kwarg.") from e
863863
p_obj = p_obj.annotation
864864

865865
if not any(check(o, p_obj) for check in check_annotations):
@@ -936,7 +936,8 @@ async def _invoke(self, ctx: ApplicationContext) -> None:
936936
# TODO: Parse the args better
937937
kwargs = {}
938938
for arg in ctx.interaction.data.get("options", []):
939-
op = find(lambda x: x.name == arg["name"], self.options)
939+
# name is used because loop variables leak in surrounding scope
940+
op = find(lambda x, name=arg["name"]: x.name == name, self.options)
940941
if op is None:
941942
continue
942943
arg = arg["value"]
@@ -1021,7 +1022,8 @@ async def _invoke(self, ctx: ApplicationContext) -> None:
10211022
arg = op._raw_type(int(arg))
10221023
except ValueError:
10231024
arg = op._raw_type(arg)
1024-
elif choice := find(lambda c: c.value == arg, op.choices):
1025+
# _arg is used because loop variables leak in surrounding scope
1026+
elif choice := find(lambda c, _arg=arg: c.value == _arg, op.choices):
10251027
arg = getattr(op._raw_type, choice.name)
10261028

10271029
kwargs[op._parameter_name] = arg
@@ -1042,7 +1044,8 @@ async def invoke_autocomplete_callback(self, ctx: AutocompleteContext):
10421044

10431045
for op in ctx.interaction.data.get("options", []):
10441046
if op.get("focused", False):
1045-
option = find(lambda o: o.name == op["name"], self.options)
1047+
# op_name is used because loop variables leak in surrounding scope
1048+
option = find(lambda o, op_name=op["name"]: o.name == op_name, self.options)
10461049
values.update({i["name"]: i["value"] for i in ctx.interaction.data["options"]})
10471050
ctx.command = self
10481051
ctx.focused = option
@@ -1155,7 +1158,7 @@ def __new__(cls, *args, **kwargs) -> SlashCommandGroup:
11551158
self.__original_kwargs__ = kwargs.copy()
11561159

11571160
self.__initial_commands__ = []
1158-
for i, c in cls.__dict__.items():
1161+
for _, c in cls.__dict__.items():
11591162
if isinstance(c, type) and SlashCommandGroup in c.__bases__:
11601163
c = c(
11611164
c.__name__,
@@ -1587,15 +1590,15 @@ def validate_parameters(self):
15871590
# next we have the 'ctx' as the next parameter
15881591
try:
15891592
next(params)
1590-
except StopIteration:
1591-
raise ClientException(f'Callback for {self.name} command is missing "ctx" parameter.')
1593+
except StopIteration as e:
1594+
raise ClientException(f'Callback for {self.name} command is missing "ctx" parameter.') from e
15921595

15931596
# next we have the 'user/message' as the next parameter
15941597
try:
15951598
next(params)
1596-
except StopIteration:
1599+
except StopIteration as e:
15971600
cmd = "user" if type(self) == UserCommand else "message"
1598-
raise ClientException(f'Callback for {self.name} command is missing "{cmd}" parameter.')
1601+
raise ClientException(f'Callback for {self.name} command is missing "{cmd}" parameter.') from e
15991602

16001603
# next there should be no more parameters
16011604
try:

discord/commands/options.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,24 +52,24 @@
5252
from ..role import Role
5353
from ..user import User
5454

55-
InputType = Union[
56-
Type[str],
57-
Type[bool],
58-
Type[int],
59-
Type[float],
60-
Type[GuildChannel],
61-
Type[Thread],
62-
Type[Member],
63-
Type[User],
64-
Type[Attachment],
65-
Type[Role],
66-
Type[Mentionable],
67-
SlashCommandOptionType,
68-
Converter,
69-
Type[Converter],
70-
Type[Enum],
71-
Type[DiscordEnum],
72-
]
55+
InputType = (
56+
Type[str]
57+
| Type[bool]
58+
| Type[int]
59+
| Type[float]
60+
| Type[GuildChannel]
61+
| Type[Thread]
62+
| Type[Member]
63+
| Type[User]
64+
| Type[Attachment]
65+
| Type[Role]
66+
| Type[Mentionable]
67+
| SlashCommandOptionType
68+
| Converter
69+
| Type[Converter]
70+
| Type[Enum]
71+
| Type[DiscordEnum]
72+
)
7373

7474
__all__ = (
7575
"ThreadOption",
@@ -271,17 +271,17 @@ def __init__(self, input_type: InputType = str, /, description: str | None = Non
271271

272272
if self.input_type == SlashCommandOptionType.integer:
273273
minmax_types = (int, type(None))
274-
minmax_typehint = Optional[int]
274+
minmax_typehint = Optional[int] # noqa: UP045
275275
elif self.input_type == SlashCommandOptionType.number:
276276
minmax_types = (int, float, type(None))
277-
minmax_typehint = Optional[Union[int, float]]
277+
minmax_typehint = Optional[int | float] # noqa: UP045
278278
else:
279279
minmax_types = (type(None),)
280280
minmax_typehint = type(None)
281281

282282
if self.input_type == SlashCommandOptionType.string:
283283
minmax_length_types = (int, type(None))
284-
minmax_length_typehint = Optional[int]
284+
minmax_length_typehint = Optional[int] # noqa: UP045
285285
else:
286286
minmax_length_types = (type(None),)
287287
minmax_length_typehint = type(None)

0 commit comments

Comments
 (0)