From 6f69d9405e050812ebc67d57ff4f3b20a6abafa6 Mon Sep 17 00:00:00 2001 From: DJ Magar <85457381+DJStompZone@users.noreply.github.com> Date: Sat, 22 Jun 2024 07:48:10 -0700 Subject: [PATCH 1/2] Add LargeInt support to Range Updated Range class to support LargeInt, Added LargeIntRangeConverter class --- disnake/ext/commands/params.py | 40 ++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/disnake/ext/commands/params.py b/disnake/ext/commands/params.py index e472c1ae13..3124e5d56e 100644 --- a/disnake/ext/commands/params.py +++ b/disnake/ext/commands/params.py @@ -356,26 +356,28 @@ def __call__(self) -> NoReturn: def __or__(self, other): return Union[self, other] # type: ignore - if TYPE_CHECKING: - # aliased import since mypy doesn't understand `Range = Annotated` - from typing_extensions import Annotated as Range, Annotated as String + from typing_extensions import Annotated as Range else: - @dataclass(frozen=True, repr=False) class Range(_BaseRange): """Type representing a number with a limited range of allowed values. + Supports int, float, and LargeInt. + See :ref:`param_ranges` for more information. .. versionadded:: 2.4 - .. versionchanged:: 2.9 + .. versionchanged:: 2.9.2 Syntax changed from ``Range[5, 10]`` to ``Range[int, 5, 10]``; - the type (:class:`int` or :class:`float`) must now be specified explicitly. + the type (:class:`int`, :class:`float`, or :class:`LargeInt`) must now be specified explicitly. """ + min_value: Any + max_value: Any + underlying_type: Type[Any] - _allowed_types = (int, float) + _allowed_types = (int, float, LargeInt) def __post_init__(self): for value in (self.min_value, self.max_value): @@ -384,13 +386,37 @@ def __post_init__(self): if self.underlying_type is int and not isinstance(value, int): raise TypeError("Range[int, ...] bounds must be int, not float") + if self.underlying_type is LargeInt and not isinstance(value, int): + raise TypeError("Range[LargeInt, ...] bounds must be int, not float") @classmethod def _infer_type(cls, params: Tuple[Any, ...]) -> Type[Any]: if any(isinstance(p, float) for p in params): return float + if any(isinstance(p, LargeInt) for p in params): + return LargeInt return int + def __call__(self, value: Any) -> Any: + value = self.underlying_type(value) + if not (self.min_value <= value <= self.max_value): + raise ValueError(f"{value} is not within the range {self.min_value} to {self.max_value}.") + return value + + + class LargeIntRangeConverter(commands.Converter): + """Utility class to enable LargeInt support""" + def __init__(self, min_value, max_value): + self.range = Range(min_value=int(min_value), max_value=int(max_value), underlying_type=LargeInt) + + async def convert(self, ctx, argument): + try: + value = self.range(argument) + except ValueError as e: + raise commands.BadArgument(str(e)) + return value + + @dataclass(frozen=True, repr=False) class String(_BaseRange): """Type representing a string option with a limited length. From 5bbfc6ac62f263fc06fd2df7b6a481eec153d453 Mon Sep 17 00:00:00 2001 From: DJ Magar <85457381+DJStompZone@users.noreply.github.com> Date: Sat, 22 Jun 2024 07:51:57 -0700 Subject: [PATCH 2/2] Whoops Let's try not to break anything shall we --- disnake/ext/commands/params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/disnake/ext/commands/params.py b/disnake/ext/commands/params.py index 3124e5d56e..0bdd234ecf 100644 --- a/disnake/ext/commands/params.py +++ b/disnake/ext/commands/params.py @@ -357,7 +357,7 @@ def __or__(self, other): return Union[self, other] # type: ignore if TYPE_CHECKING: - from typing_extensions import Annotated as Range + from typing_extensions import Annotated as Range, Annotated as String else: @dataclass(frozen=True, repr=False) class Range(_BaseRange):