1
# SPDX-License-Identifier: MIT
3
from typing import Dict, Literal, Optional
7
from disnake.permissions import PermissionOverwrite, Permissions
11
def test_init_permissions_keyword_arguments(self) -> None:
12
perms = Permissions(manage_messages=True)
14
assert perms.manage_messages is True
16
# check we only have the manage message permission
17
assert perms.value == Permissions.manage_messages.flag
19
def test_init_permissions_keyword_arguments_with_aliases(self) -> None:
20
assert Permissions(read_messages=True, view_channel=False).value == 0
21
assert Permissions(view_channel=True, read_messages=False).value == 0
23
assert Permissions(read_messages=False, view_channel=True).value == 1024
24
assert Permissions(view_channel=False, read_messages=True).value == 1024
26
def test_init_invalid_value(self) -> None:
27
with pytest.raises(TypeError, match="Expected int parameter, received str instead."):
28
Permissions("h") # type: ignore
30
def test_init_invalid_perms(self) -> None:
31
with pytest.raises(TypeError, match="'h' is not a valid permission name."):
32
Permissions(h=True) # type: ignore
34
@pytest.mark.parametrize(
35
("perms_int", "other_int", "expected"),
42
def test_is_subset(self, perms_int: int, other_int: int, expected: bool) -> None:
43
perms = Permissions(perms_int)
44
other = Permissions(other_int)
45
assert perms.is_subset(other) is expected
47
def test_is_subset_only_permissions(self) -> None:
49
with pytest.raises(TypeError, match="cannot compare Permissions with int"):
50
perms.is_subset(5) # type: ignore
52
@pytest.mark.parametrize(
53
("perms_int", "other_int", "expected"),
60
def test_is_superset(self, perms_int: int, other_int: int, expected: bool) -> None:
61
perms = Permissions(perms_int)
62
other = Permissions(other_int)
63
assert perms.is_superset(other) is expected
65
def test_is_superset_only_permissions(self) -> None:
67
with pytest.raises(TypeError, match="cannot compare Permissions with int"):
68
perms.is_superset(5) # type: ignore
70
@pytest.mark.parametrize(
71
("perms_int", "other_int", "expected"),
78
def test_is_strict_subset(self, perms_int: int, other_int: int, expected: bool) -> None:
79
perms = Permissions(perms_int)
80
other = Permissions(other_int)
81
assert perms.is_strict_subset(other) is expected
83
@pytest.mark.parametrize(
84
("perms_int", "other_int", "expected"),
91
def test_is_strict_superset(self, perms_int: int, other_int: int, expected: bool) -> None:
92
perms = Permissions(perms_int)
93
other = Permissions(other_int)
95
assert perms.is_strict_superset(other) is expected
97
@pytest.mark.parametrize(
98
("perms_dict", "update", "expected"),
101
{"view_channel": True},
102
{"move_members": True},
103
{"view_channel": True, "move_members": True},
109
perms_dict: Dict[str, bool],
110
update: Dict[str, bool],
111
expected: Dict[str, Literal[True]],
113
perms = Permissions(**perms_dict)
114
perms.update(**update)
116
expected_perms = Permissions(**expected)
118
assert perms.value == expected_perms.value
120
@pytest.mark.parametrize(
121
("update", "expected"),
123
({"read_messages": True, "view_channel": False}, 8),
124
({"view_channel": True, "read_messages": False}, 8),
125
({"read_messages": False, "view_channel": True}, 8 + 1024),
126
({"view_channel": False, "read_messages": True}, 8 + 1024),
129
def test_update_aliases(self, update: Dict[str, bool], expected: int) -> None:
130
perms = Permissions(administrator=True)
131
perms.update(**update)
132
assert perms.value == expected
134
@pytest.mark.parametrize(
135
("parameters", "expected"),
137
({"view_channel": True, "move_members": True}, None),
140
{"read_messages": True, "create_forum_threads": True},
141
{"view_channel": True, "send_messages": True},
145
def test_iter(self, parameters: Dict[str, bool], expected: Optional[Dict[str, bool]]) -> None:
146
perms = Permissions(**parameters)
148
expected = parameters
149
for key, value in iter(perms):
150
assert value == expected.pop(key, False)
151
assert not len(expected)
153
def test_update_ignores(self) -> None:
154
perms = Permissions()
155
perms.update(h=True) # type: ignore
157
@pytest.mark.parametrize(
158
("initial", "allow", "deny", "expected"),
160
(0b1010, 0b0101, 0b1111, 0b0101),
161
(0b0011, 0b0100, 0b0001, 0b0110),
162
(0x0400, 0x0401, 0x5001, 0x0401),
165
def test_handle_overwrite(self, initial: int, allow: int, deny: int, expected: int) -> None:
166
perms = Permissions(initial)
167
assert perms.value == initial
168
perms.handle_overwrite(allow, deny)
169
assert perms.value == expected
171
def test_none_is_none(self) -> None:
172
perms = Permissions.none()
173
assert perms.value == 0
175
@pytest.mark.parametrize(
192
def test_classmethods(self, method_name: str) -> None:
193
method = getattr(Permissions, method_name)
195
perms: Permissions = method()
196
assert isinstance(perms, Permissions)
198
# check that caching does not return the same permissions instance
199
perms_two: Permissions = method()
200
assert perms is not perms_two
201
assert perms.value == perms_two.value
204
class TestPermissionOverwrite:
205
def test_init(self) -> None:
206
perms = PermissionOverwrite(manage_messages=True)
208
assert perms.manage_messages is True
210
def test_init_invalid_perms(self) -> None:
211
with pytest.raises(ValueError, match="'h' is not a valid permission name."):
212
PermissionOverwrite(h=True) # type: ignore
214
def test_equality(self) -> None:
215
one = PermissionOverwrite()
216
two = PermissionOverwrite()
218
assert one is not two
221
two.ban_members = False
224
def test_set(self) -> None:
225
po = PermissionOverwrite()
226
po.attach_files = False
227
assert po.attach_files is False
229
po.attach_files = True
230
assert po.attach_files is True
232
po.attach_files = None
233
assert po.attach_files is None
235
def test_set_invalid_type(self) -> None:
236
po = PermissionOverwrite()
237
with pytest.raises(TypeError, match="Expected bool or NoneType, received str"):
238
po.connect = "h" # type: ignore
241
AttributeError, match="'PermissionOverwrite' object has no attribute 'oh'"
243
po.oh = False # type: ignore
245
@pytest.mark.parametrize(
248
({"view_channel": True}, {"ban_members": True}),
249
({"view_channel": True}, {"view_channel": True}),
250
({"administrator": True}, {"manage_channels": False}),
255
allow: Dict[str, bool],
256
deny: Dict[str, bool],
258
perm_allow = Permissions(**allow)
259
perm_deny = Permissions(**deny)
261
po = PermissionOverwrite.from_pair(perm_allow, perm_deny)
263
# iterate over the allowed perms and assert that the overwrite is what the allowed perms are
264
for perm, allowed in perm_allow:
265
# get the attr from the denied perms as denied perms override the allow list in from_pair
266
if allowed and not getattr(perm_deny, perm):
267
assert getattr(po, perm) is True
269
assert getattr(po, perm) is not True
271
for perm, denied in deny.items():
273
assert getattr(po, perm) is False
275
assert getattr(po, perm) is not False
277
@pytest.mark.parametrize(
280
# these intentionally do not interfere with each other
286
def test_pair(self, allow: int, deny: int) -> None:
287
og_perms_allow = Permissions(allow)
288
og_perms_deny = Permissions(deny)
290
po = PermissionOverwrite.from_pair(og_perms_allow, og_perms_deny)
292
perms_allow, perms_deny = po.pair()
294
assert perms_allow.value == og_perms_allow.value
295
assert perms_deny.value == og_perms_deny.value
297
def test_is_empty(self) -> None:
298
po = PermissionOverwrite()
301
po.add_reactions = True
302
assert not po.is_empty()
304
def test_update(self) -> None:
305
po = PermissionOverwrite()
306
assert po.manage_emojis is None
308
po.update(manage_emojis=True)
309
assert po.manage_emojis is True
311
assert po.manage_permissions is None
312
po.update(manage_permissions=False)
313
assert po.manage_permissions is False
315
po.update(manage_permissions=None, manage_emojis=None)
316
assert po.manage_permissions is None
317
assert po.manage_emojis is None
319
# invalid names are silently ignored
320
po.update(h=True) # type: ignore
321
assert not hasattr(po, "h")
323
@pytest.mark.parametrize(
326
({"view_channel": True}),
327
({"ban_members": None}),
328
({"view_channel": True, "administrator": False, "ban_members": None}),
329
({"kick_members": False}),
334
expected: Dict[str, bool],
336
po = PermissionOverwrite(**expected)
338
for perm, value in po:
339
assert expected.get(perm, None) is value