mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-06-07 20:28:38 +00:00
Revert "Infer select type from callback annotation
This commit is contained in:
parent
b671958e11
commit
7cf3cd51a5
@ -22,7 +22,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|||||||
DEALINGS IN THE SOFTWARE.
|
DEALINGS IN THE SOFTWARE.
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
from typing import List, Literal, Optional, TYPE_CHECKING, Tuple, Type, TypeVar, Callable, Union, Dict
|
from typing import List, Literal, Optional, TYPE_CHECKING, Tuple, Type, TypeVar, Callable, Union, Dict, overload
|
||||||
from contextvars import ContextVar
|
from contextvars import ContextVar
|
||||||
import inspect
|
import inspect
|
||||||
import os
|
import os
|
||||||
@ -31,8 +31,11 @@ from .item import Item, ItemCallbackType
|
|||||||
from ..enums import ChannelType, ComponentType
|
from ..enums import ChannelType, ComponentType
|
||||||
from ..partial_emoji import PartialEmoji
|
from ..partial_emoji import PartialEmoji
|
||||||
from ..emoji import Emoji
|
from ..emoji import Emoji
|
||||||
from ..utils import MISSING, resolve_annotation
|
from ..utils import MISSING
|
||||||
from ..components import SelectOption, SelectMenu
|
from ..components import (
|
||||||
|
SelectOption,
|
||||||
|
SelectMenu,
|
||||||
|
)
|
||||||
from ..app_commands.namespace import Namespace
|
from ..app_commands.namespace import Namespace
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
@ -69,6 +72,11 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
V = TypeVar('V', bound='View', covariant=True)
|
V = TypeVar('V', bound='View', covariant=True)
|
||||||
BaseSelectT = TypeVar('BaseSelectT', bound='BaseSelect')
|
BaseSelectT = TypeVar('BaseSelectT', bound='BaseSelect')
|
||||||
|
SelectT = TypeVar('SelectT', bound='Select')
|
||||||
|
UserSelectT = TypeVar('UserSelectT', bound='UserSelect')
|
||||||
|
RoleSelectT = TypeVar('RoleSelectT', bound='RoleSelect')
|
||||||
|
ChannelSelectT = TypeVar('ChannelSelectT', bound='ChannelSelect')
|
||||||
|
MentionableSelectT = TypeVar('MentionableSelectT', bound='MentionableSelect')
|
||||||
SelectCallbackDecorator: TypeAlias = Callable[[ItemCallbackType[V, BaseSelectT]], BaseSelectT]
|
SelectCallbackDecorator: TypeAlias = Callable[[ItemCallbackType[V, BaseSelectT]], BaseSelectT]
|
||||||
|
|
||||||
selected_values: ContextVar[Dict[str, List[PossibleValue]]] = ContextVar('selected_values')
|
selected_values: ContextVar[Dict[str, List[PossibleValue]]] = ContextVar('selected_values')
|
||||||
@ -662,32 +670,89 @@ class ChannelSelect(BaseSelect[V]):
|
|||||||
return super().values # type: ignore
|
return super().values # type: ignore
|
||||||
|
|
||||||
|
|
||||||
def _get_select_callback_parameter(func: ItemCallbackType[V, BaseSelectT]) -> Type[BaseSelect]:
|
@overload
|
||||||
params = inspect.signature(func).parameters
|
def select(
|
||||||
if len(params) != 3:
|
*,
|
||||||
raise TypeError(
|
cls: Type[SelectT] = Select,
|
||||||
f'select menu callback {func.__qualname__!r} requires 3 parameters, '
|
options: List[SelectOption] = MISSING,
|
||||||
'the view instance (self), the discord.Interaction, and the select menu itself'
|
channel_types: List[ChannelType] = ...,
|
||||||
)
|
placeholder: Optional[str] = ...,
|
||||||
|
custom_id: str = ...,
|
||||||
|
min_values: int = ...,
|
||||||
|
max_values: int = ...,
|
||||||
|
disabled: bool = ...,
|
||||||
|
row: Optional[int] = ...,
|
||||||
|
) -> SelectCallbackDecorator[V, SelectT]:
|
||||||
|
...
|
||||||
|
|
||||||
iterator = iter(params.values())
|
|
||||||
parameter = next(iterator)
|
|
||||||
for parameter in iterator:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if parameter.annotation is parameter.empty:
|
@overload
|
||||||
return Select
|
def select(
|
||||||
|
*,
|
||||||
|
cls: Type[UserSelectT],
|
||||||
|
options: List[SelectOption] = MISSING,
|
||||||
|
channel_types: List[ChannelType] = ...,
|
||||||
|
placeholder: Optional[str] = ...,
|
||||||
|
custom_id: str = ...,
|
||||||
|
min_values: int = ...,
|
||||||
|
max_values: int = ...,
|
||||||
|
disabled: bool = ...,
|
||||||
|
row: Optional[int] = ...,
|
||||||
|
) -> SelectCallbackDecorator[V, UserSelectT]:
|
||||||
|
...
|
||||||
|
|
||||||
resolved = resolve_annotation(parameter.annotation, func.__globals__, func.__globals__, {})
|
|
||||||
origin = getattr(resolved, '__origin__', resolved)
|
@overload
|
||||||
if origin is BaseSelect or not isinstance(origin, type) or not issubclass(origin, BaseSelect):
|
def select(
|
||||||
return Select
|
*,
|
||||||
return origin
|
cls: Type[RoleSelectT],
|
||||||
|
options: List[SelectOption] = MISSING,
|
||||||
|
channel_types: List[ChannelType] = ...,
|
||||||
|
placeholder: Optional[str] = ...,
|
||||||
|
custom_id: str = ...,
|
||||||
|
min_values: int = ...,
|
||||||
|
max_values: int = ...,
|
||||||
|
disabled: bool = ...,
|
||||||
|
row: Optional[int] = ...,
|
||||||
|
) -> SelectCallbackDecorator[V, RoleSelectT]:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def select(
|
||||||
|
*,
|
||||||
|
cls: Type[ChannelSelectT],
|
||||||
|
options: List[SelectOption] = MISSING,
|
||||||
|
channel_types: List[ChannelType] = ...,
|
||||||
|
placeholder: Optional[str] = ...,
|
||||||
|
custom_id: str = ...,
|
||||||
|
min_values: int = ...,
|
||||||
|
max_values: int = ...,
|
||||||
|
disabled: bool = ...,
|
||||||
|
row: Optional[int] = ...,
|
||||||
|
) -> SelectCallbackDecorator[V, ChannelSelectT]:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def select(
|
||||||
|
*,
|
||||||
|
cls: Type[MentionableSelectT],
|
||||||
|
options: List[SelectOption] = MISSING,
|
||||||
|
channel_types: List[ChannelType] = MISSING,
|
||||||
|
placeholder: Optional[str] = ...,
|
||||||
|
custom_id: str = ...,
|
||||||
|
min_values: int = ...,
|
||||||
|
max_values: int = ...,
|
||||||
|
disabled: bool = ...,
|
||||||
|
row: Optional[int] = ...,
|
||||||
|
) -> SelectCallbackDecorator[V, MentionableSelectT]:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
def select(
|
def select(
|
||||||
*,
|
*,
|
||||||
cls: Type[BaseSelectT] = Select if TYPE_CHECKING else MISSING,
|
cls: Type[BaseSelectT] = Select,
|
||||||
options: List[SelectOption] = MISSING,
|
options: List[SelectOption] = MISSING,
|
||||||
channel_types: List[ChannelType] = MISSING,
|
channel_types: List[ChannelType] = MISSING,
|
||||||
placeholder: Optional[str] = None,
|
placeholder: Optional[str] = None,
|
||||||
@ -723,9 +788,6 @@ def select(
|
|||||||
.. versionchanged:: 2.1
|
.. versionchanged:: 2.1
|
||||||
Added the following keyword-arguments: ``cls``, ``channel_types``
|
Added the following keyword-arguments: ``cls``, ``channel_types``
|
||||||
|
|
||||||
.. versionchanged:: 2.2
|
|
||||||
Now infers ``cls`` based on the callback if not supplied.
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
---------
|
---------
|
||||||
.. code-block:: python3
|
.. code-block:: python3
|
||||||
@ -740,11 +802,10 @@ def select(
|
|||||||
------------
|
------------
|
||||||
cls: Union[Type[:class:`discord.ui.Select`], Type[:class:`discord.ui.UserSelect`], Type[:class:`discord.ui.RoleSelect`], \
|
cls: Union[Type[:class:`discord.ui.Select`], Type[:class:`discord.ui.UserSelect`], Type[:class:`discord.ui.RoleSelect`], \
|
||||||
Type[:class:`discord.ui.MentionableSelect`], Type[:class:`discord.ui.ChannelSelect`]]
|
Type[:class:`discord.ui.MentionableSelect`], Type[:class:`discord.ui.ChannelSelect`]]
|
||||||
The class to use for the select menu. Defaults to inferring the type from the
|
The class to use for the select menu. Defaults to :class:`discord.ui.Select`. You can use other
|
||||||
callback if available; otherwise defaults to :class:`discord.ui.Select`.
|
select types to display different select menus to the user. See the table above for the different
|
||||||
You can use other select types to display different select menus to the user.
|
values you can get from each select type. Subclasses work as well, however the callback in the subclass will
|
||||||
See the table above for the different values you can get from each select type.
|
get overridden.
|
||||||
Subclasses work as well, however the callback in the subclass will get overridden.
|
|
||||||
placeholder: Optional[:class:`str`]
|
placeholder: Optional[:class:`str`]
|
||||||
The placeholder text that is shown if nothing is selected, if any.
|
The placeholder text that is shown if nothing is selected, if any.
|
||||||
custom_id: :class:`str`
|
custom_id: :class:`str`
|
||||||
@ -775,13 +836,10 @@ def select(
|
|||||||
def decorator(func: ItemCallbackType[V, BaseSelectT]) -> ItemCallbackType[V, BaseSelectT]:
|
def decorator(func: ItemCallbackType[V, BaseSelectT]) -> ItemCallbackType[V, BaseSelectT]:
|
||||||
if not inspect.iscoroutinefunction(func):
|
if not inspect.iscoroutinefunction(func):
|
||||||
raise TypeError('select function must be a coroutine function')
|
raise TypeError('select function must be a coroutine function')
|
||||||
if cls is MISSING:
|
callback_cls = getattr(cls, '__origin__', cls)
|
||||||
callback_cls = _get_select_callback_parameter(func)
|
|
||||||
else:
|
|
||||||
callback_cls = getattr(cls, '__origin__', cls)
|
|
||||||
if not issubclass(callback_cls, BaseSelect):
|
if not issubclass(callback_cls, BaseSelect):
|
||||||
supported_classes = ", ".join(["ChannelSelect", "MentionableSelect", "RoleSelect", "Select", "UserSelect"])
|
supported_classes = ", ".join(["ChannelSelect", "MentionableSelect", "RoleSelect", "Select", "UserSelect"])
|
||||||
raise TypeError(f'cls must be one of {supported_classes} or a subclass of one of them, not {callback_cls!r}.')
|
raise TypeError(f'cls must be one of {supported_classes} or a subclass of one of them, not {cls!r}.')
|
||||||
|
|
||||||
func.__discord_ui_model_type__ = callback_cls
|
func.__discord_ui_model_type__ = callback_cls
|
||||||
func.__discord_ui_model_kwargs__ = {
|
func.__discord_ui_model_kwargs__ = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user