From 952257ea5e71e4a44a8a403143b920f5f98f9124 Mon Sep 17 00:00:00 2001 From: AlexFlipnote Date: Sun, 5 Jan 2025 20:32:34 +0100 Subject: [PATCH] Support for typing.Literal --- discord_http/__init__.py | 2 +- discord_http/commands.py | 15 +++++++++++++++ tests/manual_testing.py | 6 ++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/discord_http/__init__.py b/discord_http/__init__.py index 881e0f4..2e42335 100644 --- a/discord_http/__init__.py +++ b/discord_http/__init__.py @@ -1,4 +1,4 @@ -__version__ = "2.0.1" +__version__ = "2.0.2" # flake8: noqa: F401 from .asset import * diff --git a/discord_http/commands.py b/discord_http/commands.py index 00b0463..39a9ecb 100644 --- a/discord_http/commands.py +++ b/discord_http/commands.py @@ -350,6 +350,18 @@ def __init__( self.__list_choices.append(parameter.name) ptype = origin.type + # If literal, replicate Choice + elif origin is Literal: + self.__list_choices.append(parameter.name) + ptype = CommandOptionType.string + + if not getattr(self.command, "__choices_params__", {}): + self.command.__choices_params__ = {} + + self.command.__choices_params__[parameter.name] = { + str(g): str(g) for g in parameter.annotation.__args__ + } + # PyRight may not recognize 'Range' due to dynamic typing. # Assuming 'origin' is a Range object. elif isinstance(origin, Range): # type: ignore[arg-type] @@ -1019,6 +1031,9 @@ def __init__(self, key: ChoiceT, value: ChoiceT): self.value: ChoiceT = value self.type: CommandOptionType = CommandOptionType.string + def __str__(self) -> str: + return str(self.key) + def __class_getitem__(cls, obj): if isinstance(obj, tuple): raise TypeError("Choice can only take one type") diff --git a/tests/manual_testing.py b/tests/manual_testing.py index cdf3ea0..5f5fe65 100644 --- a/tests/manual_testing.py +++ b/tests/manual_testing.py @@ -10,6 +10,7 @@ import secrets from datetime import time, timedelta +from typing import Literal from discord_http import ( Context, Embed, File, Member, @@ -647,6 +648,11 @@ async def test_channel(ctx: Context, channel: VoiceChannel): return ctx.response.send_message(f"You chose {channel} {repr(channel)}") +@client.command(name="test_literal") +async def test_literal(ctx: Context, choice: Literal["very", "Nice", "test"]): + return ctx.response.send_message(f"You chose {choice}") + + @client.command() async def test_search_member(ctx: Context, query: str): members = await ctx.guild.search_members(query)