From 4093ac01ca84fc434c606188816aea9ca467d126 Mon Sep 17 00:00:00 2001 From: shiftinv Date: Sat, 23 Sep 2023 14:21:55 +0200 Subject: [PATCH 1/5] test: update tests to check for regressions --- tests/ui/test_decorators.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tests/ui/test_decorators.py b/tests/ui/test_decorators.py index 86ecd65ba9..5fab1bb787 100644 --- a/tests/ui/test_decorators.py +++ b/tests/ui/test_decorators.py @@ -44,7 +44,7 @@ def test_default(self) -> None: assert func.__discord_ui_model_type__ is ui.StringSelect assert func.__discord_ui_model_kwargs__ == {"custom_id": "123"} - # from here on out we're only testing the button decorator, + # from here on out we're mostly only testing the button decorator, # as @ui.string_select etc. works identically @pytest.mark.parametrize("cls", [_CustomButton, _CustomButton[Any]]) @@ -64,7 +64,18 @@ def _test_typing_cls(self) -> None: this_should_not_work="h", # type: ignore ) - @pytest.mark.parametrize("cls", [123, int, ui.StringSelect]) - def test_cls_invalid(self, cls) -> None: - with pytest.raises(TypeError, match=r"cls argument must be"): - ui.button(cls=cls) # type: ignore + @pytest.mark.parametrize( + ("decorator", "invalid_cls"), + [ + (ui.button, ui.StringSelect), + (ui.string_select, ui.Button), + (ui.user_select, ui.Button), + (ui.role_select, ui.Button), + (ui.mentionable_select, ui.Button), + (ui.channel_select, ui.Button), + ], + ) + def test_cls_invalid(self, decorator, invalid_cls) -> None: + for cls in [123, int, invalid_cls]: + with pytest.raises(TypeError, match=r"cls argument must be"): + decorator(cls=cls) From d166ec4fcc240f11ed0130a982018cbfb446f5dd Mon Sep 17 00:00:00 2001 From: shiftinv Date: Sat, 23 Sep 2023 14:23:01 +0200 Subject: [PATCH 2/5] fix(ui): don't require `cls` argument in select decorators to be positional --- disnake/ui/select/channel.py | 4 +--- disnake/ui/select/mentionable.py | 4 +--- disnake/ui/select/role.py | 4 +--- disnake/ui/select/string.py | 4 +--- disnake/ui/select/user.py | 4 +--- 5 files changed, 5 insertions(+), 15 deletions(-) diff --git a/disnake/ui/select/channel.py b/disnake/ui/select/channel.py index a455172799..1d4ce25f9e 100644 --- a/disnake/ui/select/channel.py +++ b/disnake/ui/select/channel.py @@ -168,9 +168,7 @@ def channel_select( def channel_select( - cls: Type[Object[S_co, P]] = ChannelSelect[Any], - /, - **kwargs: Any, + cls: Type[Object[S_co, P]] = ChannelSelect[Any], **kwargs: Any ) -> Callable[[ItemCallbackType[S_co]], DecoratedItem[S_co]]: """A decorator that attaches a channel select menu to a component. diff --git a/disnake/ui/select/mentionable.py b/disnake/ui/select/mentionable.py index c9e5802f78..6d34a98804 100644 --- a/disnake/ui/select/mentionable.py +++ b/disnake/ui/select/mentionable.py @@ -144,9 +144,7 @@ def mentionable_select( def mentionable_select( - cls: Type[Object[S_co, P]] = MentionableSelect[Any], - /, - **kwargs: Any, + cls: Type[Object[S_co, P]] = MentionableSelect[Any], **kwargs: Any ) -> Callable[[ItemCallbackType[S_co]], DecoratedItem[S_co]]: """A decorator that attaches a mentionable (user/member/role) select menu to a component. diff --git a/disnake/ui/select/role.py b/disnake/ui/select/role.py index 4644b9a660..13e102292e 100644 --- a/disnake/ui/select/role.py +++ b/disnake/ui/select/role.py @@ -142,9 +142,7 @@ def role_select( def role_select( - cls: Type[Object[S_co, P]] = RoleSelect[Any], - /, - **kwargs: Any, + cls: Type[Object[S_co, P]] = RoleSelect[Any], **kwargs: Any ) -> Callable[[ItemCallbackType[S_co]], DecoratedItem[S_co]]: """A decorator that attaches a role select menu to a component. diff --git a/disnake/ui/select/string.py b/disnake/ui/select/string.py index 0a975c2aa8..3b259efea3 100644 --- a/disnake/ui/select/string.py +++ b/disnake/ui/select/string.py @@ -268,9 +268,7 @@ def string_select( def string_select( - cls: Type[Object[S_co, P]] = StringSelect[Any], - /, - **kwargs: Any, + cls: Type[Object[S_co, P]] = StringSelect[Any], **kwargs: Any ) -> Callable[[ItemCallbackType[S_co]], DecoratedItem[S_co]]: """A decorator that attaches a string select menu to a component. diff --git a/disnake/ui/select/user.py b/disnake/ui/select/user.py index 9a995739fc..298c409d8d 100644 --- a/disnake/ui/select/user.py +++ b/disnake/ui/select/user.py @@ -143,9 +143,7 @@ def user_select( def user_select( - cls: Type[Object[S_co, P]] = UserSelect[Any], - /, - **kwargs: Any, + cls: Type[Object[S_co, P]] = UserSelect[Any], **kwargs: Any ) -> Callable[[ItemCallbackType[S_co]], DecoratedItem[S_co]]: """A decorator that attaches a user select menu to a component. From c96151182e83903e6ecd54a3aea57451c7366ffd Mon Sep 17 00:00:00 2001 From: shiftinv Date: Sat, 23 Sep 2023 14:28:01 +0200 Subject: [PATCH 3/5] docs: add changelog entry --- changelog/1111.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/1111.bugfix.rst diff --git a/changelog/1111.bugfix.rst b/changelog/1111.bugfix.rst new file mode 100644 index 0000000000..4efa8693ed --- /dev/null +++ b/changelog/1111.bugfix.rst @@ -0,0 +1 @@ +Allow ``cls`` argument in select menu decorators (e.g. :func`ui.string_select`) to be specified by keyword instead of being positional-only. From daf775756509d63642d43bce6f9f48ea34f3265d Mon Sep 17 00:00:00 2001 From: shiftinv Date: Sat, 23 Sep 2023 14:28:33 +0200 Subject: [PATCH 4/5] docs: c o n s i s t e n c y --- docs/api/ui.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/ui.rst b/docs/api/ui.rst index 85c85e37c4..c7c061f137 100644 --- a/docs/api/ui.rst +++ b/docs/api/ui.rst @@ -128,7 +128,7 @@ TextInput Functions --------- -.. autofunction:: button(cls=Button, *, style=ButtonStyle.secondary, label=None, disabled=False, custom_id=..., url=None, emoji=None, row=None) +.. autofunction:: button(cls=Button, *, custom_id=..., style=ButtonStyle.secondary, label=None, disabled=False, url=None, emoji=None, row=None) :decorator: .. autofunction:: string_select(cls=StringSelect, *, custom_id=..., placeholder=None, min_values=1, max_values=1, options=..., disabled=False, row=None) From 77223557d6f5a715d77a4454e20d2746467ce0f3 Mon Sep 17 00:00:00 2001 From: shiftinv Date: Sat, 23 Sep 2023 14:30:01 +0200 Subject: [PATCH 5/5] docs: fix typo --- disnake/ui/button.py | 2 +- disnake/ui/select/channel.py | 2 +- disnake/ui/select/mentionable.py | 2 +- disnake/ui/select/role.py | 2 +- disnake/ui/select/string.py | 2 +- disnake/ui/select/user.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/disnake/ui/button.py b/disnake/ui/button.py index 8bb1e60ff2..d5e1fc7708 100644 --- a/disnake/ui/button.py +++ b/disnake/ui/button.py @@ -295,7 +295,7 @@ def button( ---------- cls: Type[:class:`Button`] The button subclass to create an instance of. If provided, the following parameters - described below do no apply. Instead, this decorator will accept the same keywords + described below do not apply. Instead, this decorator will accept the same keywords as the passed cls does. .. versionadded:: 2.6 diff --git a/disnake/ui/select/channel.py b/disnake/ui/select/channel.py index 1d4ce25f9e..a98472b547 100644 --- a/disnake/ui/select/channel.py +++ b/disnake/ui/select/channel.py @@ -185,7 +185,7 @@ def channel_select( ---------- cls: Type[:class:`ChannelSelect`] The select subclass to create an instance of. If provided, the following parameters - described below do no apply. Instead, this decorator will accept the same keywords + described below do not apply. Instead, this decorator will accept the same keywords as the passed cls does. placeholder: Optional[:class:`str`] The placeholder text that is shown if nothing is selected, if any. diff --git a/disnake/ui/select/mentionable.py b/disnake/ui/select/mentionable.py index 6d34a98804..4f0d591201 100644 --- a/disnake/ui/select/mentionable.py +++ b/disnake/ui/select/mentionable.py @@ -161,7 +161,7 @@ def mentionable_select( ---------- cls: Type[:class:`MentionableSelect`] The select subclass to create an instance of. If provided, the following parameters - described below do no apply. Instead, this decorator will accept the same keywords + described below do not apply. Instead, this decorator will accept the same keywords as the passed cls does. placeholder: Optional[:class:`str`] The placeholder text that is shown if nothing is selected, if any. diff --git a/disnake/ui/select/role.py b/disnake/ui/select/role.py index 13e102292e..69b1bcaa57 100644 --- a/disnake/ui/select/role.py +++ b/disnake/ui/select/role.py @@ -159,7 +159,7 @@ def role_select( ---------- cls: Type[:class:`RoleSelect`] The select subclass to create an instance of. If provided, the following parameters - described below do no apply. Instead, this decorator will accept the same keywords + described below do not apply. Instead, this decorator will accept the same keywords as the passed cls does. placeholder: Optional[:class:`str`] The placeholder text that is shown if nothing is selected, if any. diff --git a/disnake/ui/select/string.py b/disnake/ui/select/string.py index 3b259efea3..d38c9ea6ba 100644 --- a/disnake/ui/select/string.py +++ b/disnake/ui/select/string.py @@ -286,7 +286,7 @@ def string_select( ---------- cls: Type[:class:`StringSelect`] The select subclass to create an instance of. If provided, the following parameters - described below do no apply. Instead, this decorator will accept the same keywords + described below do not apply. Instead, this decorator will accept the same keywords as the passed cls does. .. versionadded:: 2.6 diff --git a/disnake/ui/select/user.py b/disnake/ui/select/user.py index 298c409d8d..179b9d6c74 100644 --- a/disnake/ui/select/user.py +++ b/disnake/ui/select/user.py @@ -160,7 +160,7 @@ def user_select( ---------- cls: Type[:class:`UserSelect`] The select subclass to create an instance of. If provided, the following parameters - described below do no apply. Instead, this decorator will accept the same keywords + described below do not apply. Instead, this decorator will accept the same keywords as the passed cls does. placeholder: Optional[:class:`str`] The placeholder text that is shown if nothing is selected, if any.