Skip to content

Commit

Permalink
feat(ext.bridge): add walk command functions & dynamically fetch attr…
Browse files Browse the repository at this point in the history
…s 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 <78228142+Middledot@users.noreply.github.com>
Signed-off-by: plun1331 <49261529+plun1331@users.noreply.github.com>
Signed-off-by: Lala Sabathil <lala@pycord.dev>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: BobDotCom <71356958+BobDotCom@users.noreply.github.com>
Co-authored-by: plun1331 <49261529+plun1331@users.noreply.github.com>
Co-authored-by: Lala Sabathil <lala@pycord.dev>
  • Loading branch information
5 people committed May 8, 2023
1 parent d519e95 commit c43727b
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 12 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ These changes are available on the `master` branch, but have not yet been releas
- Added `view.parent` which is set when the view was sent by
`interaction.response.send_message`.
([#2036](https://github.com/Pycord-Development/pycord/pull/2036))
- Added functions (`bridge.Bot.walk_bridge_commands` &
`BridgeCommandGroup.walk_commands`) to cycle through all bridge commands and their
children/subcommands.
([#1867](https://github.com/Pycord-Development/pycord/pull/1867))

### Changed

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

### Removed

Expand Down
16 changes: 16 additions & 0 deletions discord/ext/bridge/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from __future__ import annotations

from abc import ABC
from collections.abc import Iterator

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

return cmds

def walk_bridge_commands(
self,
) -> Iterator[BridgeCommand | BridgeCommandGroup]:
"""An iterator that recursively walks through all the bot's bridge commands.
Yields
------
Union[:class:`.BridgeCommand`, :class:`.BridgeCommandGroup`]
A bridge command or bridge group of the bot.
"""
for cmd in self._bridge_commands:
yield cmd
if isinstance(cmd, BridgeCommandGroup):
yield from cmd.walk_commands()

async def get_application_context(
self, interaction: Interaction, cls=None
) -> BridgeApplicationContext:
Expand Down
64 changes: 52 additions & 12 deletions discord/ext/bridge/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from __future__ import annotations

import inspect
from collections.abc import Iterator
from typing import TYPE_CHECKING, Any, Callable

import discord.commands.options
Expand All @@ -38,7 +39,7 @@
SlashCommandOptionType,
)

from ...utils import filter_params, find, get
from ...utils import MISSING, find, get
from ..commands import BadArgument
from ..commands import Bot as ExtBot
from ..commands import (
Expand Down Expand Up @@ -156,6 +157,8 @@ class BridgeCommand:
The prefix-based version of this bridge command.
"""

__special_attrs__ = ["slash_variant", "ext_variant", "parent"]

def __init__(self, callback, **kwargs):
self.parent = kwargs.pop("parent", None)
self.slash_variant: BridgeSlashCommand = kwargs.pop(
Expand All @@ -166,13 +169,10 @@ def __init__(self, callback, **kwargs):
) or BridgeExtCommand(callback, **kwargs)

@property
def name_localizations(self) -> dict[str, str]:
def name_localizations(self) -> dict[str, str] | None:
"""Returns name_localizations from :attr:`slash_variant`
You can edit/set name_localizations directly with
.. code-block:: python3
bridge_command.name_localizations["en-UK"] = ... # or any other locale
# or
bridge_command.name_localizations = {"en-UK": ..., "fr-FR": ...}
Expand All @@ -184,13 +184,10 @@ def name_localizations(self, value):
self.slash_variant.name_localizations = value

@property
def description_localizations(self) -> dict[str, str]:
def description_localizations(self) -> dict[str, str] | None:
"""Returns description_localizations from :attr:`slash_variant`
You can edit/set description_localizations directly with
.. code-block:: python3
bridge_command.description_localizations["en-UK"] = ... # or any other locale
# or
bridge_command.description_localizations = {"en-UK": ..., "fr-FR": ...}
Expand All @@ -201,9 +198,34 @@ def description_localizations(self) -> dict[str, str]:
def description_localizations(self, value):
self.slash_variant.description_localizations = value

@property
def qualified_name(self) -> str:
return self.slash_variant.qualified_name
def __getattribute__(self, name):
try:
# first, look for the attribute on the bridge command
return super().__getattribute__(name)
except AttributeError as e:
# if it doesn't exist, check this list, if the name of
# the parameter is here
if name is self.__special_attrs__:
raise e

# looks up the result in the variants.
# slash cmd prioritized
result = getattr(self.slash_variant, name, MISSING)
try:
if result is MISSING:
return getattr(self.ext_variant, name)
return result
except AttributeError:
raise AttributeError(
f"'{self.__class__.__name__}' object has no attribute '{name}'"
)

def __setattr__(self, name, value) -> None:
if name not in self.__special_attrs__:
setattr(self.slash_variant, name, value)
setattr(self.ext_variant, name, value)

return super().__setattr__(name, value)

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

__special_attrs__ = [
"slash_variant",
"ext_variant",
"parent",
"subcommands",
"mapped",
]

ext_variant: BridgeExtGroup
slash_variant: BridgeSlashGroup

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

def walk_commands(self) -> Iterator[BridgeCommand]:
"""An iterator that recursively walks through all the bridge group's subcommands.
Yields
------
:class:`.BridgeCommand`
A bridge command of this bridge group.
"""
yield from self.subcommands

def command(self, *args, **kwargs):
"""A decorator to register a function as a subcommand.
Expand Down

0 comments on commit c43727b

Please sign in to comment.