From 0a1a1472c4f11034c4da00919dde1068f624f45c Mon Sep 17 00:00:00 2001 From: EQUENOS <50338932+EQUENOS@users.noreply.github.com> Date: Sat, 30 Jul 2022 00:43:53 +0300 Subject: [PATCH 1/6] Fix app command copies --- disnake/ext/commands/base_core.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/disnake/ext/commands/base_core.py b/disnake/ext/commands/base_core.py index 1b430c6e89..c712d0caa9 100644 --- a/disnake/ext/commands/base_core.py +++ b/disnake/ext/commands/base_core.py @@ -26,6 +26,7 @@ import datetime import functools from abc import ABC +from copy import copy from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, TypeVar, Union, cast from disnake.app_commands import ApplicationCommand @@ -202,6 +203,8 @@ def _ensure_assignment_on_copy(self, other: AppCommandT) -> AppCommandT: if self._max_concurrency != other._max_concurrency: # _max_concurrency won't be None at this point other._max_concurrency = cast(MaxConcurrency, self._max_concurrency).copy() + if self.body != other.body: + other.body = copy(self.body) try: other.on_error = self.on_error From 8789ca8a0c9881a8a8a382c3f73214052292f227 Mon Sep 17 00:00:00 2001 From: EQUENOS <50338932+EQUENOS@users.noreply.github.com> Date: Sat, 30 Jul 2022 01:39:03 +0300 Subject: [PATCH 2/6] Create 678.bugfix.rst --- changelog/678.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/678.bugfix.rst diff --git a/changelog/678.bugfix.rst b/changelog/678.bugfix.rst new file mode 100644 index 0000000000..1ff55cfdb0 --- /dev/null +++ b/changelog/678.bugfix.rst @@ -0,0 +1 @@ +Make the :func:`.ext.commands.default_member_permissions` decorator always work in cogs. From b4a0d54b2bbc16daf76c9469da821243ac505993 Mon Sep 17 00:00:00 2001 From: EQUENOS <50338932+EQUENOS@users.noreply.github.com> Date: Wed, 3 Aug 2022 13:13:00 +0300 Subject: [PATCH 3/6] Copy only attrs that can be modified with decorators --- disnake/ext/commands/base_core.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/disnake/ext/commands/base_core.py b/disnake/ext/commands/base_core.py index c712d0caa9..f984cbbbc5 100644 --- a/disnake/ext/commands/base_core.py +++ b/disnake/ext/commands/base_core.py @@ -26,7 +26,6 @@ import datetime import functools from abc import ABC -from copy import copy from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, TypeVar, Union, cast from disnake.app_commands import ApplicationCommand @@ -203,8 +202,8 @@ def _ensure_assignment_on_copy(self, other: AppCommandT) -> AppCommandT: if self._max_concurrency != other._max_concurrency: # _max_concurrency won't be None at this point other._max_concurrency = cast(MaxConcurrency, self._max_concurrency).copy() - if self.body != other.body: - other.body = copy(self.body) + if self.body._default_member_permissions != other.body._default_member_permissions: + other.body._default_member_permissions = self.body._default_member_permissions try: other.on_error = self.on_error From 494d1af8395b04118b8d999680f10569ab17b165 Mon Sep 17 00:00:00 2001 From: EQUENOS <50338932+EQUENOS@users.noreply.github.com> Date: Sat, 20 Aug 2022 15:56:25 +0300 Subject: [PATCH 4/6] Better conditions in `_ensure_assignment_on_copy` --- disnake/ext/commands/base_core.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/disnake/ext/commands/base_core.py b/disnake/ext/commands/base_core.py index f984cbbbc5..a3dc3a5feb 100644 --- a/disnake/ext/commands/base_core.py +++ b/disnake/ext/commands/base_core.py @@ -202,8 +202,14 @@ def _ensure_assignment_on_copy(self, other: AppCommandT) -> AppCommandT: if self._max_concurrency != other._max_concurrency: # _max_concurrency won't be None at this point other._max_concurrency = cast(MaxConcurrency, self._max_concurrency).copy() + if self.body._default_member_permissions != other.body._default_member_permissions: - other.body._default_member_permissions = self.body._default_member_permissions + if "default_member_permissions" not in other.__original_kwargs__: + other.body._default_member_permissions = self.body._default_member_permissions + elif self.body._default_member_permissions is not None: + raise ValueError( + "Cannot set `default_member_permissions` in both decorator and slash_command_attrs" + ) try: other.on_error = self.on_error From 41536789320efa0cef3c2e22a7ada94b5e47e2a4 Mon Sep 17 00:00:00 2001 From: EQUENOS <50338932+EQUENOS@users.noreply.github.com> Date: Sun, 21 Aug 2022 19:55:32 +0300 Subject: [PATCH 5/6] Implement intended behavior for x_command_attrs --- disnake/ext/commands/base_core.py | 12 +++++------- disnake/ext/commands/ctx_menus_core.py | 8 +------- disnake/ext/commands/slash_core.py | 8 +------- 3 files changed, 7 insertions(+), 21 deletions(-) diff --git a/disnake/ext/commands/base_core.py b/disnake/ext/commands/base_core.py index 47f6f33cf1..5856b5dca4 100644 --- a/disnake/ext/commands/base_core.py +++ b/disnake/ext/commands/base_core.py @@ -215,13 +215,11 @@ def _ensure_assignment_on_copy(self, other: AppCommandT) -> AppCommandT: # _max_concurrency won't be None at this point other._max_concurrency = cast(MaxConcurrency, self._max_concurrency).copy() - if self.body._default_member_permissions != other.body._default_member_permissions: - if "default_member_permissions" not in other.__original_kwargs__: - other.body._default_member_permissions = self.body._default_member_permissions - elif self.body._default_member_permissions is not None: - raise ValueError( - "Cannot set `default_member_permissions` in both decorator and slash_command_attrs" - ) + if self.body._default_member_permissions != other.body._default_member_permissions and ( + "default_member_permissions" not in other.__original_kwargs__ + or self.body._default_member_permissions is not None + ): + other.body._default_member_permissions = self.body._default_member_permissions try: other.on_error = self.on_error diff --git a/disnake/ext/commands/ctx_menus_core.py b/disnake/ext/commands/ctx_menus_core.py index 10d791decb..cc90007065 100644 --- a/disnake/ext/commands/ctx_menus_core.py +++ b/disnake/ext/commands/ctx_menus_core.py @@ -208,15 +208,9 @@ def __init__( self.auto_sync: bool = True if auto_sync is None else auto_sync try: - default_perms: int = func.__default_member_permissions__ + default_member_permissions = func.__default_member_permissions__ except AttributeError: pass - else: - if default_member_permissions is not None: - raise ValueError( - "Cannot set `default_member_permissions` in both parameter and decorator" - ) - default_member_permissions = default_perms dm_permission = True if dm_permission is None else dm_permission diff --git a/disnake/ext/commands/slash_core.py b/disnake/ext/commands/slash_core.py index d41642cc44..634a951895 100644 --- a/disnake/ext/commands/slash_core.py +++ b/disnake/ext/commands/slash_core.py @@ -418,15 +418,9 @@ def __init__( desc_loc = Localized._cast(description, False) try: - default_perms: int = func.__default_member_permissions__ + default_member_permissions = func.__default_member_permissions__ except AttributeError: pass - else: - if default_member_permissions is not None: - raise ValueError( - "Cannot set `default_member_permissions` in both parameter and decorator" - ) - default_member_permissions = default_perms dm_permission = True if dm_permission is None else dm_permission From 5386c20d2c50f0f8d844adf6e66ba406161bc3ed Mon Sep 17 00:00:00 2001 From: shiftinv Date: Thu, 25 Aug 2022 00:02:11 +0200 Subject: [PATCH 6/6] test: add tests --- tests/ext/commands/test_base_core.py | 82 ++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 tests/ext/commands/test_base_core.py diff --git a/tests/ext/commands/test_base_core.py b/tests/ext/commands/test_base_core.py new file mode 100644 index 0000000000..ce8293543d --- /dev/null +++ b/tests/ext/commands/test_base_core.py @@ -0,0 +1,82 @@ +import pytest + +from disnake import Permissions +from disnake.ext import commands + + +class TestDefaultPermissions: + def test_decorator(self): + class Cog(commands.Cog): + @commands.slash_command(default_member_permissions=64) + async def cmd(self, _): + ... + + @commands.default_member_permissions(64) + @commands.slash_command() + async def above(self, _): + ... + + @commands.slash_command() + @commands.default_member_permissions(64) + async def below(self, _): + ... + + for c in (Cog, Cog()): + assert c.cmd.default_member_permissions == Permissions(64) + assert c.above.default_member_permissions == Permissions(64) + assert c.below.default_member_permissions == Permissions(64) + + def test_decorator_overwrite(self): + # putting the decorator above should fail + with pytest.raises(ValueError, match="Cannot set `default_member_permissions`"): + + class Cog(commands.Cog): + @commands.default_member_permissions(32) + @commands.slash_command(default_member_permissions=64) + async def above(self, _): + ... + + # putting the decorator below shouldn't fail + # (this is a side effect of how command copying works, + # and while this *should* probably fail, we're just testing + # for regressions for now) + class Cog2(commands.Cog): + @commands.slash_command(default_member_permissions=64) + @commands.default_member_permissions(32) + async def below(self, _): + ... + + for c in (Cog2, Cog2()): + assert c.below.default_member_permissions == Permissions(32) + + def test_attrs(self): + class Cog(commands.Cog, slash_command_attrs={"default_member_permissions": 32}): + @commands.slash_command() + async def no_overwrite(self, _): + ... + + @commands.slash_command(default_member_permissions=64) + async def overwrite(self, _): + ... + + @commands.default_member_permissions(64) + @commands.slash_command() + async def overwrite_decorator_above(self, _): + ... + + @commands.slash_command() + @commands.default_member_permissions(64) + async def overwrite_decorator_below(self, _): + ... + + assert Cog.no_overwrite.default_member_permissions is None + assert Cog().no_overwrite.default_member_permissions == Permissions(32) + + assert Cog.overwrite.default_member_permissions == Permissions(64) + assert Cog().overwrite.default_member_permissions == Permissions(64) + + assert Cog.overwrite_decorator_above.default_member_permissions == Permissions(64) + assert Cog().overwrite_decorator_above.default_member_permissions == Permissions(64) + + assert Cog.overwrite_decorator_below.default_member_permissions == Permissions(64) + assert Cog().overwrite_decorator_below.default_member_permissions == Permissions(64)