Skip to content

Commit 6bdb292

Browse files
committed
Refactor component limits and embed limits
- Introduced `EmbedLimits` class to define constraints for Discord embeds. - Removed the `ComponentLimits` enum and replaced it with a `ComponentLimits` class in `core.py` to define constraints for various UI components. - Updated all relevant UI components (Button, Checkbox, CheckboxGroup, FileUpload, InputText, MediaGallery, Modal, RadioGroup, Select, View) to use the new `ComponentLimits` class for validation. - Removed old `ComponentLimits` enum documentation from `enums.rst` and added new documentation for the `ComponentLimits` class. - Ensured all limits are consistently referenced across the codebase.
1 parent d9c8691 commit 6bdb292

15 files changed

Lines changed: 243 additions & 478 deletions

discord/components.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
from .enums import (
3333
ButtonStyle,
3434
ChannelType,
35-
ComponentLimits,
3635
ComponentType,
3736
InputTextStyle,
3837
SelectDefaultValueType,
@@ -42,6 +41,7 @@
4241
from .flags import AttachmentFlags
4342
from .partial_emoji import PartialEmoji, _EmojiTag
4443
from .utils import MISSING, find, get_slots
44+
from .ui.core import ComponentLimits
4545

4646
if TYPE_CHECKING:
4747
from . import abc
@@ -725,25 +725,25 @@ def __init__(
725725
emoji: str | GuildEmoji | AppEmoji | PartialEmoji | None = None,
726726
default: bool = False,
727727
) -> None:
728-
if len(label) > ComponentLimits.select_option_label_max.value:
728+
if len(label) > ComponentLimits.SELECT_OPTION_LABEL_MAX:
729729
raise ValueError(
730-
f"label must be {ComponentLimits.select_option_label_max.value} characters or fewer"
730+
f"label must be {ComponentLimits.SELECT_OPTION_LABEL_MAX} characters or fewer"
731731
)
732732

733733
if (
734734
value is not MISSING
735-
and len(value) > ComponentLimits.select_option_value_max.value
735+
and len(value) > ComponentLimits.SELECT_OPTION_VALUE_MAX
736736
):
737737
raise ValueError(
738-
f"value must be {ComponentLimits.select_option_value_max.value} characters or fewer"
738+
f"value must be {ComponentLimits.SELECT_OPTION_VALUE_MAX} characters or fewer"
739739
)
740740

741741
if (
742742
description is not None
743-
and len(description) > ComponentLimits.select_option_description_max.value
743+
and len(description) > ComponentLimits.SELECT_OPTION_DESCRIPTION_MAX
744744
):
745745
raise ValueError(
746-
f"description must be {ComponentLimits.select_option_description_max.value} characters or fewer"
746+
f"description must be {ComponentLimits.SELECT_OPTION_DESCRIPTION_MAX} characters or fewer"
747747
)
748748

749749
self.label = label
@@ -1540,25 +1540,25 @@ def __init__(
15401540
description: str | None = None,
15411541
default: bool = False,
15421542
) -> None:
1543-
if len(label) > ComponentLimits.select_option_label_max.value:
1543+
if len(label) > ComponentLimits.SELECT_OPTION_LABEL_MAX:
15441544
raise ValueError(
1545-
f"label must be {ComponentLimits.select_option_label_max.value} characters or fewer"
1545+
f"label must be {ComponentLimits.SELECT_OPTION_LABEL_MAX} characters or fewer"
15461546
)
15471547

15481548
if (
15491549
value is not MISSING
1550-
and len(value) > ComponentLimits.select_option_value_max.value
1550+
and len(value) > ComponentLimits.SELECT_OPTION_VALUE_MAX
15511551
):
15521552
raise ValueError(
1553-
f"value must be {ComponentLimits.select_option_value_max.value} characters or fewer"
1553+
f"value must be {ComponentLimits.SELECT_OPTION_VALUE_MAX} characters or fewer"
15541554
)
15551555

15561556
if (
15571557
description is not None
1558-
and len(description) > ComponentLimits.select_option_description_max.value
1558+
and len(description) > ComponentLimits.SELECT_OPTION_DESCRIPTION_MAX
15591559
):
15601560
raise ValueError(
1561-
f"description must be {ComponentLimits.select_option_description_max.value} characters or fewer"
1561+
f"description must be {ComponentLimits.SELECT_OPTION_DESCRIPTION_MAX} characters or fewer"
15621562
)
15631563

15641564
self.label = label
@@ -1712,25 +1712,25 @@ def __init__(
17121712
description: str | None = None,
17131713
default: bool = False,
17141714
) -> None:
1715-
if len(label) > ComponentLimits.select_option_label_max.value:
1715+
if len(label) > ComponentLimits.SELECT_OPTION_LABEL_MAX:
17161716
raise ValueError(
1717-
f"label must be {ComponentLimits.select_option_label_max.value} characters or fewer"
1717+
f"label must be {ComponentLimits.SELECT_OPTION_LABEL_MAX} characters or fewer"
17181718
)
17191719

17201720
if (
17211721
value is not MISSING
1722-
and len(value) > ComponentLimits.select_option_value_max.value
1722+
and len(value) > ComponentLimits.SELECT_OPTION_VALUE_MAX
17231723
):
17241724
raise ValueError(
1725-
f"value must be {ComponentLimits.select_option_value_max.value} characters or fewer"
1725+
f"value must be {ComponentLimits.SELECT_OPTION_VALUE_MAX} characters or fewer"
17261726
)
17271727

17281728
if (
17291729
description is not None
1730-
and len(description) > ComponentLimits.select_option_description_max.value
1730+
and len(description) > ComponentLimits.SELECT_OPTION_DESCRIPTION_MAX
17311731
):
17321732
raise ValueError(
1733-
f"description must be {ComponentLimits.select_option_description_max.value} characters or fewer"
1733+
f"description must be {ComponentLimits.SELECT_OPTION_DESCRIPTION_MAX} characters or fewer"
17341734
)
17351735

17361736
self.label = label

discord/embeds.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
__all__ = (
3535
"Embed",
36+
"EmbedLimits",
3637
"EmbedField",
3738
"EmbedAuthor",
3839
"EmbedFooter",
@@ -43,6 +44,28 @@
4344

4445
E = TypeVar("E", bound="Embed")
4546

47+
48+
class EmbedLimits:
49+
# Embed field constraints
50+
FIELDS_MAX = 25
51+
52+
# Field title/name constraints
53+
FIELD_NAME_MAX = 256
54+
55+
# Field value constraints
56+
FIELD_VALUE_MAX = 1024
57+
58+
# Embed description constraints
59+
DESCRIPTION_MAX = 4096
60+
61+
# Embed footer constraints
62+
FOOTER_TEXT_MAX = 2048
63+
64+
# Embed author constraints
65+
AUTHOR_NAME_MAX = 256
66+
TITLE_MAX = 256
67+
TOTAL_MAX = 6000
68+
4669
if TYPE_CHECKING:
4770
from discord.types.embed import Embed as EmbedData
4871
from discord.types.embed import EmbedType

discord/enums.py

Lines changed: 0 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,6 @@
8888
"SelectDefaultValueType",
8989
"ApplicationEventWebhookStatus",
9090
"InviteTargetUsersJobStatusCode",
91-
"ComponentLimits",
92-
"EmbedLimits",
9391
)
9492

9593

@@ -1210,107 +1208,6 @@ class InviteTargetUsersJobStatusCode(Enum):
12101208
failed = 3
12111209

12121210

1213-
class ComponentLimits(Enum):
1214-
# View constraints
1215-
view_children_max = 40
1216-
1217-
# ActionRow constraints
1218-
action_row_children_max = 5
1219-
1220-
# Button constraints
1221-
button_label_max = 80
1222-
1223-
# Container constraints
1224-
container_children_max = -1 # No limit
1225-
1226-
# MediaGallery constraints
1227-
media_gallery_items_min = 1
1228-
media_gallery_items_max = 10
1229-
1230-
# MediaGalleryItem constraints
1231-
media_gallery_item_description_max = 256
1232-
1233-
# Select constraints
1234-
select_placeholder_max = 150
1235-
select_min_value_min = 0
1236-
select_min_value_max = 25
1237-
select_max_value_min = 1
1238-
select_max_value_max = 25
1239-
select_options_max = 25
1240-
select_default_values_max = 25
1241-
1242-
# Select option constraints
1243-
select_option_label_max = 100
1244-
select_option_value_max = 100
1245-
select_option_description_max = 100
1246-
1247-
# Section constraints
1248-
section_accessory_max = 1
1249-
section_children_min = 1
1250-
section_children_max = 3
1251-
1252-
# TextInput constraints
1253-
text_input_max_count = 5
1254-
text_input_label_max = 45
1255-
text_input_placeholder_max = 100
1256-
text_input_min_length_min = 0
1257-
text_input_min_length_max = 4000
1258-
text_input_max_length_min = 1
1259-
text_input_max_length_max = 4000
1260-
text_input_value_max = 4000
1261-
1262-
# TextDisplay constraints
1263-
text_display_content_max = 4000
1264-
1265-
# Thumbnail constraints
1266-
thumbnail_description_max = 256
1267-
1268-
# Custom ID constraints
1269-
custom_id_min = 1
1270-
custom_id_max = 100
1271-
1272-
# RadioGroup constraints
1273-
radio_options_max = 10
1274-
1275-
# CheckboxGroup constraints
1276-
checkbox_options_max = 10
1277-
checkbox_min_values_min = 0
1278-
checkbox_min_values_max = 10
1279-
checkbox_max_values_min = 1
1280-
checkbox_max_values_max = 10
1281-
1282-
# FileUpload constraints
1283-
file_upload_min_files = 0
1284-
file_upload_max_files_max = 10
1285-
file_upload_max_values_min = 1
1286-
1287-
# Modal constraints
1288-
modal_title_max = 45
1289-
modal_rows_max = 5
1290-
1291-
1292-
class EmbedLimits(Enum):
1293-
# Embed field constraints
1294-
fields_max = 25
1295-
1296-
# Field title/name constraints
1297-
field_name_max = 256
1298-
1299-
# Field value constraints
1300-
field_value_max = 1024
1301-
1302-
# Embed description constraints
1303-
description_max = 4096
1304-
1305-
# Embed footer constraints
1306-
footer_text_max = 2048
1307-
1308-
# Embed author constraints
1309-
author_name_max = 256
1310-
title_max = 256
1311-
total_max = 6000
1312-
1313-
13141211
T = TypeVar("T")
13151212

13161213

discord/ui/button.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,16 @@ def __init__(
113113
self._row: int | None = None
114114
self._rendered_row: int | None = None
115115
super().__init__()
116-
if label and len(str(label)) > ComponentLimits.button_label_max.value:
116+
if label and len(str(label)) > ComponentLimits.BUTTON_LABEL_MAX:
117117
raise ValueError(
118-
f"label must be {ComponentLimits.button_label_max.value} characters or fewer"
118+
f"label must be {ComponentLimits.BUTTON_LABEL_MAX} characters or fewer"
119119
)
120120
if (
121121
custom_id is not None
122-
and len(str(custom_id)) > ComponentLimits.custom_id_max.value
122+
and len(str(custom_id)) > ComponentLimits.CUSTOM_ID_MAX
123123
):
124124
raise ValueError(
125-
f"custom_id must be {ComponentLimits.custom_id_max.value} characters or fewer"
125+
f"custom_id must be {ComponentLimits.CUSTOM_ID_MAX} characters or fewer"
126126
)
127127
if custom_id is not None and url is not None:
128128
raise TypeError("cannot mix both url and custom_id with Button")
@@ -213,9 +213,9 @@ def custom_id(self) -> str | None:
213213
def custom_id(self, value: str | None):
214214
if value is not None and not isinstance(value, str):
215215
raise TypeError("custom_id must be None or str")
216-
if value and len(value) > ComponentLimits.custom_id_max.value:
216+
if value and len(value) > ComponentLimits.CUSTOM_ID_MAX:
217217
raise ValueError(
218-
f"custom_id must be {ComponentLimits.custom_id_max.value} characters or fewer"
218+
f"custom_id must be {ComponentLimits.CUSTOM_ID_MAX} characters or fewer"
219219
)
220220
self.underlying.custom_id = value
221221
self._provided_custom_id = value is not None
@@ -247,9 +247,9 @@ def label(self) -> str | None:
247247

248248
@label.setter
249249
def label(self, value: str | None):
250-
if value and len(str(value)) > ComponentLimits.button_label_max.value:
250+
if value and len(str(value)) > ComponentLimits.BUTTON_LABEL_MAX:
251251
raise ValueError(
252-
f"label must be {ComponentLimits.button_label_max.value} characters or fewer"
252+
f"label must be {ComponentLimits.BUTTON_LABEL_MAX} characters or fewer"
253253
)
254254
self.underlying.label = str(value) if value is not None else value
255255

discord/ui/checkbox.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
from typing import TYPE_CHECKING
2929

3030
from ..components import Checkbox as CheckboxComponent
31-
from ..enums import ComponentLimits, ComponentType
31+
from .core import ComponentLimits
32+
from ..enums import ComponentType
3233
from .item import ModalItem
3334

3435
__all__ = ("Checkbox",)
@@ -105,9 +106,9 @@ def custom_id(self) -> str:
105106
def custom_id(self, value: str):
106107
if not isinstance(value, str):
107108
raise TypeError(f"custom_id must be str not {value.__class__.__name__}")
108-
if len(value) > ComponentLimits.custom_id_max.value:
109+
if len(value) > ComponentLimits.CUSTOM_ID_MAX:
109110
raise ValueError(
110-
f"custom_id must be {ComponentLimits.custom_id_max.value} characters or fewer"
111+
f"custom_id must be {ComponentLimits.CUSTOM_ID_MAX} characters or fewer"
111112
)
112113
self.underlying.custom_id = value
113114

0 commit comments

Comments
 (0)