-
-
Notifications
You must be signed in to change notification settings - Fork 468
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Slash command option types are broken by stringized annotations #513
Comments
@Dorukyum could you check on this. |
Ran into a similar problem without understanding it and just tested this, can confirm, the minimal code is sufficient to reproduce. To add, it's probably good practice to ALWAYS use >>> type(input_type)
<class 'str'> Simply put, as far as I know, running code on type hints is a bad idea in the first place and why PEP 563, the one that introduced To get type hints, one should use typing.get_type_hints, which correctly evaluates the types even if using the future import. So, for this one, there's two ways to go about it, as far as I can tell: Edit: I regret suggesting solution 1. It is terrible, hacky, prone to many errors and I should never have done it.
#if isinstance(input_type, str) and input_type.startswith(self.__class__.__name__):
# input_type = input_type.removeprefix(self.__class__.__name__)
# input_type = input_type.lstrip('(').rstrip(')')
# input_type = gettype(input_type)
#def gettype(name):
# t = __builtins__.get(name)
# if isinstance(t, type):
# return t
# raise ValueError(name)
from typing import TypeVar, Generic
T = TypeVar('T')
class Option(Generic[T]):
pass But then the evaluation for the actual type hinting must be done elsewhere in the code, not in the constructor as it is never actually called there. Maybe something like @bot.slash_command()
async def hello(ctx, number: Option[int]):
pass And then evaluate the Option on the call to the decorator? One can easily call What do the maintainers think? |
Another problem with doing anything with stringized annotations (as in solution #1 above) is that I could choose to import Option as DiscordSlashCommandBadaBingBadaBoomOption (quite likely to happen as "Option" is a common class name that could conflict with other code) and then as I understand it, that custom name will be stringized as itself and picked up by the inspect functions and make things even harder to parse. |
In order for solution 1 to be implemented, either the minimum version requirement would have to be set to Python >=3.9 (because |
Can someone move this to the v2.1 milestone & project? |
Using the new design created in #1251 should fix this since it uses the actual typehint. async def my_command(ctx, my_arg: "Type" = Option(...)):` |
Summary
When specifying slash command option types in a module that uses
from __future__ import annotations
, which stringizes annotations, a crash occurs.Reproduction Steps
First of all, the current examples for the slash commands doesn't tell you to use type annotations for slash command option parameters, which is required to make them work.After adding an annotation to create anint
-type option, my bot sadly crashed because it calledissubclass('int', str)
inSlashCommandOptionType.from_datatype
indiscord/enums.py.
Clearly, that function expectedint
not'int'
. I believe that theSlashCommandOptionType.from_datatype
method is receiving parameters obtained by the pythoninspect.signature(callable)
function, which unstringizes parameters from modules that usefrom __future__ import annotations
only if itseval_str
keyword argument is explicitly set toTrue
, which it isn't currently. EDIT: actually, theeval_str
keyword argument appears to be only available in Python 3.10 and not Python 3.9, which might necessitate a manual workaround for earlier versions. Also, re-reading the examples, it was my mistake to use a rawint
type annotation instead of anOption
type annotation in the first place, although it Almost worked; not sure if that is intended to be supported or not. Anyway, the problem still exists if you use Option type annotations properly.Minimal Reproducible Code
Expected Results
I expected to make a slash command with a typed option.
Actual Results
Crashed. Full traceback:
Intents
I am not passing a discord.Intents class to my client.
System Information
Checklist
Additional Context
No response
The text was updated successfully, but these errors were encountered: