28
28
import inspect
29
29
import os
30
30
from collections .abc import Sequence
31
- from typing import TYPE_CHECKING , Callable , TypeVar
31
+ from typing import TYPE_CHECKING , Any , Callable , Generic , TypeVar
32
32
33
33
from ..channel import _threaded_guild_channel_factory
34
34
from ..components import SelectDefaultValue , SelectMenu , SelectOption
62
62
from ..types .interactions import ComponentInteractionData
63
63
from .view import View
64
64
65
+ ST = TypeVar ("ST" , bound = Snowflake | str , covariant = True , default = Any )
66
+ else :
67
+ ST = TypeVar ("ST" , bound = "Snowflake | str" , covariant = True )
68
+
65
69
S = TypeVar ("S" , bound = "Select" )
66
70
V = TypeVar ("V" , bound = "View" , covariant = True )
67
71
68
72
69
- class Select (Item [V ]):
73
+ class Select (Generic [ V , ST ], Item [V ]):
70
74
"""Represents a UI select menu.
71
75
72
76
This is usually represented as a drop down menu.
@@ -198,7 +202,7 @@ def __init__(
198
202
label : str | None = None ,
199
203
description : str | None = None ,
200
204
required : bool | None = None ,
201
- default_values : Sequence [SelectDefaultValue | Snowflake ] | None = None ,
205
+ default_values : Sequence [SelectDefaultValue | ST ] | None = None ,
202
206
) -> None :
203
207
if options and select_type is not ComponentType .string_select :
204
208
raise InvalidArgument ("options parameter is only valid for string selects" )
@@ -247,7 +251,7 @@ def __init__(
247
251
self .row = row
248
252
249
253
def _handle_default_values (
250
- self , default_values : Sequence [Snowflake ] | None , select_type : ComponentType
254
+ self , default_values : Sequence [Snowflake | ST ] | None , select_type : ComponentType
251
255
) -> list [SelectDefaultValue ]:
252
256
if not default_values :
253
257
return []
@@ -320,7 +324,7 @@ def disabled(self) -> bool:
320
324
@property
321
325
def required (self ) -> bool :
322
326
"""Whether the select is required or not. Only applicable in modal selects."""
323
- return self ._underlying .required
327
+ return bool ( self ._underlying .required )
324
328
325
329
@required .setter
326
330
def required (self , value : bool ):
@@ -368,7 +372,7 @@ def default_values(self) -> list[SelectDefaultValue]:
368
372
369
373
@default_values .setter
370
374
def default_values (
371
- self , values : list [SelectDefaultValue | Snowflake ] | None
375
+ self , values : Sequence [SelectDefaultValue | ST ] | None
372
376
) -> None :
373
377
default_values = self ._handle_default_values (values , self .type )
374
378
self ._underlying .default_values = default_values
@@ -555,29 +559,25 @@ def append_option(self, option: SelectOption) -> Self:
555
559
return self
556
560
557
561
@property
558
- def values (
559
- self ,
560
- ) -> (
561
- list [str ]
562
- | list [Member | User ]
563
- | list [Role ]
564
- | list [Member | User | Role ]
565
- | list [GuildChannel | Thread ]
566
- ):
562
+ def values (self ) -> list [ST ]:
567
563
"""List[:class:`str`] | List[:class:`discord.Member` | :class:`discord.User`]] | List[:class:`discord.Role`]] |
568
564
List[:class:`discord.Member` | :class:`discord.User` | :class:`discord.Role`]] | List[:class:`discord.abc.GuildChannel`] | None:
569
565
A list of values that have been selected by the user. This will be ``None`` if the select has not been interacted with yet.
570
566
"""
571
- if self ._interaction is None :
567
+ if self ._interaction is None or self . _interaction . data is None :
572
568
# The select has not been interacted with yet
573
- return None
569
+ return []
574
570
select_type = self ._underlying .type
575
571
if select_type is ComponentType .string_select :
576
- return self ._selected_values
572
+ return self ._selected_values # type: ignore # ST is str
577
573
resolved = []
578
574
selected_values = list (self ._selected_values )
579
575
state = self ._interaction ._state
580
576
guild = self ._interaction .guild
577
+
578
+ if guild is None :
579
+ return []
580
+
581
581
resolved_data = self ._interaction .data .get ("resolved" , {})
582
582
if select_type is ComponentType .channel_select :
583
583
for channel_id , _data in resolved_data .get ("channels" , {}).items ():
@@ -602,6 +602,9 @@ def values(
602
602
# For threads, if this fallback occurs, info like thread owner id, message count,
603
603
# flags, and more will be missing due to a lack of data sent by Discord.
604
604
obj_type = _threaded_guild_channel_factory (_data ["type" ])[0 ]
605
+ if obj_type is None :
606
+ # should not be None, but assert anyways
607
+ continue
605
608
result = obj_type (state = state , data = _data , guild = guild )
606
609
resolved .append (result )
607
610
elif select_type in (
@@ -642,7 +645,7 @@ def refresh_component(self, component: SelectMenu) -> None:
642
645
643
646
def refresh_state (self , interaction : Interaction | dict ) -> None :
644
647
data : ComponentInteractionData = (
645
- interaction .data if isinstance (interaction , Interaction ) else interaction
648
+ interaction .data if isinstance (interaction , Interaction ) else interaction # type: ignore
646
649
)
647
650
self ._selected_values = data .get ("values" , [])
648
651
self ._interaction = interaction
@@ -704,7 +707,7 @@ def select(
704
707
row : int | None = None ,
705
708
id : int | None = None ,
706
709
default_values : Sequence [SelectDefaultValue | Snowflake ] | None = None ,
707
- ) -> Callable [[ItemCallbackType [Select [V ]]], Select [V ]]:
710
+ ) -> Callable [[ItemCallbackType [Select [V , ST ]]], Select [V , ST ]]:
708
711
"""A decorator that attaches a select menu to a component.
709
712
710
713
The function being decorated should have three parameters, ``self`` representing
@@ -842,7 +845,7 @@ def string_select(
842
845
disabled : bool = False ,
843
846
row : int | None = None ,
844
847
id : int | None = None ,
845
- ) -> Callable [[ItemCallbackType [Select [V ]]], Select [V ]]:
848
+ ) -> Callable [[ItemCallbackType [Select [V , str ]]], Select [V , str ]]:
846
849
"""A shortcut for :meth:`discord.ui.select` with select type :attr:`discord.ComponentType.string_select`.
847
850
848
851
.. versionadded:: 2.3
@@ -870,7 +873,7 @@ def user_select(
870
873
row : int | None = None ,
871
874
id : int | None = None ,
872
875
default_values : Sequence [SelectDefaultValue | Snowflake ] | None = None ,
873
- ) -> Callable [[ItemCallbackType [Select [V ]]], Select [V ]]:
876
+ ) -> Callable [[ItemCallbackType [Select [V , User | Member ]]], Select [V , User | Member ]]:
874
877
"""A shortcut for :meth:`discord.ui.select` with select type :attr:`discord.ComponentType.user_select`.
875
878
876
879
.. versionadded:: 2.3
@@ -898,7 +901,7 @@ def role_select(
898
901
row : int | None = None ,
899
902
id : int | None = None ,
900
903
default_values : Sequence [SelectDefaultValue | Snowflake ] | None = None ,
901
- ) -> Callable [[ItemCallbackType [Select [V ]]], Select [V ]]:
904
+ ) -> Callable [[ItemCallbackType [Select [V , Any ]]], Select [V , Role ]]:
902
905
"""A shortcut for :meth:`discord.ui.select` with select type :attr:`discord.ComponentType.role_select`.
903
906
904
907
.. versionadded:: 2.3
@@ -926,7 +929,7 @@ def mentionable_select(
926
929
row : int | None = None ,
927
930
id : int | None = None ,
928
931
default_values : Sequence [SelectDefaultValue | Snowflake ] | None = None ,
929
- ) -> Callable [[ItemCallbackType [Select [V ]]], Select [V ]]:
932
+ ) -> Callable [[ItemCallbackType [Select [V , Role | User | Member ]]], Select [V , Role | User | Member ]]:
930
933
"""A shortcut for :meth:`discord.ui.select` with select type :attr:`discord.ComponentType.mentionable_select`.
931
934
932
935
.. versionadded:: 2.3
@@ -955,7 +958,7 @@ def channel_select(
955
958
row : int | None = None ,
956
959
id : int | None = None ,
957
960
default_values : Sequence [SelectDefaultValue | Snowflake ] | None = None ,
958
- ) -> Callable [[ItemCallbackType [Select [V ]]], Select [V ]]:
961
+ ) -> Callable [[ItemCallbackType [Select [V , GuildChannel ]]], Select [V , GuildChannel ]]:
959
962
"""A shortcut for :meth:`discord.ui.select` with select type :attr:`discord.ComponentType.channel_select`.
960
963
961
964
.. versionadded:: 2.3
0 commit comments