2626
2727import inspect
2828import logging
29+ from collections .abc import Awaitable , Callable , Iterable
2930from enum import Enum
30- from typing import TYPE_CHECKING , Iterable , Literal , Optional , Type , Union
31+ from typing import TYPE_CHECKING , Any , Literal , Optional , Type , TypeVar , Union
3132
3233from ..abc import GuildChannel , Mentionable
3334from ..channel import (
4647from ..utils import MISSING , basic_autocomplete
4748
4849if TYPE_CHECKING :
50+ from ..cog import Cog
4951 from ..ext .commands import Converter
5052 from ..member import Member
5153 from ..message import Attachment
7173 Type [DiscordEnum ],
7274 ]
7375
76+ AutocompleteReturnType = Union [
77+ Iterable ["OptionChoice" ], Iterable [str ], Iterable [int ], Iterable [float ]
78+ ]
79+ T = TypeVar ("T" , bound = AutocompleteReturnType )
80+ MaybeAwaitable = Union [T , Awaitable [T ]]
81+ AutocompleteFunction = Union [
82+ Callable [[AutocompleteContext ], MaybeAwaitable [AutocompleteReturnType ]],
83+ Callable [[Cog , AutocompleteContext ], MaybeAwaitable [AutocompleteReturnType ]],
84+ Callable [
85+ [AutocompleteContext , Any ], # pyright: ignore [reportExplicitAny]
86+ MaybeAwaitable [AutocompleteReturnType ],
87+ ],
88+ Callable [
89+ [Cog , AutocompleteContext , Any ], # pyright: ignore [reportExplicitAny]
90+ MaybeAwaitable [AutocompleteReturnType ],
91+ ],
92+ ]
93+
94+
7495__all__ = (
7596 "ThreadOption" ,
7697 "Option" ,
@@ -111,11 +132,6 @@ def __init__(self, thread_type: Literal["public", "private", "news"]):
111132 self ._type = type_map [thread_type ]
112133
113134
114- AutocompleteReturnType = Union [
115- Iterable ["OptionChoice" ], Iterable [str ], Iterable [int ], Iterable [float ]
116- ]
117-
118-
119135class Option :
120136 """Represents a selectable option for a slash command.
121137
@@ -268,7 +284,7 @@ def __init__(
268284 )
269285 self .default = kwargs .pop ("default" , None )
270286
271- self ._autocomplete = None
287+ self ._autocomplete : AutocompleteFunction | None = None
272288 self .autocomplete = kwargs .pop ("autocomplete" , None )
273289 if len (enum_choices ) > 25 :
274290 self .choices : list [OptionChoice ] = []
@@ -388,22 +404,17 @@ def __repr__(self):
388404 return f"<discord.commands.{ self .__class__ .__name__ } name={ self .name } >"
389405
390406 @property
391- def autocomplete (self ):
407+ def autocomplete (self ) -> AutocompleteFunction | None :
392408 """
393409 The autocomplete handler for the option. Accepts a callable (sync or async)
394- that takes a single required argument of :class:`AutocompleteContext`.
410+ that takes a single required argument of :class:`AutocompleteContext` or two arguments
411+ of :class:`discord.Cog` (being the command's cog) and :class:`AutocompleteContext`.
395412 The callable must return an iterable of :class:`str` or :class:`OptionChoice`.
396413 Alternatively, :func:`discord.utils.basic_autocomplete` may be used in place of the callable.
397414
398415 Returns
399416 -------
400- Union[
401- Callable[[Self, AutocompleteContext, Any], AutocompleteReturnType],
402- Callable[[AutocompleteContext, Any], AutocompleteReturnType],
403- Callable[[Self, AutocompleteContext, Any], Awaitable[AutocompleteReturnType]],
404- Callable[[AutocompleteContext, Any], Awaitable[AutocompleteReturnType]],
405- None
406- ]
417+ Optional[AutocompleteFunction]
407418
408419 .. versionchanged:: 2.7
409420
@@ -413,17 +424,17 @@ def autocomplete(self):
413424 return self ._autocomplete
414425
415426 @autocomplete .setter
416- def autocomplete (self , value ) -> None :
427+ def autocomplete (self , value : AutocompleteFunction | None ) -> None :
417428 self ._autocomplete = value
418429 # this is done here so it does not have to be computed every time the autocomplete is invoked
419430 if self ._autocomplete is not None :
420- self ._autocomplete ._is_instance_method = (
431+ self ._autocomplete ._is_instance_method = ( # pyright: ignore [reportFunctionMemberAccess]
421432 sum (
422433 1
423434 for param in inspect .signature (
424- self .autocomplete
435+ self ._autocomplete
425436 ).parameters .values ()
426- if param .default == param .empty
437+ if param .default == param .empty # pyright: ignore[reportAny]
427438 and param .kind not in (param .VAR_POSITIONAL , param .VAR_KEYWORD )
428439 )
429440 == 2
0 commit comments