Skip to content

Commit c43727b

Browse files
Middledotpre-commit-ci[bot]BobDotComplun1331Lulalaby
authored
feat(ext.bridge): add walk command functions & dynamically fetch attrs in commands variants (#1867)
* feat(ext.bridge): walk command functions * fix(ext.bridge): dynamically fetch attributes ... on bridge commands * chore(changlog): add entry * chore(ext.bridge): add docs * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * use shorter Iterator return type As mentioned in https://docs.python.org/3.11/library/typing.html#typing.Generator, the Iterable and Iterator types can also be used in generator functions * fix deprecated types * finish changes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * refactor: remove comment * fix(ext.bridge): re-add code for l10n set-ing * feat(ext.bridge): dynamic set * changelog: clarify * style(pre-commit): auto fixes from pre-commit.com hooks * fix: I found a fix * style(pre-commit): auto fixes from pre-commit.com hooks --------- Signed-off-by: Middledot <[email protected]> Signed-off-by: plun1331 <[email protected]> Signed-off-by: Lala Sabathil <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: BobDotCom <[email protected]> Co-authored-by: plun1331 <[email protected]> Co-authored-by: Lala Sabathil <[email protected]>
1 parent d519e95 commit c43727b

File tree

3 files changed

+74
-12
lines changed

3 files changed

+74
-12
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ These changes are available on the `master` branch, but have not yet been releas
4949
- Added `view.parent` which is set when the view was sent by
5050
`interaction.response.send_message`.
5151
([#2036](https://github.com/Pycord-Development/pycord/pull/2036))
52+
- Added functions (`bridge.Bot.walk_bridge_commands` &
53+
`BridgeCommandGroup.walk_commands`) to cycle through all bridge commands and their
54+
children/subcommands.
55+
([#1867](https://github.com/Pycord-Development/pycord/pull/1867))
5256

5357
### Changed
5458

@@ -62,6 +66,8 @@ These changes are available on the `master` branch, but have not yet been releas
6266
([#2025](https://github.com/Pycord-Development/pycord/pull/2025))
6367
- Store `view.message` on receiving Interaction for a component.
6468
([#2036](https://github.com/Pycord-Development/pycord/pull/2036))
69+
- Attributes shared between ext and slash commands are now dynamically fetched on bridge
70+
commands. ([#1867](https://github.com/Pycord-Development/pycord/pull/1867))
6571

6672
### Removed
6773

discord/ext/bridge/bot.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from __future__ import annotations
2626

2727
from abc import ABC
28+
from collections.abc import Iterator
2829

2930
from discord.commands import ApplicationContext
3031
from discord.errors import CheckFailure, DiscordException
@@ -60,6 +61,21 @@ def bridge_commands(self) -> list[BridgeCommand | BridgeCommandGroup]:
6061

6162
return cmds
6263

64+
def walk_bridge_commands(
65+
self,
66+
) -> Iterator[BridgeCommand | BridgeCommandGroup]:
67+
"""An iterator that recursively walks through all the bot's bridge commands.
68+
69+
Yields
70+
------
71+
Union[:class:`.BridgeCommand`, :class:`.BridgeCommandGroup`]
72+
A bridge command or bridge group of the bot.
73+
"""
74+
for cmd in self._bridge_commands:
75+
yield cmd
76+
if isinstance(cmd, BridgeCommandGroup):
77+
yield from cmd.walk_commands()
78+
6379
async def get_application_context(
6480
self, interaction: Interaction, cls=None
6581
) -> BridgeApplicationContext:

discord/ext/bridge/core.py

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from __future__ import annotations
2626

2727
import inspect
28+
from collections.abc import Iterator
2829
from typing import TYPE_CHECKING, Any, Callable
2930

3031
import discord.commands.options
@@ -38,7 +39,7 @@
3839
SlashCommandOptionType,
3940
)
4041

41-
from ...utils import filter_params, find, get
42+
from ...utils import MISSING, find, get
4243
from ..commands import BadArgument
4344
from ..commands import Bot as ExtBot
4445
from ..commands import (
@@ -156,6 +157,8 @@ class BridgeCommand:
156157
The prefix-based version of this bridge command.
157158
"""
158159

160+
__special_attrs__ = ["slash_variant", "ext_variant", "parent"]
161+
159162
def __init__(self, callback, **kwargs):
160163
self.parent = kwargs.pop("parent", None)
161164
self.slash_variant: BridgeSlashCommand = kwargs.pop(
@@ -166,13 +169,10 @@ def __init__(self, callback, **kwargs):
166169
) or BridgeExtCommand(callback, **kwargs)
167170

168171
@property
169-
def name_localizations(self) -> dict[str, str]:
172+
def name_localizations(self) -> dict[str, str] | None:
170173
"""Returns name_localizations from :attr:`slash_variant`
171-
172174
You can edit/set name_localizations directly with
173-
174175
.. code-block:: python3
175-
176176
bridge_command.name_localizations["en-UK"] = ... # or any other locale
177177
# or
178178
bridge_command.name_localizations = {"en-UK": ..., "fr-FR": ...}
@@ -184,13 +184,10 @@ def name_localizations(self, value):
184184
self.slash_variant.name_localizations = value
185185

186186
@property
187-
def description_localizations(self) -> dict[str, str]:
187+
def description_localizations(self) -> dict[str, str] | None:
188188
"""Returns description_localizations from :attr:`slash_variant`
189-
190189
You can edit/set description_localizations directly with
191-
192190
.. code-block:: python3
193-
194191
bridge_command.description_localizations["en-UK"] = ... # or any other locale
195192
# or
196193
bridge_command.description_localizations = {"en-UK": ..., "fr-FR": ...}
@@ -201,9 +198,34 @@ def description_localizations(self) -> dict[str, str]:
201198
def description_localizations(self, value):
202199
self.slash_variant.description_localizations = value
203200

204-
@property
205-
def qualified_name(self) -> str:
206-
return self.slash_variant.qualified_name
201+
def __getattribute__(self, name):
202+
try:
203+
# first, look for the attribute on the bridge command
204+
return super().__getattribute__(name)
205+
except AttributeError as e:
206+
# if it doesn't exist, check this list, if the name of
207+
# the parameter is here
208+
if name is self.__special_attrs__:
209+
raise e
210+
211+
# looks up the result in the variants.
212+
# slash cmd prioritized
213+
result = getattr(self.slash_variant, name, MISSING)
214+
try:
215+
if result is MISSING:
216+
return getattr(self.ext_variant, name)
217+
return result
218+
except AttributeError:
219+
raise AttributeError(
220+
f"'{self.__class__.__name__}' object has no attribute '{name}'"
221+
)
222+
223+
def __setattr__(self, name, value) -> None:
224+
if name not in self.__special_attrs__:
225+
setattr(self.slash_variant, name, value)
226+
setattr(self.ext_variant, name, value)
227+
228+
return super().__setattr__(name, value)
207229

208230
def add_to(self, bot: ExtBot) -> None:
209231
"""Adds the command to a bot. This method is inherited by :class:`.BridgeCommandGroup`.
@@ -321,6 +343,14 @@ class BridgeCommandGroup(BridgeCommand):
321343
If :func:`map_to` is used, the mapped slash command.
322344
"""
323345

346+
__special_attrs__ = [
347+
"slash_variant",
348+
"ext_variant",
349+
"parent",
350+
"subcommands",
351+
"mapped",
352+
]
353+
324354
ext_variant: BridgeExtGroup
325355
slash_variant: BridgeSlashGroup
326356

@@ -341,6 +371,16 @@ def __init__(self, callback, *args, **kwargs):
341371
kwargs.update(map_to)
342372
self.mapped = self.slash_variant.command(**kwargs)(callback)
343373

374+
def walk_commands(self) -> Iterator[BridgeCommand]:
375+
"""An iterator that recursively walks through all the bridge group's subcommands.
376+
377+
Yields
378+
------
379+
:class:`.BridgeCommand`
380+
A bridge command of this bridge group.
381+
"""
382+
yield from self.subcommands
383+
344384
def command(self, *args, **kwargs):
345385
"""A decorator to register a function as a subcommand.
346386

0 commit comments

Comments
 (0)