From 46f64525bff48e568c4acfc2454ba6ae5afc4631 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Wed, 25 Jan 2023 00:08:36 +0000 Subject: [PATCH 01/45] Switch to dataclases' genned slots --- tanjun/clients.py | 6 ++---- tanjun/dependencies/reloaders.py | 7 +++---- tanjun/schedules.py | 3 +-- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/tanjun/clients.py b/tanjun/clients.py index 081033b56..c39d046b9 100644 --- a/tanjun/clients.py +++ b/tanjun/clients.py @@ -3058,18 +3058,16 @@ def _try_unsubscribe( pass -@dataclasses.dataclass +@dataclasses.dataclass(slots=True) class _LoadModule: - __slots__ = ("path",) path: str | pathlib.Path def __call__(self) -> types.ModuleType: return importlib.import_module(self.path) if isinstance(self.path, str) else _get_path_module(self.path) -@dataclasses.dataclass +@dataclasses.dataclass(slots=True) class _ReloadModule: - __slots__ = ("path",) path: types.ModuleType | pathlib.Path def __call__(self) -> types.ModuleType: diff --git a/tanjun/dependencies/reloaders.py b/tanjun/dependencies/reloaders.py index 6413478a0..b58fed684 100644 --- a/tanjun/dependencies/reloaders.py +++ b/tanjun/dependencies/reloaders.py @@ -546,7 +546,7 @@ def _scan_one(path: pathlib.Path, /) -> typing.Optional[int]: return None # MyPy compat -@dataclasses.dataclass +@dataclasses.dataclass(slots=True) class _ScanResult: py_paths: dict[str, _PyPathInfo] = dataclasses.field(init=False, default_factory=dict) removed_py_paths: list[str] = dataclasses.field(init=False, default_factory=list) @@ -554,9 +554,8 @@ class _ScanResult: sys_paths: dict[pathlib.Path, _PyPathInfo] = dataclasses.field(init=False, default_factory=dict) -@dataclasses.dataclass +@dataclasses.dataclass(slots=True) class _PathScanner(typing.Generic[_PathT]): - __slots__ = ("global_paths", "dead_unloads", "result_paths", "removed_paths") global_paths: dict[_PathT, _PyPathInfo] dead_unloads: set[str | pathlib.Path] result_paths: dict[_PathT, _PyPathInfo] @@ -592,7 +591,7 @@ def process(self) -> None: self.removed_paths.append(path) -@dataclasses.dataclass +@dataclasses.dataclass(slots=True) class _PathLoader(typing.Generic[_PathT]): waiting_for: dict[_PathT, int] paths: dict[_PathT, _PyPathInfo] diff --git a/tanjun/schedules.py b/tanjun/schedules.py index 0de73ac60..5e8d2fff5 100644 --- a/tanjun/schedules.py +++ b/tanjun/schedules.py @@ -595,9 +595,8 @@ def _to_sequence( return values -@dataclasses.dataclass +@dataclasses.dataclass(slots=True) class _TimeScheduleConfig: - __slots__ = ("current_date", "days", "hours", "is_weekly", "minutes", "months", "seconds", "timezone") current_date: datetime.datetime days: typing.Optional[collections.Sequence[int]] hours: collections.Sequence[int] From f521805f7d685babc38d41823d65aebb0074e178 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Fri, 3 Jun 2022 05:34:28 +0100 Subject: [PATCH 02/45] Initial restructuring --- tanjun/abc.py | 58 +++++++++++++++++++++++++------------- tanjun/checks.py | 4 ++- tanjun/clients.py | 10 +++---- tanjun/commands/base.py | 10 +++---- tanjun/commands/message.py | 47 +++++++++++++++--------------- tanjun/components.py | 10 +++---- 6 files changed, 81 insertions(+), 58 deletions(-) diff --git a/tanjun/abc.py b/tanjun/abc.py index ca133142d..ed2e7940e 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -72,6 +72,7 @@ from collections import abc as collections import hikari +import typing_extensions from alluka import abc as alluka if typing.TYPE_CHECKING: @@ -90,6 +91,7 @@ _MessageCommandT = typing.TypeVar("_MessageCommandT", bound="MessageCommand[typing.Any]") _MetaEventSigT = typing.TypeVar("_MetaEventSigT", bound="MetaEventSig") +_P = typing_extensions.ParamSpec("_P") _T = typing.TypeVar("_T") _AppCommandContextT = typing.TypeVar("_AppCommandContextT", bound="AppCommandContext") _CommandCallbackSigT = typing.TypeVar("_CommandCallbackSigT", bound="CommandCallbackSig") @@ -101,8 +103,10 @@ "_MenuTypeT", typing.Literal[hikari.CommandType.USER], typing.Literal[hikari.CommandType.MESSAGE] ) +_MaybeAwaitable = typing.Union[collections.Callable[_P, _CoroT[_T]], collections.Callable[_P, _T]] +_AutocompleteCallbackSig = collections.Callable[typing_extensions.Concatenate["AutocompleteContext", _P], _CoroT[None]] -AutocompleteCallbackSig = collections.Callable[..., _CoroT[None]] +AutocompleteCallbackSig = _AutocompleteCallbackSig[...] """Type hint of the callback an autocomplete callback should have. This will be called when handling autocomplete and should be an asynchronous @@ -111,8 +115,8 @@ autocomplete type), returns [None][] and may use dependency injection. """ - -CheckSig = typing.Union[collections.Callable[..., _CoroT[bool]], collections.Callable[..., bool]] +_CheckSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, _P], bool] +CheckSig = _CheckSig[_ContextT_contra, ...] """Type hint of a general context check used with Tanjun [tanjun.abc.ExecutableCommand][] classes. This may be registered with a [tanjun.abc.ExecutableCommand][] to add a rule @@ -123,7 +127,29 @@ current context shouldn't lead to an execution. """ -CommandCallbackSig = collections.Callable[..., _CoroT[None]] +AnyCheckSig = _CheckSig["Context", ...] + +MessageCheckSig = _CheckSig["MessageContext", ...] + +SlashCheckSig = _CheckSig["SlashContext", ...] + + +_CommandCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _P], None] + +_MenuValueT = typing.TypeVar("_MenuValueT", hikari.User, hikari.InteractionMember) +_ManuCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _MenuValueT, _P], None] +MenuCallbackSig = _ManuCallbackSig["MenuContext", _MenuValueT, ...] +"""Type hint of a context menu command callback. + +This is guaranteed two positional; arguments of type [tanjun.abc.MenuContext][] +and either `hikari.User | hikari.InteractionMember` and/or +[hikari.messages.Message][] dependent on the type(s) of menu this is. +""" + +MessageCallbackSig = _CommandCallbackSig["MessageContext", ...] +SlashCallbackSig = _CommandCallbackSig["SlashContext", ...] + +CommandCallbackSig = _CommandCallbackSig["Context", ...] """Type hint of the callback a callable [tanjun.abc.ExecutableCommand][] instance will operate on. This will be called when executing a command and will need to take one @@ -135,10 +161,9 @@ This will have to be asynchronous. """ +_ErrorHookSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, Exception, _P], typing.Optional[bool]] -ErrorHookSig = typing.Union[ - collections.Callable[..., typing.Optional[bool]], collections.Callable[..., _CoroT[typing.Optional[bool]]] -] +ErrorHookSig = _ErrorHookSig[_ContextT_contra, ...] """Type hint of the callback used as a unexpected command error hook. This will be called whenever an unexpected [Exception][] is raised during the @@ -152,8 +177,9 @@ [False][] is returned to indicate that the exception should be re-raised. """ +_HookSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, _P], None] -HookSig = typing.Union[collections.Callable[..., None], collections.Callable[..., _CoroT[None]]] +HookSig = _HookSig[_ContextT_contra, ...] """Type hint of the callback used as a general command hook. !!! note @@ -162,22 +188,16 @@ are passed dependent on the type of hook this is being registered as. """ -ListenerCallbackSig = collections.Callable[..., _CoroT[None]] +_ListenerCallbackSig = collections.Callable[typing_extensions.Concatenate[Exception, _P], _CoroT[None]] + +ListenerCallbackSig = _ListenerCallbackSig[...] """Type hint of a hikari event manager callback. This is guaranteed one positional arg of type [hikari.events.base_events.Event][] regardless of implementation and must be a coruotine function which returns [None][]. """ -MenuCommandCallbackSig = collections.Callable[..., _CoroT[None]] -"""Type hint of a context menu command callback. - -This is guaranteed two positional; arguments of type [tanjun.abc.MenuContext][] -and either `hikari.User | hikari.InteractionMember` and/or -[hikari.messages.Message][] dependent on the type(s) of menu this is. -""" - -MetaEventSig = typing.Union[collections.Callable[..., _CoroT[None]], collections.Callable[..., None]] +MetaEventSig = _MaybeAwaitable[..., None] """Type hint of a client callback. The positional arguments this is guaranteed depend on the event name its being @@ -2415,7 +2435,7 @@ class ExecutableCommand(abc.ABC, typing.Generic[_ContextT_co]): @property @abc.abstractmethod - def checks(self) -> collections.Collection[CheckSig]: + def checks(self) -> collections.Collection[CheckSig[_ContextT_co]]: """Collection of checks that must be met before the command can be executed.""" @property diff --git a/tanjun/checks.py b/tanjun/checks.py index a96b15041..9f446b3de 100644 --- a/tanjun/checks.py +++ b/tanjun/checks.py @@ -91,7 +91,9 @@ def _add_to_command(command: _CommandT, check: tanjun.CheckSig, follow_wrapped: def _optional_kwargs( - command: typing.Optional[_CommandT], check: tanjun.CheckSig, follow_wrapped: bool, / + command: typing.Optional[_CommandT], check: tanjun.AnyCheckSig, / + check: tanjun.CheckSig, + follow_wrapped: bool, ) -> typing.Union[_CommandT, collections.Callable[[_CommandT], _CommandT]]: if command: return _add_to_command(command, check, follow_wrapped) diff --git a/tanjun/clients.py b/tanjun/clients.py index c39d046b9..5154ec8da 100644 --- a/tanjun/clients.py +++ b/tanjun/clients.py @@ -75,7 +75,7 @@ import typing_extensions from typing_extensions import Self - _CheckSigT = typing.TypeVar("_CheckSigT", bound=tanjun.CheckSig) + _CheckSigT = typing.TypeVar("_CheckSigT", bound=tanjun.AnyCheckSig) _AppCmdResponse = typing.Union[ hikari.api.InteractionMessageBuilder, hikari.api.InteractionDeferredBuilder, hikari.api.InteractionModalBuilder ] @@ -679,7 +679,7 @@ def __init__( self._auto_defer_after: typing.Optional[float] = 2.0 self._cache = cache self._cached_application_id: typing.Optional[hikari.Snowflake] = None - self._checks: list[tanjun.CheckSig] = [] + self._checks: list[tanjun.AnyCheckSig] = [] self._client_callbacks: dict[str, list[tanjun.MetaEventSig]] = {} self._components: dict[str, tanjun.Component] = {} self._default_app_cmd_permissions = hikari.Permissions.NONE @@ -1067,7 +1067,7 @@ def cache(self) -> typing.Optional[hikari.api.Cache]: return self._cache @property - def checks(self) -> collections.Collection[tanjun.CheckSig]: + def checks(self) -> collections.Collection[tanjun.AnyCheckSig]: """Collection of the level [tanjun.abc.Context][] checks registered to this client. !!! note @@ -1756,7 +1756,7 @@ def set_human_only(self, value: bool = True, /) -> Self: return self - def add_check(self, *checks: tanjun.CheckSig) -> Self: + def add_check(self: _ClientT, check: tanjun.AnyCheckSig, /) -> _ClientT: """Add a generic check to this client. This will be applied to both message and slash command execution. @@ -1779,7 +1779,7 @@ def add_check(self, *checks: tanjun.CheckSig) -> Self: return self - def remove_check(self, check: tanjun.CheckSig, /) -> Self: + def remove_check(self: _ClientT, check: tanjun.AnyCheckSig, /) -> _ClientT: """Remove a check from the client. Parameters diff --git a/tanjun/commands/base.py b/tanjun/commands/base.py index c898252b0..af99b5572 100644 --- a/tanjun/commands/base.py +++ b/tanjun/commands/base.py @@ -43,7 +43,7 @@ if typing.TYPE_CHECKING: from typing_extensions import Self - _CheckSigT = typing.TypeVar("_CheckSigT", bound=tanjun.CheckSig) + _CheckSigT = typing.TypeVar("_CheckSigT", bound=tanjun.AnyCheckSig) _ContextT = typing.TypeVar("_ContextT", bound="tanjun.Context") @@ -55,13 +55,13 @@ class PartialCommand(tanjun.ExecutableCommand[_ContextT], components.AbstractCom __slots__ = ("_checks", "_component", "_hooks", "_metadata") def __init__(self) -> None: - self._checks: list[tanjun.CheckSig] = [] + self._checks: list[tanjun.AnyCheckSig] = [] self._component: typing.Optional[tanjun.Component] = None self._hooks: typing.Optional[tanjun.Hooks[_ContextT]] = None self._metadata: dict[typing.Any, typing.Any] = {} @property - def checks(self) -> collections.Collection[tanjun.CheckSig]: + def checks(self) -> collections.Collection[tanjun.AnyCheckSig]: # <>. return self._checks.copy() @@ -98,7 +98,7 @@ def set_metadata(self, key: typing.Any, value: typing.Any, /) -> Self: self._metadata[key] = value return self - def add_check(self, *checks: tanjun.CheckSig) -> Self: + def add_check(self: _PartialCommandT, check: tanjun.AnyCheckSig, /) -> _PartialCommandT: # <>. for check in checks: if check not in self._checks: @@ -106,7 +106,7 @@ def add_check(self, *checks: tanjun.CheckSig) -> Self: return self - def remove_check(self, check: tanjun.CheckSig, /) -> Self: + def remove_check(self: _PartialCommandT, check: tanjun.AnyCheckSig, /) -> _PartialCommandT: # <>. self._checks.remove(check) return self diff --git a/tanjun/commands/message.py b/tanjun/commands/message.py index e3b3d9e54..8279d2980 100644 --- a/tanjun/commands/message.py +++ b/tanjun/commands/message.py @@ -48,14 +48,15 @@ from typing_extensions import Self _AnyMessageCommandT = typing.TypeVar("_AnyMessageCommandT", bound=tanjun.MessageCommand[typing.Any]) + _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=tanjun.CommandCallbackSig) _CommandT = typing.Union[ - tanjun.MenuCommand["_CommandCallbackSigT", typing.Any], - tanjun.MessageCommand["_CommandCallbackSigT"], - tanjun.SlashCommand["_CommandCallbackSigT"], + tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], + tanjun.MessageCommand["_AnyCallbackSigT"], + tanjun.SlashCommand["_AnyCallbackSigT"], ] - _CallbackishT = typing.Union[_CommandT["_CommandCallbackSigT"], "_CommandCallbackSigT"] + _CallbackishT = typing.Union[_CommandT["_CallbackSigT"], "_CallbackSigT"] -_CommandCallbackSigT = typing.TypeVar("_CommandCallbackSigT", bound=tanjun.CommandCallbackSig) +_CallbackSigT = typing.TypeVar("_CallbackSigT", bound=tanjun.MessageCallbackSig) _OtherCallbackSigT = typing.TypeVar("_OtherCallbackSigT", bound=tanjun.CommandCallbackSig) _EMPTY_DICT: typing.Final[dict[typing.Any, typing.Any]] = {} _EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() @@ -63,14 +64,14 @@ class _ResultProto(typing.Protocol): @typing.overload - def __call__(self, _: _CommandT[_CommandCallbackSigT], /) -> MessageCommand[_CommandCallbackSigT]: + def __call__(self, _: _CommandT[_CallbackSigT], /) -> MessageCommand[_CallbackSigT]: ... @typing.overload - def __call__(self, _: _CommandCallbackSigT, /) -> MessageCommand[_CommandCallbackSigT]: + def __call__(self, _: _CallbackSigT, /) -> MessageCommand[_CallbackSigT]: ... - def __call__(self, _: _CallbackishT[_CommandCallbackSigT], /) -> MessageCommand[_CommandCallbackSigT]: + def __call__(self, _: _CallbackishT[_CallbackSigT], /) -> MessageCommand[_CallbackSigT]: raise NotImplementedError @@ -114,14 +115,14 @@ def decorator(callback: _CallbackishT[_CommandCallbackSigT], /) -> MessageComman class _GroupResultProto(typing.Protocol): @typing.overload - def __call__(self, _: _CommandT[_CommandCallbackSigT], /) -> MessageCommandGroup[_CommandCallbackSigT]: + def __call__(self, _: _CommandT[_CallbackSigT], /) -> MessageCommandGroup[_CallbackSigT]: ... @typing.overload - def __call__(self, _: _CommandCallbackSigT, /) -> MessageCommandGroup[_CommandCallbackSigT]: + def __call__(self, _: _CallbackSigT, /) -> MessageCommandGroup[_CallbackSigT]: ... - def __call__(self, _: _CallbackishT[_CommandCallbackSigT], /) -> MessageCommandGroup[_CommandCallbackSigT]: + def __call__(self, _: _CallbackishT[_CallbackSigT], /) -> MessageCommandGroup[_CallbackSigT]: raise NotImplementedError @@ -155,7 +156,7 @@ def as_message_command_group( [tanjun.Component.load_from_scope][]. """ - def decorator(callback: _CallbackishT[_CommandCallbackSigT], /) -> MessageCommandGroup[_CommandCallbackSigT]: + def decorator(callback: _CallbackishT[_CallbackSigT], /) -> MessageCommandGroup[_CallbackSigT]: if isinstance(callback, (tanjun.MenuCommand, tanjun.MessageCommand, tanjun.SlashCommand)): wrapped_command = callback callback = callback.callback @@ -170,7 +171,7 @@ def decorator(callback: _CallbackishT[_CommandCallbackSigT], /) -> MessageComman return decorator -class MessageCommand(base.PartialCommand[tanjun.MessageContext], tanjun.MessageCommand[_CommandCallbackSigT]): +class MessageCommand(base.PartialCommand[tanjun.MessageContext], tanjun.MessageCommand[_CallbackSigT]): """Standard implementation of a message command.""" __slots__ = ("_arg_names", "_callback", "_names", "_parent", "_parser", "_wrapped_command") @@ -178,7 +179,7 @@ class MessageCommand(base.PartialCommand[tanjun.MessageContext], tanjun.MessageC @typing.overload def __init__( self, - callback: _CommandT[_CommandCallbackSigT], + callback: _CommandT[_CallbackSigT], name: str, /, *names: str, @@ -190,7 +191,7 @@ def __init__( @typing.overload def __init__( self, - callback: _CommandCallbackSigT, + callback: _CallbackSigT, name: str, /, *names: str, @@ -201,7 +202,7 @@ def __init__( def __init__( self, - callback: _CallbackishT[_CommandCallbackSigT], + callback: _CallbackishT[_CallbackSigT], name: str, /, *names: str, @@ -230,7 +231,7 @@ def __init__( callback = callback.callback self._arg_names = _internal.get_kwargs(callback) if validate_arg_keys else None - self._callback: _CommandCallbackSigT = callback + self._callback: _CallbackSigT = callback self._names = list(dict.fromkeys((name, *names))) self._parent: typing.Optional[tanjun.MessageCommandGroup[typing.Any]] = None self._parser: typing.Optional[tanjun.MessageParser] = None @@ -240,7 +241,7 @@ def __repr__(self) -> str: return f"Command <{self._names}>" if typing.TYPE_CHECKING: - __call__: _CommandCallbackSigT + __call__: _CallbackSigT else: @@ -248,7 +249,7 @@ async def __call__(self, *args, **kwargs) -> None: await self._callback(*args, **kwargs) @property - def callback(self) -> _CommandCallbackSigT: + def callback(self) -> _CallbackSigT: # <>. return self._callback @@ -369,7 +370,7 @@ def load_into_component(self, component: tanjun.Component, /) -> None: self._wrapped_command.load_into_component(component) -class MessageCommandGroup(MessageCommand[_CommandCallbackSigT], tanjun.MessageCommandGroup[_CommandCallbackSigT]): +class MessageCommandGroup(MessageCommand[_CallbackSigT], tanjun.MessageCommandGroup[_CallbackSigT]): """Standard implementation of a message command group.""" __slots__ = ("_commands",) @@ -377,7 +378,7 @@ class MessageCommandGroup(MessageCommand[_CommandCallbackSigT], tanjun.MessageCo @typing.overload def __init__( self, - callback: _CommandT[_CommandCallbackSigT], + callback: _CommandT[_CallbackSigT], name: str, /, *names: str, @@ -390,7 +391,7 @@ def __init__( @typing.overload def __init__( self, - callback: _CommandCallbackSigT, + callback: _CallbackSigT, name: str, /, *names: str, @@ -402,7 +403,7 @@ def __init__( def __init__( self, - callback: _CallbackishT[_CommandCallbackSigT], + callback: _CallbackishT[_CallbackSigT], name: str, /, *names: str, diff --git a/tanjun/components.py b/tanjun/components.py index 82551083f..d37f54bcc 100644 --- a/tanjun/components.py +++ b/tanjun/components.py @@ -55,7 +55,7 @@ _AppCommandContextT = typing.TypeVar("_AppCommandContextT", bound=tanjun.AppCommandContext) _BaseSlashCommandT = typing.TypeVar("_BaseSlashCommandT", bound=tanjun.BaseSlashCommand) - _CheckSigT = typing.TypeVar("_CheckSigT", bound=tanjun.CheckSig) + _CheckSigT = typing.TypeVar("_CheckSigT", bound=tanjun.AnyCheckSig) _ListenerCallbackSigT = typing.TypeVar("_ListenerCallbackSigT", bound=tanjun.ListenerCallbackSig) _MenuCommandT = typing.TypeVar("_MenuCommandT", bound=tanjun.MenuCommand[typing.Any, typing.Any]) _MessageCommandT = typing.TypeVar("_MessageCommandT", bound=tanjun.MessageCommand[typing.Any]) @@ -197,7 +197,7 @@ def __init__(self, *, name: typing.Optional[str] = None, strict: bool = False) - When this is [True][], message command names will not be allowed to contain spaces and will have to be unique to one command within the component. """ - self._checks: list[tanjun.CheckSig] = [] + self._checks: list[tanjun.AnyCheckSig] = [] self._client: typing.Optional[tanjun.Client] = None self._client_callbacks: dict[str, list[tanjun.MetaEventSig]] = {} self._default_app_cmd_permissions: typing.Optional[hikari.Permissions] = None @@ -229,7 +229,7 @@ def is_case_sensitive(self) -> typing.Optional[bool]: return self._is_case_sensitive @property - def checks(self) -> collections.Collection[tanjun.CheckSig]: + def checks(self) -> collections.Collection[tanjun.AnyCheckSig]: """Collection of the checks being run against every command execution in this component.""" return self._checks.copy() @@ -565,7 +565,7 @@ def set_slash_hooks(self, hooks: typing.Optional[tanjun.SlashHooks], /) -> Self: self._slash_hooks = hooks return self - def add_check(self, *checks: tanjun.CheckSig) -> Self: + def add_check(self: _ComponentT, check: tanjun.AnyCheckSig, /) -> _ComponentT: """Add a command check to this component to be used for all its commands. Parameters @@ -584,7 +584,7 @@ def add_check(self, *checks: tanjun.CheckSig) -> Self: return self - def remove_check(self, check: tanjun.CheckSig, /) -> Self: + def remove_check(self: _ComponentT, check: tanjun.AnyCheckSig, /) -> _ComponentT: """Remove a command check from this component. Parameters From 4e2b78a7a79263cf6b1b3a0bd22246c29cb2100f Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Sun, 14 Aug 2022 12:17:53 +0100 Subject: [PATCH 03/45] Some post-rebase fixes --- tanjun/abc.py | 33 +++++++++--------- tanjun/commands/menu.py | 65 +++++++++++++++++++++--------------- tanjun/commands/message.py | 68 +++++++++++++++++++++++--------------- tanjun/commands/slash.py | 43 ++++++++++++++---------- 4 files changed, 124 insertions(+), 85 deletions(-) diff --git a/tanjun/abc.py b/tanjun/abc.py index ed2e7940e..f8d1cc063 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -51,7 +51,7 @@ "Hooks", "ListenerCallbackSig", "MenuCommand", - "MenuCommandCallbackSig", + "MenuCallbackSig", "MenuContext", "MenuHooks", "MessageCommand", @@ -94,11 +94,9 @@ _P = typing_extensions.ParamSpec("_P") _T = typing.TypeVar("_T") _AppCommandContextT = typing.TypeVar("_AppCommandContextT", bound="AppCommandContext") -_CommandCallbackSigT = typing.TypeVar("_CommandCallbackSigT", bound="CommandCallbackSig") _ContextT_co = typing.TypeVar("_ContextT_co", covariant=True, bound="Context") _ContextT_contra = typing.TypeVar("_ContextT_contra", bound="Context", contravariant=True) _CoroT = collections.Coroutine[typing.Any, typing.Any, _T] -_MenuCommandCallbackSigT = typing.TypeVar("_MenuCommandCallbackSigT", bound="MenuCommandCallbackSig") _MenuTypeT = typing.TypeVar( "_MenuTypeT", typing.Literal[hikari.CommandType.USER], typing.Literal[hikari.CommandType.MESSAGE] ) @@ -146,8 +144,13 @@ [hikari.messages.Message][] dependent on the type(s) of menu this is. """ +_MenuCallbackSigT = typing.TypeVar("_MenuCallbackSigT", bound="MenuCallbackSig[typing.Any]") + MessageCallbackSig = _CommandCallbackSig["MessageContext", ...] +_MessageCallbackSigT = typing.TypeVar("_MessageCallbackSigT", bound=MessageCallbackSig) + SlashCallbackSig = _CommandCallbackSig["SlashContext", ...] +_SlashCallbackSigT = typing.TypeVar("_SlashCallbackSigT", bound=SlashCallbackSig) CommandCallbackSig = _CommandCallbackSig["Context", ...] """Type hint of the callback a callable [tanjun.abc.ExecutableCommand][] instance will operate on. @@ -2122,7 +2125,7 @@ def copy(self) -> Self: raise NotImplementedError @abc.abstractmethod - def add_on_error(self, callback: ErrorHookSig, /) -> Self: + def add_on_error(self: _T, callback: ErrorHookSig[_ContextT_contra], /) -> _T: """Add an error callback to this hook object. !!! note @@ -2191,7 +2194,7 @@ async def on_error(ctx: tanjun.abc.Context, error: Exception) -> bool: """ @abc.abstractmethod - def add_on_parser_error(self, callback: HookSig, /) -> Self: + def add_on_parser_error(self: _T, callback: HookSig[_ContextT_contra], /) -> _T: """Add a parser error callback to this hook object. Parameters @@ -2242,7 +2245,7 @@ async def on_parser_error(ctx: tanjun.abc.Context, error: tanjun.ParserError) -> """ @abc.abstractmethod - def add_post_execution(self, callback: HookSig, /) -> Self: + def add_post_execution(self: _T, callback: HookSig[_ContextT_contra], /) -> _T: """Add a post-execution callback to this hook object. Parameters @@ -2290,7 +2293,7 @@ async def post_execution(ctx: tanjun.abc.Context) -> None: """ @abc.abstractmethod - def add_pre_execution(self, callback: HookSig, /) -> Self: + def add_pre_execution(self: _T, callback: HookSig[_ContextT_contra], /) -> _T: """Add a pre-execution callback for this hook object. Parameters @@ -2338,7 +2341,7 @@ async def pre_execution(ctx: tanjun.abc.Context) -> None: """ @abc.abstractmethod - def add_on_success(self, callback: HookSig, /) -> Self: + def add_on_success(self: _T, callback: HookSig[_ContextT_contra], /) -> _T: """Add a success callback to this hook object. Parameters @@ -2747,14 +2750,14 @@ async def execute_autocomplete( ... -class SlashCommand(BaseSlashCommand, abc.ABC, typing.Generic[_CommandCallbackSigT]): +class SlashCommand(BaseSlashCommand, abc.ABC, typing.Generic[_SlashCallbackSigT]): """A command that can be executed in a slash context.""" __slots__ = () @property @abc.abstractmethod - def callback(self) -> _CommandCallbackSigT: + def callback(self) -> _SlashCallbackSigT: """Callback which is called during execution.""" @property @@ -2773,14 +2776,14 @@ def str_autocompletes(self) -> collections.Mapping[str, AutocompleteCallbackSig] """Collection of the string option autocompletes.""" -class MenuCommand(AppCommand[MenuContext], typing.Generic[_MenuCommandCallbackSigT, _MenuTypeT]): +class MenuCommand(AppCommand[MenuContext], typing.Generic[_MenuCallbackSigT, _MenuTypeT]): """A contextmenu command.""" __slots__ = () @property @abc.abstractmethod - def callback(self) -> _MenuCommandCallbackSigT: + def callback(self) -> _MenuCallbackSigT: """Callback which is called during execution.""" @property @@ -2944,14 +2947,14 @@ def validate_arg_keys(self, callback_name: str, names: collections.Container[str """ -class MessageCommand(ExecutableCommand[MessageContext], abc.ABC, typing.Generic[_CommandCallbackSigT]): +class MessageCommand(ExecutableCommand[MessageContext], abc.ABC, typing.Generic[_MessageCallbackSigT]): """Standard interface of a message command.""" __slots__ = () @property @abc.abstractmethod - def callback(self) -> _CommandCallbackSigT: + def callback(self) -> _MessageCallbackSigT: """Callback which is called during execution. !!! note @@ -3036,7 +3039,7 @@ async def execute( raise NotImplementedError -class MessageCommandGroup(MessageCommand[_CommandCallbackSigT], abc.ABC): +class MessageCommandGroup(MessageCommand[_MessageCallbackSigT], abc.ABC): """Standard interface of a message command group.""" __slots__ = () diff --git a/tanjun/commands/menu.py b/tanjun/commands/menu.py index 90ea6ef79..c5902f070 100644 --- a/tanjun/commands/menu.py +++ b/tanjun/commands/menu.py @@ -48,22 +48,38 @@ from typing_extensions import Self - _CommandT = typing.Union[ - tanjun.MenuCommand["_MenuCommandCallbackSigT", typing.Any], - tanjun.MessageCommand["_MenuCommandCallbackSigT"], - tanjun.SlashCommand["_MenuCommandCallbackSigT"], + _AnyCallbackSigT = typing.TypeVar("_CommandCallbackSigT", bound="tanjun.CommandCallbackSig") + _AnyCommandT = typing.Union[ + tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], + tanjun.MessageCommand["_AnyCallbackSigT"], + tanjun.SlashCommand["_AnyCallbackSigT"], ] - _CallbackishT = typing.Union["_MenuCommandCallbackSigT", _CommandT["_MenuCommandCallbackSigT"]] + _CallbackishT = typing.Union["_AnyCallbackSigT", _AnyCommandT["_AnyCallbackSigT"]] import hikari -_MenuCommandCallbackSigT = typing.TypeVar("_MenuCommandCallbackSigT", bound="tanjun.MenuCommandCallbackSig") +_MenuCommandCallbackSigT = typing.TypeVar("_MenuCommandCallbackSigT", bound="tanjun.MenuCallbackSig[typing.Any]") _MenuTypeT = typing.TypeVar( "_MenuTypeT", typing.Literal[hikari.CommandType.USER], typing.Literal[hikari.CommandType.MESSAGE] ) _EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() +class _ResultProto(typing.Protocol[_MenuTypeT]): + @typing.overload + def __call__(self, _: _AnyCommandT[_AnyCallbackSigT], /) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: + ... + + @typing.overload + def __call__(self, _: _MenuCommandCallbackSigT, /) -> MenuCommand[_MenuCommandCallbackSigT, _MenuTypeT]: + ... + + def __call__( + self, _: _CallbackishT[_AnyCallbackSigT], / + ) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: + raise NotImplementedError + + def _as_menu( name: typing.Union[str, collections.Mapping[str, str]], type_: _MenuTypeT, @@ -75,9 +91,17 @@ def _as_menu( dm_enabled: typing.Optional[bool] = None, is_global: bool = True, ) -> _ResultProto[_MenuTypeT]: + @typing.overload + def decorator(callback: _AnyCommandT[_AnyCallbackSigT], /) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: + ... + + @typing.overload + def decorator(callback: _MenuCommandCallbackSigT, /) -> MenuCommand[_MenuCommandCallbackSigT, _MenuTypeT]: + ... + def decorator( - callback: _CallbackishT[_MenuCommandCallbackSigT], / - ) -> MenuCommand[_MenuCommandCallbackSigT, _MenuTypeT]: + callback: _CallbackishT[_AnyCallbackSigT], / + ) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: if isinstance(callback, (tanjun.MenuCommand, tanjun.MessageCommand, tanjun.SlashCommand)): wrapped_command = callback callback = callback.callback @@ -100,21 +124,6 @@ def decorator( return decorator -class _ResultProto(typing.Protocol[_MenuTypeT]): - @typing.overload - def __call__(self, _: _CommandT[_MenuCommandCallbackSigT], /) -> MenuCommand[_MenuCommandCallbackSigT, _MenuTypeT]: - ... - - @typing.overload - def __call__(self, _: _MenuCommandCallbackSigT, /) -> MenuCommand[_MenuCommandCallbackSigT, _MenuTypeT]: - ... - - def __call__( - self, _: _CallbackishT[_MenuCommandCallbackSigT], / - ) -> MenuCommand[_MenuCommandCallbackSigT, _MenuTypeT]: - raise NotImplementedError - - def as_message_menu( name: typing.Union[str, collections.Mapping[str, str]], /, @@ -317,7 +326,9 @@ class MenuCommand(base.PartialCommand[tanjun.MenuContext], tanjun.MenuCommand[_M @typing.overload def __init__( self, - callback: _CommandT[_MenuCommandCallbackSigT], + callback: _AnyCommandT[ + _AnyCallbackSigT, + ], type_: _MenuTypeT, name: typing.Union[str, collections.Mapping[str, str]], /, @@ -349,8 +360,8 @@ def __init__( ... def __init__( - self, - callback: _CallbackishT[_MenuCommandCallbackSigT], + self: MenuCommand[_AnyCallbackSigT,_MenuTypeT], + callback: _CallbackishT[_AnyCallbackSigT], type_: _MenuTypeT, name: typing.Union[str, collections.Mapping[str, str]], /, @@ -443,7 +454,7 @@ def __init__( default_member_permissions = hikari.Permissions(default_member_permissions) self._always_defer = always_defer - self._callback = callback + self._callback: _MenuCommandCallbackSigT = callback self._default_member_permissions = default_member_permissions self._defaults_to_ephemeral = default_to_ephemeral self._is_dm_enabled = dm_enabled diff --git a/tanjun/commands/message.py b/tanjun/commands/message.py index 8279d2980..93b616fab 100644 --- a/tanjun/commands/message.py +++ b/tanjun/commands/message.py @@ -49,14 +49,14 @@ _AnyMessageCommandT = typing.TypeVar("_AnyMessageCommandT", bound=tanjun.MessageCommand[typing.Any]) _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=tanjun.CommandCallbackSig) - _CommandT = typing.Union[ + _AnyCommandT = typing.Union[ tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], tanjun.MessageCommand["_AnyCallbackSigT"], tanjun.SlashCommand["_AnyCallbackSigT"], ] - _CallbackishT = typing.Union[_CommandT["_CallbackSigT"], "_CallbackSigT"] + _CallbackishT = typing.Union[_AnyCommandT["_AnyCallbackSigT"], "_AnyCallbackSigT"] -_CallbackSigT = typing.TypeVar("_CallbackSigT", bound=tanjun.MessageCallbackSig) +_MessageCallbackSigT = typing.TypeVar("_MessageCallbackSigT", bound=tanjun.MessageCallbackSig) _OtherCallbackSigT = typing.TypeVar("_OtherCallbackSigT", bound=tanjun.CommandCallbackSig) _EMPTY_DICT: typing.Final[dict[typing.Any, typing.Any]] = {} _EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() @@ -64,14 +64,14 @@ class _ResultProto(typing.Protocol): @typing.overload - def __call__(self, _: _CommandT[_CallbackSigT], /) -> MessageCommand[_CallbackSigT]: + def __call__(self, _: _AnyCommandT[_AnyCallbackSigT], /) -> MessageCommand[_AnyCallbackSigT]: ... @typing.overload - def __call__(self, _: _CallbackSigT, /) -> MessageCommand[_CallbackSigT]: + def __call__(self, _: _MessageCallbackSigT, /) -> MessageCommand[_MessageCallbackSigT]: ... - def __call__(self, _: _CallbackishT[_CallbackSigT], /) -> MessageCommand[_CallbackSigT]: + def __call__(self, _: _CallbackishT[_AnyCallbackSigT], /) -> MessageCommand[_AnyCallbackSigT]: raise NotImplementedError @@ -98,7 +98,15 @@ def as_message_command(name: str, /, *names: str, validate_arg_keys: bool = True [tanjun.Component.load_from_scope][]. """ - def decorator(callback: _CallbackishT[_CommandCallbackSigT], /) -> MessageCommand[_CommandCallbackSigT]: + @typing.overload + def decorator(callback: _AnyCommandT[_AnyCallbackSigT], /) -> MessageCommand[_AnyCallbackSigT]: + ... + + @typing.overload + def decorator(callback: _MessageCallbackSigT, /) -> MessageCommand[_MessageCallbackSigT]: + ... + + def decorator(callback: _CallbackishT[_AnyCallbackSigT], /) -> MessageCommand[_AnyCallbackSigT]: if isinstance(callback, (tanjun.MenuCommand, tanjun.MessageCommand, tanjun.SlashCommand)): wrapped_command = callback callback = callback.callback @@ -115,14 +123,14 @@ def decorator(callback: _CallbackishT[_CommandCallbackSigT], /) -> MessageComman class _GroupResultProto(typing.Protocol): @typing.overload - def __call__(self, _: _CommandT[_CallbackSigT], /) -> MessageCommandGroup[_CallbackSigT]: + def __call__(self, _: _AnyCommandT[_AnyCallbackSigT], /) -> MessageCommandGroup[_AnyCallbackSigT]: ... @typing.overload - def __call__(self, _: _CallbackSigT, /) -> MessageCommandGroup[_CallbackSigT]: + def __call__(self, _: _MessageCallbackSigT, /) -> MessageCommandGroup[_MessageCallbackSigT]: ... - def __call__(self, _: _CallbackishT[_CallbackSigT], /) -> MessageCommandGroup[_CallbackSigT]: + def __call__(self, _: _CallbackishT[_AnyCallbackSigT], /) -> MessageCommandGroup[_AnyCallbackSigT]: raise NotImplementedError @@ -156,7 +164,15 @@ def as_message_command_group( [tanjun.Component.load_from_scope][]. """ - def decorator(callback: _CallbackishT[_CallbackSigT], /) -> MessageCommandGroup[_CallbackSigT]: + @typing.overload + def decorator(callback: _AnyCommandT[_AnyCallbackSigT], /) -> MessageCommandGroup[_AnyCallbackSigT]: + ... + + @typing.overload + def decorator(callback: _MessageCallbackSigT, /) -> MessageCommandGroup[_MessageCallbackSigT]: + ... + + def decorator(callback: _CallbackishT[_AnyCallbackSigT], /) -> MessageCommandGroup[_AnyCallbackSigT]: if isinstance(callback, (tanjun.MenuCommand, tanjun.MessageCommand, tanjun.SlashCommand)): wrapped_command = callback callback = callback.callback @@ -171,15 +187,15 @@ def decorator(callback: _CallbackishT[_CallbackSigT], /) -> MessageCommandGroup[ return decorator -class MessageCommand(base.PartialCommand[tanjun.MessageContext], tanjun.MessageCommand[_CallbackSigT]): +class MessageCommand(base.PartialCommand[tanjun.MessageContext], tanjun.MessageCommand[_MessageCallbackSigT]): """Standard implementation of a message command.""" __slots__ = ("_arg_names", "_callback", "_names", "_parent", "_parser", "_wrapped_command") @typing.overload def __init__( - self, - callback: _CommandT[_CallbackSigT], + self: MessageCommand[_AnyCallbackSigT], + callback: _AnyCommandT[_AnyCallbackSigT], name: str, /, *names: str, @@ -191,7 +207,7 @@ def __init__( @typing.overload def __init__( self, - callback: _CallbackSigT, + callback: _MessageCallbackSigT, name: str, /, *names: str, @@ -201,8 +217,8 @@ def __init__( ... def __init__( - self, - callback: _CallbackishT[_CallbackSigT], + self: MessageCommand[_AnyCallbackSigT], + callback: _CallbackishT[_AnyCallbackSigT], name: str, /, *names: str, @@ -231,7 +247,7 @@ def __init__( callback = callback.callback self._arg_names = _internal.get_kwargs(callback) if validate_arg_keys else None - self._callback: _CallbackSigT = callback + self._callback: _MessageCallbackSigT = callback self._names = list(dict.fromkeys((name, *names))) self._parent: typing.Optional[tanjun.MessageCommandGroup[typing.Any]] = None self._parser: typing.Optional[tanjun.MessageParser] = None @@ -241,7 +257,7 @@ def __repr__(self) -> str: return f"Command <{self._names}>" if typing.TYPE_CHECKING: - __call__: _CallbackSigT + __call__: _MessageCallbackSigT else: @@ -249,7 +265,7 @@ async def __call__(self, *args, **kwargs) -> None: await self._callback(*args, **kwargs) @property - def callback(self) -> _CallbackSigT: + def callback(self) -> _MessageCallbackSigT: # <>. return self._callback @@ -370,15 +386,15 @@ def load_into_component(self, component: tanjun.Component, /) -> None: self._wrapped_command.load_into_component(component) -class MessageCommandGroup(MessageCommand[_CallbackSigT], tanjun.MessageCommandGroup[_CallbackSigT]): +class MessageCommandGroup(MessageCommand[_MessageCallbackSigT], tanjun.MessageCommandGroup[_MessageCallbackSigT]): """Standard implementation of a message command group.""" __slots__ = ("_commands",) @typing.overload def __init__( - self, - callback: _CommandT[_CallbackSigT], + self: MessageCommandGroup[_AnyCallbackSigT], + callback: _AnyCommandT[_AnyCallbackSigT], name: str, /, *names: str, @@ -391,7 +407,7 @@ def __init__( @typing.overload def __init__( self, - callback: _CallbackSigT, + callback: _MessageCallbackSigT, name: str, /, *names: str, @@ -402,8 +418,8 @@ def __init__( ... def __init__( - self, - callback: _CallbackishT[_CallbackSigT], + self: MessageCommandGroup[_AnyCallbackSigT], + callback: _CallbackishT[_AnyCallbackSigT], name: str, /, *names: str, diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index 302095fd1..4f74c047a 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -72,15 +72,16 @@ from hikari.api import special_endpoints as special_endpoints_api from typing_extensions import Self + _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=tanjun.CommandCallbackSig) _AutocompleteCallbackSigT = typing.TypeVar("_AutocompleteCallbackSigT", bound=tanjun.AutocompleteCallbackSig) _AnyBaseSlashCommandT = typing.TypeVar("_AnyBaseSlashCommandT", bound="tanjun.BaseSlashCommand") _SlashCommandT = typing.TypeVar("_SlashCommandT", bound="SlashCommand[typing.Any]") - _CommandT = typing.Union[ - tanjun.MenuCommand["_CommandCallbackSigT", typing.Any], - tanjun.MessageCommand["_CommandCallbackSigT"], - tanjun.SlashCommand["_CommandCallbackSigT"], + _AnyCommandT = typing.Union[ + tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], + tanjun.MessageCommand["_AnyCallbackSigT"], + tanjun.SlashCommand["_AnyCallbackSigT"], ] - _CallbackishT = typing.Union["_CommandCallbackSigT", _CommandT["_CommandCallbackSigT"]] + _CallbackishT = typing.Union["_AnyCallbackSigT", _AnyCommandT["_AnyCallbackSigT"]] _CommandCallbackSigT = typing.TypeVar("_CommandCallbackSigT", bound=tanjun.CommandCallbackSig) _EMPTY_DICT: typing.Final[dict[typing.Any, typing.Any]] = {} @@ -232,14 +233,14 @@ async def help_me_command(ctx: tanjun.abc.SlashContext) -> None: class _ResultProto(typing.Protocol): @typing.overload - def __call__(self, _: _CommandT[_CommandCallbackSigT], /) -> SlashCommand[_CommandCallbackSigT]: + def __call__(self, _: _AnyCommandT[_AnyCallbackSigT], /) -> SlashCommand[_AnyCallbackSigT]: ... @typing.overload - def __call__(self, _: _CommandCallbackSigT, /) -> SlashCommand[_CommandCallbackSigT]: + def __call__(self, _: _SlashCallbackSigT, /) -> SlashCommand[_SlashCallbackSigT]: ... - def __call__(self, _: _CallbackishT[_CommandCallbackSigT], /) -> SlashCommand[_CommandCallbackSigT]: + def __call__(self, _: _CallbackishT[_AnyCallbackSigT], /) -> SlashCommand[_AnyCallbackSigT]: raise NotImplementedError @@ -343,7 +344,15 @@ async def ping_command(self, ctx: tanjun.abc.SlashContext) -> None: * If the description is over 100 characters long. """ # noqa: D202, E501 - def decorator(callback: _CallbackishT[_CommandCallbackSigT], /) -> SlashCommand[_CommandCallbackSigT]: + @typing.overload + def decorator(callback: _AnyCommandT[_AnyCallbackSigT], /) -> SlashCommand[_AnyCallbackSigT]: + ... + + @typing.overload + def decorator(callback: _SlashCallbackSigT, /) -> SlashCommand[_SlashCallbackSigT]: + ... + + def decorator(callback: _CallbackishT[_AnyCallbackSigT], /) -> SlashCommand[_AnyCallbackSigT]: if isinstance(callback, (tanjun.MenuCommand, tanjun.MessageCommand, tanjun.SlashCommand)): wrapped_command = callback callback = callback.callback @@ -1419,7 +1428,7 @@ def _assert_in_range(name: str, value: typing.Optional[int], min_value: int, max raise ValueError(f"`{name}` must be less than or equal to {max_value}") -class SlashCommand(BaseSlashCommand, tanjun.SlashCommand[_CommandCallbackSigT]): +class SlashCommand(BaseSlashCommand, tanjun.SlashCommand[_SlashCallbackSigT]): """Standard implementation of a slash command.""" __slots__ = ( @@ -1437,8 +1446,8 @@ class SlashCommand(BaseSlashCommand, tanjun.SlashCommand[_CommandCallbackSigT]): @typing.overload def __init__( - self, - callback: _CommandT[_CommandCallbackSigT], + self: SlashCommand[_AnyCallbackSigT], + callback: _AnyCommandT[_AnyCallbackSigT], name: typing.Union[str, collections.Mapping[str, str]], description: typing.Union[str, collections.Mapping[str, str]], /, @@ -1457,7 +1466,7 @@ def __init__( @typing.overload def __init__( self, - callback: _CommandCallbackSigT, + callback: _SlashCallbackSigT, name: typing.Union[str, collections.Mapping[str, str]], description: typing.Union[str, collections.Mapping[str, str]], /, @@ -1475,7 +1484,7 @@ def __init__( def __init__( self, - callback: _CallbackishT[_CommandCallbackSigT], + callback: _CallbackishT[_AnyCallbackSigT], name: typing.Union[str, collections.Mapping[str, str]], description: typing.Union[str, collections.Mapping[str, str]], /, @@ -1576,7 +1585,7 @@ def __init__( self._builder = _SlashCommandBuilder( self.name, self.name_localisations, self.description, self.description_localisations, sort_options ) - self._callback: _CommandCallbackSigT = callback + self._callback: _SlashCallbackSigT = callback self._client: typing.Optional[tanjun.Client] = None self._float_autocompletes: dict[str, tanjun.AutocompleteCallbackSig] = {} self._int_autocompletes: dict[str, tanjun.AutocompleteCallbackSig] = {} @@ -1585,7 +1594,7 @@ def __init__( self._wrapped_command = _wrapped_command if typing.TYPE_CHECKING: - __call__: _CommandCallbackSigT + __call__: _SlashCallbackSigT else: @@ -1593,7 +1602,7 @@ async def __call__(self, *args, **kwargs) -> None: await self._callback(*args, **kwargs) @property - def callback(self) -> _CommandCallbackSigT: + def callback(self) -> _SlashCallbackSigT: # <>. return self._callback From 34e962fbba8d562d224e7dca82e30d020403c979 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 14 Aug 2022 11:18:25 +0000 Subject: [PATCH 04/45] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tanjun/abc.py | 2 +- tanjun/commands/menu.py | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/tanjun/abc.py b/tanjun/abc.py index f8d1cc063..b5d62c212 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -50,8 +50,8 @@ "HookSig", "Hooks", "ListenerCallbackSig", - "MenuCommand", "MenuCallbackSig", + "MenuCommand", "MenuContext", "MenuHooks", "MessageCommand", diff --git a/tanjun/commands/menu.py b/tanjun/commands/menu.py index c5902f070..e93d3b300 100644 --- a/tanjun/commands/menu.py +++ b/tanjun/commands/menu.py @@ -74,9 +74,7 @@ def __call__(self, _: _AnyCommandT[_AnyCallbackSigT], /) -> MenuCommand[_AnyCall def __call__(self, _: _MenuCommandCallbackSigT, /) -> MenuCommand[_MenuCommandCallbackSigT, _MenuTypeT]: ... - def __call__( - self, _: _CallbackishT[_AnyCallbackSigT], / - ) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: + def __call__(self, _: _CallbackishT[_AnyCallbackSigT], /) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: raise NotImplementedError @@ -99,9 +97,7 @@ def decorator(callback: _AnyCommandT[_AnyCallbackSigT], /) -> MenuCommand[_AnyCa def decorator(callback: _MenuCommandCallbackSigT, /) -> MenuCommand[_MenuCommandCallbackSigT, _MenuTypeT]: ... - def decorator( - callback: _CallbackishT[_AnyCallbackSigT], / - ) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: + def decorator(callback: _CallbackishT[_AnyCallbackSigT], /) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: if isinstance(callback, (tanjun.MenuCommand, tanjun.MessageCommand, tanjun.SlashCommand)): wrapped_command = callback callback = callback.callback @@ -326,6 +322,7 @@ class MenuCommand(base.PartialCommand[tanjun.MenuContext], tanjun.MenuCommand[_M @typing.overload def __init__( self, + self: MenuCommand[_AnyCallbackSigT, _MenuTypeT], callback: _AnyCommandT[ _AnyCallbackSigT, ], @@ -360,7 +357,7 @@ def __init__( ... def __init__( - self: MenuCommand[_AnyCallbackSigT,_MenuTypeT], + self: MenuCommand[_AnyCallbackSigT, _MenuTypeT], callback: _CallbackishT[_AnyCallbackSigT], type_: _MenuTypeT, name: typing.Union[str, collections.Mapping[str, str]], From acc7787dd7bc9fa483d5f697c69707e0a9b6ca9e Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Mon, 5 Sep 2022 02:59:55 +0100 Subject: [PATCH 05/45] Post-rebase fixes (mypy broken point) --- CHANGELOG.md | 3 + pyproject.toml | 2 +- tanjun/__init__.py | 2 + tanjun/_internal/__init__.py | 9 +- tanjun/abc.py | 22 +++-- tanjun/checks.py | 53 ++++++------ tanjun/clients.py | 4 +- tanjun/commands/base.py | 4 +- tanjun/commands/menu.py | 16 ++-- tanjun/commands/message.py | 10 +-- tanjun/commands/slash.py | 11 +-- tanjun/components.py | 4 +- tanjun/hooks.py | 159 +++++++++++++++++++++++++++++------ 13 files changed, 208 insertions(+), 91 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf31804c4..37687f81d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- [tanjun.MenuHooks][] is now exported top-level. + ### [2.11.2] - 2023-01-23 ### Changed - [tanjun.clients.Client.from_gateway_bot][] can now also take cache-less `ShardAware` bots. diff --git a/pyproject.toml b/pyproject.toml index 3085ed28b..7b02c7c16 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,7 @@ classifiers = [ "Topic :: Utilities", "Typing :: Typed", ] -dependencies = ["alluka>=0.1.2, <1", "hikari>=2.0.0.dev115, <3"] +dependencies = ["alluka>=0.1.2, <1", "hikari>=2.0.0.dev115, <3", "typing-extensions~=4.2"] dynamic = ["description"] [project.urls] diff --git a/tanjun/__init__.py b/tanjun/__init__.py index 0f668dce7..c6159682f 100644 --- a/tanjun/__init__.py +++ b/tanjun/__init__.py @@ -153,6 +153,7 @@ async def hello(ctx: tanjun.abc.Context, user: hikari.User | None) -> None: "dependencies", "errors", "hooks", + "MenuHooks", "inject", "inject_lc", "injected", @@ -298,6 +299,7 @@ async def hello(ctx: tanjun.abc.Context, user: hikari.User | None) -> None: from .hooks import Hooks from .hooks import MessageHooks from .hooks import SlashHooks +from .hooks import MenuHooks from .injecting import as_self_injecting from .parsing import ShlexParser from .parsing import with_argument diff --git a/tanjun/_internal/__init__.py b/tanjun/_internal/__init__.py index ade139dd7..c0fa75362 100644 --- a/tanjun/_internal/__init__.py +++ b/tanjun/_internal/__init__.py @@ -57,6 +57,7 @@ _P = typing_extensions.ParamSpec("_P") + _ContextT = typing.TypeVar("_ContextT", bound=abc.Context) _TreeT = dict[ typing.Union[str, "_IndexKeys"], typing.Union["_TreeT", list[tuple[list[str], tanjun.MessageCommand[typing.Any]]]], @@ -88,21 +89,21 @@ class _NoDefaultEnum(enum.Enum): """The type of `NO_DEFAULT`.""" -async def _execute_check(ctx: tanjun.Context, callback: tanjun.CheckSig, /) -> bool: +async def _execute_check(ctx: _ContextT, callback: tanjun.CheckSig[_ContextT], /) -> bool: if result := await ctx.call_with_async_di(callback, ctx): return result raise errors.FailedCheck -async def gather_checks(ctx: tanjun.Context, checks: collections.Iterable[tanjun.CheckSig], /) -> bool: +async def gather_checks(ctx: _ContextT, checks: collections.Iterable[tanjun.CheckSig[_ContextT]], /) -> bool: """Gather a collection of checks. Parameters ---------- - ctx + ctx : tanjun.abc.Context The context to check. - checks + checks : collections.abc.Iterable[tanjun.abc.CheckSig] An iterable of injectable checks. Returns diff --git a/tanjun/abc.py b/tanjun/abc.py index b5d62c212..4d3ce5ff0 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -84,6 +84,7 @@ _AutocompleteValueT = typing.TypeVar("_AutocompleteValueT", int, str, float) _BaseSlashCommandT = typing.TypeVar("_BaseSlashCommandT", bound="BaseSlashCommand") + _CommandCallbackSigT = typing.TypeVar("_CommandCallbackSigT", bound="CommandCallbackSig") _ErrorHookSigT = typing.TypeVar("_ErrorHookSigT", bound="ErrorHookSig") _HookSigT = typing.TypeVar("_HookSigT", bound="HookSig") _ListenerCallbackSigT = typing.TypeVar("_ListenerCallbackSigT", bound="ListenerCallbackSig") @@ -132,10 +133,13 @@ SlashCheckSig = _CheckSig["SlashContext", ...] -_CommandCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _P], None] +_CommandCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _P], collections.Coroutine[typing.Any, typing.Any, None]] _MenuValueT = typing.TypeVar("_MenuValueT", hikari.User, hikari.InteractionMember) -_ManuCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _MenuValueT, _P], None] +_ManuCallbackSig = collections.Callable[ + typing_extensions.Concatenate[_ContextT_contra, _MenuValueT, _P], + collections.Coroutine[typing.Any, typing.Any, None] +] MenuCallbackSig = _ManuCallbackSig["MenuContext", _MenuValueT, ...] """Type hint of a context menu command callback. @@ -2125,7 +2129,7 @@ def copy(self) -> Self: raise NotImplementedError @abc.abstractmethod - def add_on_error(self: _T, callback: ErrorHookSig[_ContextT_contra], /) -> _T: + def add_on_error(self, callback: ErrorHookSig[_ContextT_contra], /) -> Self: """Add an error callback to this hook object. !!! note @@ -2194,7 +2198,7 @@ async def on_error(ctx: tanjun.abc.Context, error: Exception) -> bool: """ @abc.abstractmethod - def add_on_parser_error(self: _T, callback: HookSig[_ContextT_contra], /) -> _T: + def add_on_parser_error(self, callback: HookSig[_ContextT_contra], /) -> Self: """Add a parser error callback to this hook object. Parameters @@ -2245,7 +2249,7 @@ async def on_parser_error(ctx: tanjun.abc.Context, error: tanjun.ParserError) -> """ @abc.abstractmethod - def add_post_execution(self: _T, callback: HookSig[_ContextT_contra], /) -> _T: + def add_post_execution(self, callback: HookSig[_ContextT_contra], /) -> Self: """Add a post-execution callback to this hook object. Parameters @@ -2293,7 +2297,7 @@ async def post_execution(ctx: tanjun.abc.Context) -> None: """ @abc.abstractmethod - def add_pre_execution(self: _T, callback: HookSig[_ContextT_contra], /) -> _T: + def add_pre_execution(self, callback: HookSig[_ContextT_contra], /) -> Self: """Add a pre-execution callback for this hook object. Parameters @@ -2341,7 +2345,7 @@ async def pre_execution(ctx: tanjun.abc.Context) -> None: """ @abc.abstractmethod - def add_on_success(self: _T, callback: HookSig[_ContextT_contra], /) -> _T: + def add_on_success(self, callback: HookSig[_ContextT_contra], /) -> Self: """Add a success callback to this hook object. Parameters @@ -2495,7 +2499,7 @@ def set_hooks(self, hooks: typing.Optional[Hooks[_ContextT_co]], /) -> Self: """ @abc.abstractmethod - def add_check(self, *checks: CheckSig) -> Self: # TODO: remove or add with_check? + def add_check(self, *checks: CheckSig[_ContextT_co]) -> Self: # TODO: remove or add with_check? """Add a check to the command. Parameters @@ -2510,7 +2514,7 @@ def add_check(self, *checks: CheckSig) -> Self: # TODO: remove or add with_chec """ @abc.abstractmethod - def remove_check(self, check: CheckSig, /) -> Self: + def remove_check(self, check: CheckSig[_ContextT_co], /) -> Self: """Remove a check from the command. Parameters diff --git a/tanjun/checks.py b/tanjun/checks.py index 9f446b3de..fa5434bfc 100644 --- a/tanjun/checks.py +++ b/tanjun/checks.py @@ -69,10 +69,11 @@ from ._internal import localisation if typing.TYPE_CHECKING: + _ContextT_contra = typing.TypeVar("_ContextT_contra", bound=tanjun.Context, contravariant=True) - class _AnyCallback(typing.Protocol): + class _AnyCallback(typing.Protocol[_ContextT_contra]): async def __call__( - self, ctx: tanjun.Context, /, *, localiser: typing.Optional[dependencies.AbstractLocaliser] = None + self, ctx: _ContextT_contra, /, *, localiser: typing.Optional[dependencies.AbstractLocaliser] = None ) -> bool: raise NotImplementedError @@ -80,9 +81,10 @@ async def __call__( _CommandT = typing.TypeVar("_CommandT", bound="tanjun.ExecutableCommand[typing.Any]") # This errors on earlier 3.9 releases when not quotes cause dumb handling of the [_CommandT] list _CallbackReturnT = typing.Union[_CommandT, "collections.Callable[[_CommandT], _CommandT]"] +_ContextT = typing.TypeVar("_ContextT", bound=tanjun.Context) -def _add_to_command(command: _CommandT, check: tanjun.CheckSig, follow_wrapped: bool) -> _CommandT: +def _add_to_command(command: _CommandT, check: tanjun.AnyCheckSig, follow_wrapped: bool) -> _CommandT: if follow_wrapped: for wrapped in _internal.collect_wrapped(command): wrapped.add_check(check) @@ -91,9 +93,7 @@ def _add_to_command(command: _CommandT, check: tanjun.CheckSig, follow_wrapped: def _optional_kwargs( - command: typing.Optional[_CommandT], check: tanjun.AnyCheckSig, / - check: tanjun.CheckSig, - follow_wrapped: bool, + command: typing.Optional[_CommandT], check: tanjun.AnyCheckSig, follow_wrapped: bool ) -> typing.Union[_CommandT, collections.Callable[[_CommandT], _CommandT]]: if command: return _add_to_command(command, check, follow_wrapped) @@ -982,7 +982,7 @@ def with_own_permission_check( def with_check( - check: tanjun.CheckSig, /, *, follow_wrapped: bool = False + check: tanjun.AnyCheckSig, /, *, follow_wrapped: bool = False ) -> collections.Callable[[_CommandT], _CommandT]: """Add a generic check to a command. @@ -1002,13 +1002,13 @@ def with_check( return lambda command: _add_to_command(command, check, follow_wrapped) -class _AllChecks: +class _AllChecks(typing.Generic[_ContextT]): __slots__ = ("_checks", "__weakref__") - def __init__(self, checks: list[tanjun.CheckSig]) -> None: + def __init__(self, checks: list[tanjun.CheckSig[_ContextT]]) -> None: self._checks = checks - async def __call__(self, ctx: tanjun.Context, /) -> bool: + async def __call__(self, ctx: _ContextT, /) -> bool: for check in self._checks: # noqa: SIM111 if not await ctx.call_with_async_di(check, ctx): return False @@ -1017,8 +1017,8 @@ async def __call__(self, ctx: tanjun.Context, /) -> bool: def all_checks( - check: tanjun.CheckSig, /, *checks: tanjun.CheckSig -) -> collections.Callable[[tanjun.Context], collections.Coroutine[typing.Any, typing.Any, bool]]: + check: tanjun.CheckSig[_ContextT], /, *checks: tanjun.CheckSig[_ContextT] +) -> collections.Callable[[_ContextT], collections.Coroutine[typing.Any, typing.Any, bool]]: """Combine multiple check callbacks into a check which will only pass if all the callbacks pass. This ensures that the callbacks are run in the order they were supplied in @@ -1036,12 +1036,12 @@ def all_checks( collections.abc.Callable[[tanjun.abc.Context], collections.abc.Coroutine[typing.Any, typing.Any, bool]] A check which will pass if all of the provided check callbacks pass. """ - return _AllChecks([check, *checks]) + return _AllChecks[_ContextT]([check, *checks]) def with_all_checks( - check: tanjun.CheckSig, /, *checks: tanjun.CheckSig, follow_wrapped: bool = False -) -> collections.Callable[[_CommandT], _CommandT]: + check: tanjun.AnyCheckSig, /, *checks: tanjun.AnyCheckSig, follow_wrapped: bool = False +) -> collections.Callable[[_CommandT], _CommandT]: # TODO: specialise with overloading """Add a check which will pass if all the provided checks pass through a decorator call. This ensures that the callbacks are run in the order they were supplied in @@ -1065,12 +1065,12 @@ def with_all_checks( return lambda c: _add_to_command(c, all_checks(check, *checks), follow_wrapped) -class _AnyChecks(_Check): +class _AnyChecks(_Check, typing.Generic[_ContextT]): __slots__ = ("_checks", "_suppress") def __init__( self, - checks: list[tanjun.CheckSig], + checks: list[tanjun.CheckSig[_ContextT]], error: typing.Optional[collections.Callable[[], Exception]], error_message: typing.Union[str, collections.Mapping[str, str], None], halt_execution: bool, @@ -1081,11 +1081,7 @@ def __init__( self._suppress = suppress async def __call__( - self, - ctx: tanjun.Context, - /, - *, - localiser: alluka.Injected[typing.Optional[dependencies.AbstractLocaliser]] = None, + self, ctx: _ContextT, /, *, localiser: alluka.Injected[typing.Optional[dependencies.AbstractLocaliser]] = None ) -> bool: for check in self._checks: try: @@ -1102,14 +1098,14 @@ async def __call__( def any_checks( - check: tanjun.CheckSig, + check: tanjun.CheckSig[_ContextT], /, - *checks: tanjun.CheckSig, + *checks: tanjun.CheckSig[_ContextT], error: typing.Optional[collections.Callable[[], Exception]] = None, error_message: typing.Union[str, collections.Mapping[str, str], None], halt_execution: bool = False, suppress: tuple[type[Exception], ...] = (errors.CommandError, errors.HaltExecution), -) -> _AnyCallback: +) -> _AnyCallback[_ContextT]: """Combine multiple checks into a check which'll pass if any of the callbacks pass. This ensures that the callbacks are run in the order they were supplied in @@ -1143,13 +1139,14 @@ def any_checks( collections.Callable[[tanjun.abc.ExecutableCommand], tanjun.abc.ExecutableCommand] A decorator which adds the generated check to a command. """ - return _AnyChecks([check, *checks], error, error_message, halt_execution, suppress) + return _AnyChecks[_ContextT]([check, *checks], error, error_message, halt_execution, suppress) +# Specialising this would be too much boiler plate so for now this just isn't getting that feature. def with_any_checks( - check: tanjun.CheckSig, + check: tanjun.AnyCheckSig, /, - *checks: tanjun.CheckSig, + *checks: tanjun.AnyCheckSig, error: typing.Optional[collections.Callable[[], Exception]] = None, error_message: typing.Union[str, collections.Mapping[str, str], None], follow_wrapped: bool = False, diff --git a/tanjun/clients.py b/tanjun/clients.py index 5154ec8da..3ec05254f 100644 --- a/tanjun/clients.py +++ b/tanjun/clients.py @@ -1756,7 +1756,7 @@ def set_human_only(self, value: bool = True, /) -> Self: return self - def add_check(self: _ClientT, check: tanjun.AnyCheckSig, /) -> _ClientT: + def add_check(self, *checks: tanjun.AnyCheckSig) -> Self: """Add a generic check to this client. This will be applied to both message and slash command execution. @@ -1779,7 +1779,7 @@ def add_check(self: _ClientT, check: tanjun.AnyCheckSig, /) -> _ClientT: return self - def remove_check(self: _ClientT, check: tanjun.AnyCheckSig, /) -> _ClientT: + def remove_check(self, check: tanjun.AnyCheckSig, /) -> Self: """Remove a check from the client. Parameters diff --git a/tanjun/commands/base.py b/tanjun/commands/base.py index af99b5572..2f323d54c 100644 --- a/tanjun/commands/base.py +++ b/tanjun/commands/base.py @@ -98,7 +98,7 @@ def set_metadata(self, key: typing.Any, value: typing.Any, /) -> Self: self._metadata[key] = value return self - def add_check(self: _PartialCommandT, check: tanjun.AnyCheckSig, /) -> _PartialCommandT: + def add_check(self, *checks: tanjun.AnyCheckSig) -> Self: # <>. for check in checks: if check not in self._checks: @@ -106,7 +106,7 @@ def add_check(self: _PartialCommandT, check: tanjun.AnyCheckSig, /) -> _PartialC return self - def remove_check(self: _PartialCommandT, check: tanjun.AnyCheckSig, /) -> _PartialCommandT: + def remove_check(self, check: tanjun.AnyCheckSig, /) -> Self: # <>. self._checks.remove(check) return self diff --git a/tanjun/commands/menu.py b/tanjun/commands/menu.py index e93d3b300..ccb262f64 100644 --- a/tanjun/commands/menu.py +++ b/tanjun/commands/menu.py @@ -48,9 +48,8 @@ from typing_extensions import Self - _AnyCallbackSigT = typing.TypeVar("_CommandCallbackSigT", bound="tanjun.CommandCallbackSig") + _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound="tanjun.CommandCallbackSig") _AnyCommandT = typing.Union[ - tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], tanjun.MessageCommand["_AnyCallbackSigT"], tanjun.SlashCommand["_AnyCallbackSigT"], ] @@ -70,12 +69,16 @@ class _ResultProto(typing.Protocol[_MenuTypeT]): def __call__(self, _: _AnyCommandT[_AnyCallbackSigT], /) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: ... + @typing.overload + def __call__(self, _: tanjun.MenuCommand[_AnyCallbackSigT, typing.Any], /) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: + ... + @typing.overload def __call__(self, _: _MenuCommandCallbackSigT, /) -> MenuCommand[_MenuCommandCallbackSigT, _MenuTypeT]: ... - def __call__(self, _: _CallbackishT[_AnyCallbackSigT], /) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: - raise NotImplementedError + # def __call__(self, _: _CallbackishT[_AnyCallbackSigT], /) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: + # raise NotImplementedError def _as_menu( @@ -321,11 +324,8 @@ class MenuCommand(base.PartialCommand[tanjun.MenuContext], tanjun.MenuCommand[_M @typing.overload def __init__( - self, self: MenuCommand[_AnyCallbackSigT, _MenuTypeT], - callback: _AnyCommandT[ - _AnyCallbackSigT, - ], + callback: _AnyCommandT[_AnyCallbackSigT,], type_: _MenuTypeT, name: typing.Union[str, collections.Mapping[str, str]], /, diff --git a/tanjun/commands/message.py b/tanjun/commands/message.py index 93b616fab..65967ffaf 100644 --- a/tanjun/commands/message.py +++ b/tanjun/commands/message.py @@ -51,8 +51,7 @@ _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=tanjun.CommandCallbackSig) _AnyCommandT = typing.Union[ tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], - tanjun.MessageCommand["_AnyCallbackSigT"], - tanjun.SlashCommand["_AnyCallbackSigT"], + tanjun.SlashCommand["_AnyCallbackSigT"] ] _CallbackishT = typing.Union[_AnyCommandT["_AnyCallbackSigT"], "_AnyCallbackSigT"] @@ -127,11 +126,12 @@ def __call__(self, _: _AnyCommandT[_AnyCallbackSigT], /) -> MessageCommandGroup[ ... @typing.overload - def __call__(self, _: _MessageCallbackSigT, /) -> MessageCommandGroup[_MessageCallbackSigT]: + def __call__(self, _: tanjun.MessageCommand[_AnyCallbackSigT], /) -> MessageCommandGroup[_AnyCallbackSigT]: ... - def __call__(self, _: _CallbackishT[_AnyCallbackSigT], /) -> MessageCommandGroup[_AnyCallbackSigT]: - raise NotImplementedError + @typing.overload + def __call__(self, _: _MessageCallbackSigT, /) -> MessageCommandGroup[_MessageCallbackSigT]: + ... def as_message_command_group( diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index 4f74c047a..a7536add6 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -78,12 +78,12 @@ _SlashCommandT = typing.TypeVar("_SlashCommandT", bound="SlashCommand[typing.Any]") _AnyCommandT = typing.Union[ tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], - tanjun.MessageCommand["_AnyCallbackSigT"], - tanjun.SlashCommand["_AnyCallbackSigT"], + tanjun.MessageCommand["_AnyCallbackSigT"] ] _CallbackishT = typing.Union["_AnyCallbackSigT", _AnyCommandT["_AnyCallbackSigT"]] _CommandCallbackSigT = typing.TypeVar("_CommandCallbackSigT", bound=tanjun.CommandCallbackSig) +_SlashCallbackSigT = typing.TypeVar("_SlashCallbackSigT", bound=tanjun.SlashCallbackSig) _EMPTY_DICT: typing.Final[dict[typing.Any, typing.Any]] = {} _EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() @@ -237,11 +237,12 @@ def __call__(self, _: _AnyCommandT[_AnyCallbackSigT], /) -> SlashCommand[_AnyCal ... @typing.overload - def __call__(self, _: _SlashCallbackSigT, /) -> SlashCommand[_SlashCallbackSigT]: + def __call__(self, _: tanjun.SlashCommand[_AnyCallbackSigT], /) -> SlashCommand[_AnyCallbackSigT]: ... - def __call__(self, _: _CallbackishT[_AnyCallbackSigT], /) -> SlashCommand[_AnyCallbackSigT]: - raise NotImplementedError + @typing.overload + def __call__(self, _: _SlashCallbackSigT, /) -> SlashCommand[_SlashCallbackSigT]: + ... def as_slash_command( diff --git a/tanjun/components.py b/tanjun/components.py index d37f54bcc..2df150b9c 100644 --- a/tanjun/components.py +++ b/tanjun/components.py @@ -565,7 +565,7 @@ def set_slash_hooks(self, hooks: typing.Optional[tanjun.SlashHooks], /) -> Self: self._slash_hooks = hooks return self - def add_check(self: _ComponentT, check: tanjun.AnyCheckSig, /) -> _ComponentT: + def add_check(self, *checks: tanjun.AnyCheckSig) -> Self: """Add a command check to this component to be used for all its commands. Parameters @@ -584,7 +584,7 @@ def add_check(self: _ComponentT, check: tanjun.AnyCheckSig, /) -> _ComponentT: return self - def remove_check(self: _ComponentT, check: tanjun.AnyCheckSig, /) -> _ComponentT: + def remove_check(self, check: tanjun.AnyCheckSig, /) -> Self: """Remove a command check from this component. Parameters diff --git a/tanjun/hooks.py b/tanjun/hooks.py index 26d061915..eeb92a7b9 100644 --- a/tanjun/hooks.py +++ b/tanjun/hooks.py @@ -44,10 +44,23 @@ if typing.TYPE_CHECKING: from typing_extensions import Self - _CommandT = typing.TypeVar("_CommandT", bound=tanjun.ExecutableCommand[typing.Any]) - _ErrorHookSigT = typing.TypeVar("_ErrorHookSigT", bound=tanjun.ErrorHookSig) - _HookSigT = typing.TypeVar("_HookSigT", bound=tanjun.HookSig) - _HooksT = typing.TypeVar("_HooksT", bound="Hooks[typing.Any]") + _AnyCommandT = typing.TypeVar("_AnyCommandT", bound=tanjun.ExecutableCommand[typing.Any]) + _CommandT = typing.TypeVar("_CommandT", bound=tanjun.ExecutableCommand[tanjun.Context]) + _MenuCommandT = typing.TypeVar("_MenuCommandT", bound=tanjun.ExecutableCommand[tanjun.MenuContext]) + _MessageCommandT = typing.TypeVar("_MessageCommandT", bound=tanjun.ExecutableCommand[tanjun.MessageContext]) + _SlashCommandT = typing.TypeVar("_SlashCommandT", bound=tanjun.ExecutableCommand[tanjun.SlashContext]) + + _AnyErrorHookSigT = typing.TypeVar("_AnyErrorHookSigT", bound=tanjun.ErrorHookSig[typing.Any]) + _ErrorHookSigT = typing.TypeVar("_ErrorHookSigT", bound=tanjun.ErrorHookSig[tanjun.Context]) + _MenuErrorHookSigT = typing.TypeVar("_MenuErrorHookSigT", bound=tanjun.ErrorHookSig[tanjun.MenuContext]) + _MessageErrorHookSigT = typing.TypeVar("_MessageErrorHookSigT", bound=tanjun.ErrorHookSig[tanjun.MessageContext]) + _SlashErrorHookSigT = typing.TypeVar("_SlashErrorHookSigT", bound=tanjun.ErrorHookSig[tanjun.SlashContext]) + + _AnyHookSigT = typing.TypeVar("_AnyHookSigT", bound=tanjun.HookSig[typing.Any]) + _HookSigT = typing.TypeVar("_HookSigT", bound=tanjun.HookSig[tanjun.Context]) + _MenuHookSigT = typing.TypeVar("_MenuHookSigT", bound=tanjun.HookSig[tanjun.MenuContext]) + _MessageHookSigT = typing.TypeVar("_MessageHookSigT", bound=tanjun.HookSig[tanjun.MessageContext]) + _SlashHookSigT = typing.TypeVar("_SlashHookSigT", bound=tanjun.HookSig[tanjun.SlashContext]) _ContextT_contra = typing.TypeVar("_ContextT_contra", bound=tanjun.Context, contravariant=True) @@ -75,13 +88,29 @@ class Hooks(tanjun.Hooks[_ContextT_contra]): def __init__(self) -> None: """Initialise a command hook object.""" - self._error_callbacks: list[tanjun.ErrorHookSig] = [] - self._parser_error_callbacks: list[tanjun.HookSig] = [] - self._pre_execution_callbacks: list[tanjun.HookSig] = [] - self._post_execution_callbacks: list[tanjun.HookSig] = [] - self._success_callbacks: list[tanjun.HookSig] = [] + self._error_callbacks: list[tanjun.ErrorHookSig[_ContextT_contra]] = [] + self._parser_error_callbacks: list[tanjun.HookSig[_ContextT_contra]] = [] + self._pre_execution_callbacks: list[tanjun.HookSig[_ContextT_contra]] = [] + self._post_execution_callbacks: list[tanjun.HookSig[_ContextT_contra]] = [] + self._success_callbacks: list[tanjun.HookSig[_ContextT_contra]] = [] - def add_to_command(self, command: _CommandT, /) -> _CommandT: + @typing.overload + def add_to_command(self: MenuHooks, command: _MenuCommandT, /) -> _MenuCommandT: + ... + + @typing.overload + def add_to_command(self: MessageHooks, command: _MessageCommandT, /) -> _MessageCommandT: + ... + + @typing.overload + def add_to_command(self: SlashHooks, command: _SlashCommandT, /) -> _SlashCommandT: + ... + + @typing.overload + def add_to_command(self: AnyHooks, command: _CommandT, /) -> _CommandT: + ... + + def add_to_command(self, command: _AnyCommandT, /) -> _AnyCommandT: """Add this hook object to a command. !!! note @@ -115,12 +144,12 @@ def copy(self) -> Self: """Copy this hook object.""" return copy.deepcopy(self) # TODO: maybe don't - def add_on_error(self, callback: tanjun.ErrorHookSig, /) -> Self: + def add_on_error(self, callback: tanjun.ErrorHookSig[_ContextT_contra], /) -> Self: # <>. self._error_callbacks.append(callback) return self - def set_on_error(self, callback: typing.Optional[tanjun.ErrorHookSig], /) -> Self: + def set_on_error(self, callback: typing.Optional[tanjun.ErrorHookSig[_ContextT_contra]], /) -> Self: """Set the error callback for this hook object. !!! note @@ -151,17 +180,33 @@ def set_on_error(self, callback: typing.Optional[tanjun.ErrorHookSig], /) -> Sel self._error_callbacks.clear() return self.add_on_error(callback) if callback else self - def with_on_error(self, callback: _ErrorHookSigT, /) -> _ErrorHookSigT: + @typing.overload + def with_on_error(self: MenuHooks, callback: _MenuErrorHookSigT, /) -> _MenuErrorHookSigT: + ... + + @typing.overload + def with_on_error(self: MessageHooks, callback: _MessageErrorHookSigT, /) -> _MessageErrorHookSigT: + ... + + @typing.overload + def with_on_error(self: SlashHooks, callback: _SlashErrorHookSigT, /) -> _SlashErrorHookSigT: + ... + + # @typing.overload + # def with_on_error(self: AnyHooks, callback: _ErrorHookSigT, /) -> _ErrorHookSigT: + # ... + + def with_on_error(self, callback: _AnyErrorHookSigT, /) -> _AnyErrorHookSigT: # <>. self.add_on_error(callback) return callback - def add_on_parser_error(self, callback: tanjun.HookSig, /) -> Self: + def add_on_parser_error(self, callback: tanjun.HookSig[_ContextT_contra], /) -> Self: # <>. self._parser_error_callbacks.append(callback) return self - def set_on_parser_error(self, callback: typing.Optional[tanjun.HookSig], /) -> Self: + def set_on_parser_error(self, callback: typing.Optional[tanjun.HookSig[_ContextT_contra]], /) -> Self: """Set the parser error callback for this hook object. Parameters @@ -185,17 +230,33 @@ def set_on_parser_error(self, callback: typing.Optional[tanjun.HookSig], /) -> S self._parser_error_callbacks.clear() return self.add_on_parser_error(callback) if callback else self - def with_on_parser_error(self, callback: _HookSigT, /) -> _HookSigT: + @typing.overload + def with_on_parser_error(self: MenuHooks, callback: _MenuHookSigT, /) -> _MenuHookSigT: + ... + + @typing.overload + def with_on_parser_error(self: MessageHooks, callback: _MessageHookSigT, /) -> _MessageHookSigT: + ... + + @typing.overload + def with_on_parser_error(self: SlashHooks, callback: _SlashHookSigT, /) -> _SlashHookSigT: + ... + + # @typing.overload + # def with_on_parser_error(self: AnyHooks, callback: _HookSigT, /) -> _HookSigT: + # ... + + def with_on_parser_error(self, callback: _AnyHookSigT, /) -> _AnyHookSigT: # <>. self.add_on_parser_error(callback) return callback - def add_post_execution(self, callback: tanjun.HookSig, /) -> Self: + def add_post_execution(self, callback: tanjun.HookSig[_ContextT_contra], /) -> Self: # <>. self._post_execution_callbacks.append(callback) return self - def set_post_execution(self, callback: typing.Optional[tanjun.HookSig], /) -> Self: + def set_post_execution(self, callback: typing.Optional[tanjun.HookSig[_ContextT_contra]], /) -> Self: """Set the post-execution callback for this hook object. Parameters @@ -216,17 +277,33 @@ def set_post_execution(self, callback: typing.Optional[tanjun.HookSig], /) -> Se self._post_execution_callbacks.clear() return self.add_post_execution(callback) if callback else self - def with_post_execution(self, callback: _HookSigT, /) -> _HookSigT: + @typing.overload + def with_post_execution(self: MenuHooks, callback: _MenuHookSigT, /) -> _MenuHookSigT: + ... + + @typing.overload + def with_post_execution(self: MessageHooks, callback: _MessageHookSigT, /) -> _MessageHookSigT: + ... + + @typing.overload + def with_post_execution(self: SlashHooks, callback: _SlashHookSigT, /) -> _SlashHookSigT: + ... + + # @typing.overload + # def with_post_execution(self: AnyHooks, callback: _HookSigT, /) -> _HookSigT: + # ... + + def with_post_execution(self, callback: _AnyHookSigT, /) -> _AnyHookSigT: # <>. self.add_post_execution(callback) return callback - def add_pre_execution(self, callback: tanjun.HookSig, /) -> Self: + def add_pre_execution(self, callback: tanjun.HookSig[_ContextT_contra], /) -> Self: # <>. self._pre_execution_callbacks.append(callback) return self - def set_pre_execution(self, callback: typing.Optional[tanjun.HookSig], /) -> Self: + def set_pre_execution(self, callback: typing.Optional[tanjun.HookSig[_ContextT_contra]], /) -> Self: """Set the pre-execution callback for this hook object. Parameters @@ -247,17 +324,33 @@ def set_pre_execution(self, callback: typing.Optional[tanjun.HookSig], /) -> Sel self._pre_execution_callbacks.clear() return self.add_pre_execution(callback) if callback else self - def with_pre_execution(self, callback: _HookSigT, /) -> _HookSigT: + @typing.overload + def with_pre_execution(self: MenuHooks, callback: _MenuHookSigT, /) -> _MenuHookSigT: + ... + + @typing.overload + def with_pre_execution(self: MessageHooks, callback: _MessageHookSigT, /) -> _MessageHookSigT: + ... + + @typing.overload + def with_pre_execution(self: SlashHooks, callback: _SlashHookSigT, /) -> _SlashHookSigT: + ... + + # @typing.overload + # def with_pre_execution(self: AnyHooks, callback: _HookSigT, /) -> _HookSigT: + # ... + + def with_pre_execution(self, callback: _AnyHookSigT, /) -> _AnyHookSigT: # <>. self.add_pre_execution(callback) return callback - def add_on_success(self, callback: tanjun.HookSig, /) -> Self: + def add_on_success(self, callback: tanjun.HookSig[_ContextT_contra], /) -> Self: # <>. self._success_callbacks.append(callback) return self - def set_on_success(self, callback: typing.Optional[tanjun.HookSig], /) -> Self: + def set_on_success(self, callback: typing.Optional[tanjun.HookSig[_ContextT_contra]], /) -> Self: """Set the success callback for this hook object. Parameters @@ -278,7 +371,23 @@ def set_on_success(self, callback: typing.Optional[tanjun.HookSig], /) -> Self: self._success_callbacks.clear() return self.add_on_success(callback) if callback else self - def with_on_success(self, callback: _HookSigT, /) -> _HookSigT: + @typing.overload + def with_on_success(self: MenuHooks, callback: _MenuHookSigT, /) -> _MenuHookSigT: + ... + + @typing.overload + def with_on_success(self: MessageHooks, callback: _MessageHookSigT, /) -> _MessageHookSigT: + ... + + @typing.overload + def with_on_success(self: SlashHooks, callback: _SlashHookSigT, /) -> _SlashHookSigT: + ... + + # @typing.overload + # def with_on_success(self: AnyHooks, callback: _HookSigT, /) -> _HookSigT: + # ... + + def with_on_success(self, callback: _AnyHookSigT, /) -> _AnyHookSigT: # <>. self.add_on_success(callback) return callback From 8ce093ec9c5328cf3c32d6a8c2f4cd7d51731303 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Sun, 22 Jan 2023 21:16:56 +0000 Subject: [PATCH 06/45] More type-checking fixes --- tanjun/__init__.py | 4 +- tanjun/_internal/__init__.py | 2 +- tanjun/abc.py | 107 ++++++++++++++++-- tanjun/commands/base.py | 6 +- tanjun/commands/menu.py | 203 ++++++++++++++++++++++------------- tanjun/commands/message.py | 30 ++++-- tanjun/commands/slash.py | 3 +- tanjun/hooks.py | 2 - 8 files changed, 251 insertions(+), 106 deletions(-) diff --git a/tanjun/__init__.py b/tanjun/__init__.py index c6159682f..3ddca3607 100644 --- a/tanjun/__init__.py +++ b/tanjun/__init__.py @@ -115,6 +115,7 @@ async def hello(ctx: tanjun.abc.Context, user: hikari.User | None) -> None: "InteractionAcceptsEnum", "LazyConstant", "MenuCommand", + "MenuHooks", "MessageAcceptsEnum", "MessageCommand", "MessageCommandGroup", @@ -153,7 +154,6 @@ async def hello(ctx: tanjun.abc.Context, user: hikari.User | None) -> None: "dependencies", "errors", "hooks", - "MenuHooks", "inject", "inject_lc", "injected", @@ -297,9 +297,9 @@ async def hello(ctx: tanjun.abc.Context, user: hikari.User | None) -> None: from .errors import TooManyArgumentsError from .hooks import AnyHooks from .hooks import Hooks +from .hooks import MenuHooks from .hooks import MessageHooks from .hooks import SlashHooks -from .hooks import MenuHooks from .injecting import as_self_injecting from .parsing import ShlexParser from .parsing import with_argument diff --git a/tanjun/_internal/__init__.py b/tanjun/_internal/__init__.py index c0fa75362..207d043df 100644 --- a/tanjun/_internal/__init__.py +++ b/tanjun/_internal/__init__.py @@ -57,7 +57,7 @@ _P = typing_extensions.ParamSpec("_P") - _ContextT = typing.TypeVar("_ContextT", bound=abc.Context) + _ContextT = typing.TypeVar("_ContextT", bound=tanjun.Context) _TreeT = dict[ typing.Union[str, "_IndexKeys"], typing.Union["_TreeT", list[tuple[list[str], tanjun.MessageCommand[typing.Any]]]], diff --git a/tanjun/abc.py b/tanjun/abc.py index 4d3ce5ff0..e4fe8fa35 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -84,9 +84,17 @@ _AutocompleteValueT = typing.TypeVar("_AutocompleteValueT", int, str, float) _BaseSlashCommandT = typing.TypeVar("_BaseSlashCommandT", bound="BaseSlashCommand") - _CommandCallbackSigT = typing.TypeVar("_CommandCallbackSigT", bound="CommandCallbackSig") - _ErrorHookSigT = typing.TypeVar("_ErrorHookSigT", bound="ErrorHookSig") - _HookSigT = typing.TypeVar("_HookSigT", bound="HookSig") + + _AnyErrorHookSigT = typing.TypeVar("_AnyErrorHookSigT", bound="ErrorHookSig[typing.Any]") + _MenuErrorHookSigT = typing.TypeVar("_MenuErrorHookSigT", bound="ErrorHookSig[MenuContext]") + _MessageErrorHookSigT = typing.TypeVar("_MessageErrorHookSigT", bound="ErrorHookSig[MessageContext]") + _SlashErrorHookSigT = typing.TypeVar("_SlashErrorHookSigT", bound="ErrorHookSig[SlashContext]") + + _AnyHookSigT = typing.TypeVar("_AnyHookSigT", bound="HookSig[typing.Any]") + _MenuHookSigT = typing.TypeVar("_MenuHookSigT", bound="HookSig[MenuContext]") + _MessageHookSigT = typing.TypeVar("_MessageHookSigT", bound="HookSig[MessageContext]") + _SlashHookSigT = typing.TypeVar("_SlashHookSigT", bound="HookSig[SlashContext]") + _ListenerCallbackSigT = typing.TypeVar("_ListenerCallbackSigT", bound="ListenerCallbackSig") _MenuCommandT = typing.TypeVar("_MenuCommandT", bound="MenuCommand[typing.Any, typing.Any]") _MessageCommandT = typing.TypeVar("_MessageCommandT", bound="MessageCommand[typing.Any]") @@ -133,12 +141,14 @@ SlashCheckSig = _CheckSig["SlashContext", ...] -_CommandCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _P], collections.Coroutine[typing.Any, typing.Any, None]] +_CommandCallbackSig = collections.Callable[ + typing_extensions.Concatenate[_ContextT_contra, _P], collections.Coroutine[typing.Any, typing.Any, None] +] -_MenuValueT = typing.TypeVar("_MenuValueT", hikari.User, hikari.InteractionMember) +_MenuValueT = typing.TypeVar("_MenuValueT", hikari.Message, hikari.InteractionMember) _ManuCallbackSig = collections.Callable[ typing_extensions.Concatenate[_ContextT_contra, _MenuValueT, _P], - collections.Coroutine[typing.Any, typing.Any, None] + collections.Coroutine[typing.Any, typing.Any, None], ] MenuCallbackSig = _ManuCallbackSig["MenuContext", _MenuValueT, ...] """Type hint of a context menu command callback. @@ -2155,8 +2165,23 @@ def add_on_error(self, callback: ErrorHookSig[_ContextT_contra], /) -> Self: The hook object to enable method chaining. """ + @typing.overload + @abc.abstractmethod + def with_on_error(self: MenuHooks, callback: _MenuErrorHookSigT, /) -> _MenuErrorHookSigT: + ... + + @typing.overload + @abc.abstractmethod + def with_on_error(self: MessageHooks, callback: _MessageErrorHookSigT, /) -> _MessageErrorHookSigT: + ... + + @typing.overload + @abc.abstractmethod + def with_on_error(self: SlashHooks, callback: _SlashErrorHookSigT, /) -> _SlashErrorHookSigT: + ... + @abc.abstractmethod - def with_on_error(self, callback: _ErrorHookSigT, /) -> _ErrorHookSigT: + def with_on_error(self, callback: _AnyErrorHookSigT, /) -> _AnyErrorHookSigT: """Add an error callback to this hook object through a decorator call. !!! note @@ -2219,8 +2244,23 @@ def add_on_parser_error(self, callback: HookSig[_ContextT_contra], /) -> Self: The hook object to enable method chaining. """ + @typing.overload + @abc.abstractmethod + def with_on_parser_error(self: MenuHooks, callback: _MenuHookSigT, /) -> _MenuHookSigT: + ... + + @typing.overload + @abc.abstractmethod + def with_on_parser_error(self: MessageHooks, callback: _MessageHookSigT, /) -> _MessageHookSigT: + ... + + @typing.overload + @abc.abstractmethod + def with_on_parser_error(self: SlashHooks, callback: _SlashHookSigT, /) -> _SlashHookSigT: + ... + @abc.abstractmethod - def with_on_parser_error(self, callback: _HookSigT, /) -> _HookSigT: + def with_on_parser_error(self, callback: _AnyHookSigT, /) -> _AnyHookSigT: """Add a parser error callback to this hook object through a decorator call. Examples @@ -2267,8 +2307,23 @@ def add_post_execution(self, callback: HookSig[_ContextT_contra], /) -> Self: The hook object to enable method chaining. """ + @typing.overload + @abc.abstractmethod + def with_post_execution(self: MenuHooks, callback: _MenuHookSigT, /) -> _MenuHookSigT: + ... + + @typing.overload + @abc.abstractmethod + def with_post_execution(self: MessageHooks, callback: _MessageHookSigT, /) -> _MessageHookSigT: + ... + + @typing.overload + @abc.abstractmethod + def with_post_execution(self: SlashHooks, callback: _SlashHookSigT, /) -> _SlashHookSigT: + ... + @abc.abstractmethod - def with_post_execution(self, callback: _HookSigT, /) -> _HookSigT: + def with_post_execution(self, callback: _AnyHookSigT, /) -> _AnyHookSigT: """Add a post-execution callback to this hook object through a decorator call. Examples @@ -2315,8 +2370,23 @@ def add_pre_execution(self, callback: HookSig[_ContextT_contra], /) -> Self: The hook object to enable method chaining. """ + @typing.overload + @abc.abstractmethod + def with_pre_execution(self: MenuHooks, callback: _MenuHookSigT, /) -> _MenuHookSigT: + ... + + @typing.overload + @abc.abstractmethod + def with_pre_execution(self: MessageHooks, callback: _MessageHookSigT, /) -> _MessageHookSigT: + ... + + @typing.overload + @abc.abstractmethod + def with_pre_execution(self: SlashHooks, callback: _SlashHookSigT, /) -> _SlashHookSigT: + ... + @abc.abstractmethod - def with_pre_execution(self, callback: _HookSigT, /) -> _HookSigT: + def with_pre_execution(self, callback: _AnyHookSigT, /) -> _AnyHookSigT: """Add a pre-execution callback to this hook object through a decorator call. Examples @@ -2363,8 +2433,23 @@ def add_on_success(self, callback: HookSig[_ContextT_contra], /) -> Self: The hook object to enable method chaining. """ + @typing.overload + @abc.abstractmethod + def with_on_success(self: MenuHooks, callback: _MenuHookSigT, /) -> _MenuHookSigT: + ... + + @typing.overload + @abc.abstractmethod + def with_on_success(self: MessageHooks, callback: _MessageHookSigT, /) -> _MessageHookSigT: + ... + + @typing.overload + @abc.abstractmethod + def with_on_success(self: SlashHooks, callback: _SlashHookSigT, /) -> _SlashHookSigT: + ... + @abc.abstractmethod - def with_on_success(self, callback: _HookSigT, /) -> _HookSigT: + def with_on_success(self, callback: _AnyHookSigT, /) -> _AnyHookSigT: """Add a success callback to this hook object through a decorator call. Examples diff --git a/tanjun/commands/base.py b/tanjun/commands/base.py index 2f323d54c..af35dbf82 100644 --- a/tanjun/commands/base.py +++ b/tanjun/commands/base.py @@ -55,7 +55,7 @@ class PartialCommand(tanjun.ExecutableCommand[_ContextT], components.AbstractCom __slots__ = ("_checks", "_component", "_hooks", "_metadata") def __init__(self) -> None: - self._checks: list[tanjun.AnyCheckSig] = [] + self._checks: list[tanjun.CheckSig[_ContextT]] = [] self._component: typing.Optional[tanjun.Component] = None self._hooks: typing.Optional[tanjun.Hooks[_ContextT]] = None self._metadata: dict[typing.Any, typing.Any] = {} @@ -98,7 +98,7 @@ def set_metadata(self, key: typing.Any, value: typing.Any, /) -> Self: self._metadata[key] = value return self - def add_check(self, *checks: tanjun.AnyCheckSig) -> Self: + def add_check(self, *checks: tanjun.CheckSig[_ContextT]) -> Self: # <>. for check in checks: if check not in self._checks: @@ -106,7 +106,7 @@ def add_check(self, *checks: tanjun.AnyCheckSig) -> Self: return self - def remove_check(self, check: tanjun.AnyCheckSig, /) -> Self: + def remove_check(self, check: tanjun.CheckSig[_ContextT], /) -> Self: # <>. self._checks.remove(check) return self diff --git a/tanjun/commands/menu.py b/tanjun/commands/menu.py index ccb262f64..94b630ce9 100644 --- a/tanjun/commands/menu.py +++ b/tanjun/commands/menu.py @@ -48,81 +48,47 @@ from typing_extensions import Self - _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound="tanjun.CommandCallbackSig") - _AnyCommandT = typing.Union[ - tanjun.MessageCommand["_AnyCallbackSigT"], - tanjun.SlashCommand["_AnyCallbackSigT"], - ] + _AnyCallbackSigT = typing.TypeVar( + "_AnyCallbackSigT", bound=collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, None]] + ) + _MessageCallbackSigT = typing.TypeVar("_MessageCallbackSigT", bound="tanjun.MenuCallbackSig[hikari.Message]") + _UserCallbackSigT = typing.TypeVar("_UserCallbackSigT", bound="tanjun.MenuCallbackSig[hikari.InteractionMember]") + + _AnyCommandT = typing.Union[tanjun.MessageCommand["_AnyCallbackSigT"], tanjun.SlashCommand["_AnyCallbackSigT"],] _CallbackishT = typing.Union["_AnyCallbackSigT", _AnyCommandT["_AnyCallbackSigT"]] import hikari -_MenuCommandCallbackSigT = typing.TypeVar("_MenuCommandCallbackSigT", bound="tanjun.MenuCallbackSig[typing.Any]") +_AnyMenuCallbackSigT = typing.TypeVar("_AnyMenuCallbackSigT", bound="tanjun.MenuCallbackSig[typing.Any]") _MenuTypeT = typing.TypeVar( "_MenuTypeT", typing.Literal[hikari.CommandType.USER], typing.Literal[hikari.CommandType.MESSAGE] ) _EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() -class _ResultProto(typing.Protocol[_MenuTypeT]): +class _MessageResultProto(typing.Protocol): @typing.overload - def __call__(self, _: _AnyCommandT[_AnyCallbackSigT], /) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: + def __call__( + self, _: _AnyCommandT[_MessageCallbackSigT], / + ) -> MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]]: ... @typing.overload - def __call__(self, _: tanjun.MenuCommand[_AnyCallbackSigT, typing.Any], /) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: + def __call__( + self, _: tanjun.MenuCommand[_MessageCallbackSigT, typing.Any], / + ) -> MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]]: ... @typing.overload - def __call__(self, _: _MenuCommandCallbackSigT, /) -> MenuCommand[_MenuCommandCallbackSigT, _MenuTypeT]: + def __call__( + self, _: _MessageCallbackSigT, / + ) -> MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]]: ... # def __call__(self, _: _CallbackishT[_AnyCallbackSigT], /) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: # raise NotImplementedError -def _as_menu( - name: typing.Union[str, collections.Mapping[str, str]], - type_: _MenuTypeT, - /, - *, - always_defer: bool = False, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, - is_global: bool = True, -) -> _ResultProto[_MenuTypeT]: - @typing.overload - def decorator(callback: _AnyCommandT[_AnyCallbackSigT], /) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: - ... - - @typing.overload - def decorator(callback: _MenuCommandCallbackSigT, /) -> MenuCommand[_MenuCommandCallbackSigT, _MenuTypeT]: - ... - - def decorator(callback: _CallbackishT[_AnyCallbackSigT], /) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: - if isinstance(callback, (tanjun.MenuCommand, tanjun.MessageCommand, tanjun.SlashCommand)): - wrapped_command = callback - callback = callback.callback - - else: - wrapped_command = None - - return MenuCommand( - callback, - type_, - name, - always_defer=always_defer, - default_member_permissions=default_member_permissions, - default_to_ephemeral=default_to_ephemeral, - dm_enabled=dm_enabled, - is_global=is_global, - _wrapped_command=wrapped_command, - ) - - return decorator - - def as_message_menu( name: typing.Union[str, collections.Mapping[str, str]], /, @@ -132,7 +98,7 @@ def as_message_menu( default_to_ephemeral: typing.Optional[bool] = None, dm_enabled: typing.Optional[bool] = None, is_global: bool = True, -) -> _ResultProto[typing.Literal[hikari.CommandType.MESSAGE]]: +) -> _MessageResultProto: """Build a message [tanjun.MenuCommand][] by decorating a function. !!! note @@ -200,15 +166,65 @@ async def message_command(self, ctx: tanjun.abc.MenuContext, message: hikari.Mes * If the command name isn't in the length range of 1 to 32. * If the command name has uppercase characters. """ - return _as_menu( - name, - hikari.CommandType.MESSAGE, - always_defer=always_defer, - default_member_permissions=default_member_permissions, - default_to_ephemeral=default_to_ephemeral, - dm_enabled=dm_enabled, - is_global=is_global, - ) + + @typing.overload + def decorator( + callback: _AnyCommandT[_MessageCallbackSigT], / + ) -> MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]]: + ... + + @typing.overload + def decorator( + callback: _MessageCallbackSigT, / + ) -> MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]]: + ... + + def decorator( + callback: _CallbackishT[_MessageCallbackSigT], / + ) -> MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]]: + if isinstance(callback, (tanjun.MenuCommand, tanjun.MessageCommand, tanjun.SlashCommand)): + wrapped_command = callback + callback = callback.callback + + else: + wrapped_command = None + + return MenuCommand( + callback, + hikari.CommandType.MESSAGE, + name, + always_defer=always_defer, + default_member_permissions=default_member_permissions, + default_to_ephemeral=default_to_ephemeral, + dm_enabled=dm_enabled, + is_global=is_global, + _wrapped_command=wrapped_command, + ) + + return decorator + + +class _UserResultProto(typing.Protocol): + @typing.overload + def __call__( + self, _: _AnyCommandT[_UserCallbackSigT], / + ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: + ... + + @typing.overload + def __call__( + self, _: tanjun.MenuCommand[_UserCallbackSigT, typing.Any], / + ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: + ... + + @typing.overload + def __call__( + self, _: _UserCallbackSigT, / + ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: + ... + + # def __call__(self, _: _CallbackishT[_AnyCallbackSigT], /) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: + # raise NotImplementedError def as_user_menu( @@ -220,7 +236,7 @@ def as_user_menu( default_to_ephemeral: typing.Optional[bool] = None, dm_enabled: typing.Optional[bool] = None, is_global: bool = True, -) -> _ResultProto[typing.Literal[hikari.CommandType.USER]]: +) -> _UserResultProto: """Build a user [tanjun.MenuCommand][] by decorating a function. !!! note @@ -290,21 +306,54 @@ async def user_command( * If the command name isn't in the length range of 1 to 32. * If the command name has uppercase characters. """ - return _as_menu( - name, - hikari.CommandType.USER, - always_defer=always_defer, - default_member_permissions=default_member_permissions, - default_to_ephemeral=default_to_ephemeral, - dm_enabled=dm_enabled, - is_global=is_global, - ) + + @typing.overload + def decorator( + callback: _AnyCommandT[_UserCallbackSigT], / + ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: + ... + + @typing.overload + def decorator( + callback: tanjun.MenuCommand[_UserCallbackSigT, typing.Any], / + ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: + ... + + @typing.overload + def decorator( + callback: _UserCallbackSigT, / + ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: + ... + + def decorator( + callback: _CallbackishT[_UserCallbackSigT], / + ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: + if isinstance(callback, (tanjun.MenuCommand, tanjun.MessageCommand, tanjun.SlashCommand)): + wrapped_command = callback + callback = callback.callback + + else: + wrapped_command = None + + return MenuCommand( + callback, + hikari.CommandType.USER, + name, + always_defer=always_defer, + default_member_permissions=default_member_permissions, + default_to_ephemeral=default_to_ephemeral, + dm_enabled=dm_enabled, + is_global=is_global, + _wrapped_command=wrapped_command, + ) + + return decorator _VALID_TYPES = frozenset((hikari.CommandType.MESSAGE, hikari.CommandType.USER)) -class MenuCommand(base.PartialCommand[tanjun.MenuContext], tanjun.MenuCommand[_MenuCommandCallbackSigT, _MenuTypeT]): +class MenuCommand(base.PartialCommand[tanjun.MenuContext], tanjun.MenuCommand[_AnyMenuCallbackSigT, _MenuTypeT]): """Base class used for the standard menu command implementations.""" __slots__ = ( @@ -342,7 +391,7 @@ def __init__( @typing.overload def __init__( self, - callback: _MenuCommandCallbackSigT, + callback: _AnyMenuCallbackSigT, type_: _MenuTypeT, name: typing.Union[str, collections.Mapping[str, str]], /, @@ -451,7 +500,7 @@ def __init__( default_member_permissions = hikari.Permissions(default_member_permissions) self._always_defer = always_defer - self._callback: _MenuCommandCallbackSigT = callback + self._callback: _AnyMenuCallbackSigT = callback self._default_member_permissions = default_member_permissions self._defaults_to_ephemeral = default_to_ephemeral self._is_dm_enabled = dm_enabled @@ -463,7 +512,7 @@ def __init__( self._wrapped_command = _wrapped_command if typing.TYPE_CHECKING: - __call__: _MenuCommandCallbackSigT + __call__: _AnyMenuCallbackSigT else: @@ -471,7 +520,7 @@ async def __call__(self, *args, **kwargs) -> None: await self._callback(*args, **kwargs) @property - def callback(self) -> _MenuCommandCallbackSigT: + def callback(self) -> _AnyMenuCallbackSigT: # <>. return self._callback diff --git a/tanjun/commands/message.py b/tanjun/commands/message.py index 65967ffaf..580e03a84 100644 --- a/tanjun/commands/message.py +++ b/tanjun/commands/message.py @@ -50,8 +50,7 @@ _AnyMessageCommandT = typing.TypeVar("_AnyMessageCommandT", bound=tanjun.MessageCommand[typing.Any]) _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=tanjun.CommandCallbackSig) _AnyCommandT = typing.Union[ - tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], - tanjun.SlashCommand["_AnyCallbackSigT"] + tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], tanjun.SlashCommand["_AnyCallbackSigT"] ] _CallbackishT = typing.Union[_AnyCommandT["_AnyCallbackSigT"], "_AnyCallbackSigT"] @@ -67,11 +66,12 @@ def __call__(self, _: _AnyCommandT[_AnyCallbackSigT], /) -> MessageCommand[_AnyC ... @typing.overload - def __call__(self, _: _MessageCallbackSigT, /) -> MessageCommand[_MessageCallbackSigT]: + def __call__(self, _: tanjun.MessageCommand[_AnyCallbackSigT], /) -> MessageCommand[_AnyCallbackSigT]: ... - def __call__(self, _: _CallbackishT[_AnyCallbackSigT], /) -> MessageCommand[_AnyCallbackSigT]: - raise NotImplementedError + @typing.overload + def __call__(self, _: _MessageCallbackSigT, /) -> MessageCommand[_MessageCallbackSigT]: + ... def as_message_command(name: str, /, *names: str, validate_arg_keys: bool = True) -> _ResultProto: @@ -101,11 +101,18 @@ def as_message_command(name: str, /, *names: str, validate_arg_keys: bool = True def decorator(callback: _AnyCommandT[_AnyCallbackSigT], /) -> MessageCommand[_AnyCallbackSigT]: ... + @typing.overload + def decorator(callback: tanjun.MessageCommand[_AnyCallbackSigT], /) -> MessageCommand[_AnyCallbackSigT]: + ... + @typing.overload def decorator(callback: _MessageCallbackSigT, /) -> MessageCommand[_MessageCallbackSigT]: ... - def decorator(callback: _CallbackishT[_AnyCallbackSigT], /) -> MessageCommand[_AnyCallbackSigT]: + # TODO: make ExecutableCommand generic and simplify + def decorator( + callback: typing.Union[tanjun.ExecutableCommand[typing.Any], _MessageCallbackSigT], / + ) -> MessageCommand[typing.Any]: if isinstance(callback, (tanjun.MenuCommand, tanjun.MessageCommand, tanjun.SlashCommand)): wrapped_command = callback callback = callback.callback @@ -168,11 +175,18 @@ def as_message_command_group( def decorator(callback: _AnyCommandT[_AnyCallbackSigT], /) -> MessageCommandGroup[_AnyCallbackSigT]: ... + @typing.overload + def decorator(callback: tanjun.MessageCommand[_AnyCallbackSigT], /) -> MessageCommandGroup[_AnyCallbackSigT]: + ... + @typing.overload def decorator(callback: _MessageCallbackSigT, /) -> MessageCommandGroup[_MessageCallbackSigT]: ... - def decorator(callback: _CallbackishT[_AnyCallbackSigT], /) -> MessageCommandGroup[_AnyCallbackSigT]: + # TODO: make executable command generic and simplify + def decorator( + callback: typing.Union[tanjun.ExecutableCommand[typing.Any], _MessageCallbackSigT], / + ) -> MessageCommandGroup[typing.Any]: if isinstance(callback, (tanjun.MenuCommand, tanjun.MessageCommand, tanjun.SlashCommand)): wrapped_command = callback callback = callback.callback @@ -516,7 +530,7 @@ def as_sub_command(self, name: str, /, *names: str, validate_arg_keys: bool = Tr """ def decorator( - callback: typing.Union[_OtherCallbackSigT, _CommandT[_OtherCallbackSigT]], / + callback: typing.Union[_OtherCallbackSigT, _AnyCommandT[_OtherCallbackSigT]], / ) -> MessageCommand[_OtherCallbackSigT]: return self.with_command(as_message_command(name, *names, validate_arg_keys=validate_arg_keys)(callback)) diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index a7536add6..37bbb10df 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -77,8 +77,7 @@ _AnyBaseSlashCommandT = typing.TypeVar("_AnyBaseSlashCommandT", bound="tanjun.BaseSlashCommand") _SlashCommandT = typing.TypeVar("_SlashCommandT", bound="SlashCommand[typing.Any]") _AnyCommandT = typing.Union[ - tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], - tanjun.MessageCommand["_AnyCallbackSigT"] + tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], tanjun.MessageCommand["_AnyCallbackSigT"] ] _CallbackishT = typing.Union["_AnyCallbackSigT", _AnyCommandT["_AnyCallbackSigT"]] diff --git a/tanjun/hooks.py b/tanjun/hooks.py index eeb92a7b9..ce5847ffb 100644 --- a/tanjun/hooks.py +++ b/tanjun/hooks.py @@ -51,13 +51,11 @@ _SlashCommandT = typing.TypeVar("_SlashCommandT", bound=tanjun.ExecutableCommand[tanjun.SlashContext]) _AnyErrorHookSigT = typing.TypeVar("_AnyErrorHookSigT", bound=tanjun.ErrorHookSig[typing.Any]) - _ErrorHookSigT = typing.TypeVar("_ErrorHookSigT", bound=tanjun.ErrorHookSig[tanjun.Context]) _MenuErrorHookSigT = typing.TypeVar("_MenuErrorHookSigT", bound=tanjun.ErrorHookSig[tanjun.MenuContext]) _MessageErrorHookSigT = typing.TypeVar("_MessageErrorHookSigT", bound=tanjun.ErrorHookSig[tanjun.MessageContext]) _SlashErrorHookSigT = typing.TypeVar("_SlashErrorHookSigT", bound=tanjun.ErrorHookSig[tanjun.SlashContext]) _AnyHookSigT = typing.TypeVar("_AnyHookSigT", bound=tanjun.HookSig[typing.Any]) - _HookSigT = typing.TypeVar("_HookSigT", bound=tanjun.HookSig[tanjun.Context]) _MenuHookSigT = typing.TypeVar("_MenuHookSigT", bound=tanjun.HookSig[tanjun.MenuContext]) _MessageHookSigT = typing.TypeVar("_MessageHookSigT", bound=tanjun.HookSig[tanjun.MessageContext]) _SlashHookSigT = typing.TypeVar("_SlashHookSigT", bound=tanjun.HookSig[tanjun.SlashContext]) From 53515098125c1b3fc38d7d44851e06811ab87cea Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Sun, 22 Jan 2023 22:24:05 +0000 Subject: [PATCH 07/45] More typing fixes + backwards compat fixes --- tanjun/abc.py | 92 ++++++++++++++++++++++------------------- tanjun/clients.py | 16 ++++--- tanjun/commands/base.py | 2 +- tanjun/components.py | 14 ++++--- 4 files changed, 70 insertions(+), 54 deletions(-) diff --git a/tanjun/abc.py b/tanjun/abc.py index e4fe8fa35..c4d2693b8 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -32,6 +32,7 @@ from __future__ import annotations __all__: list[str] = [ + "AnyCheckSig", "AnyHooks", "AppCommand", "AppCommandContext", @@ -42,7 +43,6 @@ "Client", "ClientCallbackNames", "ClientLoader", - "CommandCallbackSig", "Component", "Context", "ErrorHookSig", @@ -95,7 +95,7 @@ _MessageHookSigT = typing.TypeVar("_MessageHookSigT", bound="HookSig[MessageContext]") _SlashHookSigT = typing.TypeVar("_SlashHookSigT", bound="HookSig[SlashContext]") - _ListenerCallbackSigT = typing.TypeVar("_ListenerCallbackSigT", bound="ListenerCallbackSig") + _ListenerCallbackSigT = typing.TypeVar("_ListenerCallbackSigT", bound="ListenerCallbackSig[typing.Any]") _MenuCommandT = typing.TypeVar("_MenuCommandT", bound="MenuCommand[typing.Any, typing.Any]") _MessageCommandT = typing.TypeVar("_MessageCommandT", bound="MessageCommand[typing.Any]") _MetaEventSigT = typing.TypeVar("_MetaEventSigT", bound="MetaEventSig") @@ -106,6 +106,7 @@ _ContextT_co = typing.TypeVar("_ContextT_co", covariant=True, bound="Context") _ContextT_contra = typing.TypeVar("_ContextT_contra", bound="Context", contravariant=True) _CoroT = collections.Coroutine[typing.Any, typing.Any, _T] +_MenuValueT = typing.TypeVar("_MenuValueT", hikari.Message, hikari.InteractionMember) _MenuTypeT = typing.TypeVar( "_MenuTypeT", typing.Literal[hikari.CommandType.USER], typing.Literal[hikari.CommandType.MESSAGE] ) @@ -124,59 +125,61 @@ _CheckSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, _P], bool] CheckSig = _CheckSig[_ContextT_contra, ...] -"""Type hint of a general context check used with Tanjun [tanjun.abc.ExecutableCommand][] classes. +"""Type hint of a generic context check used with Tanjun [tanjun.abc.ExecutableCommand][] classes. This may be registered with a [tanjun.abc.ExecutableCommand][] to add a rule -which decides whether it should execute for each context passed to it. This -should take one positional argument of type [tanjun.abc.Context][] and may -either be a synchronous or asynchronous callback which returns [bool][] where -returning [False][] or raising [tanjun.FailedCheck][] will indicate that the +which decides whether it should execute for each context passed to it. + +This should take one positional argument of type [tanjun.abc.Context][] and may +either be a synchronous or asynchronous callback which returns [bool][]. +Returning [False][] or raising [tanjun.FailedCheck][] will indicate that the current context shouldn't lead to an execution. """ AnyCheckSig = _CheckSig["Context", ...] +"""Type hint of a check callback for any command type.""" -MessageCheckSig = _CheckSig["MessageContext", ...] - -SlashCheckSig = _CheckSig["SlashContext", ...] +CommandCallbackSig = collections.Callable[..., _CoroT[None]] +"""Deprecated type hint used to represent any command callback.""" +_CommandCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _P], _CoroT[None]] -_CommandCallbackSig = collections.Callable[ - typing_extensions.Concatenate[_ContextT_contra, _P], collections.Coroutine[typing.Any, typing.Any, None] -] - -_MenuValueT = typing.TypeVar("_MenuValueT", hikari.Message, hikari.InteractionMember) -_ManuCallbackSig = collections.Callable[ - typing_extensions.Concatenate[_ContextT_contra, _MenuValueT, _P], - collections.Coroutine[typing.Any, typing.Any, None], -] +_ManuCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _MenuValueT, _P], _CoroT[None],] MenuCallbackSig = _ManuCallbackSig["MenuContext", _MenuValueT, ...] """Type hint of a context menu command callback. This is guaranteed two positional; arguments of type [tanjun.abc.MenuContext][] and either `hikari.User | hikari.InteractionMember` and/or -[hikari.messages.Message][] dependent on the type(s) of menu this is. +[hikari.messages.Message][] dependent on the type(s) of menu this is, +and may use dependency injection. + +This must be asynchronous and return [None][]. """ +MenuCommandCallbackSig = MenuCallbackSig +"""Deprecated alias of [tanjun.abc.MenuCallbackSig][].""" + _MenuCallbackSigT = typing.TypeVar("_MenuCallbackSigT", bound="MenuCallbackSig[typing.Any]") MessageCallbackSig = _CommandCallbackSig["MessageContext", ...] +"""Type hint of a message command callback. + +This is guaranteed one positional argument of type [tanjun.abc.MessageContext][] and +may use dependency injection. + +This must be asynchronous and return [None][]. +""" _MessageCallbackSigT = typing.TypeVar("_MessageCallbackSigT", bound=MessageCallbackSig) SlashCallbackSig = _CommandCallbackSig["SlashContext", ...] -_SlashCallbackSigT = typing.TypeVar("_SlashCallbackSigT", bound=SlashCallbackSig) - -CommandCallbackSig = _CommandCallbackSig["Context", ...] -"""Type hint of the callback a callable [tanjun.abc.ExecutableCommand][] instance will operate on. +"""Type hint of a slash command callback. -This will be called when executing a command and will need to take one -positional argument of type [tanjun.abc.Context][] where any other required or -optional keyword arguments will be based on the parser instance for the command -if applicable and dependency injection. +This is guaranteed one positional argument of type [tanjun.abc.SlashContext][] and +may use dependency injection. -!!! note - This will have to be asynchronous. +This must be asynchronous and return [None][]. """ +_SlashCallbackSigT = typing.TypeVar("_SlashCallbackSigT", bound=SlashCallbackSig) _ErrorHookSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, Exception, _P], typing.Optional[bool]] @@ -205,9 +208,10 @@ are passed dependent on the type of hook this is being registered as. """ -_ListenerCallbackSig = collections.Callable[typing_extensions.Concatenate[Exception, _P], _CoroT[None]] +_EventT = typing.TypeVar("_EventT", bound=hikari.Event) +_ListenerCallbackSig = collections.Callable[typing_extensions.Concatenate[_EventT, _P], _CoroT[None]] -ListenerCallbackSig = _ListenerCallbackSig[...] +ListenerCallbackSig = _ListenerCallbackSig[_EventT, ...] """Type hint of a hikari event manager callback. This is guaranteed one positional arg of type [hikari.events.base_events.Event][] @@ -3286,7 +3290,9 @@ def message_commands(self) -> collections.Collection[MessageCommand[typing.Any]] @property @abc.abstractmethod - def listeners(self) -> collections.Mapping[type[hikari.Event], collections.Collection[ListenerCallbackSig]]: + def listeners( + self, + ) -> collections.Mapping[type[hikari.Event], collections.Collection[ListenerCallbackSig[typing.Any]]]: """Mapping of event types to the listeners registered for them in this component.""" @property @@ -3508,12 +3514,12 @@ def with_message_command( """ @abc.abstractmethod - def add_listener(self, event: type[hikari.Event], /, *callbacks: ListenerCallbackSig) -> Self: + def add_listener(self, event: type[_EventT], /, *callbacks: ListenerCallbackSig[_EventT]) -> Self: """Add a listener to this component. Parameters ---------- - event + event : type[hikari.events.base_events.Event] The event to listen for. *callbacks The callbacks to add. @@ -3525,12 +3531,12 @@ def add_listener(self, event: type[hikari.Event], /, *callbacks: ListenerCallbac """ @abc.abstractmethod - def remove_listener(self, event: type[hikari.Event], listener: ListenerCallbackSig, /) -> Self: + def remove_listener(self, event: type[_EventT], listener: ListenerCallbackSig[_EventT], /) -> Self: """Remove a listener from this component. Parameters ---------- - event + event : type[hikari.events.base_events.Event] The event to listen for. listener The listener to remove. @@ -3931,7 +3937,9 @@ def is_case_sensitive(self) -> bool: @property # TODO: switch over to a mapping of event to collection cause convenience @abc.abstractmethod - def listeners(self) -> collections.Mapping[type[hikari.Event], collections.Collection[ListenerCallbackSig]]: + def listeners( + self, + ) -> collections.Mapping[type[hikari.Event], collections.Collection[ListenerCallbackSig[typing.Any]]]: """Mapping of event types to the listeners registered in this client.""" @property @@ -4428,12 +4436,12 @@ async def on_close() -> None: """ @abc.abstractmethod - def add_listener(self, event_type: type[hikari.Event], /, *callbacks: ListenerCallbackSig) -> Self: + def add_listener(self, event_type: type[_EventT], /, *callbacks: ListenerCallbackSig[_EventT]) -> Self: """Add a listener to the client. Parameters ---------- - event_type + event_type : type[hikari.events.base_events.Event] The event type to add a listener for. *callbacks The callbacks to register as a listener. @@ -4449,12 +4457,12 @@ def add_listener(self, event_type: type[hikari.Event], /, *callbacks: ListenerCa """ @abc.abstractmethod - def remove_listener(self, event_type: type[hikari.Event], callback: ListenerCallbackSig, /) -> Self: + def remove_listener(self, event_type: type[_EventT], callback: ListenerCallbackSig[_EventT], /) -> Self: """Remove a listener from the client. Parameters ---------- - event_type + event_type : type[hikari.events.base_events.Event] The event type to remove a listener for. callback The callback to remove. diff --git a/tanjun/clients.py b/tanjun/clients.py index 3ec05254f..a5261bc7b 100644 --- a/tanjun/clients.py +++ b/tanjun/clients.py @@ -79,7 +79,8 @@ _AppCmdResponse = typing.Union[ hikari.api.InteractionMessageBuilder, hikari.api.InteractionDeferredBuilder, hikari.api.InteractionModalBuilder ] - _ListenerCallbackSigT = typing.TypeVar("_ListenerCallbackSigT", bound=tanjun.ListenerCallbackSig) + _EventT = typing.TypeVar("_EventT", bound=hikari.Event) + _ListenerCallbackSigT = typing.TypeVar("_ListenerCallbackSigT", bound=tanjun.ListenerCallbackSig[typing.Any]) _MetaEventSigT = typing.TypeVar("_MetaEventSigT", bound=tanjun.MetaEventSig) _PrefixGetterSigT = typing.TypeVar("_PrefixGetterSigT", bound="PrefixGetterSig") _T = typing.TypeVar("_T") @@ -699,7 +700,10 @@ def __init__( self._is_closing = False self._listeners: dict[ type[hikari.Event], - dict[tanjun.ListenerCallbackSig, alluka.abc.AsyncSelfInjecting[tanjun.ListenerCallbackSig]], + dict[ + tanjun.ListenerCallbackSig[typing.Any], + alluka.abc.AsyncSelfInjecting[tanjun.ListenerCallbackSig[typing.Any]], + ], ] = {} self._loop: typing.Optional[asyncio.AbstractEventLoop] = None self._make_autocomplete_context: _AutocompleteContextMakerProto = context.AutocompleteContext @@ -1086,7 +1090,9 @@ def events(self) -> typing.Optional[hikari.api.EventManager]: return self._events @property - def listeners(self) -> collections.Mapping[type[hikari.Event], collections.Collection[tanjun.ListenerCallbackSig]]: + def listeners( + self, + ) -> collections.Mapping[type[hikari.Event], collections.Collection[tanjun.ListenerCallbackSig[typing.Any]]]: return _internal.CastedView(self._listeners, lambda x: [callback.callback for callback in x.values()]) @property @@ -1935,7 +1941,7 @@ def decorator(callback: _MetaEventSigT, /) -> _MetaEventSigT: return decorator - def add_listener(self, event_type: type[hikari.Event], /, *callbacks: tanjun.ListenerCallbackSig) -> Self: + def add_listener(self, event_type: type[_EventT], /, *callbacks: tanjun.ListenerCallbackSig[_EventT]) -> Self: # <>. for callback in callbacks: injected = self.injector.as_async_self_injecting(callback) @@ -1954,7 +1960,7 @@ def add_listener(self, event_type: type[hikari.Event], /, *callbacks: tanjun.Lis return self - def remove_listener(self, event_type: type[hikari.Event], callback: tanjun.ListenerCallbackSig, /) -> Self: + def remove_listener(self, event_type: type[_EventT], callback: tanjun.ListenerCallbackSig[_EventT], /) -> Self: # <>. callbacks = self._listeners[event_type] diff --git a/tanjun/commands/base.py b/tanjun/commands/base.py index af35dbf82..588062dc0 100644 --- a/tanjun/commands/base.py +++ b/tanjun/commands/base.py @@ -61,7 +61,7 @@ def __init__(self) -> None: self._metadata: dict[typing.Any, typing.Any] = {} @property - def checks(self) -> collections.Collection[tanjun.AnyCheckSig]: + def checks(self) -> collections.Collection[tanjun.CheckSig[_ContextT]]: # <>. return self._checks.copy() diff --git a/tanjun/components.py b/tanjun/components.py index 2df150b9c..b671fe8ef 100644 --- a/tanjun/components.py +++ b/tanjun/components.py @@ -56,7 +56,8 @@ _AppCommandContextT = typing.TypeVar("_AppCommandContextT", bound=tanjun.AppCommandContext) _BaseSlashCommandT = typing.TypeVar("_BaseSlashCommandT", bound=tanjun.BaseSlashCommand) _CheckSigT = typing.TypeVar("_CheckSigT", bound=tanjun.AnyCheckSig) - _ListenerCallbackSigT = typing.TypeVar("_ListenerCallbackSigT", bound=tanjun.ListenerCallbackSig) + _EventT = typing.TypeVar("_EventT", bound=hikari.Event) + _ListenerCallbackSigT = typing.TypeVar("_ListenerCallbackSigT", bound=tanjun.ListenerCallbackSig[typing.Any]) _MenuCommandT = typing.TypeVar("_MenuCommandT", bound=tanjun.MenuCommand[typing.Any, typing.Any]) _MessageCommandT = typing.TypeVar("_MessageCommandT", bound=tanjun.MessageCommand[typing.Any]) _MetaEventSigT = typing.TypeVar("_MetaEventSigT", bound=tanjun.MetaEventSig) @@ -205,7 +206,7 @@ def __init__(self, *, name: typing.Optional[str] = None, strict: bool = False) - self._dms_enabled_for_app_cmds: typing.Optional[bool] = None self._hooks: typing.Optional[tanjun.AnyHooks] = None self._is_case_sensitive: typing.Optional[bool] = None - self._listeners: dict[type[hikari.Event], list[tanjun.ListenerCallbackSig]] = {} + self._listeners: dict[type[hikari.Event], list[tanjun.ListenerCallbackSig[typing.Any]]] = {} self._loop: typing.Optional[asyncio.AbstractEventLoop] = None self._menu_commands: dict[tuple[hikari.CommandType, str], tanjun.MenuCommand[typing.Any, typing.Any]] = {} self._menu_hooks: typing.Optional[tanjun.MenuHooks] = None @@ -303,7 +304,9 @@ def message_commands(self) -> collections.Collection[tanjun.MessageCommand[typin return self._message_commands.commands.copy() @property - def listeners(self) -> collections.Mapping[type[hikari.Event], collections.Collection[tanjun.ListenerCallbackSig]]: + def listeners( + self, + ) -> collections.Mapping[type[hikari.Event], collections.Collection[tanjun.ListenerCallbackSig[typing.Any]]]: # <>. return _internal.CastedView(self._listeners, lambda x: x.copy()) @@ -986,7 +989,7 @@ def with_message_command( # <>. return _with_command(self.add_message_command, command, copy=copy) - def add_listener(self, event: type[hikari.Event], /, *callbacks: tanjun.ListenerCallbackSig) -> Self: + def add_listener(self, event: type[_EventT], /, *callbacks: tanjun.ListenerCallbackSig[_EventT]) -> Self: # <>. for listener in callbacks: try: @@ -1004,7 +1007,7 @@ def add_listener(self, event: type[hikari.Event], /, *callbacks: tanjun.Listener return self - def remove_listener(self, event: type[hikari.Event], listener: tanjun.ListenerCallbackSig, /) -> Self: + def remove_listener(self, event: type[_EventT], listener: tanjun.ListenerCallbackSig[_EventT], /) -> Self: # <>. self._listeners[event].remove(listener) if not self._listeners[event]: @@ -1015,7 +1018,6 @@ def remove_listener(self, event: type[hikari.Event], listener: tanjun.ListenerCa return self - # TODO: make event optional? def with_listener( self, *event_types: type[hikari.Event] ) -> collections.Callable[[_ListenerCallbackSigT], _ListenerCallbackSigT]: From 56604bd8eaf9b6384a8b3effcd95c8c935211466 Mon Sep 17 00:00:00 2001 From: "always-on-duty[bot]" <120557446+always-on-duty[bot]@users.noreply.github.com> Date: Sun, 22 Jan 2023 22:25:26 +0000 Subject: [PATCH 08/45] Freeze PR dependency changes --- dev-requirements/constraints.in | 1 + dev-requirements/constraints.txt | 3 +++ dev-requirements/type-checking.txt | 14 +++++++------- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/dev-requirements/constraints.in b/dev-requirements/constraints.in index 0e09a12ec..e6dc4e34e 100644 --- a/dev-requirements/constraints.in +++ b/dev-requirements/constraints.in @@ -1,2 +1,3 @@ alluka>=0.1.2, <1 hikari>=2.0.0.dev115, <3 +typing-extensions~=4.2 diff --git a/dev-requirements/constraints.txt b/dev-requirements/constraints.txt index cee34ebd5..878e6a76a 100644 --- a/dev-requirements/constraints.txt +++ b/dev-requirements/constraints.txt @@ -269,6 +269,9 @@ multidict==6.0.4 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf \ --hash=sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d \ --hash=sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba +typing-extensions==4.4.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ + --hash=sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa \ + --hash=sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e yarl==1.8.2 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:009a028127e0a1755c38b03244c0bea9d5565630db9c4cf9572496e947137a87 \ --hash=sha256:0414fd91ce0b763d4eadb4456795b307a71524dbacd015c657bb2a39db2eab89 \ diff --git a/dev-requirements/type-checking.txt b/dev-requirements/type-checking.txt index ff5f9eeaa..ba445ab3c 100644 --- a/dev-requirements/type-checking.txt +++ b/dev-requirements/type-checking.txt @@ -482,10 +482,10 @@ pydantic==1.10.4 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:f2f7eb6273dd12472d7f218e1fef6f7c7c2f00ac2e1ecde4db8824c457300416 \ --hash=sha256:fdf88ab63c3ee282c76d652fc86518aacb737ff35796023fae56a65ced1a5978 \ --hash=sha256:fdf8d759ef326962b4678d89e275ffc55b7ce59d917d9f72233762061fd04a2d -pyright==1.1.291 ; python_full_version >= "3.9.0" and python_version < "3.12" \ - --hash=sha256:2dbd133ee400e81ff319d0701bc47545a7ab1cd7dcfcf46c7de37d9b0fbbb76f \ - --hash=sha256:3946f43f1a99f8e438eee1738ad0649d8bd7ac36dded25849245993ab02671bd -pytest-asyncio==0.20.3 ; python_full_version >= "3.9.0" and python_version < "3.12" \ +pyright==1.1.290 ; python_full_version >= "3.9.0" and python_version < "3.12" \ + --hash=sha256:956d8efc70eb5a54da54c82feef842affd3a81719c8864769cd196e211961e3a \ + --hash=sha256:c1a57ad812f740fc7fb6bb416cd7e3f46f4e88384c723192402a77e2e756b550 +pytest-asyncio==0.20.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ --hash=sha256:83cbf01169ce3e8eb71c6c278ccb0574d1a7a3bb8eaaf5e50e0ad342afb33b36 \ --hash=sha256:f129998b209d04fcc65c96fc85c11e5316738358909a8399e93be553d7656442 pytest-cov==4.0.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ @@ -506,9 +506,9 @@ pytest==7.2.1 ; python_full_version >= "3.9.0" and python_version < "3.12" \ python-dateutil==2.8.2 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 -setuptools==67.0.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ - --hash=sha256:883131c5b6efa70b9101c7ef30b2b7b780a4283d5fc1616383cdf22c83cbefe6 \ - --hash=sha256:9d790961ba6219e9ff7d9557622d2fe136816a264dd01d5997cfc057d804853d +setuptools==66.1.1 ; python_full_version >= "3.9.0" and python_version < "3.12" \ + --hash=sha256:6f590d76b713d5de4e49fe4fbca24474469f53c83632d5d0fd056f7ff7e8112b \ + --hash=sha256:ac4008d396bc9cd983ea483cb7139c0240a07bbc74ffb6232fceffedc6cf03a8 six==1.16.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 From 5bf2fe920dd3a2861c9a3b91db10d640b5c0a94a Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Sun, 22 Jan 2023 23:16:13 +0000 Subject: [PATCH 09/45] Typing fixes and simplifications --- tanjun/commands/menu.py | 76 +++++------------------ tanjun/commands/message.py | 122 ++++++------------------------------- tanjun/commands/slash.py | 96 ++++++++--------------------- 3 files changed, 57 insertions(+), 237 deletions(-) diff --git a/tanjun/commands/menu.py b/tanjun/commands/menu.py index 94b630ce9..cc7c53823 100644 --- a/tanjun/commands/menu.py +++ b/tanjun/commands/menu.py @@ -54,7 +54,11 @@ _MessageCallbackSigT = typing.TypeVar("_MessageCallbackSigT", bound="tanjun.MenuCallbackSig[hikari.Message]") _UserCallbackSigT = typing.TypeVar("_UserCallbackSigT", bound="tanjun.MenuCallbackSig[hikari.InteractionMember]") - _AnyCommandT = typing.Union[tanjun.MessageCommand["_AnyCallbackSigT"], tanjun.SlashCommand["_AnyCallbackSigT"],] + _AnyCommandT = typing.Union[ + tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], + tanjun.MessageCommand["_AnyCallbackSigT"], + tanjun.SlashCommand["_AnyCallbackSigT"], + ] _CallbackishT = typing.Union["_AnyCallbackSigT", _AnyCommandT["_AnyCallbackSigT"]] import hikari @@ -73,21 +77,12 @@ def __call__( ) -> MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]]: ... - @typing.overload - def __call__( - self, _: tanjun.MenuCommand[_MessageCallbackSigT, typing.Any], / - ) -> MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]]: - ... - @typing.overload def __call__( self, _: _MessageCallbackSigT, / ) -> MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]]: ... - # def __call__(self, _: _CallbackishT[_AnyCallbackSigT], /) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: - # raise NotImplementedError - def as_message_menu( name: typing.Union[str, collections.Mapping[str, str]], @@ -150,7 +145,7 @@ async def message_command(self, ctx: tanjun.abc.MenuContext, message: hikari.Mes Returns ------- - collections.abc.Callable[[tanjun.abc.MenuCommandCallbackSig], MenuCommand] + collections.abc.Callable[[tanjun.abc.MenuCallbackSig], MenuCommand] The decorator callback used to make a [tanjun.MenuCommand][]. This can either wrap a raw command callback or another callable command instance @@ -167,18 +162,6 @@ async def message_command(self, ctx: tanjun.abc.MenuContext, message: hikari.Mes * If the command name has uppercase characters. """ - @typing.overload - def decorator( - callback: _AnyCommandT[_MessageCallbackSigT], / - ) -> MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]]: - ... - - @typing.overload - def decorator( - callback: _MessageCallbackSigT, / - ) -> MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]]: - ... - def decorator( callback: _CallbackishT[_MessageCallbackSigT], / ) -> MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]]: @@ -211,21 +194,12 @@ def __call__( ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: ... - @typing.overload - def __call__( - self, _: tanjun.MenuCommand[_UserCallbackSigT, typing.Any], / - ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: - ... - @typing.overload def __call__( self, _: _UserCallbackSigT, / ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: ... - # def __call__(self, _: _CallbackishT[_AnyCallbackSigT], /) -> MenuCommand[_AnyCallbackSigT, _MenuTypeT]: - # raise NotImplementedError - def as_user_menu( name: typing.Union[str, collections.Mapping[str, str]], @@ -290,7 +264,7 @@ async def user_command( Returns ------- - collections.abc.Callable[[tanjun.abc.MenuCommandCallbackSig], MenuCommand] + collections.abc.Callable[[tanjun.abc.MenuCallbackSig], MenuCommand] The decorator callback used to make a [tanjun.MenuCommand][]. This can either wrap a raw command callback or another callable command instance @@ -307,24 +281,6 @@ async def user_command( * If the command name has uppercase characters. """ - @typing.overload - def decorator( - callback: _AnyCommandT[_UserCallbackSigT], / - ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: - ... - - @typing.overload - def decorator( - callback: tanjun.MenuCommand[_UserCallbackSigT, typing.Any], / - ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: - ... - - @typing.overload - def decorator( - callback: _UserCallbackSigT, / - ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: - ... - def decorator( callback: _CallbackishT[_UserCallbackSigT], / ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: @@ -373,9 +329,9 @@ class MenuCommand(base.PartialCommand[tanjun.MenuContext], tanjun.MenuCommand[_A @typing.overload def __init__( - self: MenuCommand[_AnyCallbackSigT, _MenuTypeT], - callback: _AnyCommandT[_AnyCallbackSigT,], - type_: _MenuTypeT, + self: MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]], + callback: _CallbackishT[_UserCallbackSigT], + type_: typing.Literal[hikari.CommandType.USER], name: typing.Union[str, collections.Mapping[str, str]], /, *, @@ -390,9 +346,9 @@ def __init__( @typing.overload def __init__( - self, - callback: _AnyMenuCallbackSigT, - type_: _MenuTypeT, + self: MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]], + callback: _CallbackishT[_MessageCallbackSigT], + type_: typing.Literal[hikari.CommandType.MESSAGE], name: typing.Union[str, collections.Mapping[str, str]], /, *, @@ -406,8 +362,8 @@ def __init__( ... def __init__( - self: MenuCommand[_AnyCallbackSigT, _MenuTypeT], - callback: _CallbackishT[_AnyCallbackSigT], + self, + callback: _CallbackishT[_AnyMenuCallbackSigT], type_: _MenuTypeT, name: typing.Union[str, collections.Mapping[str, str]], /, @@ -471,7 +427,7 @@ def __init__( Returns ------- - collections.abc.Callable[[tanjun.abc.MenuCommandCallbackSig], MenuCommand] + collections.abc.Callable[[tanjun.abc.MenuCallbackSig], MenuCommand] The decorator callback used to make a [tanjun.MenuCommand][]. This can either wrap a raw command callback or another callable command instance diff --git a/tanjun/commands/message.py b/tanjun/commands/message.py index 580e03a84..b281287a1 100644 --- a/tanjun/commands/message.py +++ b/tanjun/commands/message.py @@ -48,25 +48,23 @@ from typing_extensions import Self _AnyMessageCommandT = typing.TypeVar("_AnyMessageCommandT", bound=tanjun.MessageCommand[typing.Any]) - _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=tanjun.CommandCallbackSig) + _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=collections.Callable[..., typing.Any]) _AnyCommandT = typing.Union[ - tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], tanjun.SlashCommand["_AnyCallbackSigT"] + tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], + tanjun.MessageCommand[_AnyCallbackSigT], + tanjun.SlashCommand["_AnyCallbackSigT"], ] - _CallbackishT = typing.Union[_AnyCommandT["_AnyCallbackSigT"], "_AnyCallbackSigT"] + _CallbackishT = typing.Union[_AnyCommandT["_MessageCallbackSigT"], "_MessageCallbackSigT"] _MessageCallbackSigT = typing.TypeVar("_MessageCallbackSigT", bound=tanjun.MessageCallbackSig) -_OtherCallbackSigT = typing.TypeVar("_OtherCallbackSigT", bound=tanjun.CommandCallbackSig) +_OtherCallbackSigT = typing.TypeVar("_OtherCallbackSigT", bound=tanjun.MessageCallbackSig) _EMPTY_DICT: typing.Final[dict[typing.Any, typing.Any]] = {} _EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() class _ResultProto(typing.Protocol): @typing.overload - def __call__(self, _: _AnyCommandT[_AnyCallbackSigT], /) -> MessageCommand[_AnyCallbackSigT]: - ... - - @typing.overload - def __call__(self, _: tanjun.MessageCommand[_AnyCallbackSigT], /) -> MessageCommand[_AnyCallbackSigT]: + def __call__(self, _: _AnyCommandT[_MessageCallbackSigT], /) -> MessageCommand[_MessageCallbackSigT]: ... @typing.overload @@ -88,7 +86,7 @@ def as_message_command(name: str, /, *names: str, validate_arg_keys: bool = True Returns ------- - collections.abc.Callable[[tanjun.abc.CommandCallbackSig], MessageCommand] + collections.abc.Callable[[tanjun.abc.MessageCallbackSig], MessageCommand] The decorator callback used to make a [tanjun.MessageCommand][]. This can either wrap a raw command callback or another callable command instance @@ -97,22 +95,7 @@ def as_message_command(name: str, /, *names: str, validate_arg_keys: bool = True [tanjun.Component.load_from_scope][]. """ - @typing.overload - def decorator(callback: _AnyCommandT[_AnyCallbackSigT], /) -> MessageCommand[_AnyCallbackSigT]: - ... - - @typing.overload - def decorator(callback: tanjun.MessageCommand[_AnyCallbackSigT], /) -> MessageCommand[_AnyCallbackSigT]: - ... - - @typing.overload - def decorator(callback: _MessageCallbackSigT, /) -> MessageCommand[_MessageCallbackSigT]: - ... - - # TODO: make ExecutableCommand generic and simplify - def decorator( - callback: typing.Union[tanjun.ExecutableCommand[typing.Any], _MessageCallbackSigT], / - ) -> MessageCommand[typing.Any]: + def decorator(callback: _CallbackishT[_MessageCallbackSigT], /) -> MessageCommand[typing.Any]: if isinstance(callback, (tanjun.MenuCommand, tanjun.MessageCommand, tanjun.SlashCommand)): wrapped_command = callback callback = callback.callback @@ -129,11 +112,7 @@ def decorator( class _GroupResultProto(typing.Protocol): @typing.overload - def __call__(self, _: _AnyCommandT[_AnyCallbackSigT], /) -> MessageCommandGroup[_AnyCallbackSigT]: - ... - - @typing.overload - def __call__(self, _: tanjun.MessageCommand[_AnyCallbackSigT], /) -> MessageCommandGroup[_AnyCallbackSigT]: + def __call__(self, _: _AnyCommandT[_MessageCallbackSigT], /) -> MessageCommandGroup[_MessageCallbackSigT]: ... @typing.overload @@ -162,7 +141,7 @@ def as_message_command_group( Returns ------- - collections.abc.Callable[[tanjun.abc.CommandCallbackSig], MessageCommand] + collections.abc.Callable[[tanjun.abc.MessageCallbackSig], MessageCommand] The decorator callback used to make a [tanjun.MessageCommandGroup][]. This can either wrap a raw command callback or another callable command instance @@ -171,22 +150,7 @@ def as_message_command_group( [tanjun.Component.load_from_scope][]. """ - @typing.overload - def decorator(callback: _AnyCommandT[_AnyCallbackSigT], /) -> MessageCommandGroup[_AnyCallbackSigT]: - ... - - @typing.overload - def decorator(callback: tanjun.MessageCommand[_AnyCallbackSigT], /) -> MessageCommandGroup[_AnyCallbackSigT]: - ... - - @typing.overload - def decorator(callback: _MessageCallbackSigT, /) -> MessageCommandGroup[_MessageCallbackSigT]: - ... - - # TODO: make executable command generic and simplify - def decorator( - callback: typing.Union[tanjun.ExecutableCommand[typing.Any], _MessageCallbackSigT], / - ) -> MessageCommandGroup[typing.Any]: + def decorator(callback: _CallbackishT[_MessageCallbackSigT], /) -> MessageCommandGroup[typing.Any]: if isinstance(callback, (tanjun.MenuCommand, tanjun.MessageCommand, tanjun.SlashCommand)): wrapped_command = callback callback = callback.callback @@ -206,33 +170,9 @@ class MessageCommand(base.PartialCommand[tanjun.MessageContext], tanjun.MessageC __slots__ = ("_arg_names", "_callback", "_names", "_parent", "_parser", "_wrapped_command") - @typing.overload - def __init__( - self: MessageCommand[_AnyCallbackSigT], - callback: _AnyCommandT[_AnyCallbackSigT], - name: str, - /, - *names: str, - validate_arg_keys: bool = True, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, - ) -> None: - ... - - @typing.overload def __init__( self, - callback: _MessageCallbackSigT, - name: str, - /, - *names: str, - validate_arg_keys: bool = True, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, - ) -> None: - ... - - def __init__( - self: MessageCommand[_AnyCallbackSigT], - callback: _CallbackishT[_AnyCallbackSigT], + callback: _CallbackishT[_MessageCallbackSigT], name: str, /, *names: str, @@ -405,35 +345,9 @@ class MessageCommandGroup(MessageCommand[_MessageCallbackSigT], tanjun.MessageCo __slots__ = ("_commands",) - @typing.overload - def __init__( - self: MessageCommandGroup[_AnyCallbackSigT], - callback: _AnyCommandT[_AnyCallbackSigT], - name: str, - /, - *names: str, - strict: bool = False, - validate_arg_keys: bool = True, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, - ) -> None: - ... - - @typing.overload def __init__( self, - callback: _MessageCallbackSigT, - name: str, - /, - *names: str, - strict: bool = False, - validate_arg_keys: bool = True, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, - ) -> None: - ... - - def __init__( - self: MessageCommandGroup[_AnyCallbackSigT], - callback: _CallbackishT[_AnyCallbackSigT], + callback: _CallbackishT[_MessageCallbackSigT], name: str, /, *names: str, @@ -522,7 +436,7 @@ def as_sub_command(self, name: str, /, *names: str, validate_arg_keys: bool = Tr Returns ------- - collections.abc.Callable[[tanjun.abc.CommandCallbackSig], MessageCommand] + collections.abc.Callable[[tanjun.abc.MessageCallbackSig], MessageCommand] The decorator callback used to make a sub-command. This can either wrap a raw command callback or another callable command instance @@ -557,16 +471,14 @@ def as_sub_group( Returns ------- - collections.abc.Callable[[tanjun.abc.CommandCallbackSig], MessageCommand] + collections.abc.Callable[[tanjun.abc.MessageCallbackSig], MessageCommand] The decorator callback used to make a sub-command group. This can either wrap a raw command callback or another callable command instance (e.g. [tanjun.MenuCommand][], [tanjun.MessageCommand][], [tanjun.SlashCommand][]). """ - def decorator( - callback: typing.Union[_OtherCallbackSigT, _CommandT[_OtherCallbackSigT]], / - ) -> MessageCommandGroup[_OtherCallbackSigT]: + def decorator(callback: _CallbackishT[_OtherCallbackSigT], /) -> MessageCommandGroup[_OtherCallbackSigT]: return self.with_command( as_message_command_group(name, *names, strict=strict, validate_arg_keys=validate_arg_keys)(callback) ) diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index 37bbb10df..ce9334bd5 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -72,16 +72,17 @@ from hikari.api import special_endpoints as special_endpoints_api from typing_extensions import Self - _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=tanjun.CommandCallbackSig) + _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=collections.Callable[..., typing.Any]) _AutocompleteCallbackSigT = typing.TypeVar("_AutocompleteCallbackSigT", bound=tanjun.AutocompleteCallbackSig) _AnyBaseSlashCommandT = typing.TypeVar("_AnyBaseSlashCommandT", bound="tanjun.BaseSlashCommand") _SlashCommandT = typing.TypeVar("_SlashCommandT", bound="SlashCommand[typing.Any]") _AnyCommandT = typing.Union[ - tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], tanjun.MessageCommand["_AnyCallbackSigT"] + tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], + tanjun.MessageCommand["_AnyCallbackSigT"], + tanjun.SlashCommand["_AnyCallbackSigT"], ] - _CallbackishT = typing.Union["_AnyCallbackSigT", _AnyCommandT["_AnyCallbackSigT"]] + _CallbackishT = typing.Union["_SlashCallbackSigT", _AnyCommandT["_SlashCallbackSigT"]] -_CommandCallbackSigT = typing.TypeVar("_CommandCallbackSigT", bound=tanjun.CommandCallbackSig) _SlashCallbackSigT = typing.TypeVar("_SlashCallbackSigT", bound=tanjun.SlashCallbackSig) _EMPTY_DICT: typing.Final[dict[typing.Any, typing.Any]] = {} _EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() @@ -90,6 +91,7 @@ collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, typing.Any]], collections.Callable[..., typing.Any], ] +"""Type hint of a slash command option converter.""" _SCOMMAND_NAME_REG: typing.Final[str] = r"^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$" @@ -232,11 +234,7 @@ async def help_me_command(ctx: tanjun.abc.SlashContext) -> None: class _ResultProto(typing.Protocol): @typing.overload - def __call__(self, _: _AnyCommandT[_AnyCallbackSigT], /) -> SlashCommand[_AnyCallbackSigT]: - ... - - @typing.overload - def __call__(self, _: tanjun.SlashCommand[_AnyCallbackSigT], /) -> SlashCommand[_AnyCallbackSigT]: + def __call__(self, _: _AnyCommandT[_SlashCallbackSigT], /) -> SlashCommand[_SlashCallbackSigT]: ... @typing.overload @@ -326,7 +324,7 @@ async def ping_command(self, ctx: tanjun.abc.SlashContext) -> None: Returns ------- - collections.abc.Callable[[tanjun.abc.CommandCallbackSig], SlashCommand] + collections.abc.Callable[[tanjun.abc.SlashCallbackSig], SlashCommand] The decorator callback used to make a [tanjun.SlashCommand][]. This can either wrap a raw command callback or another callable command instance @@ -344,15 +342,7 @@ async def ping_command(self, ctx: tanjun.abc.SlashContext) -> None: * If the description is over 100 characters long. """ # noqa: D202, E501 - @typing.overload - def decorator(callback: _AnyCommandT[_AnyCallbackSigT], /) -> SlashCommand[_AnyCallbackSigT]: - ... - - @typing.overload - def decorator(callback: _SlashCallbackSigT, /) -> SlashCommand[_SlashCallbackSigT]: - ... - - def decorator(callback: _CallbackishT[_AnyCallbackSigT], /) -> SlashCommand[_AnyCallbackSigT]: + def decorator(callback: _CallbackishT[_SlashCallbackSigT], /) -> SlashCommand[_SlashCallbackSigT]: if isinstance(callback, (tanjun.MenuCommand, tanjun.MessageCommand, tanjun.SlashCommand)): wrapped_command = callback callback = callback.callback @@ -406,7 +396,7 @@ async def command(self, ctx: tanjun.abc.SlashContext, name: hikari.Attachment) - Returns ------- - collections.abc.Callable[[_SlashCommandT], _SlashCommandT] + collections.abc.Callable[[tanjun.SlashCommand], tanjun.SlashCommand] Decorator callback which adds the option to the command. """ return lambda command: command.add_attachment_option( @@ -444,7 +434,7 @@ async def command(self, ctx: tanjun.abc.SlashContext, name: str) -> None: Returns ------- - collections.abc.Callable[[_SlashCommandT], _SlashCommandT] + collections.abc.Callable[[tanjun.SlashCommand], tanjun.SlashCommand] Decorator callback which adds the option to the command. """ return lambda c: c.add_str_option( @@ -492,7 +482,7 @@ async def command(self, ctx: tanjun.abc.SlashContext, int_value: int) -> None: Returns ------- - collections.abc.Callable[[_SlashCommandT], _SlashCommandT] + collections.abc.Callable[[tanjun.SlashCommand], tanjun.SlashCommand] Decorator callback which adds the option to the command. """ return lambda c: c.add_int_option( @@ -541,7 +531,7 @@ async def command(self, ctx: tanjun.abc.SlashContext, float_value: float) -> Non Returns ------- - collections.abc.Callable[[_SlashCommandT], _SlashCommandT] + collections.abc.Callable[[tanjun.SlashCommand], tanjun.SlashCommand] Decorator callback which adds the option to the command. """ return lambda c: c.add_float_option( @@ -585,7 +575,7 @@ async def command(self, ctx: tanjun.abc.SlashContext, flag: bool) -> None: Returns ------- - collections.abc.Callable[[_SlashCommandT], _SlashCommandT] + collections.abc.Callable[[tanjun.SlashCommand], tanjun.SlashCommand] Decorator callback which adds the option to the command. """ return lambda c: c.add_bool_option(name, description, default=default, key=key, pass_as_kwarg=pass_as_kwarg) @@ -621,7 +611,7 @@ async def command(self, ctx: tanjun.abc.SlashContext, user: Union[InteractionMem Returns ------- - collections.abc.Callable[[_SlashCommandT], _SlashCommandT] + collections.abc.Callable[[tanjun.SlashCommand], tanjun.SlashCommand] Decorator callback which adds the option to the command. """ return lambda c: c.add_user_option(name, description, default=default, key=key, pass_as_kwarg=pass_as_kwarg) @@ -654,7 +644,7 @@ async def command(self, ctx: tanjun.abc.SlashContext, member: hikari.Interaction Returns ------- - collections.abc.Callable[[_SlashCommandT], _SlashCommandT] + collections.abc.Callable[[tanjun.SlashCommand], tanjun.SlashCommand] Decorator callback which adds the option to the command. """ return lambda c: c.add_member_option(name, description, default=default, key=key) @@ -689,7 +679,7 @@ async def command(self, ctx: tanjun.abc.SlashContext, channel: hikari.Interactio Returns ------- - collections.abc.Callable[[_SlashCommandT], _SlashCommandT] + collections.abc.Callable[[tanjun.SlashCommand], tanjun.SlashCommand] Decorator callback which adds the option to the command. """ return lambda c: c.add_channel_option( @@ -722,7 +712,7 @@ async def command(self, ctx: tanjun.abc.SlashContext, role: hikari.Role) -> None Returns ------- - collections.abc.Callable[[_SlashCommandT], _SlashCommandT] + collections.abc.Callable[[tanjun.SlashCommand], tanjun.SlashCommand] Decorator callback which adds the option to the command. """ return lambda c: c.add_role_option(name, description, default=default, key=key, pass_as_kwarg=pass_as_kwarg) @@ -757,7 +747,7 @@ async def command(self, ctx: tanjun.abc.SlashContext, mentionable: [Role, Intera Returns ------- - collections.abc.Callable[[_SlashCommandT], _SlashCommandT] + collections.abc.Callable[[tanjun.SlashCommand], tanjun.SlashCommand] Decorator callback which adds the option to the command. """ return lambda c: c.add_mentionable_option(name, description, default=default, key=key, pass_as_kwarg=pass_as_kwarg) @@ -1259,7 +1249,7 @@ def as_sub_command( Returns ------- - collections.abc.Callable[[tanjun.abc.CommandCallbackSig], SlashCommand] + collections.abc.Callable[[tanjun.abc.SlashCallbackSig], SlashCommand] The decorator callback used to make a sub-command. This can either wrap a raw command callback or another callable command instance @@ -1275,7 +1265,7 @@ def as_sub_command( * If the description is over 100 characters long. """ # noqa: D202, E501 - def decorator(callback: _CallbackishT[_CommandCallbackSigT], /) -> SlashCommand[_CommandCallbackSigT]: + def decorator(callback: _CallbackishT[_SlashCallbackSigT], /) -> SlashCommand[_SlashCallbackSigT]: return self.with_command( as_slash_command( name, @@ -1444,49 +1434,11 @@ class SlashCommand(BaseSlashCommand, tanjun.SlashCommand[_SlashCallbackSigT]): "_wrapped_command", ) - @typing.overload - def __init__( - self: SlashCommand[_AnyCallbackSigT], - callback: _AnyCommandT[_AnyCallbackSigT], - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], - /, - *, - always_defer: bool = False, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, - is_global: bool = True, - sort_options: bool = True, - validate_arg_keys: bool = True, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, - ) -> None: - ... - - @typing.overload def __init__( self, - callback: _SlashCallbackSigT, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], - /, - *, - always_defer: bool = False, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, - is_global: bool = True, - sort_options: bool = True, - validate_arg_keys: bool = True, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, - ) -> None: - ... - - def __init__( - self, - callback: _CallbackishT[_AnyCallbackSigT], - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + callback: _CallbackishT[_SlashCallbackSigT], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, always_defer: bool = False, From b2b00fb6ef91ab31a913e19d86aef8a71beafcf0 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Mon, 23 Jan 2023 03:47:47 +0000 Subject: [PATCH 10/45] Improve autocomplete and converter typing --- tanjun/abc.py | 23 ++++--- tanjun/annotations.py | 26 +++++--- tanjun/clients.py | 42 ++++++++----- tanjun/commands/slash.py | 127 ++++++++++++++++++++------------------- tanjun/parsing.py | 11 +++- 5 files changed, 134 insertions(+), 95 deletions(-) diff --git a/tanjun/abc.py b/tanjun/abc.py index c4d2693b8..fc540c2ed 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -36,8 +36,8 @@ "AnyHooks", "AppCommand", "AppCommandContext", - "AutocompleteCallbackSig", "AutocompleteContext", + "AutocompleteSig", "BaseSlashCommand", "CheckSig", "Client", @@ -82,7 +82,6 @@ from typing_extensions import Self - _AutocompleteValueT = typing.TypeVar("_AutocompleteValueT", int, str, float) _BaseSlashCommandT = typing.TypeVar("_BaseSlashCommandT", bound="BaseSlashCommand") _AnyErrorHookSigT = typing.TypeVar("_AnyErrorHookSigT", bound="ErrorHookSig[typing.Any]") @@ -112,17 +111,25 @@ ) _MaybeAwaitable = typing.Union[collections.Callable[_P, _CoroT[_T]], collections.Callable[_P, _T]] -_AutocompleteCallbackSig = collections.Callable[typing_extensions.Concatenate["AutocompleteContext", _P], _CoroT[None]] -AutocompleteCallbackSig = _AutocompleteCallbackSig[...] + +_AutocompleteValueT = typing.TypeVar("_AutocompleteValueT", int, str, float) +_AutocompleteSig = collections.Callable[ + typing_extensions.Concatenate["AutocompleteContext", _AutocompleteValueT, _P], _CoroT[None] +] + +AutocompleteSig = _AutocompleteSig[_AutocompleteValueT, ...] """Type hint of the callback an autocomplete callback should have. This will be called when handling autocomplete and should be an asynchronous callback which two positional arguments of type [tanjun.abc.AutocompleteContext][] and -`str | int | float` (with the 2nd argument type being decided by the +`str` or `int` or `float` (with the 2nd argument type being decided by the autocomplete type), returns [None][] and may use dependency injection. """ +AutocompleteCallbackSig = AutocompleteSig +"""Deprecated alias of [tanjun.abc.AutocompleteSig][]""" + _CheckSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, _P], bool] CheckSig = _CheckSig[_ContextT_contra, ...] """Type hint of a generic context check used with Tanjun [tanjun.abc.ExecutableCommand][] classes. @@ -2855,17 +2862,17 @@ def callback(self) -> _SlashCallbackSigT: @property @abc.abstractmethod - def float_autocompletes(self) -> collections.Mapping[str, AutocompleteCallbackSig]: + def float_autocompletes(self) -> collections.Mapping[str, AutocompleteSig[float]]: """Collection of the float option autocompletes.""" @property @abc.abstractmethod - def int_autocompletes(self) -> collections.Mapping[str, AutocompleteCallbackSig]: + def int_autocompletes(self) -> collections.Mapping[str, AutocompleteSig[int]]: """Collection of the integer option autocompletes.""" @property @abc.abstractmethod - def str_autocompletes(self) -> collections.Mapping[str, AutocompleteCallbackSig]: + def str_autocompletes(self) -> collections.Mapping[str, AutocompleteSig[str]]: """Collection of the string option autocompletes.""" diff --git a/tanjun/annotations.py b/tanjun/annotations.py index 962a8a133..05b960a2e 100644 --- a/tanjun/annotations.py +++ b/tanjun/annotations.py @@ -90,8 +90,20 @@ from .commands import slash if typing.TYPE_CHECKING: + import typing_extensions from typing_extensions import Self + _P = typing_extensions.ParamSpec("_P") + _ConverterValueT = typing.TypeVar("_ConverterValueT", bound=typing.Union[int, str, float]) + __ConverterSig = typing.Union[ + collections.Callable[ + typing_extensions.Concatenate[_ConverterValueT, _P], + collections.Coroutine[typing.Any, typing.Any, typing.Any], + ], + collections.Callable[typing_extensions.Concatenate[_ConverterValueT, _P], typing.Any], + ] + _ConverterSig = __ConverterSig[_ConverterValueT, ...] + _T = typing.TypeVar("_T") _ChannelTypeIsh = typing.Union[type[hikari.PartialChannel], int] _ChoiceT = typing.TypeVar("_ChoiceT", int, float, str) @@ -268,12 +280,12 @@ def set_config(self, config: _ArgConfig, /) -> None: class _ConvertedMeta(abc.ABCMeta): def __getitem__( - cls, converters: typing.Union[parsing.ConverterSig[_T], tuple[parsing.ConverterSig[_T]]], / - ) -> type[_T]: + cls, converters: typing.Union[_ConverterSig[_ConverterValueT], tuple[_ConverterSig[_ConverterValueT]]], / + ) -> type[_ConverterValueT]: if not isinstance(converters, tuple): converters = (converters,) - return typing.cast(type[_T], typing.Annotated[typing.Any, Converted(*converters)]) + return typing.cast("type[_ConverterValueT]", typing.Annotated[typing.Any, Converted(*converters)]) class Converted(_ConfigIdentifier, metaclass=_ConvertedMeta): @@ -297,9 +309,7 @@ async def command( __slots__ = ("_converters",) - def __init__( - self, converter: parsing.ConverterSig[typing.Any], /, *other_converters: parsing.ConverterSig[typing.Any] - ) -> None: + def __init__(self, converter: _ConverterSig[typing.Any], /, *other_converters: _ConverterSig[typing.Any]) -> None: """Create a converted instance. Parameters @@ -318,7 +328,7 @@ def __init__( self._converters = [converter, *other_converters] @property - def converters(self) -> collections.Sequence[parsing.ConverterSig[typing.Any]]: + def converters(self) -> collections.Sequence[_ConverterSig[typing.Any]]: """A sequence of the converters.""" return self._converters @@ -1116,7 +1126,7 @@ def __init__(self, parameter: inspect.Parameter, /, *, description: typing.Optio self.aliases: typing.Optional[collections.Sequence[str]] = None self.channel_types: typing.Optional[collections.Sequence[_ChannelTypeIsh]] = None self.choices: typing.Optional[collections.Mapping[str, _ChoiceUnion]] = None - self.converters: typing.Optional[collections.Sequence[parsing.ConverterSig[typing.Any]]] = None + self.converters: typing.Optional[collections.Sequence[_ConverterSig[typing.Any]]] = None self.default: typing.Any = parsing.UNDEFINED if parameter.default is parameter.empty else parameter.default self.description: typing.Optional[str] = description self.empty_value: typing.Union[parsing.UndefinedT, typing.Any] = parsing.UNDEFINED diff --git a/tanjun/clients.py b/tanjun/clients.py index a5261bc7b..af06702b7 100644 --- a/tanjun/clients.py +++ b/tanjun/clients.py @@ -489,6 +489,32 @@ async def __call__(self) -> None: ) +def _log_clients( + cache: typing.Optional[hikari.api.Cache], + events: typing.Optional[hikari.api.EventManager], + server: typing.Optional[hikari.api.InteractionServer], + rest: hikari.api.RESTClient, + shards: typing.Optional[hikari.ShardAware], + event_managed: bool, + /, +) -> None: + _LOGGER.info( + "%s initialised with the following components: %s", + "Event-managed client" if event_managed else "Client", + ", ".join( + name + for name, value in [ + ("cache", cache), + ("event manager", events), + ("interaction server", server), + ("rest", rest), + ("shard manager", shards), + ] + if value + ), + ) + + class Client(tanjun.Client): """Tanjun's standard [tanjun.abc.Client][] implementation. @@ -655,21 +681,7 @@ def __init__( * If `command_ids` is passed when `declare_global_commands` is `False`. """ if _LOGGER.isEnabledFor(logging.INFO): - _LOGGER.info( - "%s initialised with the following components: %s", - "Event-managed client" if event_managed else "Client", - ", ".join( - name - for name, value in [ - ("cache", cache), - ("event manager", events), - ("interaction server", server), - ("rest", rest), - ("shard manager", shards), - ] - if value - ), - ) + _log_clients(cache, events, server, rest, shards, event_managed) if not events and not server: _LOGGER.warning( diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index ce9334bd5..6e55e99f6 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -58,6 +58,7 @@ from collections import abc as collections import hikari +import typing_extensions from .. import _internal from .. import abc as tanjun @@ -73,7 +74,6 @@ from typing_extensions import Self _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=collections.Callable[..., typing.Any]) - _AutocompleteCallbackSigT = typing.TypeVar("_AutocompleteCallbackSigT", bound=tanjun.AutocompleteCallbackSig) _AnyBaseSlashCommandT = typing.TypeVar("_AnyBaseSlashCommandT", bound="tanjun.BaseSlashCommand") _SlashCommandT = typing.TypeVar("_SlashCommandT", bound="SlashCommand[typing.Any]") _AnyCommandT = typing.Union[ @@ -83,15 +83,27 @@ ] _CallbackishT = typing.Union["_SlashCallbackSigT", _AnyCommandT["_SlashCallbackSigT"]] + _IntAutocompleteSigT = typing.TypeVar("_IntAutocompleteSigT", bound=tanjun.AutocompleteSig[int]) + _FloatAutocompleteSigT = typing.TypeVar("_FloatAutocompleteSigT", bound=tanjun.AutocompleteSig[float]) + _StrAutocompleteSigT = typing.TypeVar("_StrAutocompleteSigT", bound=tanjun.AutocompleteSig[str]) + + _SlashCallbackSigT = typing.TypeVar("_SlashCallbackSigT", bound=tanjun.SlashCallbackSig) _EMPTY_DICT: typing.Final[dict[typing.Any, typing.Any]] = {} _EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() -ConverterSig = typing.Union[ - collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, typing.Any]], - collections.Callable[..., typing.Any], +_ConvertT = typing.TypeVar("_ConvertT", int, float, str) +_P = typing_extensions.ParamSpec("_P") +_ConverterSig = typing.Union[ + collections.Callable[ + typing_extensions.Concatenate[_ConvertT, _P], collections.Coroutine[typing.Any, typing.Any, typing.Any] + ], + collections.Callable[typing_extensions.Concatenate[_ConvertT, _P], typing.Any], ] + +ConverterSig = _ConverterSig[_ConvertT, ...] """Type hint of a slash command option converter.""" +_AnyConverterSig = typing.Union[ConverterSig[float], ConverterSig[int], ConverterSig[str]] _SCOMMAND_NAME_REG: typing.Final[str] = r"^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$" @@ -409,9 +421,9 @@ def with_str_slash_option( description: typing.Union[str, collections.Mapping[str, str]], /, *, - autocomplete: typing.Optional[tanjun.AutocompleteCallbackSig] = None, + autocomplete: typing.Optional[tanjun.AutocompleteSig[str]] = None, choices: typing.Union[collections.Mapping[str, str], collections.Sequence[str], None] = None, - converters: typing.Union[collections.Sequence[ConverterSig], ConverterSig] = (), + converters: typing.Union[collections.Sequence[ConverterSig[str]], ConverterSig[str]] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_length: typing.Optional[int] = None, @@ -457,9 +469,9 @@ def with_int_slash_option( description: typing.Union[str, collections.Mapping[str, str]], /, *, - autocomplete: typing.Optional[tanjun.AutocompleteCallbackSig] = None, + autocomplete: typing.Optional[tanjun.AutocompleteSig[int]] = None, choices: typing.Optional[collections.Mapping[str, int]] = None, - converters: typing.Union[collections.Collection[ConverterSig], ConverterSig] = (), + converters: typing.Union[collections.Collection[ConverterSig[int]], ConverterSig[int]] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_value: typing.Optional[int] = None, @@ -506,9 +518,9 @@ def with_float_slash_option( /, *, always_float: bool = True, - autocomplete: typing.Optional[tanjun.AutocompleteCallbackSig] = None, + autocomplete: typing.Optional[tanjun.AutocompleteSig[float]] = None, choices: typing.Optional[collections.Mapping[str, float]] = None, - converters: typing.Union[collections.Collection[ConverterSig], ConverterSig] = (), + converters: typing.Union[collections.Collection[ConverterSig[float]], ConverterSig[float]] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_value: typing.Optional[float] = None, @@ -763,7 +775,7 @@ def __init__( name: str, option_type: typing.Union[hikari.OptionType, int], always_float: bool = False, - converters: typing.Optional[list[ConverterSig]] = None, + converters: typing.Optional[list[_AnyConverterSig]] = None, only_member: bool = False, default: typing.Any = UNDEFINED_DEFAULT, ) -> None: @@ -795,9 +807,6 @@ async def convert(self, ctx: tanjun.SlashContext, value: typing.Any, /) -> typin raise errors.ConversionError(f"Couldn't convert {self.type} '{self.name}'", self.name, errors=exceptions) -_SlashCommandBuilderT = typing.TypeVar("_SlashCommandBuilderT", bound="_SlashCommandBuilder") - - class _SlashCommandBuilder(hikari.impl.SlashCommandBuilder): __slots__ = ("_has_been_sorted", "_options_dict", "_sort_options") @@ -1539,9 +1548,9 @@ def __init__( ) self._callback: _SlashCallbackSigT = callback self._client: typing.Optional[tanjun.Client] = None - self._float_autocompletes: dict[str, tanjun.AutocompleteCallbackSig] = {} - self._int_autocompletes: dict[str, tanjun.AutocompleteCallbackSig] = {} - self._str_autocompletes: dict[str, tanjun.AutocompleteCallbackSig] = {} + self._float_autocompletes: dict[str, tanjun.AutocompleteSig[float]] = {} + self._int_autocompletes: dict[str, tanjun.AutocompleteSig[int]] = {} + self._str_autocompletes: dict[str, tanjun.AutocompleteSig[str]] = {} self._tracked_options: dict[str, _TrackedOption] = {} self._wrapped_command = _wrapped_command @@ -1559,17 +1568,17 @@ def callback(self) -> _SlashCallbackSigT: return self._callback @property - def float_autocompletes(self) -> collections.Mapping[str, tanjun.AutocompleteCallbackSig]: + def float_autocompletes(self) -> collections.Mapping[str, tanjun.AutocompleteSig[float]]: # <>. return self._float_autocompletes.copy() @property - def int_autocompletes(self) -> collections.Mapping[str, tanjun.AutocompleteCallbackSig]: + def int_autocompletes(self) -> collections.Mapping[str, tanjun.AutocompleteSig[int]]: # <>. return self._int_autocompletes.copy() @property - def str_autocompletes(self) -> collections.Mapping[str, tanjun.AutocompleteCallbackSig]: + def str_autocompletes(self) -> collections.Mapping[str, tanjun.AutocompleteSig[str]]: # <>. return self._str_autocompletes.copy() @@ -1623,7 +1632,7 @@ def _add_option( choices: typing.Union[ collections.Mapping[str, typing.Union[str, int, float]], collections.Sequence[typing.Any], None ] = None, - converters: typing.Union[collections.Iterable[ConverterSig], ConverterSig] = (), + converters: typing.Union[collections.Iterable[_AnyConverterSig], _AnyConverterSig] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_length: typing.Optional[int] = None, @@ -1789,9 +1798,9 @@ def add_str_option( description: typing.Union[str, collections.Mapping[str, str]], /, *, - autocomplete: typing.Optional[tanjun.AutocompleteCallbackSig] = None, + autocomplete: typing.Optional[tanjun.AutocompleteSig[str]] = None, choices: typing.Union[collections.Mapping[str, str], collections.Sequence[str], None] = None, - converters: typing.Union[collections.Sequence[ConverterSig], ConverterSig] = (), + converters: typing.Union[collections.Sequence[ConverterSig[str]], ConverterSig[str]] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_length: typing.Optional[int] = None, @@ -1820,8 +1829,8 @@ def add_str_option( The autocomplete callback for the option. More information on this callback's signature can be found at - [tanjun.abc.AutocompleteCallbackSig][] and the 2nd positional - argument should be of type [str][]. + [tanjun.abc.AutocompleteSig][] and the 2nd positional argument + should be of type [str][]. choices The option's choices. @@ -1937,9 +1946,9 @@ def add_int_option( description: typing.Union[str, collections.Mapping[str, str]], /, *, - autocomplete: typing.Optional[tanjun.AutocompleteCallbackSig] = None, + autocomplete: typing.Optional[tanjun.AutocompleteSig[int]] = None, choices: typing.Optional[collections.Mapping[str, int]] = None, - converters: typing.Union[collections.Collection[ConverterSig], ConverterSig] = (), + converters: typing.Union[collections.Collection[ConverterSig[int]], ConverterSig[int]] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_value: typing.Optional[int] = None, @@ -1963,8 +1972,8 @@ def add_int_option( The autocomplete callback for the option. More information on this callback's signature can be found at - [tanjun.abc.AutocompleteCallbackSig][] and the 2nd positional - argument should be of type [int][]. + [tanjun.abc.AutocompleteSig][] and the 2nd positional argument + should be of type [int][]. choices The option's choices. @@ -2048,9 +2057,9 @@ def add_float_option( /, *, always_float: bool = True, - autocomplete: typing.Optional[tanjun.AutocompleteCallbackSig] = None, + autocomplete: typing.Optional[tanjun.AutocompleteSig[float]] = None, choices: typing.Optional[collections.Mapping[str, float]] = None, - converters: typing.Union[collections.Collection[ConverterSig], ConverterSig] = (), + converters: typing.Union[collections.Collection[ConverterSig[float]], ConverterSig[float]] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_value: typing.Optional[float] = None, @@ -2080,8 +2089,8 @@ def add_float_option( The autocomplete callback for the option. More information on this callback's signature can be found at - [tanjun.abc.AutocompleteCallbackSig][] and the 2nd positional - argument should be of type [float][]. + [tanjun.abc.AutocompleteSig][] and the 2nd positional argument + should be of type [float][]. choices The option's choices. @@ -2567,7 +2576,7 @@ def add_mentionable_option( pass_as_kwarg=pass_as_kwarg, ) - def set_float_autocomplete(self, name: str, callback: typing.Optional[tanjun.AutocompleteCallbackSig], /) -> Self: + def set_float_autocomplete(self, name: str, callback: typing.Optional[tanjun.AutocompleteSig[float]], /) -> Self: """Set the autocomplete callback for a float option. Parameters @@ -2581,8 +2590,8 @@ def set_float_autocomplete(self, name: str, callback: typing.Optional[tanjun.Aut The autocomplete callback for the option. More information on this callback's signature can be found at - [tanjun.abc.AutocompleteCallbackSig][] and the 2nd positional - argument should be of type [float][]. + [tanjun.abc.AutocompleteSig][] and the 2nd positional argument + should be of type [float][]. Passing [None][] here will remove the autocomplete callback for the option. @@ -2619,7 +2628,7 @@ def set_float_autocomplete(self, name: str, callback: typing.Optional[tanjun.Aut def with_float_autocomplete( self, name: str, / - ) -> collections.Callable[[_AutocompleteCallbackSigT], _AutocompleteCallbackSigT]: + ) -> collections.Callable[[_FloatAutocompleteSigT], _FloatAutocompleteSigT]: """Set the autocomplete callback for a float option through a decorator call. Parameters @@ -2632,12 +2641,12 @@ def with_float_autocomplete( Returns ------- - Collections.abc.Callable[[tanjun.abc.AutocompleteCallbackSig], tanjun.abc.AutocompleteCallbackSig] + Collections.abc.Callable[[tanjun.abc.AutocompleteSig[float]], tanjun.abc.AutocompleteSig[float]] Decorator callback used to capture the autocomplete callback. More information on the autocomplete signature can be found at - [tanjun.abc.AutocompleteCallbackSig][] and the 2nd positional - argument should be of type [float][]. + [tanjun.abc.AutocompleteSig][] and the 2nd positional argument + should be of type [float][]. Raises ------ @@ -2647,13 +2656,13 @@ def with_float_autocomplete( Raises a type error if the option isn't of type `float`. """ - def decorator(callback: _AutocompleteCallbackSigT, /) -> _AutocompleteCallbackSigT: + def decorator(callback: _FloatAutocompleteSigT, /) -> _FloatAutocompleteSigT: self.set_float_autocomplete(name, callback) return callback return decorator - def set_int_autocomplete(self, name: str, callback: tanjun.AutocompleteCallbackSig, /) -> Self: + def set_int_autocomplete(self, name: str, callback: tanjun.AutocompleteSig[int], /) -> Self: """Set the autocomplete callback for a string option. Parameters @@ -2667,8 +2676,8 @@ def set_int_autocomplete(self, name: str, callback: tanjun.AutocompleteCallbackS The autocomplete callback for the option. More information on this callback's signature can be found at - [tanjun.abc.AutocompleteCallbackSig][] and the 2nd positional - argument should be of type [str][]. + [tanjun.abc.AutocompleteSig][] and the 2nd positional argument + should be of type [str][]. Passing [None][] here will remove the autocomplete callback for the option. @@ -2697,9 +2706,7 @@ def set_int_autocomplete(self, name: str, callback: tanjun.AutocompleteCallbackS self._int_autocompletes[name] = callback return self - def with_int_autocomplete( - self, name: str, / - ) -> collections.Callable[[_AutocompleteCallbackSigT], _AutocompleteCallbackSigT]: + def with_int_autocomplete(self, name: str, /) -> collections.Callable[[_IntAutocompleteSigT], _IntAutocompleteSigT]: """Set the autocomplete callback for a integer option through a decorator call. Parameters @@ -2712,12 +2719,12 @@ def with_int_autocomplete( Returns ------- - Collections.abc.Callable[[tanjun.abc.AutocompleteCallbackSig], tanjun.abc.AutocompleteCallbackSig] + Collections.abc.Callable[[tanjun.abc.AutocompleteSig[int]], tanjun.abc.AutocompleteSig[int]] Decorator callback used to capture the autocomplete callback. More information on the autocomplete signature can be found at - [tanjun.abc.AutocompleteCallbackSig][] and the 2nd positional - argument should be of type [int][]. + [tanjun.abc.AutocompleteSig][] and the 2nd positional argument + should be of type [int][]. Raises ------ @@ -2727,13 +2734,13 @@ def with_int_autocomplete( Raises a type error if the option isn't of type `int`. """ - def decorator(callback: _AutocompleteCallbackSigT, /) -> _AutocompleteCallbackSigT: + def decorator(callback: _IntAutocompleteSigT, /) -> _IntAutocompleteSigT: self.set_int_autocomplete(name, callback) return callback return decorator - def set_str_autocomplete(self, name: str, callback: tanjun.AutocompleteCallbackSig, /) -> Self: + def set_str_autocomplete(self, name: str, callback: tanjun.AutocompleteSig[str], /) -> Self: """Set the autocomplete callback for a str option. Parameters @@ -2747,8 +2754,8 @@ def set_str_autocomplete(self, name: str, callback: tanjun.AutocompleteCallbackS The autocomplete callback for the option. More information on this callback's signature can be found at - [tanjun.abc.AutocompleteCallbackSig][] and the 2nd positional - argument should be of type [str][]. + [tanjun.abc.AutocompleteSig][] and the 2nd positional argument + should be of type [str][]. Passing [None][] here will remove the autocomplete callback for the option. @@ -2777,9 +2784,7 @@ def set_str_autocomplete(self, name: str, callback: tanjun.AutocompleteCallbackS self._str_autocompletes[name] = callback return self - def with_str_autocomplete( - self, name: str, / - ) -> collections.Callable[[_AutocompleteCallbackSigT], _AutocompleteCallbackSigT]: + def with_str_autocomplete(self, name: str, /) -> collections.Callable[[_StrAutocompleteSigT], _StrAutocompleteSigT]: """Set the autocomplete callback for a string option through a decorator call. Parameters @@ -2792,12 +2797,12 @@ def with_str_autocomplete( Returns ------- - Collections.abc.Callable[[tanjun.abc.AutocompleteCallbackSig], tanjun.abc.AutocompleteCallbackSig] + Collections.abc.Callable[[tanjun.abc.AutocompleteSig[str]], tanjun.abc.AutocompleteSig[str]] Decorator callback used to capture the autocomplete callback. More information on the autocomplete signature can be found at - [tanjun.abc.AutocompleteCallbackSig][] and the 2nd positional - argument should be of type [str][]. + [tanjun.abc.AutocompleteSig][] and the 2nd positional argument + should be of type [str][]. Raises ------ @@ -2807,7 +2812,7 @@ def with_str_autocomplete( Raises a type error if the option isn't of type `str`. """ - def decorator(callback: _AutocompleteCallbackSigT, /) -> _AutocompleteCallbackSigT: + def decorator(callback: _StrAutocompleteSigT, /) -> _StrAutocompleteSigT: self.set_str_autocomplete(name, callback) return callback diff --git a/tanjun/parsing.py b/tanjun/parsing.py index 5ef67bfe1..795a9c66f 100644 --- a/tanjun/parsing.py +++ b/tanjun/parsing.py @@ -56,6 +56,8 @@ import typing from collections import abc as collections +import typing_extensions + from . import abc as tanjun from . import conversion from . import errors @@ -82,10 +84,13 @@ def __len__(self) -> int: _T = typing.TypeVar("_T") - -ConverterSig = typing.Union[ - collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, _T]], collections.Callable[..., _T] +_P = typing_extensions.ParamSpec("_P") +_ConverterSig = typing.Union[ + collections.Callable[typing_extensions.Concatenate[str, _P], collections.Coroutine[typing.Any, typing.Any, _T]], + collections.Callable[typing_extensions.Concatenate[str, _P], _T], ] + +ConverterSig = _ConverterSig[..., _T] # TODO: is this correct? """Type hint of a converter used within a parser instance. This must be a callable or asynchronous callable which takes one position From a3c1b8b3ca0edaa00599e3e882debd0f8a8218cd Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Tue, 24 Jan 2023 01:44:23 +0000 Subject: [PATCH 11/45] Post-rebase fixes --- pyproject.toml | 2 +- tanjun/_internal/__init__.py | 9 +++---- tanjun/abc.py | 4 +-- tanjun/annotations.py | 15 ++++++----- tanjun/checks.py | 12 ++++----- tanjun/clients.py | 16 ++++++----- tanjun/commands/menu.py | 18 ++++++------- tanjun/commands/message.py | 17 ++++++------ tanjun/commands/slash.py | 52 ++++++++++++++++++------------------ tanjun/hooks.py | 10 +++---- tanjun/parsing.py | 8 +++--- 11 files changed, 81 insertions(+), 82 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7b02c7c16..b7707ba94 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -148,7 +148,7 @@ default_sessions = [ extra_test_installs = ["."] path_ignore = "tanjun\\/_internal\\/vendor\\/" project_name = "tanjun" -top_level_targets = ["./examples", "./noxfile.py", "./tanjun", "./tests"] +top_level_targets = ["./examples", "./noxfile.py", "./tanjun"] # , "./tests"] [tool.piped.github_actions.freeze_for_pr] [tool.piped.github_actions.lint] diff --git a/tanjun/_internal/__init__.py b/tanjun/_internal/__init__.py index 207d043df..e1a08b714 100644 --- a/tanjun/_internal/__init__.py +++ b/tanjun/_internal/__init__.py @@ -55,19 +55,16 @@ from .. import abc as tanjun + _T = typing.TypeVar("_T") _P = typing_extensions.ParamSpec("_P") _ContextT = typing.TypeVar("_ContextT", bound=tanjun.Context) - _TreeT = dict[ - typing.Union[str, "_IndexKeys"], - typing.Union["_TreeT", list[tuple[list[str], tanjun.MessageCommand[typing.Any]]]], - ] + _CoroT = collections.Coroutine[typing.Any, typing.Any, _T] + _TreeT = dict["str | _IndexKeys", "_TreeT | list[tuple[list[str], tanjun.MessageCommand[typing.Any]]]",] -_T = typing.TypeVar("_T") _KeyT = typing.TypeVar("_KeyT") _OtherT = typing.TypeVar("_OtherT") -_CoroT = collections.Coroutine[typing.Any, typing.Any, _T] _LOGGER = logging.getLogger("hikari.tanjun") diff --git a/tanjun/abc.py b/tanjun/abc.py index fc540c2ed..fc01d3aa5 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -110,7 +110,7 @@ "_MenuTypeT", typing.Literal[hikari.CommandType.USER], typing.Literal[hikari.CommandType.MESSAGE] ) -_MaybeAwaitable = typing.Union[collections.Callable[_P, _CoroT[_T]], collections.Callable[_P, _T]] +_MaybeAwaitable = collections.Callable[_P, _CoroT[_T]] | collections.Callable[_P, _T] _AutocompleteValueT = typing.TypeVar("_AutocompleteValueT", int, str, float) @@ -188,7 +188,7 @@ """ _SlashCallbackSigT = typing.TypeVar("_SlashCallbackSigT", bound=SlashCallbackSig) -_ErrorHookSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, Exception, _P], typing.Optional[bool]] +_ErrorHookSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, Exception, _P], bool | None] ErrorHookSig = _ErrorHookSig[_ContextT_contra, ...] """Type hint of the callback used as a unexpected command error hook. diff --git a/tanjun/annotations.py b/tanjun/annotations.py index 05b960a2e..a2ebe5517 100644 --- a/tanjun/annotations.py +++ b/tanjun/annotations.py @@ -94,14 +94,15 @@ from typing_extensions import Self _P = typing_extensions.ParamSpec("_P") - _ConverterValueT = typing.TypeVar("_ConverterValueT", bound=typing.Union[int, str, float]) - __ConverterSig = typing.Union[ + # TODO: test this + _ConverterValueT = typing.TypeVar("_ConverterValueT", bound=int | str | float) + __ConverterSig = ( collections.Callable[ typing_extensions.Concatenate[_ConverterValueT, _P], collections.Coroutine[typing.Any, typing.Any, typing.Any], - ], - collections.Callable[typing_extensions.Concatenate[_ConverterValueT, _P], typing.Any], - ] + ] + | collections.Callable[typing_extensions.Concatenate[_ConverterValueT, _P], typing.Any] + ) _ConverterSig = __ConverterSig[_ConverterValueT, ...] _T = typing.TypeVar("_T") @@ -280,7 +281,7 @@ def set_config(self, config: _ArgConfig, /) -> None: class _ConvertedMeta(abc.ABCMeta): def __getitem__( - cls, converters: typing.Union[_ConverterSig[_ConverterValueT], tuple[_ConverterSig[_ConverterValueT]]], / + cls, converters: _ConverterSig[_ConverterValueT] | tuple[_ConverterSig[_ConverterValueT]], / ) -> type[_ConverterValueT]: if not isinstance(converters, tuple): converters = (converters,) @@ -1126,7 +1127,7 @@ def __init__(self, parameter: inspect.Parameter, /, *, description: typing.Optio self.aliases: typing.Optional[collections.Sequence[str]] = None self.channel_types: typing.Optional[collections.Sequence[_ChannelTypeIsh]] = None self.choices: typing.Optional[collections.Mapping[str, _ChoiceUnion]] = None - self.converters: typing.Optional[collections.Sequence[_ConverterSig[typing.Any]]] = None + self.converters: collections.Sequence[_ConverterSig[typing.Any]] | None = None self.default: typing.Any = parsing.UNDEFINED if parameter.default is parameter.empty else parameter.default self.description: typing.Optional[str] = description self.empty_value: typing.Union[parsing.UndefinedT, typing.Any] = parsing.UNDEFINED diff --git a/tanjun/checks.py b/tanjun/checks.py index fa5434bfc..c029a75ed 100644 --- a/tanjun/checks.py +++ b/tanjun/checks.py @@ -73,14 +73,12 @@ class _AnyCallback(typing.Protocol[_ContextT_contra]): async def __call__( - self, ctx: _ContextT_contra, /, *, localiser: typing.Optional[dependencies.AbstractLocaliser] = None + self, ctx: _ContextT_contra, /, *, localiser: dependencies.AbstractLocaliser | None = None ) -> bool: raise NotImplementedError -_CommandT = typing.TypeVar("_CommandT", bound="tanjun.ExecutableCommand[typing.Any]") -# This errors on earlier 3.9 releases when not quotes cause dumb handling of the [_CommandT] list -_CallbackReturnT = typing.Union[_CommandT, "collections.Callable[[_CommandT], _CommandT]"] + _ContextT = typing.TypeVar("_ContextT", bound=tanjun.Context) @@ -93,8 +91,8 @@ def _add_to_command(command: _CommandT, check: tanjun.AnyCheckSig, follow_wrappe def _optional_kwargs( - command: typing.Optional[_CommandT], check: tanjun.AnyCheckSig, follow_wrapped: bool -) -> typing.Union[_CommandT, collections.Callable[[_CommandT], _CommandT]]: + command: _CommandT | None, check: tanjun.AnyCheckSig, follow_wrapped: bool +) -> _CommandT | collections.Callable[[_CommandT], _CommandT]: if command: return _add_to_command(command, check, follow_wrapped) @@ -1081,7 +1079,7 @@ def __init__( self._suppress = suppress async def __call__( - self, ctx: _ContextT, /, *, localiser: alluka.Injected[typing.Optional[dependencies.AbstractLocaliser]] = None + self, ctx: _ContextT, /, *, localiser: alluka.Injected[dependencies.AbstractLocaliser | None] = None ) -> bool: for check in self._checks: try: diff --git a/tanjun/clients.py b/tanjun/clients.py index af06702b7..3c4c8858d 100644 --- a/tanjun/clients.py +++ b/tanjun/clients.py @@ -76,9 +76,11 @@ from typing_extensions import Self _CheckSigT = typing.TypeVar("_CheckSigT", bound=tanjun.AnyCheckSig) - _AppCmdResponse = typing.Union[ - hikari.api.InteractionMessageBuilder, hikari.api.InteractionDeferredBuilder, hikari.api.InteractionModalBuilder - ] + _AppCmdResponse = ( + hikari.api.InteractionMessageBuilder + | hikari.api.InteractionDeferredBuilder + | hikari.api.InteractionModalBuilder + ) _EventT = typing.TypeVar("_EventT", bound=hikari.Event) _ListenerCallbackSigT = typing.TypeVar("_ListenerCallbackSigT", bound=tanjun.ListenerCallbackSig[typing.Any]) _MetaEventSigT = typing.TypeVar("_MetaEventSigT", bound=tanjun.MetaEventSig) @@ -490,11 +492,11 @@ async def __call__(self) -> None: def _log_clients( - cache: typing.Optional[hikari.api.Cache], - events: typing.Optional[hikari.api.EventManager], - server: typing.Optional[hikari.api.InteractionServer], + cache: hikari.api.Cache | None, + events: hikari.api.EventManager | None, + server: hikari.api.InteractionServer | None, rest: hikari.api.RESTClient, - shards: typing.Optional[hikari.ShardAware], + shards: hikari.ShardAware | None, event_managed: bool, /, ) -> None: diff --git a/tanjun/commands/menu.py b/tanjun/commands/menu.py index cc7c53823..08ec4eb64 100644 --- a/tanjun/commands/menu.py +++ b/tanjun/commands/menu.py @@ -51,15 +51,15 @@ _AnyCallbackSigT = typing.TypeVar( "_AnyCallbackSigT", bound=collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, None]] ) - _MessageCallbackSigT = typing.TypeVar("_MessageCallbackSigT", bound="tanjun.MenuCallbackSig[hikari.Message]") - _UserCallbackSigT = typing.TypeVar("_UserCallbackSigT", bound="tanjun.MenuCallbackSig[hikari.InteractionMember]") - - _AnyCommandT = typing.Union[ - tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], - tanjun.MessageCommand["_AnyCallbackSigT"], - tanjun.SlashCommand["_AnyCallbackSigT"], - ] - _CallbackishT = typing.Union["_AnyCallbackSigT", _AnyCommandT["_AnyCallbackSigT"]] + _MessageCallbackSigT = typing.TypeVar("_MessageCallbackSigT", bound=tanjun.MenuCallbackSig[hikari.Message]) + _UserCallbackSigT = typing.TypeVar("_UserCallbackSigT", bound=tanjun.MenuCallbackSig[hikari.InteractionMember]) + + _AnyCommandT = ( + tanjun.MenuCommand[_AnyCallbackSigT, typing.Any] + | tanjun.MessageCommand[_AnyCallbackSigT] + | tanjun.SlashCommand[_AnyCallbackSigT] + ) + _CallbackishT = _AnyCallbackSigT | _AnyCommandT[_AnyCallbackSigT] import hikari diff --git a/tanjun/commands/message.py b/tanjun/commands/message.py index b281287a1..016fc163a 100644 --- a/tanjun/commands/message.py +++ b/tanjun/commands/message.py @@ -49,15 +49,16 @@ _AnyMessageCommandT = typing.TypeVar("_AnyMessageCommandT", bound=tanjun.MessageCommand[typing.Any]) _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=collections.Callable[..., typing.Any]) - _AnyCommandT = typing.Union[ - tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], - tanjun.MessageCommand[_AnyCallbackSigT], - tanjun.SlashCommand["_AnyCallbackSigT"], - ] - _CallbackishT = typing.Union[_AnyCommandT["_MessageCallbackSigT"], "_MessageCallbackSigT"] + _AnyCommandT = ( + tanjun.MenuCommand[_AnyCallbackSigT, typing.Any] + | tanjun.MessageCommand[_AnyCallbackSigT] + | tanjun.SlashCommand[_AnyCallbackSigT] + ) + _CallbackishT: typing.TypeAlias = "_AnyCommandT[_MessageCallbackSigT] | _MessageCallbackSigT" + _OtherCallbackSigT = typing.TypeVar("_OtherCallbackSigT", bound=tanjun.MessageCallbackSig) + _MessageCallbackSigT = typing.TypeVar("_MessageCallbackSigT", bound=tanjun.MessageCallbackSig) -_OtherCallbackSigT = typing.TypeVar("_OtherCallbackSigT", bound=tanjun.MessageCallbackSig) _EMPTY_DICT: typing.Final[dict[typing.Any, typing.Any]] = {} _EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() @@ -444,7 +445,7 @@ def as_sub_command(self, name: str, /, *names: str, validate_arg_keys: bool = Tr """ def decorator( - callback: typing.Union[_OtherCallbackSigT, _AnyCommandT[_OtherCallbackSigT]], / + callback: _OtherCallbackSigT | _AnyCommandT[_OtherCallbackSigT], / ) -> MessageCommand[_OtherCallbackSigT]: return self.with_command(as_message_command(name, *names, validate_arg_keys=validate_arg_keys)(callback)) diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index 6e55e99f6..e9ee7f870 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -76,12 +76,13 @@ _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=collections.Callable[..., typing.Any]) _AnyBaseSlashCommandT = typing.TypeVar("_AnyBaseSlashCommandT", bound="tanjun.BaseSlashCommand") _SlashCommandT = typing.TypeVar("_SlashCommandT", bound="SlashCommand[typing.Any]") - _AnyCommandT = typing.Union[ - tanjun.MenuCommand["_AnyCallbackSigT", typing.Any], - tanjun.MessageCommand["_AnyCallbackSigT"], - tanjun.SlashCommand["_AnyCallbackSigT"], - ] - _CallbackishT = typing.Union["_SlashCallbackSigT", _AnyCommandT["_SlashCallbackSigT"]] + _AnyCommandT = ( + tanjun.MenuCommand[_AnyCallbackSigT, typing.Any] + | tanjun.MessageCommand[_AnyCallbackSigT] + | tanjun.SlashCommand[_AnyCallbackSigT] + ) + _AnyConverterSig: typing.TypeAlias = "ConverterSig[float] | ConverterSig[int] | ConverterSig[str]" + _CallbackishT: typing.TypeAlias = "_SlashCallbackSigT | _AnyCommandT[_SlashCallbackSigT]" _IntAutocompleteSigT = typing.TypeVar("_IntAutocompleteSigT", bound=tanjun.AutocompleteSig[int]) _FloatAutocompleteSigT = typing.TypeVar("_FloatAutocompleteSigT", bound=tanjun.AutocompleteSig[float]) @@ -94,16 +95,15 @@ _ConvertT = typing.TypeVar("_ConvertT", int, float, str) _P = typing_extensions.ParamSpec("_P") -_ConverterSig = typing.Union[ +_ConverterSig = ( collections.Callable[ typing_extensions.Concatenate[_ConvertT, _P], collections.Coroutine[typing.Any, typing.Any, typing.Any] - ], - collections.Callable[typing_extensions.Concatenate[_ConvertT, _P], typing.Any], -] + ] + | collections.Callable[typing_extensions.Concatenate[_ConvertT, _P], typing.Any] +) ConverterSig = _ConverterSig[_ConvertT, ...] """Type hint of a slash command option converter.""" -_AnyConverterSig = typing.Union[ConverterSig[float], ConverterSig[int], ConverterSig[str]] _SCOMMAND_NAME_REG: typing.Final[str] = r"^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$" @@ -421,9 +421,9 @@ def with_str_slash_option( description: typing.Union[str, collections.Mapping[str, str]], /, *, - autocomplete: typing.Optional[tanjun.AutocompleteSig[str]] = None, + autocomplete: tanjun.AutocompleteSig[str] | None = None, choices: typing.Union[collections.Mapping[str, str], collections.Sequence[str], None] = None, - converters: typing.Union[collections.Sequence[ConverterSig[str]], ConverterSig[str]] = (), + converters: collections.Sequence[ConverterSig[str]] | ConverterSig[str] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_length: typing.Optional[int] = None, @@ -469,9 +469,9 @@ def with_int_slash_option( description: typing.Union[str, collections.Mapping[str, str]], /, *, - autocomplete: typing.Optional[tanjun.AutocompleteSig[int]] = None, + autocomplete: tanjun.AutocompleteSig[int] | None = None, choices: typing.Optional[collections.Mapping[str, int]] = None, - converters: typing.Union[collections.Collection[ConverterSig[int]], ConverterSig[int]] = (), + converters: collections.Collection[ConverterSig[int]] | ConverterSig[int] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_value: typing.Optional[int] = None, @@ -518,9 +518,9 @@ def with_float_slash_option( /, *, always_float: bool = True, - autocomplete: typing.Optional[tanjun.AutocompleteSig[float]] = None, + autocomplete: tanjun.AutocompleteSig[float] | None = None, choices: typing.Optional[collections.Mapping[str, float]] = None, - converters: typing.Union[collections.Collection[ConverterSig[float]], ConverterSig[float]] = (), + converters: collections.Collection[ConverterSig[float]] | ConverterSig[float] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_value: typing.Optional[float] = None, @@ -775,7 +775,7 @@ def __init__( name: str, option_type: typing.Union[hikari.OptionType, int], always_float: bool = False, - converters: typing.Optional[list[_AnyConverterSig]] = None, + converters: list[_AnyConverterSig] | None = None, only_member: bool = False, default: typing.Any = UNDEFINED_DEFAULT, ) -> None: @@ -1632,7 +1632,7 @@ def _add_option( choices: typing.Union[ collections.Mapping[str, typing.Union[str, int, float]], collections.Sequence[typing.Any], None ] = None, - converters: typing.Union[collections.Iterable[_AnyConverterSig], _AnyConverterSig] = (), + converters: collections.Iterable[_AnyConverterSig] | _AnyConverterSig = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_length: typing.Optional[int] = None, @@ -1798,9 +1798,9 @@ def add_str_option( description: typing.Union[str, collections.Mapping[str, str]], /, *, - autocomplete: typing.Optional[tanjun.AutocompleteSig[str]] = None, + autocomplete: tanjun.AutocompleteSig[str] | None = None, choices: typing.Union[collections.Mapping[str, str], collections.Sequence[str], None] = None, - converters: typing.Union[collections.Sequence[ConverterSig[str]], ConverterSig[str]] = (), + converters: collections.Sequence[ConverterSig[str]] | ConverterSig[str] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_length: typing.Optional[int] = None, @@ -1946,9 +1946,9 @@ def add_int_option( description: typing.Union[str, collections.Mapping[str, str]], /, *, - autocomplete: typing.Optional[tanjun.AutocompleteSig[int]] = None, + autocomplete: tanjun.AutocompleteSig[int] | None = None, choices: typing.Optional[collections.Mapping[str, int]] = None, - converters: typing.Union[collections.Collection[ConverterSig[int]], ConverterSig[int]] = (), + converters: collections.Collection[ConverterSig[int]] | ConverterSig[int] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_value: typing.Optional[int] = None, @@ -2057,9 +2057,9 @@ def add_float_option( /, *, always_float: bool = True, - autocomplete: typing.Optional[tanjun.AutocompleteSig[float]] = None, + autocomplete: tanjun.AutocompleteSig[float] | None = None, choices: typing.Optional[collections.Mapping[str, float]] = None, - converters: typing.Union[collections.Collection[ConverterSig[float]], ConverterSig[float]] = (), + converters: collections.Collection[ConverterSig[float]] | ConverterSig[float] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_value: typing.Optional[float] = None, @@ -2576,7 +2576,7 @@ def add_mentionable_option( pass_as_kwarg=pass_as_kwarg, ) - def set_float_autocomplete(self, name: str, callback: typing.Optional[tanjun.AutocompleteSig[float]], /) -> Self: + def set_float_autocomplete(self, name: str, callback: tanjun.AutocompleteSig[float] | None, /) -> Self: """Set the autocomplete callback for a float option. Parameters diff --git a/tanjun/hooks.py b/tanjun/hooks.py index ce5847ffb..d2f738b94 100644 --- a/tanjun/hooks.py +++ b/tanjun/hooks.py @@ -147,7 +147,7 @@ def add_on_error(self, callback: tanjun.ErrorHookSig[_ContextT_contra], /) -> Se self._error_callbacks.append(callback) return self - def set_on_error(self, callback: typing.Optional[tanjun.ErrorHookSig[_ContextT_contra]], /) -> Self: + def set_on_error(self, callback: tanjun.ErrorHookSig[_ContextT_contra] | None, /) -> Self: """Set the error callback for this hook object. !!! note @@ -204,7 +204,7 @@ def add_on_parser_error(self, callback: tanjun.HookSig[_ContextT_contra], /) -> self._parser_error_callbacks.append(callback) return self - def set_on_parser_error(self, callback: typing.Optional[tanjun.HookSig[_ContextT_contra]], /) -> Self: + def set_on_parser_error(self, callback: tanjun.HookSig[_ContextT_contra] | None, /) -> Self: """Set the parser error callback for this hook object. Parameters @@ -254,7 +254,7 @@ def add_post_execution(self, callback: tanjun.HookSig[_ContextT_contra], /) -> S self._post_execution_callbacks.append(callback) return self - def set_post_execution(self, callback: typing.Optional[tanjun.HookSig[_ContextT_contra]], /) -> Self: + def set_post_execution(self, callback: tanjun.HookSig[_ContextT_contra] | None, /) -> Self: """Set the post-execution callback for this hook object. Parameters @@ -301,7 +301,7 @@ def add_pre_execution(self, callback: tanjun.HookSig[_ContextT_contra], /) -> Se self._pre_execution_callbacks.append(callback) return self - def set_pre_execution(self, callback: typing.Optional[tanjun.HookSig[_ContextT_contra]], /) -> Self: + def set_pre_execution(self, callback: tanjun.HookSig[_ContextT_contra] | None, /) -> Self: """Set the pre-execution callback for this hook object. Parameters @@ -348,7 +348,7 @@ def add_on_success(self, callback: tanjun.HookSig[_ContextT_contra], /) -> Self: self._success_callbacks.append(callback) return self - def set_on_success(self, callback: typing.Optional[tanjun.HookSig[_ContextT_contra]], /) -> Self: + def set_on_success(self, callback: tanjun.HookSig[_ContextT_contra] | None, /) -> Self: """Set the success callback for this hook object. Parameters diff --git a/tanjun/parsing.py b/tanjun/parsing.py index 795a9c66f..f17a8ea77 100644 --- a/tanjun/parsing.py +++ b/tanjun/parsing.py @@ -85,10 +85,10 @@ def __len__(self) -> int: _T = typing.TypeVar("_T") _P = typing_extensions.ParamSpec("_P") -_ConverterSig = typing.Union[ - collections.Callable[typing_extensions.Concatenate[str, _P], collections.Coroutine[typing.Any, typing.Any, _T]], - collections.Callable[typing_extensions.Concatenate[str, _P], _T], -] +_ConverterSig = ( + collections.Callable[typing_extensions.Concatenate[str, _P], collections.Coroutine[typing.Any, typing.Any, _T]] + | collections.Callable[typing_extensions.Concatenate[str, _P], _T] +) ConverterSig = _ConverterSig[..., _T] # TODO: is this correct? """Type hint of a converter used within a parser instance. From dd1824be0da9438a2ef5c97f74e89396bc7f8310 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Tue, 24 Jan 2023 01:50:52 +0000 Subject: [PATCH 12/45] Fix typings in tests --- pyproject.toml | 2 +- tests/commands/test_base.py | 5 +++-- tests/test_annotations.py | 6 +++--- tests/test_annotations_future_annotations.py | 6 +++--- tests/test_clients.py | 4 ++-- tests/test_components.py | 4 ++-- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b7707ba94..7b02c7c16 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -148,7 +148,7 @@ default_sessions = [ extra_test_installs = ["."] path_ignore = "tanjun\\/_internal\\/vendor\\/" project_name = "tanjun" -top_level_targets = ["./examples", "./noxfile.py", "./tanjun"] # , "./tests"] +top_level_targets = ["./examples", "./noxfile.py", "./tanjun", "./tests"] [tool.piped.github_actions.freeze_for_pr] [tool.piped.github_actions.lint] diff --git a/tests/commands/test_base.py b/tests/commands/test_base.py index b2da14303..e4aac86ce 100644 --- a/tests/commands/test_base.py +++ b/tests/commands/test_base.py @@ -41,6 +41,7 @@ import pytest +import tanjun from tanjun.commands import base as base_command _T = typing.TypeVar("_T") @@ -132,7 +133,7 @@ def test_add_check_with_multiple_checks(self, command: base_command.PartialComma assert command.checks == [mock_check_2, mock_check_3, mock_check_1] def test_remove_check(self, command: base_command.PartialCommand[typing.Any]): - def mock_check() -> bool: + def mock_check(ctx: tanjun.abc.Context) -> bool: raise NotImplementedError command.add_check(mock_check) @@ -151,7 +152,7 @@ def test_with_check(self, command: base_command.PartialCommand[typing.Any]): add_check.assert_called_once_with(mock_check) def test_with_check_when_already_present(self, command: base_command.PartialCommand[typing.Any]): - def mock_check() -> bool: + def mock_check(ctx: tanjun.abc.Context) -> bool: raise NotImplementedError command.add_check(mock_check).with_check(mock_check) diff --git a/tests/test_annotations.py b/tests/test_annotations.py index d15695b33..e59eeeb93 100644 --- a/tests/test_annotations.py +++ b/tests/test_annotations.py @@ -238,7 +238,7 @@ def test_with_nested_message_command_and_incompatible_parser_set(): @tanjun.as_message_command("command") @tanjun.as_slash_command("command", "description") - async def command(ctx: tanjun.abc.MessageContext, foo: typing.Annotated[annotations.Int, "desc"]): + async def command(ctx: tanjun.abc.Context, foo: typing.Annotated[annotations.Int, "desc"]): ... command.set_parser(mock_parser) @@ -1380,7 +1380,7 @@ def test_with_flag(): @tanjun.as_message_command("meow") @tanjun.as_slash_command("beep", "boop") async def callback( - ctx: tanjun.abc.MessageContext, + ctx: tanjun.abc.Context, meep: typing.Annotated[annotations.Str, annotations.Flag(), "bb"] = "", eep: typing.Annotated[ annotations.Int, annotations.Flag(aliases=("--hi", "--bye"), empty_value=empty_value), "b" @@ -1435,7 +1435,7 @@ def test_with_flag_and_deprecated_default(): @tanjun.as_message_command("meow") @tanjun.as_slash_command("beep", "boop") async def callback( - ctx: tanjun.abc.MessageContext, + ctx: tanjun.abc.Context, eep: typing.Annotated[annotations.Int, annotations.Flag(default=1231), "b"] = 545454, ) -> None: ... diff --git a/tests/test_annotations_future_annotations.py b/tests/test_annotations_future_annotations.py index d96c157ef..649527876 100644 --- a/tests/test_annotations_future_annotations.py +++ b/tests/test_annotations_future_annotations.py @@ -100,7 +100,7 @@ def test_with_nested_message_command_and_incompatible_parser_set(): @tanjun.as_message_command("command") @tanjun.as_slash_command("command", "description") - async def command(ctx: tanjun.abc.MessageContext, foo: typing.Annotated[annotations.Int, "desc"]): + async def command(ctx: tanjun.abc.Context, foo: typing.Annotated[annotations.Int, "desc"]): ... command.set_parser(mock_parser) @@ -1266,7 +1266,7 @@ def test_with_flag(): @tanjun.as_message_command("meow") @tanjun.as_slash_command("beep", "boop") async def callback( - ctx: tanjun.abc.MessageContext, + ctx: tanjun.abc.Context, meep: typing.Annotated[annotations.Str, annotations.Flag(), "bb"] = "", eep: typing.Annotated[ annotations.Int, annotations.Flag(aliases=("--hi", "--bye"), empty_value=empty_value), "b" @@ -1321,7 +1321,7 @@ def test_with_flag_and_deprecated_default(): @tanjun.as_message_command("meow") @tanjun.as_slash_command("beep", "boop") async def callback( - ctx: tanjun.abc.MessageContext, + ctx: tanjun.abc.Context, eep: typing.Annotated[annotations.Int, annotations.Flag(default=1231), "b"] = 545454, ) -> None: ... diff --git a/tests/test_clients.py b/tests/test_clients.py index 17875be01..e95755034 100644 --- a/tests/test_clients.py +++ b/tests/test_clients.py @@ -1260,7 +1260,7 @@ class StubClient(tanjun.Client): client = StubClient(mock.Mock()) with pytest.raises(ValueError, match="Missing positional event argument"): - client.with_listener()(callback) + client.with_listener()(callback) # type: ignore add_listener_.assert_not_called() @@ -1276,7 +1276,7 @@ class StubClient(tanjun.Client): client = StubClient(mock.Mock()) with pytest.raises(ValueError, match="Missing positional event argument"): - client.with_listener()(callback) + client.with_listener()(callback) # type: ignore add_listener_.assert_not_called() diff --git a/tests/test_components.py b/tests/test_components.py index b0d5c48cd..573e4fa70 100644 --- a/tests/test_components.py +++ b/tests/test_components.py @@ -1229,7 +1229,7 @@ async def callback(*, event: hikari.Event, **kwargs: str) -> None: )() with pytest.raises(ValueError, match="Missing positional event argument"): - component.with_listener()(callback) + component.with_listener()(callback) # type: ignore add_listener.assert_not_called() @@ -1243,7 +1243,7 @@ async def callback() -> None: )() with pytest.raises(ValueError, match="Missing positional event argument"): - component.with_listener()(callback) + component.with_listener()(callback) # type: ignore add_listener.assert_not_called() From b121e9b45af0ab3771beabba2e5ca3630b91da8a Mon Sep 17 00:00:00 2001 From: "always-on-duty[bot]" <120557446+always-on-duty[bot]@users.noreply.github.com> Date: Tue, 24 Jan 2023 01:58:09 +0000 Subject: [PATCH 13/45] Freeze PR dependency changes --- dev-requirements/constraints.txt | 4 ++-- dev-requirements/type-checking.txt | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dev-requirements/constraints.txt b/dev-requirements/constraints.txt index 878e6a76a..a1dcfe872 100644 --- a/dev-requirements/constraints.txt +++ b/dev-requirements/constraints.txt @@ -269,10 +269,10 @@ multidict==6.0.4 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf \ --hash=sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d \ --hash=sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba -typing-extensions==4.4.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ +typing-extensions==4.4.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ --hash=sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa \ --hash=sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e -yarl==1.8.2 ; python_full_version >= "3.9.0" and python_version < "3.12" \ +yarl==1.8.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ --hash=sha256:009a028127e0a1755c38b03244c0bea9d5565630db9c4cf9572496e947137a87 \ --hash=sha256:0414fd91ce0b763d4eadb4456795b307a71524dbacd015c657bb2a39db2eab89 \ --hash=sha256:0978f29222e649c351b173da2b9b4665ad1feb8d1daa9d971eb90df08702668a \ diff --git a/dev-requirements/type-checking.txt b/dev-requirements/type-checking.txt index ba445ab3c..148130a9f 100644 --- a/dev-requirements/type-checking.txt +++ b/dev-requirements/type-checking.txt @@ -270,7 +270,7 @@ iniconfig==2.0.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ jinja2==3.1.2 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 -markupsafe==2.1.2 ; python_full_version >= "3.9.0" and python_version < "3.12" \ +markupsafe==2.1.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ --hash=sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed \ --hash=sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc \ --hash=sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2 \ @@ -321,7 +321,7 @@ markupsafe==2.1.2 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2 \ --hash=sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6 \ --hash=sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58 -multidict==6.0.4 ; python_full_version >= "3.9.0" and python_version < "3.12" \ +multidict==6.0.4 ; python_full_version >= "3.10.0" and python_version < "3.12" \ --hash=sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9 \ --hash=sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8 \ --hash=sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03 \ @@ -482,7 +482,7 @@ pydantic==1.10.4 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:f2f7eb6273dd12472d7f218e1fef6f7c7c2f00ac2e1ecde4db8824c457300416 \ --hash=sha256:fdf88ab63c3ee282c76d652fc86518aacb737ff35796023fae56a65ced1a5978 \ --hash=sha256:fdf8d759ef326962b4678d89e275ffc55b7ce59d917d9f72233762061fd04a2d -pyright==1.1.290 ; python_full_version >= "3.9.0" and python_version < "3.12" \ +pyright==1.1.290 ; python_full_version >= "3.10.0" and python_version < "3.12" \ --hash=sha256:956d8efc70eb5a54da54c82feef842affd3a81719c8864769cd196e211961e3a \ --hash=sha256:c1a57ad812f740fc7fb6bb416cd7e3f46f4e88384c723192402a77e2e756b550 pytest-asyncio==0.20.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ @@ -506,10 +506,10 @@ pytest==7.2.1 ; python_full_version >= "3.9.0" and python_version < "3.12" \ python-dateutil==2.8.2 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 -setuptools==66.1.1 ; python_full_version >= "3.9.0" and python_version < "3.12" \ +setuptools==66.1.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ --hash=sha256:6f590d76b713d5de4e49fe4fbca24474469f53c83632d5d0fd056f7ff7e8112b \ --hash=sha256:ac4008d396bc9cd983ea483cb7139c0240a07bbc74ffb6232fceffedc6cf03a8 -six==1.16.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ +six==1.16.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 termcolor==2.2.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ From fd02905e42fc7d0eb3953fba9416e626019e1edb Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Tue, 24 Jan 2023 02:28:03 +0000 Subject: [PATCH 14/45] Fixes --- tanjun/_internal/__init__.py | 2 +- tanjun/abc.py | 4 ++-- tanjun/checks.py | 5 +++++ tanjun/commands/base.py | 2 +- tanjun/commands/menu.py | 2 +- tanjun/commands/message.py | 4 ++-- tanjun/commands/slash.py | 2 +- tanjun/dependencies/limiters.py | 4 ++-- tanjun/hooks.py | 20 -------------------- tanjun/schedules.py | 2 +- 10 files changed, 16 insertions(+), 31 deletions(-) diff --git a/tanjun/_internal/__init__.py b/tanjun/_internal/__init__.py index e1a08b714..700a72bbb 100644 --- a/tanjun/_internal/__init__.py +++ b/tanjun/_internal/__init__.py @@ -60,7 +60,7 @@ _ContextT = typing.TypeVar("_ContextT", bound=tanjun.Context) _CoroT = collections.Coroutine[typing.Any, typing.Any, _T] - _TreeT = dict["str | _IndexKeys", "_TreeT | list[tuple[list[str], tanjun.MessageCommand[typing.Any]]]",] + _TreeT = dict["str | _IndexKeys", "_TreeT | list[tuple[list[str], tanjun.MessageCommand[typing.Any]]]"] _KeyT = typing.TypeVar("_KeyT") diff --git a/tanjun/abc.py b/tanjun/abc.py index fc01d3aa5..e7bab886d 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -151,7 +151,7 @@ _CommandCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _P], _CoroT[None]] -_ManuCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _MenuValueT, _P], _CoroT[None],] +_ManuCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _MenuValueT, _P], _CoroT[None]] MenuCallbackSig = _ManuCallbackSig["MenuContext", _MenuValueT, ...] """Type hint of a context menu command callback. @@ -166,7 +166,7 @@ MenuCommandCallbackSig = MenuCallbackSig """Deprecated alias of [tanjun.abc.MenuCallbackSig][].""" -_MenuCallbackSigT = typing.TypeVar("_MenuCallbackSigT", bound="MenuCallbackSig[typing.Any]") +_MenuCallbackSigT = typing.TypeVar("_MenuCallbackSigT", bound=MenuCallbackSig[typing.Any]) MessageCallbackSig = _CommandCallbackSig["MessageContext", ...] """Type hint of a message command callback. diff --git a/tanjun/checks.py b/tanjun/checks.py index c029a75ed..12e736924 100644 --- a/tanjun/checks.py +++ b/tanjun/checks.py @@ -77,6 +77,11 @@ async def __call__( ) -> bool: raise NotImplementedError + _CommandT = typing.TypeVar("_CommandT", bound=tanjun.ExecutableCommand[typing.Any]) + _CallbackReturnT = _CommandT | collections.Callable[[_CommandT], _CommandT] + _MenuCommandT = typing.TypeVar("_MenuCommandT", bound=tanjun.MenuCommand[typing.Any, typing.Any]) + _MessageCommandT = typing.TypeVar("_MessageCommandT", bound=tanjun.MessageCommand[typing.Any]) + _SlashCommandT = typing.TypeVar("_SlashCommandT", bound=tanjun.BaseSlashCommand) _ContextT = typing.TypeVar("_ContextT", bound=tanjun.Context) diff --git a/tanjun/commands/base.py b/tanjun/commands/base.py index 588062dc0..306caaeb4 100644 --- a/tanjun/commands/base.py +++ b/tanjun/commands/base.py @@ -46,7 +46,7 @@ _CheckSigT = typing.TypeVar("_CheckSigT", bound=tanjun.AnyCheckSig) -_ContextT = typing.TypeVar("_ContextT", bound="tanjun.Context") +_ContextT = typing.TypeVar("_ContextT", bound=tanjun.Context) class PartialCommand(tanjun.ExecutableCommand[_ContextT], components.AbstractComponentLoader): diff --git a/tanjun/commands/menu.py b/tanjun/commands/menu.py index 08ec4eb64..800fbc401 100644 --- a/tanjun/commands/menu.py +++ b/tanjun/commands/menu.py @@ -63,7 +63,7 @@ import hikari -_AnyMenuCallbackSigT = typing.TypeVar("_AnyMenuCallbackSigT", bound="tanjun.MenuCallbackSig[typing.Any]") +_AnyMenuCallbackSigT = typing.TypeVar("_AnyMenuCallbackSigT", bound=tanjun.MenuCallbackSig[typing.Any]) _MenuTypeT = typing.TypeVar( "_MenuTypeT", typing.Literal[hikari.CommandType.USER], typing.Literal[hikari.CommandType.MESSAGE] ) diff --git a/tanjun/commands/message.py b/tanjun/commands/message.py index 016fc163a..cd2af4efd 100644 --- a/tanjun/commands/message.py +++ b/tanjun/commands/message.py @@ -96,7 +96,7 @@ def as_message_command(name: str, /, *names: str, validate_arg_keys: bool = True [tanjun.Component.load_from_scope][]. """ - def decorator(callback: _CallbackishT[_MessageCallbackSigT], /) -> MessageCommand[typing.Any]: + def decorator(callback: _CallbackishT[_MessageCallbackSigT], /) -> MessageCommand[_MessageCallbackSigT]: if isinstance(callback, (tanjun.MenuCommand, tanjun.MessageCommand, tanjun.SlashCommand)): wrapped_command = callback callback = callback.callback @@ -151,7 +151,7 @@ def as_message_command_group( [tanjun.Component.load_from_scope][]. """ - def decorator(callback: _CallbackishT[_MessageCallbackSigT], /) -> MessageCommandGroup[typing.Any]: + def decorator(callback: _CallbackishT[_MessageCallbackSigT], /) -> MessageCommandGroup[_MessageCallbackSigT]: if isinstance(callback, (tanjun.MenuCommand, tanjun.MessageCommand, tanjun.SlashCommand)): wrapped_command = callback callback = callback.callback diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index e9ee7f870..2b1df7ea8 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -74,7 +74,7 @@ from typing_extensions import Self _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=collections.Callable[..., typing.Any]) - _AnyBaseSlashCommandT = typing.TypeVar("_AnyBaseSlashCommandT", bound="tanjun.BaseSlashCommand") + _AnyBaseSlashCommandT = typing.TypeVar("_AnyBaseSlashCommandT", bound=tanjun.BaseSlashCommand) _SlashCommandT = typing.TypeVar("_SlashCommandT", bound="SlashCommand[typing.Any]") _AnyCommandT = ( tanjun.MenuCommand[_AnyCallbackSigT, typing.Any] diff --git a/tanjun/dependencies/limiters.py b/tanjun/dependencies/limiters.py index 7c034608e..26ecdfbf3 100644 --- a/tanjun/dependencies/limiters.py +++ b/tanjun/dependencies/limiters.py @@ -68,8 +68,8 @@ if typing.TYPE_CHECKING: from typing_extensions import Self - _CommandT = typing.TypeVar("_CommandT", bound="tanjun.ExecutableCommand[typing.Any]") - _OtherCommandT = typing.TypeVar("_OtherCommandT", bound="tanjun.ExecutableCommand[typing.Any]") + _CommandT = typing.TypeVar("_CommandT", bound=tanjun.ExecutableCommand[typing.Any]) + _OtherCommandT = typing.TypeVar("_OtherCommandT", bound=tanjun.ExecutableCommand[typing.Any]) _LOGGER: typing.Final[logging.Logger] = logging.getLogger("hikari.tanjun") diff --git a/tanjun/hooks.py b/tanjun/hooks.py index d2f738b94..72d64d119 100644 --- a/tanjun/hooks.py +++ b/tanjun/hooks.py @@ -190,10 +190,6 @@ def with_on_error(self: MessageHooks, callback: _MessageErrorHookSigT, /) -> _Me def with_on_error(self: SlashHooks, callback: _SlashErrorHookSigT, /) -> _SlashErrorHookSigT: ... - # @typing.overload - # def with_on_error(self: AnyHooks, callback: _ErrorHookSigT, /) -> _ErrorHookSigT: - # ... - def with_on_error(self, callback: _AnyErrorHookSigT, /) -> _AnyErrorHookSigT: # <>. self.add_on_error(callback) @@ -240,10 +236,6 @@ def with_on_parser_error(self: MessageHooks, callback: _MessageHookSigT, /) -> _ def with_on_parser_error(self: SlashHooks, callback: _SlashHookSigT, /) -> _SlashHookSigT: ... - # @typing.overload - # def with_on_parser_error(self: AnyHooks, callback: _HookSigT, /) -> _HookSigT: - # ... - def with_on_parser_error(self, callback: _AnyHookSigT, /) -> _AnyHookSigT: # <>. self.add_on_parser_error(callback) @@ -287,10 +279,6 @@ def with_post_execution(self: MessageHooks, callback: _MessageHookSigT, /) -> _M def with_post_execution(self: SlashHooks, callback: _SlashHookSigT, /) -> _SlashHookSigT: ... - # @typing.overload - # def with_post_execution(self: AnyHooks, callback: _HookSigT, /) -> _HookSigT: - # ... - def with_post_execution(self, callback: _AnyHookSigT, /) -> _AnyHookSigT: # <>. self.add_post_execution(callback) @@ -334,10 +322,6 @@ def with_pre_execution(self: MessageHooks, callback: _MessageHookSigT, /) -> _Me def with_pre_execution(self: SlashHooks, callback: _SlashHookSigT, /) -> _SlashHookSigT: ... - # @typing.overload - # def with_pre_execution(self: AnyHooks, callback: _HookSigT, /) -> _HookSigT: - # ... - def with_pre_execution(self, callback: _AnyHookSigT, /) -> _AnyHookSigT: # <>. self.add_pre_execution(callback) @@ -381,10 +365,6 @@ def with_on_success(self: MessageHooks, callback: _MessageHookSigT, /) -> _Messa def with_on_success(self: SlashHooks, callback: _SlashHookSigT, /) -> _SlashHookSigT: ... - # @typing.overload - # def with_on_success(self: AnyHooks, callback: _HookSigT, /) -> _HookSigT: - # ... - def with_on_success(self, callback: _AnyHookSigT, /) -> _AnyHookSigT: # <>. self.add_on_success(callback) diff --git a/tanjun/schedules.py b/tanjun/schedules.py index 5e8d2fff5..97e39d01c 100644 --- a/tanjun/schedules.py +++ b/tanjun/schedules.py @@ -56,7 +56,7 @@ _OtherCallbackT = typing.TypeVar("_OtherCallbackT", bound="_CallbackSig") _CallbackSig = collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, None]] -_CallbackSigT = typing.TypeVar("_CallbackSigT", bound="_CallbackSig") +_CallbackSigT = typing.TypeVar("_CallbackSigT", bound=_CallbackSig) class AbstractSchedule(abc.ABC): From 77019952740a3ce9d5ccb50cd3d7258e7685d8e9 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Tue, 24 Jan 2023 02:28:33 +0000 Subject: [PATCH 15/45] Remove seemingly unnecessary overloading --- tanjun/commands/menu.py | 36 ++++++------------------------------ tanjun/commands/message.py | 32 ++++++++------------------------ tanjun/commands/slash.py | 14 ++------------ 3 files changed, 16 insertions(+), 66 deletions(-) diff --git a/tanjun/commands/menu.py b/tanjun/commands/menu.py index 800fbc401..6328d949b 100644 --- a/tanjun/commands/menu.py +++ b/tanjun/commands/menu.py @@ -70,20 +70,6 @@ _EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() -class _MessageResultProto(typing.Protocol): - @typing.overload - def __call__( - self, _: _AnyCommandT[_MessageCallbackSigT], / - ) -> MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]]: - ... - - @typing.overload - def __call__( - self, _: _MessageCallbackSigT, / - ) -> MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]]: - ... - - def as_message_menu( name: typing.Union[str, collections.Mapping[str, str]], /, @@ -93,7 +79,9 @@ def as_message_menu( default_to_ephemeral: typing.Optional[bool] = None, dm_enabled: typing.Optional[bool] = None, is_global: bool = True, -) -> _MessageResultProto: +) -> collections.Callable[ + [_CallbackishT[_MessageCallbackSigT]], MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]] +]: """Build a message [tanjun.MenuCommand][] by decorating a function. !!! note @@ -187,20 +175,6 @@ def decorator( return decorator -class _UserResultProto(typing.Protocol): - @typing.overload - def __call__( - self, _: _AnyCommandT[_UserCallbackSigT], / - ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: - ... - - @typing.overload - def __call__( - self, _: _UserCallbackSigT, / - ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: - ... - - def as_user_menu( name: typing.Union[str, collections.Mapping[str, str]], /, @@ -210,7 +184,9 @@ def as_user_menu( default_to_ephemeral: typing.Optional[bool] = None, dm_enabled: typing.Optional[bool] = None, is_global: bool = True, -) -> _UserResultProto: +) -> collections.Callable[ + [_CallbackishT[_UserCallbackSigT]], MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]] +]: """Build a user [tanjun.MenuCommand][] by decorating a function. !!! note diff --git a/tanjun/commands/message.py b/tanjun/commands/message.py index cd2af4efd..3fcf76252 100644 --- a/tanjun/commands/message.py +++ b/tanjun/commands/message.py @@ -63,17 +63,9 @@ _EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() -class _ResultProto(typing.Protocol): - @typing.overload - def __call__(self, _: _AnyCommandT[_MessageCallbackSigT], /) -> MessageCommand[_MessageCallbackSigT]: - ... - - @typing.overload - def __call__(self, _: _MessageCallbackSigT, /) -> MessageCommand[_MessageCallbackSigT]: - ... - - -def as_message_command(name: str, /, *names: str, validate_arg_keys: bool = True) -> _ResultProto: +def as_message_command( + name: str, /, *names: str, validate_arg_keys: bool = True +) -> collections.Callable[[_CallbackishT[_MessageCallbackSigT]], MessageCommand[_MessageCallbackSigT]]: """Build a message command from a decorated callback. Parameters @@ -111,19 +103,9 @@ def decorator(callback: _CallbackishT[_MessageCallbackSigT], /) -> MessageComman return decorator -class _GroupResultProto(typing.Protocol): - @typing.overload - def __call__(self, _: _AnyCommandT[_MessageCallbackSigT], /) -> MessageCommandGroup[_MessageCallbackSigT]: - ... - - @typing.overload - def __call__(self, _: _MessageCallbackSigT, /) -> MessageCommandGroup[_MessageCallbackSigT]: - ... - - def as_message_command_group( name: str, /, *names: str, strict: bool = False, validate_arg_keys: bool = True -) -> _GroupResultProto: +) -> collections.Callable[[_CallbackishT[_MessageCallbackSigT]], MessageCommandGroup[_MessageCallbackSigT]]: """Build a message command group from a decorated callback. Parameters @@ -423,7 +405,9 @@ def add_command(self, command: tanjun.MessageCommand[typing.Any], /) -> Self: return self - def as_sub_command(self, name: str, /, *names: str, validate_arg_keys: bool = True) -> _ResultProto: + def as_sub_command( + self, name: str, /, *names: str, validate_arg_keys: bool = True + ) -> collections.Callable[[_CallbackishT[_OtherCallbackSigT]], MessageCommand[_OtherCallbackSigT]]: """Build a message command in this group from a decorated callback. Parameters @@ -453,7 +437,7 @@ def decorator( def as_sub_group( self, name: str, /, *names: str, strict: bool = False, validate_arg_keys: bool = True - ) -> _GroupResultProto: + ) -> collections.Callable[[_CallbackishT[_OtherCallbackSigT]], MessageCommandGroup[_OtherCallbackSigT]]: """Build a message command group in this group from a decorated callback. Parameters diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index 2b1df7ea8..5ff96380e 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -244,16 +244,6 @@ async def help_me_command(ctx: tanjun.abc.SlashContext) -> None: ) -class _ResultProto(typing.Protocol): - @typing.overload - def __call__(self, _: _AnyCommandT[_SlashCallbackSigT], /) -> SlashCommand[_SlashCallbackSigT]: - ... - - @typing.overload - def __call__(self, _: _SlashCallbackSigT, /) -> SlashCommand[_SlashCallbackSigT]: - ... - - def as_slash_command( name: typing.Union[str, collections.Mapping[str, str]], description: typing.Union[str, collections.Mapping[str, str]], @@ -266,7 +256,7 @@ def as_slash_command( is_global: bool = True, sort_options: bool = True, validate_arg_keys: bool = True, -) -> _ResultProto: +) -> collections.Callable[[_CallbackishT[_SlashCallbackSigT]], SlashCommand[_SlashCallbackSigT]]: r"""Build a [tanjun.SlashCommand][] by decorating a function. !!! note @@ -1221,7 +1211,7 @@ def as_sub_command( default_to_ephemeral: typing.Optional[bool] = None, sort_options: bool = True, validate_arg_keys: bool = True, - ) -> _ResultProto: + ) -> collections.Callable[[_CallbackishT[_SlashCallbackSigT]], SlashCommand[_SlashCallbackSigT]]: r"""Build a [tanjun.SlashCommand][] in this command group by decorating a function. !!! note From 56fd21054d583ebe67decffd10568fd87fac956a Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Tue, 24 Jan 2023 04:03:36 +0000 Subject: [PATCH 16/45] Bring back overloads for as_cmd and cmd.init Turns out these were necessary specifically for mypy --- tanjun/abc.py | 1 - tanjun/commands/menu.py | 82 +++++++++++++++++++++++++++++++++---- tanjun/commands/message.py | 84 ++++++++++++++++++++++++++++++++++++-- tanjun/commands/slash.py | 54 +++++++++++++++++++++++- 4 files changed, 207 insertions(+), 14 deletions(-) diff --git a/tanjun/abc.py b/tanjun/abc.py index e7bab886d..0ce5fa585 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -112,7 +112,6 @@ _MaybeAwaitable = collections.Callable[_P, _CoroT[_T]] | collections.Callable[_P, _T] - _AutocompleteValueT = typing.TypeVar("_AutocompleteValueT", int, str, float) _AutocompleteSig = collections.Callable[ typing_extensions.Concatenate["AutocompleteContext", _AutocompleteValueT, _P], _CoroT[None] diff --git a/tanjun/commands/menu.py b/tanjun/commands/menu.py index 6328d949b..2192a2567 100644 --- a/tanjun/commands/menu.py +++ b/tanjun/commands/menu.py @@ -70,6 +70,22 @@ _EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() +# While these overloads may seem redundant/unnecessary, MyPy cannot understand +# this when expressed through `callback: _CallbackIshT[_MessageCallbackSigT]`. +class _AsMsgResultProto(typing.Protocol): + @typing.overload + def __call__( + self, _: _MessageCallbackSigT, / + ) -> MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]]: + ... + + @typing.overload + def __call__( + self, _: _AnyCommandT[_MessageCallbackSigT], / + ) -> MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]]: + ... + + def as_message_menu( name: typing.Union[str, collections.Mapping[str, str]], /, @@ -79,9 +95,7 @@ def as_message_menu( default_to_ephemeral: typing.Optional[bool] = None, dm_enabled: typing.Optional[bool] = None, is_global: bool = True, -) -> collections.Callable[ - [_CallbackishT[_MessageCallbackSigT]], MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]] -]: +) -> _AsMsgResultProto: """Build a message [tanjun.MenuCommand][] by decorating a function. !!! note @@ -175,6 +189,22 @@ def decorator( return decorator +# While these overloads may seem redundant/unnecessary, MyPy cannot understand +# this when expressed through `callback: _CallbackIshT[_MessageCallbackSigT]`. +class _AsUserResultProto(typing.Protocol): + @typing.overload + def __call__( + self, _: _UserCallbackSigT, / + ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: + ... + + @typing.overload + def __call__( + self, _: _AnyCommandT[_UserCallbackSigT], / + ) -> MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]]: + ... + + def as_user_menu( name: typing.Union[str, collections.Mapping[str, str]], /, @@ -184,9 +214,7 @@ def as_user_menu( default_to_ephemeral: typing.Optional[bool] = None, dm_enabled: typing.Optional[bool] = None, is_global: bool = True, -) -> collections.Callable[ - [_CallbackishT[_UserCallbackSigT]], MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]] -]: +) -> _AsUserResultProto: """Build a user [tanjun.MenuCommand][] by decorating a function. !!! note @@ -306,7 +334,26 @@ class MenuCommand(base.PartialCommand[tanjun.MenuContext], tanjun.MenuCommand[_A @typing.overload def __init__( self: MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]], - callback: _CallbackishT[_UserCallbackSigT], + callback: _UserCallbackSigT, + type_: typing.Literal[hikari.CommandType.USER], + name: str | collections.Mapping[str, str], + /, + *, + always_defer: bool = False, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, + is_global: bool = True, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, + ) -> None: + ... + + # While this extra overload may seem redundant/unnecessary, MyPy cannot understand + # this when expressed through `callback: _CallbackIshT[_MessageCallbackSigT]`. + @typing.overload + def __init__( + self: MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]], + callback: _AnyCommandT[_UserCallbackSigT], type_: typing.Literal[hikari.CommandType.USER], name: typing.Union[str, collections.Mapping[str, str]], /, @@ -323,7 +370,26 @@ def __init__( @typing.overload def __init__( self: MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]], - callback: _CallbackishT[_MessageCallbackSigT], + callback: _MessageCallbackSigT, + type_: typing.Literal[hikari.CommandType.MESSAGE], + name: str | collections.Mapping[str, str], + /, + *, + always_defer: bool = False, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, + is_global: bool = True, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, + ) -> None: + ... + + # While this extra overload may seem redundant/unnecessary, MyPy cannot understand + # this when expressed through `callback: _CallbackIshT[_MessageCallbackSigT]`. + @typing.overload + def __init__( + self: MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]], + callback: _AnyCommandT[_MessageCallbackSigT], type_: typing.Literal[hikari.CommandType.MESSAGE], name: typing.Union[str, collections.Mapping[str, str]], /, diff --git a/tanjun/commands/message.py b/tanjun/commands/message.py index 3fcf76252..8a27cd958 100644 --- a/tanjun/commands/message.py +++ b/tanjun/commands/message.py @@ -63,9 +63,19 @@ _EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() -def as_message_command( - name: str, /, *names: str, validate_arg_keys: bool = True -) -> collections.Callable[[_CallbackishT[_MessageCallbackSigT]], MessageCommand[_MessageCallbackSigT]]: +# While these overloads may seem redundant/unnecessary, MyPy cannot understand +# this when expressed through callback: _CallbackIshT[_MessageCallbackSigT]. +class _AsMsgResultProto(typing.Protocol): + @typing.overload + def __call__(self, _: _MessageCallbackSigT, /) -> MessageCommand[_MessageCallbackSigT]: + ... + + @typing.overload + def __call__(self, _: _AnyCommandT[_MessageCallbackSigT], /) -> MessageCommand[_MessageCallbackSigT]: + ... + + +def as_message_command(name: str, /, *names: str, validate_arg_keys: bool = True) -> _AsMsgResultProto: """Build a message command from a decorated callback. Parameters @@ -103,9 +113,21 @@ def decorator(callback: _CallbackishT[_MessageCallbackSigT], /) -> MessageComman return decorator +# While these overloads may seem redundant/unnecessary, MyPy cannot understand +# this when expressed through `callback: _CallbackIshT[_MessageCallbackSigT]`. +class _AsGroupResultProto(typing.Protocol): + @typing.overload + def __call__(self, _: _MessageCallbackSigT, /) -> MessageCommandGroup[_MessageCallbackSigT]: + ... + + @typing.overload + def __call__(self, _: _AnyCommandT[_MessageCallbackSigT], /) -> MessageCommandGroup[_MessageCallbackSigT]: + ... + + def as_message_command_group( name: str, /, *names: str, strict: bool = False, validate_arg_keys: bool = True -) -> collections.Callable[[_CallbackishT[_MessageCallbackSigT]], MessageCommandGroup[_MessageCallbackSigT]]: +) -> _AsGroupResultProto: """Build a message command group from a decorated callback. Parameters @@ -153,6 +175,32 @@ class MessageCommand(base.PartialCommand[tanjun.MessageContext], tanjun.MessageC __slots__ = ("_arg_names", "_callback", "_names", "_parent", "_parser", "_wrapped_command") + # While these overloads may seem redundant/unnecessary, MyPy cannot understand + # this when expressed through `callback: _CallbackIshT[_MessageCallbackSigT]`. + @typing.overload + def __init__( + self, + callback: _MessageCallbackSigT, + name: str, + /, + *names: str, + validate_arg_keys: bool = True, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, + ) -> None: + ... + + @typing.overload + def __init__( + self, + callback: _AnyCommandT[_MessageCallbackSigT], + name: str, + /, + *names: str, + validate_arg_keys: bool = True, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, + ) -> None: + ... + def __init__( self, callback: _CallbackishT[_MessageCallbackSigT], @@ -328,6 +376,34 @@ class MessageCommandGroup(MessageCommand[_MessageCallbackSigT], tanjun.MessageCo __slots__ = ("_commands",) + # While these overloads may seem redundant/unnecessary, MyPy cannot understand + # this when expressed through `callback: _CallbackIshT[_MessageCallbackSigT]`. + @typing.overload + def __init__( + self, + callback: _MessageCallbackSigT, + name: str, + /, + *names: str, + strict: bool = False, + validate_arg_keys: bool = True, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, + ) -> None: + ... + + @typing.overload + def __init__( + self, + callback: _AnyCommandT[_MessageCallbackSigT], + name: str, + /, + *names: str, + strict: bool = False, + validate_arg_keys: bool = True, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, + ) -> None: + ... + def __init__( self, callback: _CallbackishT[_MessageCallbackSigT], diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index 5ff96380e..6e60a5a69 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -244,6 +244,18 @@ async def help_me_command(ctx: tanjun.abc.SlashContext) -> None: ) +# While these overloads may seem redundant/unnecessary, MyPy cannot understand +# this when expressed through `callback: _CallbackIshT[_SlashCallbackSigT]`. +class _AsSlashResultProto(typing.Protocol): + @typing.overload + def __call__(self, _: _SlashCallbackSigT, /) -> SlashCommand[_SlashCallbackSigT]: + ... + + @typing.overload + def __call__(self, _: _AnyCommandT[_SlashCallbackSigT], /) -> SlashCommand[_SlashCallbackSigT]: + ... + + def as_slash_command( name: typing.Union[str, collections.Mapping[str, str]], description: typing.Union[str, collections.Mapping[str, str]], @@ -256,7 +268,7 @@ def as_slash_command( is_global: bool = True, sort_options: bool = True, validate_arg_keys: bool = True, -) -> collections.Callable[[_CallbackishT[_SlashCallbackSigT]], SlashCommand[_SlashCallbackSigT]]: +) -> _AsSlashResultProto: r"""Build a [tanjun.SlashCommand][] by decorating a function. !!! note @@ -1433,6 +1445,46 @@ class SlashCommand(BaseSlashCommand, tanjun.SlashCommand[_SlashCallbackSigT]): "_wrapped_command", ) + # While these overloads may seem redundant/unnecessary, MyPy cannot understand + # this when expressed through `callback: _CallbackIshT[_SlashCallbackSigT]`. + @typing.overload + def __init__( + self, + callback: _SlashCallbackSigT, + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], + /, + *, + always_defer: bool = False, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, + is_global: bool = True, + sort_options: bool = True, + validate_arg_keys: bool = True, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, + ) -> None: + ... + + @typing.overload + def __init__( + self, + callback: _AnyCommandT[_SlashCallbackSigT], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], + /, + *, + always_defer: bool = False, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, + is_global: bool = True, + sort_options: bool = True, + validate_arg_keys: bool = True, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, + ) -> None: + ... + def __init__( self, callback: _CallbackishT[_SlashCallbackSigT], From 9ab6701ba357c5f48234bf5d943b60b9905c8f65 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Tue, 24 Jan 2023 07:23:39 +0000 Subject: [PATCH 17/45] Add overloading for with_check + bump min typing-extensions --- pyproject.toml | 2 +- tanjun/checks.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7b02c7c16..0f28904af 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,7 @@ classifiers = [ "Topic :: Utilities", "Typing :: Typed", ] -dependencies = ["alluka>=0.1.2, <1", "hikari>=2.0.0.dev115, <3", "typing-extensions~=4.2"] +dependencies = ["alluka>=0.1.2, <1", "hikari>=2.0.0.dev115, <3", "typing-extensions~=4.4"] dynamic = ["description"] [project.urls] diff --git a/tanjun/checks.py b/tanjun/checks.py index 12e736924..befbcf4e3 100644 --- a/tanjun/checks.py +++ b/tanjun/checks.py @@ -984,9 +984,40 @@ def with_own_permission_check( ) +@typing.overload def with_check( check: tanjun.AnyCheckSig, /, *, follow_wrapped: bool = False ) -> collections.Callable[[_CommandT], _CommandT]: + ... + + +@typing.overload +def with_check( + check: tanjun.CheckSig[tanjun.MenuContext], /, *, follow_wrapped: bool = False +) -> collections.Callable[[_MenuCommandT], _MenuCommandT]: + ... + + +@typing.overload +def with_check( + check: tanjun.CheckSig[tanjun.MessageContext], /, *, follow_wrapped: bool = False +) -> collections.Callable[[_MessageCommandT], _MessageCommandT]: + ... + + +@typing.overload +def with_check( + check: tanjun.CheckSig[tanjun.SlashContext], /, *, follow_wrapped: bool = False +) -> collections.Callable[[_SlashCommandT], _SlashCommandT]: + ... + + +def with_check( + check: tanjun.CheckSig[typing.Any], /, *, follow_wrapped: bool = False +) -> (collections.Callable[[_CommandT], _CommandT] | + collections.Callable[[_MenuCommandT], _MenuCommandT] | + collections.Callable[[_MessageCommandT], _MessageCommandT] | + collections.Callable[[_SlashCommandT], _SlashCommandT]): """Add a generic check to a command. Parameters From d6c21dfa2158f97e8a22c80e01f8fcf061fcd3ed Mon Sep 17 00:00:00 2001 From: "always-on-duty[bot]" <120557446+always-on-duty[bot]@users.noreply.github.com> Date: Tue, 24 Jan 2023 07:24:44 +0000 Subject: [PATCH 18/45] Reformat PR code --- tanjun/checks.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tanjun/checks.py b/tanjun/checks.py index befbcf4e3..99f18ecbb 100644 --- a/tanjun/checks.py +++ b/tanjun/checks.py @@ -1014,10 +1014,12 @@ def with_check( def with_check( check: tanjun.CheckSig[typing.Any], /, *, follow_wrapped: bool = False -) -> (collections.Callable[[_CommandT], _CommandT] | - collections.Callable[[_MenuCommandT], _MenuCommandT] | - collections.Callable[[_MessageCommandT], _MessageCommandT] | - collections.Callable[[_SlashCommandT], _SlashCommandT]): +) -> ( + collections.Callable[[_CommandT], _CommandT] + | collections.Callable[[_MenuCommandT], _MenuCommandT] + | collections.Callable[[_MessageCommandT], _MessageCommandT] + | collections.Callable[[_SlashCommandT], _SlashCommandT] +): """Add a generic check to a command. Parameters From 0d5a40b8bb0da59b5a33a199bac52b72e190dd8a Mon Sep 17 00:00:00 2001 From: "always-on-duty[bot]" <120557446+always-on-duty[bot]@users.noreply.github.com> Date: Tue, 24 Jan 2023 07:25:01 +0000 Subject: [PATCH 19/45] Freeze PR dependency changes --- dev-requirements/constraints.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements/constraints.in b/dev-requirements/constraints.in index e6dc4e34e..d2eeac918 100644 --- a/dev-requirements/constraints.in +++ b/dev-requirements/constraints.in @@ -1,3 +1,3 @@ alluka>=0.1.2, <1 hikari>=2.0.0.dev115, <3 -typing-extensions~=4.2 +typing-extensions~=4.4 From b458eb7b7c236c5fff206320a9d810690867a98e Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Tue, 24 Jan 2023 08:06:27 +0000 Subject: [PATCH 20/45] Fix hook types --- tanjun/abc.py | 64 +++++++++++++++++++++++++++++++++++++++++++------ tanjun/hooks.py | 39 ++++++++++++++++++++++++------ 2 files changed, 89 insertions(+), 14 deletions(-) diff --git a/tanjun/abc.py b/tanjun/abc.py index 0ce5fa585..99784c985 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -59,6 +59,7 @@ "MessageContext", "MessageHooks", "MetaEventSig", + "ParserHookSig", "SlashCommand", "SlashCommandGroup", "SlashContext", @@ -82,6 +83,8 @@ from typing_extensions import Self + from . import errors + _BaseSlashCommandT = typing.TypeVar("_BaseSlashCommandT", bound="BaseSlashCommand") _AnyErrorHookSigT = typing.TypeVar("_AnyErrorHookSigT", bound="ErrorHookSig[typing.Any]") @@ -89,6 +92,11 @@ _MessageErrorHookSigT = typing.TypeVar("_MessageErrorHookSigT", bound="ErrorHookSig[MessageContext]") _SlashErrorHookSigT = typing.TypeVar("_SlashErrorHookSigT", bound="ErrorHookSig[SlashContext]") + _AnyParserHookSigT = typing.TypeVar("_AnyParserHookSigT", bound="ParserHookSig[typing.Any]") + _MenuParserHookSigT = typing.TypeVar("_MenuParserHookSigT", bound="ParserHookSig[MenuContext]") + _MessageParserHookSigT = typing.TypeVar("_MessageParserHookSigT", bound="ParserHookSig[MessageContext]") + _SlashParserHookSigT = typing.TypeVar("_SlashParserHookSigT", bound="ParserHookSig[SlashContext]") + _AnyHookSigT = typing.TypeVar("_AnyHookSigT", bound="HookSig[typing.Any]") _MenuHookSigT = typing.TypeVar("_MenuHookSigT", bound="HookSig[MenuContext]") _MessageHookSigT = typing.TypeVar("_MessageHookSigT", bound="HookSig[MessageContext]") @@ -127,7 +135,7 @@ """ AutocompleteCallbackSig = AutocompleteSig -"""Deprecated alias of [tanjun.abc.AutocompleteSig][]""" +"""Deprecated alias of [tanjun.abc.AutocompleteSig][].""" _CheckSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, _P], bool] CheckSig = _CheckSig[_ContextT_contra, ...] @@ -193,7 +201,8 @@ """Type hint of the callback used as a unexpected command error hook. This will be called whenever an unexpected [Exception][] is raised during the -execution stage of a command (not including expected [tanjun.TanjunError][]). +execution stage of a command (ignoring [tanjun.ParserError][] and expected +[tanjun.TanjunError][] subclasses). This should take two positional arguments - of type [tanjun.abc.Context][] and [Exception][] - and may be either a synchronous or asynchronous callback which @@ -203,6 +212,22 @@ [False][] is returned to indicate that the exception should be re-raised. """ +_ParserHookSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, "errors.ParserError", _P], bool | None] + +ParserHookSig = _ParserHookSig[_ContextT_contra, ...] +"""Type hint of the callback used as a command parser error hook. + +This will be called whenever an parser [ParserError][tanjun.errors.ParserError] +is raised during the execution stage of a command. + +This should take two positional arguments - of type [tanjun.abc.Context][] and +[ParserError][tanjun.errors.ParserError] - and may be either a synchronous or +asynchronous callback which returns [None][] and may take advantage of +dependency injection. + +Parser errors are always suppressed (unlike general errors). +""" + _HookSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, _P], None] HookSig = _HookSig[_ContextT_contra, ...] @@ -2175,6 +2200,11 @@ def add_on_error(self, callback: ErrorHookSig[_ContextT_contra], /) -> Self: The hook object to enable method chaining. """ + @typing.overload + @abc.abstractmethod + def with_on_error(self: AnyHooks, callback: _AnyErrorHookSigT, /) -> _AnyErrorHookSigT: + ... + @typing.overload @abc.abstractmethod def with_on_error(self: MenuHooks, callback: _MenuErrorHookSigT, /) -> _MenuErrorHookSigT: @@ -2233,7 +2263,7 @@ async def on_error(ctx: tanjun.abc.Context, error: Exception) -> bool: """ @abc.abstractmethod - def add_on_parser_error(self, callback: HookSig[_ContextT_contra], /) -> Self: + def add_on_parser_error(self, callback: ParserHookSig[_ContextT_contra], /) -> Self: """Add a parser error callback to this hook object. Parameters @@ -2256,21 +2286,26 @@ def add_on_parser_error(self, callback: HookSig[_ContextT_contra], /) -> Self: @typing.overload @abc.abstractmethod - def with_on_parser_error(self: MenuHooks, callback: _MenuHookSigT, /) -> _MenuHookSigT: + def with_on_parser_error(self: AnyHooks, callback: _AnyParserHookSigT, /) -> _AnyParserHookSigT: ... @typing.overload @abc.abstractmethod - def with_on_parser_error(self: MessageHooks, callback: _MessageHookSigT, /) -> _MessageHookSigT: + def with_on_parser_error(self: MenuHooks, callback: _MenuParserHookSigT, /) -> _MenuParserHookSigT: ... @typing.overload @abc.abstractmethod - def with_on_parser_error(self: SlashHooks, callback: _SlashHookSigT, /) -> _SlashHookSigT: + def with_on_parser_error(self: MessageHooks, callback: _MessageParserHookSigT, /) -> _MessageParserHookSigT: ... + @typing.overload @abc.abstractmethod - def with_on_parser_error(self, callback: _AnyHookSigT, /) -> _AnyHookSigT: + def with_on_parser_error(self: SlashHooks, callback: _SlashParserHookSigT, /) -> _SlashParserHookSigT: + ... + + @abc.abstractmethod + def with_on_parser_error(self, callback: _AnyParserHookSigT, /) -> _AnyParserHookSigT: """Add a parser error callback to this hook object through a decorator call. Examples @@ -2317,6 +2352,11 @@ def add_post_execution(self, callback: HookSig[_ContextT_contra], /) -> Self: The hook object to enable method chaining. """ + @typing.overload + @abc.abstractmethod + def with_post_execution(self: AnyHooks, callback: _AnyHookSigT, /) -> _AnyHookSigT: + ... + @typing.overload @abc.abstractmethod def with_post_execution(self: MenuHooks, callback: _MenuHookSigT, /) -> _MenuHookSigT: @@ -2380,6 +2420,11 @@ def add_pre_execution(self, callback: HookSig[_ContextT_contra], /) -> Self: The hook object to enable method chaining. """ + @typing.overload + @abc.abstractmethod + def with_pre_execution(self: AnyHooks, callback: _AnyHookSigT, /) -> _AnyHookSigT: + ... + @typing.overload @abc.abstractmethod def with_pre_execution(self: MenuHooks, callback: _MenuHookSigT, /) -> _MenuHookSigT: @@ -2443,6 +2488,11 @@ def add_on_success(self, callback: HookSig[_ContextT_contra], /) -> Self: The hook object to enable method chaining. """ + @typing.overload + @abc.abstractmethod + def with_on_success(self: AnyHooks, callback: _AnyHookSigT, /) -> _AnyHookSigT: + ... + @typing.overload @abc.abstractmethod def with_on_success(self: MenuHooks, callback: _MenuHookSigT, /) -> _MenuHookSigT: diff --git a/tanjun/hooks.py b/tanjun/hooks.py index 72d64d119..4ee4b9727 100644 --- a/tanjun/hooks.py +++ b/tanjun/hooks.py @@ -55,6 +55,11 @@ _MessageErrorHookSigT = typing.TypeVar("_MessageErrorHookSigT", bound=tanjun.ErrorHookSig[tanjun.MessageContext]) _SlashErrorHookSigT = typing.TypeVar("_SlashErrorHookSigT", bound=tanjun.ErrorHookSig[tanjun.SlashContext]) + _AnyParserHookSigT = typing.TypeVar("_AnyParserHookSigT", bound=tanjun.ParserHookSig[typing.Any]) + _MenuParserHookSigT = typing.TypeVar("_MenuParserHookSigT", bound=tanjun.ParserHookSig[tanjun.MenuContext]) + _MessageParserHookSigT = typing.TypeVar("_MessageParserHookSigT", bound=tanjun.ParserHookSig[tanjun.MessageContext]) + _SlashParserHookSigT = typing.TypeVar("_SlashParserHookSigT", bound=tanjun.ParserHookSig[tanjun.SlashContext]) + _AnyHookSigT = typing.TypeVar("_AnyHookSigT", bound=tanjun.HookSig[typing.Any]) _MenuHookSigT = typing.TypeVar("_MenuHookSigT", bound=tanjun.HookSig[tanjun.MenuContext]) _MessageHookSigT = typing.TypeVar("_MessageHookSigT", bound=tanjun.HookSig[tanjun.MessageContext]) @@ -87,7 +92,7 @@ class Hooks(tanjun.Hooks[_ContextT_contra]): def __init__(self) -> None: """Initialise a command hook object.""" self._error_callbacks: list[tanjun.ErrorHookSig[_ContextT_contra]] = [] - self._parser_error_callbacks: list[tanjun.HookSig[_ContextT_contra]] = [] + self._parser_error_callbacks: list[tanjun.ParserHookSig[_ContextT_contra]] = [] self._pre_execution_callbacks: list[tanjun.HookSig[_ContextT_contra]] = [] self._post_execution_callbacks: list[tanjun.HookSig[_ContextT_contra]] = [] self._success_callbacks: list[tanjun.HookSig[_ContextT_contra]] = [] @@ -178,6 +183,10 @@ def set_on_error(self, callback: tanjun.ErrorHookSig[_ContextT_contra] | None, / self._error_callbacks.clear() return self.add_on_error(callback) if callback else self + @typing.overload + def with_on_error(self: AnyHooks, callback: _AnyErrorHookSigT, /) -> _AnyErrorHookSigT: + ... + @typing.overload def with_on_error(self: MenuHooks, callback: _MenuErrorHookSigT, /) -> _MenuErrorHookSigT: ... @@ -195,12 +204,12 @@ def with_on_error(self, callback: _AnyErrorHookSigT, /) -> _AnyErrorHookSigT: self.add_on_error(callback) return callback - def add_on_parser_error(self, callback: tanjun.HookSig[_ContextT_contra], /) -> Self: + def add_on_parser_error(self, callback: tanjun.ParserHookSig[_ContextT_contra], /) -> Self: # <>. self._parser_error_callbacks.append(callback) return self - def set_on_parser_error(self, callback: tanjun.HookSig[_ContextT_contra] | None, /) -> Self: + def set_on_parser_error(self, callback: tanjun.ParserHookSig[_ContextT_contra] | None, /) -> Self: """Set the parser error callback for this hook object. Parameters @@ -225,18 +234,22 @@ def set_on_parser_error(self, callback: tanjun.HookSig[_ContextT_contra] | None, return self.add_on_parser_error(callback) if callback else self @typing.overload - def with_on_parser_error(self: MenuHooks, callback: _MenuHookSigT, /) -> _MenuHookSigT: + def with_on_parser_error(self: AnyHooks, callback: _AnyParserHookSigT, /) -> _AnyParserHookSigT: ... @typing.overload - def with_on_parser_error(self: MessageHooks, callback: _MessageHookSigT, /) -> _MessageHookSigT: + def with_on_parser_error(self: MenuHooks, callback: _MenuParserHookSigT, /) -> _MenuParserHookSigT: ... @typing.overload - def with_on_parser_error(self: SlashHooks, callback: _SlashHookSigT, /) -> _SlashHookSigT: + def with_on_parser_error(self: MessageHooks, callback: _MessageParserHookSigT, /) -> _MessageParserHookSigT: ... - def with_on_parser_error(self, callback: _AnyHookSigT, /) -> _AnyHookSigT: + @typing.overload + def with_on_parser_error(self: SlashHooks, callback: _SlashParserHookSigT, /) -> _SlashParserHookSigT: + ... + + def with_on_parser_error(self, callback: _AnyParserHookSigT, /) -> _AnyParserHookSigT: # <>. self.add_on_parser_error(callback) return callback @@ -267,6 +280,10 @@ def set_post_execution(self, callback: tanjun.HookSig[_ContextT_contra] | None, self._post_execution_callbacks.clear() return self.add_post_execution(callback) if callback else self + @typing.overload + def with_post_execution(self: AnyHooks, callback: _AnyHookSigT, /) -> _AnyHookSigT: + ... + @typing.overload def with_post_execution(self: MenuHooks, callback: _MenuHookSigT, /) -> _MenuHookSigT: ... @@ -310,6 +327,10 @@ def set_pre_execution(self, callback: tanjun.HookSig[_ContextT_contra] | None, / self._pre_execution_callbacks.clear() return self.add_pre_execution(callback) if callback else self + @typing.overload + def with_pre_execution(self: AnyHooks, callback: _AnyHookSigT, /) -> _AnyHookSigT: + ... + @typing.overload def with_pre_execution(self: MenuHooks, callback: _MenuHookSigT, /) -> _MenuHookSigT: ... @@ -353,6 +374,10 @@ def set_on_success(self, callback: tanjun.HookSig[_ContextT_contra] | None, /) - self._success_callbacks.clear() return self.add_on_success(callback) if callback else self + @typing.overload + def with_on_success(self: AnyHooks, callback: _AnyHookSigT, /) -> _AnyHookSigT: + ... + @typing.overload def with_on_success(self: MenuHooks, callback: _MenuHookSigT, /) -> _MenuHookSigT: ... From d9eb54cfcfaa6338926a9d0ab859252826dd04ba Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Tue, 24 Jan 2023 11:43:56 +0000 Subject: [PATCH 21/45] Fix annotations.Converted typing --- tanjun/annotations.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/tanjun/annotations.py b/tanjun/annotations.py index a2ebe5517..f16703b8f 100644 --- a/tanjun/annotations.py +++ b/tanjun/annotations.py @@ -94,16 +94,13 @@ from typing_extensions import Self _P = typing_extensions.ParamSpec("_P") - # TODO: test this - _ConverterValueT = typing.TypeVar("_ConverterValueT", bound=int | str | float) __ConverterSig = ( collections.Callable[ - typing_extensions.Concatenate[_ConverterValueT, _P], - collections.Coroutine[typing.Any, typing.Any, typing.Any], + typing_extensions.Concatenate[str, _P], collections.Coroutine[typing.Any, typing.Any, "_T"], ] - | collections.Callable[typing_extensions.Concatenate[_ConverterValueT, _P], typing.Any] + | collections.Callable[typing_extensions.Concatenate[str, _P], "_T"] ) - _ConverterSig = __ConverterSig[_ConverterValueT, ...] + _ConverterSig = __ConverterSig[..., "_T"] _T = typing.TypeVar("_T") _ChannelTypeIsh = typing.Union[type[hikari.PartialChannel], int] @@ -280,13 +277,11 @@ def set_config(self, config: _ArgConfig, /) -> None: class _ConvertedMeta(abc.ABCMeta): - def __getitem__( - cls, converters: _ConverterSig[_ConverterValueT] | tuple[_ConverterSig[_ConverterValueT]], / - ) -> type[_ConverterValueT]: + def __getitem__(cls, converters: _ConverterSig[_T] | tuple[_ConverterSig[_T]], /) -> type[_T]: if not isinstance(converters, tuple): converters = (converters,) - return typing.cast("type[_ConverterValueT]", typing.Annotated[typing.Any, Converted(*converters)]) + return typing.cast("type[_T]", typing.Annotated[typing.Any, Converted(*converters)]) class Converted(_ConfigIdentifier, metaclass=_ConvertedMeta): @@ -1259,7 +1254,6 @@ def to_slash_option(self, command: slash.SlashCommand[typing.Any], /) -> None: self.slash_name, d, choices=_ensure_values("choice", float, self.choices), # TODO: can we pass ints here as well? - converters=self.converters or (), default=self._slash_default(), key=self.parameter.name, min_value=self.min_value, # TODO: explicitly cast to float? @@ -1269,7 +1263,6 @@ def to_slash_option(self, command: slash.SlashCommand[typing.Any], /) -> None: self.slash_name, d, choices=_ensure_values("choice", int, self.choices), - converters=self.converters or (), default=self._slash_default(), key=self.parameter.name, min_value=_ensure_value("min", int, self.min_value), From 007bd618a274ee7b907d0916a5ba082832e52a5e Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Tue, 24 Jan 2023 12:00:08 +0000 Subject: [PATCH 22/45] simplify maybe coroutine types --- tanjun/abc.py | 6 +++--- tanjun/annotations.py | 9 +++------ tanjun/commands/menu.py | 2 +- tanjun/commands/slash.py | 9 +++------ tanjun/components.py | 4 +--- tanjun/parsing.py | 7 +++---- 6 files changed, 14 insertions(+), 23 deletions(-) diff --git a/tanjun/abc.py b/tanjun/abc.py index 99784c985..12ad31e8e 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -118,7 +118,7 @@ "_MenuTypeT", typing.Literal[hikari.CommandType.USER], typing.Literal[hikari.CommandType.MESSAGE] ) -_MaybeAwaitable = collections.Callable[_P, _CoroT[_T]] | collections.Callable[_P, _T] +_MaybeAwaitable = collections.Callable[_P, _CoroT[_T] | _T] _AutocompleteValueT = typing.TypeVar("_AutocompleteValueT", int, str, float) _AutocompleteSig = collections.Callable[ @@ -156,8 +156,6 @@ CommandCallbackSig = collections.Callable[..., _CoroT[None]] """Deprecated type hint used to represent any command callback.""" -_CommandCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _P], _CoroT[None]] - _ManuCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _MenuValueT, _P], _CoroT[None]] MenuCallbackSig = _ManuCallbackSig["MenuContext", _MenuValueT, ...] """Type hint of a context menu command callback. @@ -175,6 +173,8 @@ _MenuCallbackSigT = typing.TypeVar("_MenuCallbackSigT", bound=MenuCallbackSig[typing.Any]) +_CommandCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _P], _CoroT[None]] + MessageCallbackSig = _CommandCallbackSig["MessageContext", ...] """Type hint of a message command callback. diff --git a/tanjun/annotations.py b/tanjun/annotations.py index f16703b8f..7e99e7d9c 100644 --- a/tanjun/annotations.py +++ b/tanjun/annotations.py @@ -94,12 +94,9 @@ from typing_extensions import Self _P = typing_extensions.ParamSpec("_P") - __ConverterSig = ( - collections.Callable[ - typing_extensions.Concatenate[str, _P], collections.Coroutine[typing.Any, typing.Any, "_T"], - ] - | collections.Callable[typing_extensions.Concatenate[str, _P], "_T"] - ) + __ConverterSig = collections.Callable[ + typing_extensions.Concatenate[str, _P], "collections.Coroutine[typing.Any, typing.Any, _T] | _T", + ] _ConverterSig = __ConverterSig[..., "_T"] _T = typing.TypeVar("_T") diff --git a/tanjun/commands/menu.py b/tanjun/commands/menu.py index 2192a2567..ff826cdf0 100644 --- a/tanjun/commands/menu.py +++ b/tanjun/commands/menu.py @@ -430,7 +430,7 @@ def __init__( Parameters ---------- - callback : collections.abc.Callable[[tanjun.abc.MenuContext, ...], collections.abc.Coroutine[Any, ANy, None]] + callback : collections.abc.Callable[[tanjun.abc.MenuContext, ...], collections.abc.Coroutine[Any, Any, None]] Callback to execute when the command is invoked. This should be an asynchronous callback which takes one positional diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index 6e60a5a69..deaa88ea5 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -95,13 +95,10 @@ _ConvertT = typing.TypeVar("_ConvertT", int, float, str) _P = typing_extensions.ParamSpec("_P") -_ConverterSig = ( - collections.Callable[ - typing_extensions.Concatenate[_ConvertT, _P], collections.Coroutine[typing.Any, typing.Any, typing.Any] - ] - | collections.Callable[typing_extensions.Concatenate[_ConvertT, _P], typing.Any] -) +_ConverterSig = collections.Callable[ + typing_extensions.Concatenate[_ConvertT, _P], collections.Coroutine[typing.Any, typing.Any, typing.Any] | typing.Any +] ConverterSig = _ConverterSig[_ConvertT, ...] """Type hint of a slash command option converter.""" diff --git a/tanjun/components.py b/tanjun/components.py index b671fe8ef..d0c9e54ea 100644 --- a/tanjun/components.py +++ b/tanjun/components.py @@ -70,9 +70,7 @@ # This errors on earlier 3.9 releases when not quotes cause dumb handling of the [_CommandT] list _WithCommandReturnSig = typing.Union[_CommandT, "collections.Callable[[_CommandT], _CommandT]"] -OnCallbackSig = typing.Union[ - collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, None]], collections.Callable[..., None] -] +OnCallbackSig = collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, None] | None] """Type hint of a on_open or on_close component callback. These support dependency injection, should expect no positional arguments and diff --git a/tanjun/parsing.py b/tanjun/parsing.py index f17a8ea77..a2477ba03 100644 --- a/tanjun/parsing.py +++ b/tanjun/parsing.py @@ -85,10 +85,9 @@ def __len__(self) -> int: _T = typing.TypeVar("_T") _P = typing_extensions.ParamSpec("_P") -_ConverterSig = ( - collections.Callable[typing_extensions.Concatenate[str, _P], collections.Coroutine[typing.Any, typing.Any, _T]] - | collections.Callable[typing_extensions.Concatenate[str, _P], _T] -) +_ConverterSig = collections.Callable[ + typing_extensions.Concatenate[str, _P], collections.Coroutine[typing.Any, typing.Any, _T] | _T +] ConverterSig = _ConverterSig[..., _T] # TODO: is this correct? """Type hint of a converter used within a parser instance. From b68725b37f09c12b662ca9ef0d96b624ff564244 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Tue, 24 Jan 2023 12:10:40 +0000 Subject: [PATCH 23/45] Remove dated TODO --- tanjun/parsing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tanjun/parsing.py b/tanjun/parsing.py index a2477ba03..6c7eec642 100644 --- a/tanjun/parsing.py +++ b/tanjun/parsing.py @@ -89,7 +89,7 @@ def __len__(self) -> int: typing_extensions.Concatenate[str, _P], collections.Coroutine[typing.Any, typing.Any, _T] | _T ] -ConverterSig = _ConverterSig[..., _T] # TODO: is this correct? +ConverterSig = _ConverterSig[..., _T] """Type hint of a converter used within a parser instance. This must be a callable or asynchronous callable which takes one position From 26b3fd22bb44d766ca0b6c1678c948565b5e0ef8 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Tue, 24 Jan 2023 23:32:02 +0000 Subject: [PATCH 24/45] Test and behaviour fixes --- CHANGELOG.md | 7 ++ dev-requirements/tests.in | 1 - tanjun/annotations.py | 75 ++++++++++++++------ tanjun/commands/slash.py | 12 ++-- tests/commands/test_slash.py | 29 ++++++++ tests/test_annotations.py | 10 +-- tests/test_annotations_future_annotations.py | 10 +-- 7 files changed, 108 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37687f81d..13186a1be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - [tanjun.MenuHooks][] is now exported top-level. +### Fixed +- [tanjun.annotations.Converted][] now properly overrides the actual type annotation for + slash commands. +- The `add_{}_option` and `with_{}_option` methods for the standard slash command impl + will no-longer mishandle iterable but non-sequence types like [enum.Enum][] as if + they were a sequence of converters when they are passed as the value for `converters`. + ### [2.11.2] - 2023-01-23 ### Changed - [tanjun.clients.Client.from_gateway_bot][] can now also take cache-less `ShardAware` bots. diff --git a/dev-requirements/tests.in b/dev-requirements/tests.in index b68f82021..384742211 100644 --- a/dev-requirements/tests.in +++ b/dev-requirements/tests.in @@ -5,4 +5,3 @@ freezegun>=1.2.2, <2 pytest-asyncio>=0.20.1, <1 pytest-timeout>=2.1, <3 pytest-xdist>=3.1, <4 -typing-extensions~=4.4 diff --git a/tanjun/annotations.py b/tanjun/annotations.py index 7e99e7d9c..b94e36966 100644 --- a/tanjun/annotations.py +++ b/tanjun/annotations.py @@ -193,25 +193,54 @@ def set_config(self, config: _ArgConfig, /) -> None: """An argument which takes a user.""" +class _FloatEnumConverter(_ConfigIdentifier): + """Specialised converters for float enum choices.""" + + __slots__ = ("_enum",) + + def __init__(self, enum: collections.Callable[[float], typing.Any]) -> None: + self._enum = enum + + def set_config(self, config: _ArgConfig, /) -> None: + config.float_converter = self._enum + + +class _IntEnumConverter(_ConfigIdentifier): + """Specialised converters for int enum choices.""" + + __slots__ = ("_enum",) + + def __init__(self, enum: collections.Callable[[int], typing.Any]) -> None: + self._enum = enum + + def set_config(self, config: _ArgConfig, /) -> None: + config.int_converter = self._enum + + class _ChoicesMeta(abc.ABCMeta): def __getitem__(cls, enum_: type[_EnumT], /) -> type[_EnumT]: - if issubclass(enum_, int): + if issubclass(enum_, float): + type_ = float + choices = Choices(enum_.__members__) + converter = _FloatEnumConverter(enum_) + + elif issubclass(enum_, int): type_ = int choices = Choices(enum_.__members__) + converter = _IntEnumConverter(enum_) elif issubclass(enum_, str): type_ = str choices = Choices(enum_.__members__) - - elif issubclass(enum_, float): - type_ = float - choices = Choices(enum_.__members__) + converter = None else: raise TypeError("Enum must be a subclass of str, float or int") # TODO: do we want to wrap the convert callback to give better failed parse messages? - return typing.cast(type[_EnumT], typing.Annotated[enum_, choices, Converted(enum_), _TypeOverride(type_)]) + return typing.cast( + type[_EnumT], typing.Annotated[enum_, choices, converter, Converted(enum_), _TypeOverride(type_)] + ) class Choices(_ConfigIdentifier, metaclass=_ChoicesMeta): @@ -326,7 +355,8 @@ def converters(self) -> collections.Sequence[_ConverterSig[typing.Any]]: return self._converters def set_config(self, config: _ArgConfig, /) -> None: - config.converters = self._converters + config.str_converters = self._converters + config.option_type = str Color = typing.Annotated[hikari.Color, Converted(conversion.to_color)] @@ -529,9 +559,6 @@ async def command( __slots__ = () - def __init__(self) -> None: - """Create a positional instance.""" - def set_config(self, config: _ArgConfig, /) -> None: config.is_positional = True @@ -1097,10 +1124,11 @@ class _ArgConfig: "aliases", "channel_types", "choices", - "converters", "default", "description", "empty_value", + "float_converter", + "int_converter", "is_greedy", "is_positional", "min_length", @@ -1113,16 +1141,19 @@ class _ArgConfig: "range_or_slice", "slash_name", "snowflake_converter", + "str_converters", ) def __init__(self, parameter: inspect.Parameter, /, *, description: typing.Optional[str]) -> None: self.aliases: typing.Optional[collections.Sequence[str]] = None self.channel_types: typing.Optional[collections.Sequence[_ChannelTypeIsh]] = None self.choices: typing.Optional[collections.Mapping[str, _ChoiceUnion]] = None - self.converters: collections.Sequence[_ConverterSig[typing.Any]] | None = None self.default: typing.Any = parsing.UNDEFINED if parameter.default is parameter.empty else parameter.default self.description: typing.Optional[str] = description self.empty_value: typing.Union[parsing.UndefinedT, typing.Any] = parsing.UNDEFINED + self.float_converter: collections.Callable[[float], typing.Any] | None = None + self.int_converter: collections.Callable[[int], typing.Any] | None = None + # The float and int converters are just for Choices[Enum]. self.is_greedy: bool = False self.is_positional: typing.Optional[bool] = None self.min_length: typing.Optional[int] = None @@ -1135,6 +1166,7 @@ def __init__(self, parameter: inspect.Parameter, /, *, description: typing.Optio self.range_or_slice: typing.Union[range, slice, None] = None self.slash_name: str = parameter.name self.snowflake_converter: typing.Optional[collections.Callable[[str], hikari.Snowflake]] = None + self.str_converters: collections.Sequence[_ConverterSig[typing.Any]] | None = None def finalise_slice(self) -> None: if not self.range_or_slice: @@ -1158,8 +1190,8 @@ def finalise_slice(self) -> None: self.max_value = max_value def to_message_option(self, command: message.MessageCommand[typing.Any], /) -> None: - if self.converters: - converters = self.converters + if self.str_converters: + converters = self.str_converters elif self.option_type: if self.snowflake_converter and self.option_type in _MESSAGE_ID_ONLY: @@ -1225,15 +1257,14 @@ def _slash_default(self) -> typing.Any: return slash.UNDEFINED_DEFAULT if self.default is parsing.UNDEFINED else self.default def to_slash_option(self, command: slash.SlashCommand[typing.Any], /) -> None: - option_type = self.option_type - if not option_type and self.converters: - option_type = str + if self.str_converters and not self.option_type: + self.option_type = str - if option_type: + if self.option_type: if not self.description: raise ValueError(f"Missing description for argument {self.parameter.name!r}") - self.SLASH_OPTION_ADDER[option_type](self, command, self.description) + self.SLASH_OPTION_ADDER[self.option_type](self, command, self.description) SLASH_OPTION_ADDER: dict[ typing.Any, collections.Callable[[Self, slash.SlashCommand[typing.Any], str], slash.SlashCommand[typing.Any]] @@ -1251,6 +1282,7 @@ def to_slash_option(self, command: slash.SlashCommand[typing.Any], /) -> None: self.slash_name, d, choices=_ensure_values("choice", float, self.choices), # TODO: can we pass ints here as well? + converters=self.float_converter or (), default=self._slash_default(), key=self.parameter.name, min_value=self.min_value, # TODO: explicitly cast to float? @@ -1260,6 +1292,7 @@ def to_slash_option(self, command: slash.SlashCommand[typing.Any], /) -> None: self.slash_name, d, choices=_ensure_values("choice", int, self.choices), + converters=self.int_converter or (), default=self._slash_default(), key=self.parameter.name, min_value=_ensure_value("min", int, self.min_value), @@ -1278,7 +1311,7 @@ def to_slash_option(self, command: slash.SlashCommand[typing.Any], /) -> None: self.slash_name, d, choices=_ensure_values("choice", str, self.choices), - converters=self.converters or (), + converters=self.str_converters or (), default=self._slash_default(), key=self.parameter.name, min_length=self.min_length, @@ -1369,7 +1402,7 @@ def parse_annotated_args( arg_config.range_or_slice = arg arg_config.finalise_slice() - if arg_config.option_type or arg_config.converters: + if arg_config.option_type or arg_config.str_converters: for slash_command in slash_commands: arg_config.to_slash_option(slash_command) diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index deaa88ea5..210234ff0 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -470,7 +470,7 @@ def with_int_slash_option( *, autocomplete: tanjun.AutocompleteSig[int] | None = None, choices: typing.Optional[collections.Mapping[str, int]] = None, - converters: collections.Collection[ConverterSig[int]] | ConverterSig[int] = (), + converters: collections.Sequence[ConverterSig[int]] | ConverterSig[int] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_value: typing.Optional[int] = None, @@ -519,7 +519,7 @@ def with_float_slash_option( always_float: bool = True, autocomplete: tanjun.AutocompleteSig[float] | None = None, choices: typing.Optional[collections.Mapping[str, float]] = None, - converters: collections.Collection[ConverterSig[float]] | ConverterSig[float] = (), + converters: collections.Sequence[ConverterSig[float]] | ConverterSig[float] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_value: typing.Optional[float] = None, @@ -1671,7 +1671,7 @@ def _add_option( choices: typing.Union[ collections.Mapping[str, typing.Union[str, int, float]], collections.Sequence[typing.Any], None ] = None, - converters: collections.Iterable[_AnyConverterSig] | _AnyConverterSig = (), + converters: collections.Sequence[_AnyConverterSig] | _AnyConverterSig = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_length: typing.Optional[int] = None, @@ -1702,7 +1702,7 @@ def _add_option( raise ValueError(f"{key!r} is not a valid keyword argument for {self._callback}") type_ = hikari.OptionType(type_) - if isinstance(converters, collections.Iterable): + if isinstance(converters, collections.Sequence): converters = list(converters) else: @@ -1987,7 +1987,7 @@ def add_int_option( *, autocomplete: tanjun.AutocompleteSig[int] | None = None, choices: typing.Optional[collections.Mapping[str, int]] = None, - converters: collections.Collection[ConverterSig[int]] | ConverterSig[int] = (), + converters: collections.Sequence[ConverterSig[int]] | ConverterSig[int] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_value: typing.Optional[int] = None, @@ -2098,7 +2098,7 @@ def add_float_option( always_float: bool = True, autocomplete: tanjun.AutocompleteSig[float] | None = None, choices: typing.Optional[collections.Mapping[str, float]] = None, - converters: collections.Collection[ConverterSig[float]] | ConverterSig[float] = (), + converters: collections.Sequence[ConverterSig[float]] | ConverterSig[float] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_value: typing.Optional[float] = None, diff --git a/tests/commands/test_slash.py b/tests/commands/test_slash.py index a25ea34ec..c24fa6871 100644 --- a/tests/commands/test_slash.py +++ b/tests/commands/test_slash.py @@ -34,6 +34,7 @@ # pyright: reportPrivateUsage=none # This leads to too many false-positives around mocks. +import enum import inspect import re import types @@ -1871,6 +1872,16 @@ def test_add_str_option_with_localised_description_too_short(self, command: tanj with pytest.raises(ValueError, match="Description must be greater than or equal to 1 characters in length"): command.add_str_option("name", {hikari.Locale.IT: ""}) + def test_add_str_option_when_converters_is_flat_enum(self, command: tanjun.SlashCommand[typing.Any]): + class Enum(str, enum.Enum): + FOO = "i can't" + BAR = "meow" + BAZ = "something will change" + + command.add_str_option("boom", "No u", converters=Enum) + + assert list(command._tracked_options["boom"].converters) == [Enum] + def test_add_int_option(self, command: tanjun.SlashCommand[typing.Any]): mock_converter = mock.Mock() @@ -2086,6 +2097,15 @@ def test_add_int_option_with_localised_description_too_short(self, command: tanj with pytest.raises(ValueError, match="Description must be greater than or equal to 1 characters in length"): command.add_int_option("name", {hikari.Locale.IT: ""}) + def test_add_int_option_when_converters_is_flat_enum(self, command: tanjun.SlashCommand[typing.Any]): + class Enum(int, enum.Enum): + THERE_IS_NO = 543 + THERE_IS_YES = 123123 + + command.add_int_option("see", "seesee", converters=[Enum]) + + assert list(command._tracked_options["see"].converters) == [Enum] + def test_add_float_option(self, command: tanjun.SlashCommand[typing.Any]): mock_converter = mock.Mock() command.add_float_option( @@ -2323,6 +2343,15 @@ def test_add_float_option_with_localised_description_too_short(self, command: ta with pytest.raises(ValueError, match="Description must be greater than or equal to 1 characters in length"): command.add_float_option("name", {hikari.Locale.IT: ""}) + def test_add_float_option_when_converters_is_flat_enum(self, command: tanjun.SlashCommand[typing.Any]): + class Enum(enum.Enum): + MEOW = 431.123 + NYAA = 3243.543 + + command.add_float_option("sesese", "asasasa", converters=[Enum]) + + assert list(command._tracked_options["sesese"].converters) == [Enum] + def test_add_bool_option(self, command: tanjun.SlashCommand[typing.Any]): command.add_bool_option("eaassa", "saas", default="feel", key="o") diff --git a/tests/test_annotations.py b/tests/test_annotations.py index e59eeeb93..0fec5c3e1 100644 --- a/tests/test_annotations.py +++ b/tests/test_annotations.py @@ -1086,8 +1086,10 @@ def test_with_converted(): @tanjun.as_message_command("nyaa") async def command( ctx: tanjun.abc.Context, - boo: typing.Annotated[annotations.Str, annotations.Converted(mock_callback_1, mock_callback_2), "description"], - bam: typing.Annotated[typing.Optional[annotations.Int], annotations.Converted(mock_callback_3), "nom"] = None, + boo: typing.Annotated[str, annotations.Converted(mock_callback_1, mock_callback_2), "description"], + bam: typing.Annotated[ + typing.Optional[int], annotations.Converted(mock_callback_3), "nom" # noqa: NU002 + ] = None, ) -> None: ... @@ -1096,7 +1098,7 @@ async def command( type=hikari.OptionType.STRING, name="boo", channel_types=None, description="description", is_required=True ), hikari.CommandOption( - type=hikari.OptionType.INTEGER, name="bam", channel_types=None, description="nom", is_required=False + type=hikari.OptionType.STRING, name="bam", channel_types=None, description="nom", is_required=False ), ] @@ -1117,7 +1119,7 @@ async def command( assert tracked_option.is_only_member is False assert tracked_option.key == "bam" assert tracked_option.name == "bam" - assert tracked_option.type is hikari.OptionType.INTEGER + assert tracked_option.type is hikari.OptionType.STRING assert isinstance(command.wrapped_command, tanjun.MessageCommand) assert isinstance(command.wrapped_command.parser, tanjun.ShlexParser) diff --git a/tests/test_annotations_future_annotations.py b/tests/test_annotations_future_annotations.py index 649527876..a4057eb46 100644 --- a/tests/test_annotations_future_annotations.py +++ b/tests/test_annotations_future_annotations.py @@ -968,8 +968,10 @@ def test_with_converted(): @tanjun.as_message_command("nyaa") async def command( ctx: tanjun.abc.Context, - boo: typing.Annotated[annotations.Str, annotations.Converted(mock_callback_1, mock_callback_2), "description"], - bam: typing.Annotated[typing.Optional[annotations.Int], annotations.Converted(mock_callback_3), "nom"] = None, + boo: typing.Annotated[str, annotations.Converted(mock_callback_1, mock_callback_2), "description"], + bam: typing.Annotated[ + typing.Optional[int], annotations.Converted(mock_callback_3), "nom" # noqa: NU002 + ] = None, ) -> None: ... @@ -978,7 +980,7 @@ async def command( type=hikari.OptionType.STRING, name="boo", channel_types=None, description="description", is_required=True ), hikari.CommandOption( - type=hikari.OptionType.INTEGER, name="bam", channel_types=None, description="nom", is_required=False + type=hikari.OptionType.STRING, name="bam", channel_types=None, description="nom", is_required=False ), ] @@ -999,7 +1001,7 @@ async def command( assert tracked_option.is_only_member is False assert tracked_option.key == "bam" assert tracked_option.name == "bam" - assert tracked_option.type is hikari.OptionType.INTEGER + assert tracked_option.type is hikari.OptionType.STRING assert isinstance(command.wrapped_command, tanjun.MessageCommand) assert isinstance(command.wrapped_command.parser, tanjun.ShlexParser) From 215e20d34d0f7eb019add8cd7c9df8ff07da06f2 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Wed, 25 Jan 2023 08:04:42 +0000 Subject: [PATCH 25/45] Revert lil logic change to to_slash_option --- tanjun/annotations.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tanjun/annotations.py b/tanjun/annotations.py index b94e36966..1dedf4c61 100644 --- a/tanjun/annotations.py +++ b/tanjun/annotations.py @@ -1257,14 +1257,15 @@ def _slash_default(self) -> typing.Any: return slash.UNDEFINED_DEFAULT if self.default is parsing.UNDEFINED else self.default def to_slash_option(self, command: slash.SlashCommand[typing.Any], /) -> None: - if self.str_converters and not self.option_type: - self.option_type = str + option_type = self.option_type + if not option_type and self.str_converters: + option_type = str - if self.option_type: + if option_type: if not self.description: raise ValueError(f"Missing description for argument {self.parameter.name!r}") - self.SLASH_OPTION_ADDER[self.option_type](self, command, self.description) + self.SLASH_OPTION_ADDER[option_type](self, command, self.description) SLASH_OPTION_ADDER: dict[ typing.Any, collections.Callable[[Self, slash.SlashCommand[typing.Any], str], slash.SlashCommand[typing.Any]] From a9c3737e6e445e1ca893f7f299762e200cdc2e40 Mon Sep 17 00:00:00 2001 From: "always-on-duty[bot]" <120557446+always-on-duty[bot]@users.noreply.github.com> Date: Wed, 25 Jan 2023 10:03:58 +0000 Subject: [PATCH 26/45] Freeze PR dependency changes --- dev-requirements/flake8.txt | 321 ++++++++++++++++++++++++++++- dev-requirements/tests.txt | 4 +- dev-requirements/type-checking.txt | 10 +- 3 files changed, 327 insertions(+), 8 deletions(-) diff --git a/dev-requirements/flake8.txt b/dev-requirements/flake8.txt index 4bbd7e7c2..1d8d813ca 100644 --- a/dev-requirements/flake8.txt +++ b/dev-requirements/flake8.txt @@ -1 +1,320 @@ --r ../piped/python/base-requirements/library-flake8.txt +# +# This file is autogenerated by pip-compile-cross-platform +# To update, run: +# +# pip-compile-cross-platform dev-requirements/flake8.in --output-file dev-requirements/flake8.txt --min-python-version 3.10.0,<3.12 +# +astor==0.8.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5 \ + --hash=sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e +attrs==22.2.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836 \ + --hash=sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99 +bandit==1.7.4 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:2d63a8c573417bae338962d4b9b06fbc6080f74ecd955a092849e1e65c717bd2 \ + --hash=sha256:412d3f259dab4077d0e7f0c11f50f650cc7d10db905d98f6520a95a18049658a +black==22.12.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320 \ + --hash=sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351 \ + --hash=sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350 \ + --hash=sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f \ + --hash=sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf \ + --hash=sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148 \ + --hash=sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4 \ + --hash=sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d \ + --hash=sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc \ + --hash=sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d \ + --hash=sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2 \ + --hash=sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f +click==8.1.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \ + --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48 +colorama==0.4.6 ; python_full_version >= "3.10.0" and python_version < "3.12" and platform_system == "Windows" \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 +eradicate==2.1.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:8bfaca181db9227dc88bdbce4d051a9627604c2243e7d85324f6d6ce0fd08bb2 \ + --hash=sha256:aac7384ab25b1bf21c4c012de9b4bf8398945a14c98c911545b2ea50ab558014 +flake8-async==22.11.14 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:317cf0f882a2f4a09c2250c451acff8358d7faec8a0aa54521b6e69336fe9d0b \ + --hash=sha256:b4db2d55883653b47d4bfd946fdf506e8958bb4ca35974790b8c3e620fc1abff +flake8-bandit==4.1.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:068e09287189cbfd7f986e92605adea2067630b75380c6b5733dab7d87f9a84e \ + --hash=sha256:4c8a53eb48f23d4ef1e59293657181a3c989d0077c9952717e98a0eace43e06d +flake8-black==0.3.6 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:0dfbca3274777792a5bcb2af887a4cad72c72d0e86c94e08e3a3de151bb41c34 \ + --hash=sha256:fe8ea2eca98d8a504f22040d9117347f6b367458366952862ac3586e7d4eeaca +flake8-broken-line==0.6.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:a02268f11a18837c83c59013a36cc00fee9e17a042745cc0c9895f1c9f6acc16 \ + --hash=sha256:c0ab336ff7de228dbffbe56d67b3615bb21fb15f3ed0604fa7bdf9feb72d7d88 +flake8-builtins==2.1.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:12ff1ee96dd4e1f3141141ee6c45a5c7d3b3c440d0949e9b8d345c42b39c51d4 \ + --hash=sha256:469e8f03d6d0edf4b1e62b6d5a97dce4598592c8a13ec8f0952e7a185eba50a1 +flake8-coding==1.3.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:79704112c44d09d4ab6c8965e76a20c3f7073d52146db60303bce777d9612260 \ + --hash=sha256:b8f4d5157a8f74670e6cfea732c3d9f4291a4e994c8701d2c55f787c6e6cb741 +flake8-comments==0.1.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:42250cb4a51dc59e6db25f1291cfb16b78ea233f72dac32a5bc7b09c691235ea \ + --hash=sha256:780b4fc2820ed4ff8a0a98f3fc993f776ede1aecbe0c6cec64d93814b21c9234 +flake8-comprehensions==3.10.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:412052ac4a947f36b891143430fef4859705af11b2572fbb689f90d372cf26ab \ + --hash=sha256:d763de3c74bc18a79c039a7ec732e0a1985b0c79309ceb51e56401ad0a2cd44e +flake8-deprecated==2.0.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:8c61d2cb8d487118b6c20392b25f08ba1ec49c759e4ea562c7a60172912bc7ee \ + --hash=sha256:c7659a530aa76c3ad8be0c1e8331ed56d882ef8bfba074501a545bb3352b0c23 +flake8-docstrings==1.6.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:99cac583d6c7e32dd28bbfbef120a7c0d1b6dde4adb5a9fd441c4227a6534bde \ + --hash=sha256:9fe7c6a306064af8e62a055c2f61e9eb1da55f84bb39caef2b84ce53708ac34b +flake8-eradicate==1.4.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:3088cfd6717d1c9c6c3ac45ef2e5f5b6c7267f7504d5a74b781500e95cb9c7e1 \ + --hash=sha256:e3bbd0871be358e908053c1ab728903c114f062ba596b4d40c852fd18f473d56 +flake8-executable==2.1.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:619fe023e00c3d8e5113521d7200e1ebb04587c12d157f9a2fb167feb8cae66b \ + --hash=sha256:f0a66c97c3b99ce63bc1f01ce602d6bd048e4fc5dc0d7a13be2bfa3deb023a34 +flake8-fixme==1.1.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:226a6f2ef916730899f29ac140bed5d4a17e5aba79f00a0e3ae1eff1997cb1ac \ + --hash=sha256:50cade07d27a4c30d4f12351478df87339e67640c83041b664724bda6d16f33a +flake8-functions==0.0.7 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:40584b05d57e5ab185545bcfa08aa0edca52b04646d0df266e2b1667d6437184 \ + --hash=sha256:f2f75545c2b0df9eeba0ad316e2ac38c101676970b4441300fc07af3226a44f6 +flake8-future-annotations==1.1.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:555f16f51ae24ab4d0683b1ce8d0f59d36259c3a7e776bd5642f58c78ce7d3ab \ + --hash=sha256:df416bd2b9e1eda7ea639a5fd2a083dabb942ffe49d197f836df380d0dcf6608 +flake8-html==0.4.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:8b870299620cc4a06f73644a1b4d457799abeca1cc914c62ae71ec5bf65c79a5 \ + --hash=sha256:8f126748b1b0edd6cd39e87c6192df56e2f8655b0aa2bb00ffeac8cf27be4325 +flake8-if-statements==1.0.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:4de1a05c6840ed7ca419a0de6038a343317fe327401a91c887cd8661730662c9 \ + --hash=sha256:7a247fab5f409e3f2c18c3d92e1f7a9a9d1a8e0cd3aa1d446a17097e16ecddab +flake8-implicit-str-concat==0.3.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:a89ebc50567790fb7b83e032ed4014ae0db70e35d89e269c3323967135023600 \ + --hash=sha256:c0e6ae227e46238e4c87844091f8072892caeccd3bb266576a7d449eadbf53a0 +flake8-isort==5.0.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:0951398c343c67f4933407adbbfb495d4df7c038650c5d05753a006efcfeb390 \ + --hash=sha256:8c4ab431d87780d0c8336e9614e50ef11201bc848ef64ca017532dec39d4bf49 +flake8-mutable==1.2.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:38fd9dadcbcda6550a916197bc40ed76908119dabb37fbcca30873666c31d2d5 \ + --hash=sha256:ee9b77111b867d845177bbc289d87d541445ffcc6029a0c5c65865b42b18c6a6 +flake8-new-union-types==0.4.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:0a9dd421099f2525f8be525977ff6632b13b68719a7b0807cf49028d4287b0aa \ + --hash=sha256:92737a2f598772d5aedd05b5450c5dd200e0f1acd42b3c1f95dbbe3211af2009 +flake8-no-pep420==2.3.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:1b965a18508ac7842de288740aa43627d3a5bb2be64f7d5d70d55cb691c3de84 \ + --hash=sha256:ccba3efa05c50b1c2712d78807cca81e563ab571d6b3bcb90228e87388704cf5 +flake8-pep3101==2.0.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:1d818e1f53c6d26e875714f2f041ec15fbb23c17e2268dbbb024e9c3383541cd \ + --hash=sha256:ae2ee1758734a473ca971b4bf9ff09c961b6099916db91fdb6b9718328dfcacb +flake8-pep585==0.1.6 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:67feae956ccf7ef20c5cfe57bb63f5342e4f7898fd1cb1d3a8a8a52e26393fd2 \ + --hash=sha256:8b7bccfa760c40baedb28dc48b1b514907867b3551a7aec87552d115355a6def +flake8-plugin-utils==1.3.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:1fe43e3e9acf3a7c0f6b88f5338cad37044d2f156c43cb6b080b5f9da8a76f06 \ + --hash=sha256:20fa2a8ca2decac50116edb42e6af0a1253ef639ad79941249b840531889c65a +flake8-print==5.0.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:76915a2a389cc1c0879636c219eb909c38501d3a43cc8dae542081c9ba48bdf9 \ + --hash=sha256:84a1a6ea10d7056b804221ac5e62b1cee1aefc897ce16f2e5c42d3046068f5d8 +flake8-printf-formatting==1.1.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:0f9e1308ac290356e4b271d4f26adfc3f9165680a7b6c221503b0f3e155a2784 \ + --hash=sha256:d908ffabdf08581043a50572744fd60563d82386630b0335445894120089d2df +flake8-pytest-style==1.6.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:5fedb371a950e9fe0e0e6bfc854be7d99151271208f34cd2cc517681ece27780 \ + --hash=sha256:c1175713e9e11b78cd1a035ed0bca0d1e41d09c4af329a952750b61d4194ddac +flake8-pytest==1.4 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:19f543b2d1cc89d61b76f19d0a9e58e9a110a035175f701b3425c363a7732c56 \ + --hash=sha256:97328f258ffad9fe18babb3b0714a16b121505ad3ac87d4e33020874555d0784 +flake8-raise==0.0.5 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:0a9890e16b851402d9b0d4fafe6c34890eab73835a2c2079c3850a25be575623 \ + --hash=sha256:df26e5c542a58c8f8786d978e18ad7e54126a0ef5c6241c35dafaca7e2bbb808 +flake8-simplify==0.19.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:1057320e9312d75849541fee822900d27bcad05b2405edc84713affee635629e \ + --hash=sha256:2fb083bf5142a98d9c9554755cf2f56f8926eb4a33eae30c0809041b1546879e +flake8-typing-imports==1.14.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:0612976976f1e90bd4588a03d9be5a9c408411e5dc46b29cc6b052e5de42277c \ + --hash=sha256:3008214280cd96092e7ebbad87dc62bb0e03020c12e8c342f6565cbddfdd67c7 +flake8-use-fstring==1.4 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:6550bf722585eb97dffa8343b0f1c372101f5c4ab5b07ebf0edd1c79880cdd39 +flake8-use-pathlib==0.3.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:0ef19f255a51601bcf04ff54f25ef8a466dff68210cd95b4f1db36a78ace5223 \ + --hash=sha256:c7b6d71575b575f7d70ebf3f1d7f2dd6685e401d3280208f1db9dbb6bfa32608 +flake8-variables-names==0.0.5 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:30133e14ee2300e13a60393a00f74d98110c76070ac67d1ab91606f02824a7e1 \ + --hash=sha256:e3277031696bbe10b5132b49938cde1d70fcae9561533b7bd7ab8e69cb27addb +flake8==5.0.4 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db \ + --hash=sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248 +gitdb==4.0.10 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a \ + --hash=sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7 +gitpython==3.1.30 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:769c2d83e13f5d938b7688479da374c4e3d49f71549aaf462b646db9602ea6f8 \ + --hash=sha256:cd455b0000615c60e286208ba540271af9fe531fa6a87cc590a7298785ab2882 +isort==5.11.4 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6 \ + --hash=sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b +jinja2==3.1.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ + --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 +markdown-it-py==2.1.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27 \ + --hash=sha256:cf7e59fed14b5ae17c0006eff14a2d9a00ed5f3a846148153899a0224e2c07da +markupsafe==2.1.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed \ + --hash=sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc \ + --hash=sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2 \ + --hash=sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460 \ + --hash=sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7 \ + --hash=sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0 \ + --hash=sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1 \ + --hash=sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa \ + --hash=sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03 \ + --hash=sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323 \ + --hash=sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65 \ + --hash=sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013 \ + --hash=sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036 \ + --hash=sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f \ + --hash=sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4 \ + --hash=sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419 \ + --hash=sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2 \ + --hash=sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619 \ + --hash=sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a \ + --hash=sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a \ + --hash=sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd \ + --hash=sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7 \ + --hash=sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666 \ + --hash=sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65 \ + --hash=sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859 \ + --hash=sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625 \ + --hash=sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff \ + --hash=sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156 \ + --hash=sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd \ + --hash=sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba \ + --hash=sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f \ + --hash=sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1 \ + --hash=sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094 \ + --hash=sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a \ + --hash=sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513 \ + --hash=sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed \ + --hash=sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d \ + --hash=sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3 \ + --hash=sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147 \ + --hash=sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c \ + --hash=sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603 \ + --hash=sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601 \ + --hash=sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a \ + --hash=sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1 \ + --hash=sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d \ + --hash=sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3 \ + --hash=sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54 \ + --hash=sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2 \ + --hash=sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6 \ + --hash=sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58 +mccabe==0.7.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \ + --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e +mdurl==0.1.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ + --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba +more-itertools==8.14.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:1bc4f91ee5b1b31ac7ceacc17c09befe6a40a503907baf9c839c229b5095cfd2 \ + --hash=sha256:c09443cd3d5438b8dafccd867a6bc1cb0894389e90cb53d227456b0b0bccb750 +mr-proper==0.0.7 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:03b517b19e617537f711ce418b125e5f2efd82ec881539cdee83195c78c14a02 \ + --hash=sha256:74a1b60240c46f10ba518707ef72811a01e5c270da0a78b5dd2dd923d99fdb14 +mypy-extensions==0.4.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d \ + --hash=sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8 +pathspec==0.11.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:3a66eb970cbac598f9e5ccb5b2cf58930cd8e3ed86d393d541eaf2d8b1705229 \ + --hash=sha256:64d338d4e0914e91c1792321e6907b5a593f1ab1851de7fc269557a21b30ebbc +pbr==5.11.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b \ + --hash=sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3 +pep8-naming==0.13.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:1705f046dfcd851378aac3be1cd1551c7c1e5ff363bacad707d43007877fa971 \ + --hash=sha256:1a86b8c71a03337c97181917e2b472f0f5e4ccb06844a0d6f0a33522549e7a80 +platformdirs==2.6.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490 \ + --hash=sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2 +pycodestyle==2.9.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785 \ + --hash=sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b +pydocstyle==6.3.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019 \ + --hash=sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1 +pyflakes==2.5.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2 \ + --hash=sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3 +pygments==2.14.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297 \ + --hash=sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717 +pyproject-flake8==5.0.4.post1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:457e52dde1b7a1f84b5230c70d61afa58ced64a44b81a609f19e972319fa68ed \ + --hash=sha256:c2dfdf1064f47efbb2e4faf1a32b0b6a6ea67dc4d1debb98d862b0cdee377941 +pyyaml==6.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ + --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ + --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ + --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ + --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ + --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ + --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ + --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ + --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ + --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ + --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ + --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ + --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ + --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ + --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ + --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ + --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ + --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ + --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ + --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ + --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ + --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ + --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ + --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ + --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ + --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ + --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ + --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ + --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ + --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ + --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ + --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ + --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ + --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 +rich==13.2.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:7c963f0d03819221e9ac561e1bc866e3f95a02248c1234daa48954e6d381c003 \ + --hash=sha256:f1a00cdd3eebf999a15d85ec498bfe0b1a77efe9b34f645768a54132ef444ac5 +setuptools==66.1.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:6f590d76b713d5de4e49fe4fbca24474469f53c83632d5d0fd056f7ff7e8112b \ + --hash=sha256:ac4008d396bc9cd983ea483cb7139c0240a07bbc74ffb6232fceffedc6cf03a8 +smmap==5.0.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94 \ + --hash=sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936 +snowballstemmer==2.2.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1 \ + --hash=sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a +stdlib-list==0.8.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:2ae0712a55b68f3fbbc9e58d6fa1b646a062188f49745b495f94d3310a9fdd3e \ + --hash=sha256:a1e503719720d71e2ed70ed809b385c60cd3fb555ba7ec046b96360d30b16d9f +stevedore==4.1.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:7f8aeb6e3f90f96832c301bff21a7eb5eefbe894c88c506483d355565d88cc1a \ + --hash=sha256:aa6436565c069b2946fe4ebff07f5041e0c8bf18c7376dd29edf80cf7d524e4e +toml==0.10.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ + --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f +tomli==2.0.1 ; python_full_version >= "3.10.0" and python_full_version < "3.11.0a7" \ + --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ + --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f +tryceratops==1.1.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:58e56b33eeb7a9cfd643957069bb1872ebe26c1eeac7abb1877c9535b7e473db \ + --hash=sha256:f4770960782a2ae87cad7a7fd1206476468d0f41383c9fd7a49c6d537534015e diff --git a/dev-requirements/tests.txt b/dev-requirements/tests.txt index 1cc9a52ef..a434635bf 100644 --- a/dev-requirements/tests.txt +++ b/dev-requirements/tests.txt @@ -113,7 +113,7 @@ colorama==0.4.6 ; python_full_version >= "3.9.0" and python_version < "3.12" and colorlog==6.7.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662 \ --hash=sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5 -coverage[toml]==7.1.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ +coverage[toml]==7.1.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ --hash=sha256:04481245ef966fbd24ae9b9e537ce899ae584d521dfbe78f89cad003c38ca2ab \ --hash=sha256:0c45948f613d5d18c9ec5eaa203ce06a653334cf1bd47c783a12d0dd4fd9c851 \ --hash=sha256:10188fe543560ec4874f974b5305cd1a8bdcfa885ee00ea3a03733464c4ca265 \ @@ -165,7 +165,7 @@ coverage[toml]==7.1.0 ; python_full_version >= "3.9.0" and python_version < "3.1 --hash=sha256:f2cba5c6db29ce991029b5e4ac51eb36774458f0a3b8d3137241b32d1bb91f06 \ --hash=sha256:f5b4198d85a3755d27e64c52f8c95d6333119e49fd001ae5798dac872c95e0f8 \ --hash=sha256:ffeeb38ee4a80a30a6877c5c4c359e5498eec095878f1581453202bfacc8fbc2 -exceptiongroup==1.1.0 ; python_full_version >= "3.9.0" and python_version < "3.11" \ +exceptiongroup==1.1.0 ; python_full_version >= "3.10.0" and python_version < "3.11" \ --hash=sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e \ --hash=sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23 execnet==1.9.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ diff --git a/dev-requirements/type-checking.txt b/dev-requirements/type-checking.txt index 148130a9f..7d7c7c980 100644 --- a/dev-requirements/type-checking.txt +++ b/dev-requirements/type-checking.txt @@ -116,7 +116,7 @@ colorama==0.4.6 ; python_full_version >= "3.9.0" and python_version < "3.12" and colorlog==6.7.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662 \ --hash=sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5 -coverage[toml]==7.1.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ +coverage[toml]==7.1.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ --hash=sha256:04481245ef966fbd24ae9b9e537ce899ae584d521dfbe78f89cad003c38ca2ab \ --hash=sha256:0c45948f613d5d18c9ec5eaa203ce06a653334cf1bd47c783a12d0dd4fd9c851 \ --hash=sha256:10188fe543560ec4874f974b5305cd1a8bdcfa885ee00ea3a03733464c4ca265 \ @@ -168,7 +168,7 @@ coverage[toml]==7.1.0 ; python_full_version >= "3.9.0" and python_version < "3.1 --hash=sha256:f2cba5c6db29ce991029b5e4ac51eb36774458f0a3b8d3137241b32d1bb91f06 \ --hash=sha256:f5b4198d85a3755d27e64c52f8c95d6333119e49fd001ae5798dac872c95e0f8 \ --hash=sha256:ffeeb38ee4a80a30a6877c5c4c359e5498eec095878f1581453202bfacc8fbc2 -distlib==0.3.6 ; python_full_version >= "3.9.0" and python_version < "3.12" \ +distlib==0.3.6 ; python_full_version >= "3.10.0" and python_version < "3.12" \ --hash=sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46 \ --hash=sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e exceptiongroup==1.1.0 ; python_full_version >= "3.9.0" and python_version < "3.11" \ @@ -482,9 +482,9 @@ pydantic==1.10.4 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:f2f7eb6273dd12472d7f218e1fef6f7c7c2f00ac2e1ecde4db8824c457300416 \ --hash=sha256:fdf88ab63c3ee282c76d652fc86518aacb737ff35796023fae56a65ced1a5978 \ --hash=sha256:fdf8d759ef326962b4678d89e275ffc55b7ce59d917d9f72233762061fd04a2d -pyright==1.1.290 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:956d8efc70eb5a54da54c82feef842affd3a81719c8864769cd196e211961e3a \ - --hash=sha256:c1a57ad812f740fc7fb6bb416cd7e3f46f4e88384c723192402a77e2e756b550 +pyright==1.1.291 ; python_full_version >= "3.10.0" and python_version < "3.12" \ + --hash=sha256:2dbd133ee400e81ff319d0701bc47545a7ab1cd7dcfcf46c7de37d9b0fbbb76f \ + --hash=sha256:3946f43f1a99f8e438eee1738ad0649d8bd7ac36dded25849245993ab02671bd pytest-asyncio==0.20.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ --hash=sha256:83cbf01169ce3e8eb71c6c278ccb0574d1a7a3bb8eaaf5e50e0ad342afb33b36 \ --hash=sha256:f129998b209d04fcc65c96fc85c11e5316738358909a8399e93be553d7656442 From bb7b2838e34f0977a17ff147ea0469bbbb7ed659 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Wed, 25 Jan 2023 10:40:55 +0000 Subject: [PATCH 27/45] Remove some unnecessary annotations logic --- tanjun/annotations.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tanjun/annotations.py b/tanjun/annotations.py index 1dedf4c61..5659130de 100644 --- a/tanjun/annotations.py +++ b/tanjun/annotations.py @@ -1257,15 +1257,11 @@ def _slash_default(self) -> typing.Any: return slash.UNDEFINED_DEFAULT if self.default is parsing.UNDEFINED else self.default def to_slash_option(self, command: slash.SlashCommand[typing.Any], /) -> None: - option_type = self.option_type - if not option_type and self.str_converters: - option_type = str - - if option_type: + if self.option_type: if not self.description: raise ValueError(f"Missing description for argument {self.parameter.name!r}") - self.SLASH_OPTION_ADDER[option_type](self, command, self.description) + self.SLASH_OPTION_ADDER[self.option_type](self, command, self.description) SLASH_OPTION_ADDER: dict[ typing.Any, collections.Callable[[Self, slash.SlashCommand[typing.Any], str], slash.SlashCommand[typing.Any]] @@ -1403,7 +1399,7 @@ def parse_annotated_args( arg_config.range_or_slice = arg arg_config.finalise_slice() - if arg_config.option_type or arg_config.str_converters: + if arg_config.option_type: for slash_command in slash_commands: arg_config.to_slash_option(slash_command) From 3bde5bb8453c2bc6c13f3cb925650f55329d572f Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Wed, 25 Jan 2023 10:52:22 +0000 Subject: [PATCH 28/45] Avoid unnecessarily building typevars and importing at runtime --- tanjun/annotations.py | 55 ++++++++++++++++-------------- tanjun/checks.py | 3 +- tanjun/commands/slash.py | 5 ++- tanjun/dependencies/async_cache.py | 5 ++- tanjun/dependencies/limiters.py | 13 ++++--- tanjun/dependencies/locales.py | 7 ++-- tanjun/dependencies/reloaders.py | 3 +- tanjun/hooks.py | 3 +- tanjun/parsing.py | 3 +- tanjun/permissions.py | 3 +- 10 files changed, 54 insertions(+), 46 deletions(-) diff --git a/tanjun/annotations.py b/tanjun/annotations.py index 5659130de..abdb81793 100644 --- a/tanjun/annotations.py +++ b/tanjun/annotations.py @@ -90,24 +90,27 @@ from .commands import slash if typing.TYPE_CHECKING: + import enum + import typing_extensions from typing_extensions import Self + _T = typing.TypeVar("_T") _P = typing_extensions.ParamSpec("_P") __ConverterSig = collections.Callable[ - typing_extensions.Concatenate[str, _P], "collections.Coroutine[typing.Any, typing.Any, _T] | _T", + typing_extensions.Concatenate[str, _P], collections.Coroutine[typing.Any, typing.Any, _T] | _T, ] - _ConverterSig = __ConverterSig[..., "_T"] + _ConverterSig = __ConverterSig[..., _T] + _ChannelTypeIsh = type[hikari.PartialChannel] | int + _ChoiceUnion = int | float | str + _ChoiceT = typing.TypeVar("_ChoiceT", int, float, str) + _CommandUnion = slash.SlashCommand[typing.Any] | message.MessageCommand[typing.Any] + _CommandUnionT = typing.TypeVar("_CommandUnionT", bound=_CommandUnion) + _EnumT = typing.TypeVar("_EnumT", bound=enum.Enum) + _NumberT = typing.TypeVar("_NumberT", float, int) + -_T = typing.TypeVar("_T") -_ChannelTypeIsh = typing.Union[type[hikari.PartialChannel], int] -_ChoiceT = typing.TypeVar("_ChoiceT", int, float, str) -_ChoiceUnion = typing.Union[int, float, str] -_CommandUnion = typing.Union[slash.SlashCommand[typing.Any], message.MessageCommand[typing.Any]] -_CommandUnionT = typing.TypeVar("_CommandUnionT", bound=_CommandUnion) -_EnumT = typing.TypeVar("_EnumT", bound=enum.Enum) -_MentionableUnion = typing.Union[hikari.User, hikari.Role] -_NumberT = typing.TypeVar("_NumberT", float, int) +_MentionableUnion = hikari.User | hikari.Role class _ConfigIdentifier(abc.ABC): @@ -239,7 +242,7 @@ def __getitem__(cls, enum_: type[_EnumT], /) -> type[_EnumT]: # TODO: do we want to wrap the convert callback to give better failed parse messages? return typing.cast( - type[_EnumT], typing.Annotated[enum_, choices, converter, Converted(enum_), _TypeOverride(type_)] + "type[_EnumT]", typing.Annotated[enum_, choices, converter, Converted(enum_), _TypeOverride(type_)] ) @@ -376,10 +379,10 @@ class _DefaultMeta(abc.ABCMeta): def __getitem__(cls, value: typing.Union[type[_T], tuple[type[_T], _T]], /) -> type[_T]: if isinstance(value, tuple): type_ = value[0] - return typing.cast(type[_T], typing.Annotated[type_, Default(value[1])]) + return typing.cast("type[_T]", typing.Annotated[type_, Default(value[1])]) - type_ = typing.cast(type[_T], value) - return typing.cast(type[_T], typing.Annotated[type_, Default()]) + type_ = typing.cast("type[_T]", value) + return typing.cast("type[_T]", typing.Annotated[type_, Default()]) class Default(_ConfigIdentifier, metaclass=_DefaultMeta): @@ -532,7 +535,7 @@ def set_config(self, config: _ArgConfig, /) -> None: class _PositionalMeta(abc.ABCMeta): def __getitem__(cls, type_: type[_T], /) -> type[_T]: - return typing.cast(type[_T], typing.Annotated[type_, Positional()]) + return typing.cast("type[_T]", typing.Annotated[type_, Positional()]) class Positional(_ConfigIdentifier, metaclass=_PositionalMeta): @@ -565,7 +568,7 @@ def set_config(self, config: _ArgConfig, /) -> None: class _GreedyMeta(abc.ABCMeta): def __getitem__(cls, type_: type[_T], /) -> type[_T]: - return typing.cast(type[_T], typing.Annotated[type_, Greedy()]) + return typing.cast("type[_T]", typing.Annotated[type_, Greedy()]) class Greedy(_ConfigIdentifier, metaclass=_GreedyMeta): @@ -603,7 +606,7 @@ def __getitem__(cls, value: typing.Union[int, tuple[int, int]], /) -> type[str]: else: obj = Length(*value) - return typing.cast(type[str], typing.Annotated[Str, obj]) + return typing.cast("type[str]", typing.Annotated[Str, obj]) class Length(_ConfigIdentifier, metaclass=_LengthMeta): @@ -697,9 +700,9 @@ def set_config(self, config: _ArgConfig, /) -> None: class _MaxMeta(abc.ABCMeta): def __getitem__(cls, value: _NumberT, /) -> type[_NumberT]: if isinstance(value, int): - return typing.cast(type[_NumberT], typing.Annotated[Int, Max(value)]) + return typing.cast("type[_NumberT]", typing.Annotated[Int, Max(value)]) - return typing.cast(type[_NumberT], typing.Annotated[Float, Max(value)]) + return typing.cast("type[_NumberT]", typing.Annotated[Float, Max(value)]) class Max(_ConfigIdentifier, metaclass=_MaxMeta): @@ -746,9 +749,9 @@ def set_config(self, config: _ArgConfig, /) -> None: class _MinMeta(abc.ABCMeta): def __getitem__(cls, value: _NumberT, /) -> type[_NumberT]: if isinstance(value, int): - return typing.cast(type[_NumberT], typing.Annotated[Int, Min(value)]) + return typing.cast("type[_NumberT]", typing.Annotated[Int, Min(value)]) - return typing.cast(type[_NumberT], typing.Annotated[Float, Min(value)]) + return typing.cast("type[_NumberT]", typing.Annotated[Float, Min(value)]) class Min(_ConfigIdentifier, metaclass=_MinMeta): @@ -866,9 +869,9 @@ def __getitem__(cls, range_: tuple[_NumberT, _NumberT], /) -> type[_NumberT]: # This better matches how type checking (well pyright at least) will # prefer to go to float if either value is float. if isinstance(range_[0], float) or isinstance(range_[1], float): - return typing.cast(type[_NumberT], typing.Annotated[Float, Ranged(range_[0], range_[1])]) + return typing.cast("type[_NumberT]", typing.Annotated[Float, Ranged(range_[0], range_[1])]) - return typing.cast(type[_NumberT], typing.Annotated[Int, Ranged(range_[0], range_[1])]) + return typing.cast("type[_NumberT]", typing.Annotated[Int, Ranged(range_[0], range_[1])]) class Ranged(_ConfigIdentifier, metaclass=_RangedMeta): @@ -1045,7 +1048,7 @@ def __getitem__( if not isinstance(value, collections.Collection): value = (value,) - return typing.cast(type[hikari.PartialChannel], typing.Annotated[Channel, TheseChannels(*value)]) + return typing.cast("type[hikari.PartialChannel]", typing.Annotated[Channel, TheseChannels(*value)]) class TheseChannels(_ConfigIdentifier, metaclass=_TheseChannelsMeta): @@ -1095,7 +1098,7 @@ def _ensure_values( f"{name.capitalize()} of type {type(value).__name__} is not valid for a {type_.__name__} argument" ) - return typing.cast(collections.Mapping[str, _T], mapping) + return typing.cast("collections.Mapping[str, _T]", mapping) _OPTION_TYPE_TO_CONVERTERS: dict[typing.Any, tuple[collections.Callable[..., typing.Any], ...]] = { diff --git a/tanjun/checks.py b/tanjun/checks.py index 99f18ecbb..ef50939d9 100644 --- a/tanjun/checks.py +++ b/tanjun/checks.py @@ -55,7 +55,6 @@ ] import typing -from collections import abc as collections import alluka import hikari @@ -69,6 +68,8 @@ from ._internal import localisation if typing.TYPE_CHECKING: + from collections import abc as collections + _ContextT_contra = typing.TypeVar("_ContextT_contra", bound=tanjun.Context, contravariant=True) class _AnyCallback(typing.Protocol[_ContextT_contra]): diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index 210234ff0..192c753a8 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -90,9 +90,6 @@ _SlashCallbackSigT = typing.TypeVar("_SlashCallbackSigT", bound=tanjun.SlashCallbackSig) -_EMPTY_DICT: typing.Final[dict[typing.Any, typing.Any]] = {} -_EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() - _ConvertT = typing.TypeVar("_ConvertT", int, float, str) _P = typing_extensions.ParamSpec("_P") @@ -102,6 +99,8 @@ ConverterSig = _ConverterSig[_ConvertT, ...] """Type hint of a slash command option converter.""" +_EMPTY_DICT: typing.Final[dict[typing.Any, typing.Any]] = {} +_EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() _SCOMMAND_NAME_REG: typing.Final[str] = r"^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$" _VALID_NAME_UNICODE_CATEGORIES = frozenset( diff --git a/tanjun/dependencies/async_cache.py b/tanjun/dependencies/async_cache.py index e4d6f9ccf..03bf4630c 100644 --- a/tanjun/dependencies/async_cache.py +++ b/tanjun/dependencies/async_cache.py @@ -80,7 +80,10 @@ from .. import errors -_DefaultT = typing.TypeVar("_DefaultT") +if typing.TYPE_CHECKING: + _DefaultT = typing.TypeVar("_DefaultT") + + _KeyT = typing.TypeVar("_KeyT") _ValueT = typing.TypeVar("_ValueT") diff --git a/tanjun/dependencies/limiters.py b/tanjun/dependencies/limiters.py index 26ecdfbf3..31060a76e 100644 --- a/tanjun/dependencies/limiters.py +++ b/tanjun/dependencies/limiters.py @@ -50,7 +50,6 @@ import enum import logging import typing -from collections import abc as collections import alluka import hikari @@ -66,10 +65,16 @@ from . import owners if typing.TYPE_CHECKING: + from collections import abc as collections + from typing_extensions import Self _CommandT = typing.TypeVar("_CommandT", bound=tanjun.ExecutableCommand[typing.Any]) _OtherCommandT = typing.TypeVar("_OtherCommandT", bound=tanjun.ExecutableCommand[typing.Any]) + _InnerResourceSig = collections.Callable[[], "_InnerResourceT"] + + +_InnerResourceT = typing.TypeVar("_InnerResourceT", bound="_InnerResourceProto") _LOGGER: typing.Final[logging.Logger] = logging.getLogger("hikari.tanjun") @@ -310,9 +315,6 @@ def has_expired(self) -> bool: raise NotImplementedError -_InnerResourceT = typing.TypeVar("_InnerResourceT", bound=_InnerResourceProto) - - class _BaseResource(abc.ABC, typing.Generic[_InnerResourceT]): __slots__ = ("make_resource",) @@ -336,9 +338,6 @@ async def try_into_inner(self, ctx: tanjun.Context, /) -> typing.Optional[_Inner raise NotImplementedError -_InnerResourceSig = collections.Callable[[], _InnerResourceT] - - class _FlatResource(_BaseResource[_InnerResourceT]): __slots__ = ("mapping", "resource") diff --git a/tanjun/dependencies/locales.py b/tanjun/dependencies/locales.py index 47447fa93..4289a373e 100644 --- a/tanjun/dependencies/locales.py +++ b/tanjun/dependencies/locales.py @@ -35,13 +35,14 @@ import abc import typing -from collections import abc as collections - -from .. import abc as tanjun if typing.TYPE_CHECKING: + from collections import abc as collections + from typing_extensions import Self + from .. import abc as tanjun + class AbstractLocaliser(abc.ABC): """Abstract class of a string localiser.""" diff --git a/tanjun/dependencies/reloaders.py b/tanjun/dependencies/reloaders.py index b58fed684..2ef34d229 100644 --- a/tanjun/dependencies/reloaders.py +++ b/tanjun/dependencies/reloaders.py @@ -41,7 +41,6 @@ import logging import pathlib import typing -from collections import abc as collections import alluka import hikari @@ -51,6 +50,8 @@ from .. import errors if typing.TYPE_CHECKING: + from collections import abc as collections + from typing_extensions import Self _BuilderDict = dict[tuple[hikari.CommandType, str], hikari.api.CommandBuilder] diff --git a/tanjun/hooks.py b/tanjun/hooks.py index 4ee4b9727..9b2a8c706 100644 --- a/tanjun/hooks.py +++ b/tanjun/hooks.py @@ -36,12 +36,13 @@ import asyncio import copy import typing -from collections import abc as collections from . import abc as tanjun from . import errors if typing.TYPE_CHECKING: + from collections import abc as collections + from typing_extensions import Self _AnyCommandT = typing.TypeVar("_AnyCommandT", bound=tanjun.ExecutableCommand[typing.Any]) diff --git a/tanjun/parsing.py b/tanjun/parsing.py index 6c7eec642..a8ad8a187 100644 --- a/tanjun/parsing.py +++ b/tanjun/parsing.py @@ -80,6 +80,7 @@ def __len__(self) -> int: raise NotImplementedError _CmpProtoT = typing.TypeVar("_CmpProtoT", bound=_CmpProto[typing.Any]) + _MaybeIterable: typing.TypeAlias = "collections.Iterable[_T] | _T" _SizedCmpProtoT = typing.TypeVar("_SizedCmpProtoT", bound=_SizedCmpProto[typing.Any]) @@ -96,8 +97,6 @@ def __len__(self) -> int: [str][], argument and returns the resultant value. """ -_MaybeIterable = typing.Union[collections.Iterable[_T], _T] - class UndefinedT: """Singleton used to indicate an undefined value within parsing logic.""" diff --git a/tanjun/permissions.py b/tanjun/permissions.py index cd24c7b4b..63c73c4a5 100644 --- a/tanjun/permissions.py +++ b/tanjun/permissions.py @@ -41,7 +41,6 @@ ] import typing -from collections import abc as collections import hikari @@ -49,6 +48,8 @@ from .dependencies import async_cache if typing.TYPE_CHECKING: + from collections import abc as collections + from . import abc as tanjun From 00dc1ae37e0c5cd0966983befb9c922d0472f34a Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Wed, 25 Jan 2023 12:45:59 +0000 Subject: [PATCH 29/45] Some doc and type-checking fixes --- tanjun/abc.py | 10 +- tanjun/checks.py | 106 ++++++++++++++++++- tanjun/clients.py | 1 + tanjun/commands/menu.py | 2 +- tanjun/commands/message.py | 4 +- tanjun/commands/slash.py | 2 +- tests/test_annotations_future_annotations.py | 2 +- tests/test_clients.py | 2 +- tests/test_clients_future_annotations.py | 2 +- tests/test_components.py | 2 +- tests/test_components_future_annotations.py | 2 +- 11 files changed, 119 insertions(+), 16 deletions(-) diff --git a/tanjun/abc.py b/tanjun/abc.py index 12ad31e8e..9123276b1 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -2244,7 +2244,7 @@ async def on_error(ctx: tanjun.abc.Context, error: Exception) -> bool: Parameters ---------- - callback : ErrorHookSig + callback : tanjun.abc.ErrorHookSig The callback to add to this hook. This callback should take two positional arguments (of type @@ -2320,7 +2320,7 @@ async def on_parser_error(ctx: tanjun.abc.Context, error: tanjun.ParserError) -> Parameters ---------- - callback : HookSig + callback : tanjun.abc.ParserHookSig The parser error callback to add to this hook. This callback should take two positional arguments (of type @@ -2388,7 +2388,7 @@ async def post_execution(ctx: tanjun.abc.Context) -> None: Parameters ---------- - callback : HookSig + callback : tanjun.abc.HookSig The post-execution callback to add to this hook. This callback should take one positional argument (of type @@ -2456,7 +2456,7 @@ async def pre_execution(ctx: tanjun.abc.Context) -> None: Parameters ---------- - callback : HookSig + callback : tanjun.abc.HookSig The pre-execution callback to add to this hook. This callback should take one positional argument (of type @@ -2524,7 +2524,7 @@ async def on_success(ctx: tanjun.abc.Context) -> None: Parameters ---------- - callback : HookSig + callback : tanjun.abc.HookSig The success callback to add to this hook. This callback should take one positional argument (of type diff --git a/tanjun/checks.py b/tanjun/checks.py index ef50939d9..d591964a2 100644 --- a/tanjun/checks.py +++ b/tanjun/checks.py @@ -1076,9 +1076,51 @@ def all_checks( return _AllChecks[_ContextT]([check, *checks]) +@typing.overload def with_all_checks( check: tanjun.AnyCheckSig, /, *checks: tanjun.AnyCheckSig, follow_wrapped: bool = False -) -> collections.Callable[[_CommandT], _CommandT]: # TODO: specialise with overloading +) -> collections.Callable[[_CommandT], _CommandT]: + ... + + +@typing.overload +def with_all_checks( + check: tanjun.CheckSig[tanjun.MenuContext], + /, + *checks: tanjun.CheckSig[tanjun.MenuContext], + follow_wrapped: bool = False, +) -> collections.Callable[[_MenuCommandT], _MenuCommandT]: + ... + + +@typing.overload +def with_all_checks( + check: tanjun.CheckSig[tanjun.MessageContext], + /, + *checks: tanjun.CheckSig[tanjun.MessageContext], + follow_wrapped: bool = False, +) -> collections.Callable[[_MessageCommandT], _MessageCommandT]: + ... + + +@typing.overload +def with_all_checks( + check: tanjun.CheckSig[tanjun.SlashContext], + /, + *checks: tanjun.CheckSig[tanjun.SlashContext], + follow_wrapped: bool = False, +) -> collections.Callable[[_SlashCommandT], _SlashCommandT]: + ... + + +def with_all_checks( + check: tanjun.CheckSig[typing.Any], /, *checks: tanjun.CheckSig[typing.Any], follow_wrapped: bool = False +) -> ( + collections.Callable[[_CommandT], _CommandT] + | collections.Callable[[_MenuCommandT], _MenuCommandT] + | collections.Callable[[_MessageCommandT], _MessageCommandT] + | collections.Callable[[_SlashCommandT], _SlashCommandT] +): """Add a check which will pass if all the provided checks pass through a decorator call. This ensures that the callbacks are run in the order they were supplied in @@ -1179,7 +1221,7 @@ def any_checks( return _AnyChecks[_ContextT]([check, *checks], error, error_message, halt_execution, suppress) -# Specialising this would be too much boiler plate so for now this just isn't getting that feature. +@typing.overload def with_any_checks( check: tanjun.AnyCheckSig, /, @@ -1190,6 +1232,66 @@ def with_any_checks( halt_execution: bool = False, suppress: tuple[type[Exception], ...] = (errors.CommandError, errors.HaltExecution), ) -> collections.Callable[[_CommandT], _CommandT]: + ... + + +@typing.overload +def with_any_checks( + check: tanjun.CheckSig[tanjun.MenuContext], + /, + *checks: tanjun.CheckSig[tanjun.MenuContext], + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None, + follow_wrapped: bool = False, + halt_execution: bool = False, + suppress: tuple[type[Exception], ...] = (errors.CommandError, errors.HaltExecution), +) -> collections.Callable[[_MenuCommandT], _MenuCommandT]: + ... + + +@typing.overload +def with_any_checks( + check: tanjun.CheckSig[tanjun.MessageContext], + /, + *checks: tanjun.CheckSig[tanjun.MessageContext], + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None, + follow_wrapped: bool = False, + halt_execution: bool = False, + suppress: tuple[type[Exception], ...] = (errors.CommandError, errors.HaltExecution), +) -> collections.Callable[[_MessageCommandT], _MessageCommandT]: + ... + + +@typing.overload +def with_any_checks( + check: tanjun.CheckSig[tanjun.SlashContext], + /, + *checks: tanjun.CheckSig[tanjun.SlashContext], + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None, + follow_wrapped: bool = False, + halt_execution: bool = False, + suppress: tuple[type[Exception], ...] = (errors.CommandError, errors.HaltExecution), +) -> collections.Callable[[_SlashCommandT], _SlashCommandT]: + ... + + +def with_any_checks( + check: tanjun.CheckSig[typing.Any], + /, + *checks: tanjun.CheckSig[typing.Any], + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None, + follow_wrapped: bool = False, + halt_execution: bool = False, + suppress: tuple[type[Exception], ...] = (errors.CommandError, errors.HaltExecution), +) -> ( + collections.Callable[[_CommandT], _CommandT] + | collections.Callable[[_MenuCommandT], _MenuCommandT] + | collections.Callable[[_MessageCommandT], _MessageCommandT] + | collections.Callable[[_SlashCommandT], _SlashCommandT] +): """Add a check which'll pass if any of the provided checks pass through a decorator call. This ensures that the callbacks are run in the order they were supplied in diff --git a/tanjun/clients.py b/tanjun/clients.py index 3c4c8858d..2efacb595 100644 --- a/tanjun/clients.py +++ b/tanjun/clients.py @@ -1107,6 +1107,7 @@ def events(self) -> typing.Optional[hikari.api.EventManager]: def listeners( self, ) -> collections.Mapping[type[hikari.Event], collections.Collection[tanjun.ListenerCallbackSig[typing.Any]]]: + # <>. return _internal.CastedView(self._listeners, lambda x: [callback.callback for callback in x.values()]) @property diff --git a/tanjun/commands/menu.py b/tanjun/commands/menu.py index ff826cdf0..04fd22e71 100644 --- a/tanjun/commands/menu.py +++ b/tanjun/commands/menu.py @@ -430,7 +430,7 @@ def __init__( Parameters ---------- - callback : collections.abc.Callable[[tanjun.abc.MenuContext, ...], collections.abc.Coroutine[Any, Any, None]] + callback : tanjun.abc.MenuCallbackSig Callback to execute when the command is invoked. This should be an asynchronous callback which takes one positional diff --git a/tanjun/commands/message.py b/tanjun/commands/message.py index 8a27cd958..502e86a92 100644 --- a/tanjun/commands/message.py +++ b/tanjun/commands/message.py @@ -214,7 +214,7 @@ def __init__( Parameters ---------- - callback : collections.abc.Callable[[tanjun.abc.MessageContext, ...], collections.abc.Coroutine[None]] + callback : tanjun.abc.MessageCallbackSig Callback to execute when the command is invoked. This should be an asynchronous callback which takes one positional @@ -418,7 +418,7 @@ def __init__( Parameters ---------- - callback : collections.abc.Callable[[tanjun.abc.MessageContext, ...], collections.abc.Coroutine[None]] + callback : tanjun.abc.MessageCallbackSig Callback to execute when the command is invoked. This should be an asynchronous callback which takes one positional diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index 192c753a8..9d9ba8377 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -1514,7 +1514,7 @@ def __init__( Parameters ---------- - callback : collections.abc.Callable[[tanjun.abc.SlashContext, ...], collections.abc.Coroutine[Any, Any, None]] + callback : tanjun.abc.SlashCallbackSig Callback to execute when the command is invoked. This should be an asynchronous callback which takes one positional diff --git a/tests/test_annotations_future_annotations.py b/tests/test_annotations_future_annotations.py index a4057eb46..22b73f972 100644 --- a/tests/test_annotations_future_annotations.py +++ b/tests/test_annotations_future_annotations.py @@ -663,7 +663,7 @@ async def callback( with pytest.raises( TypeError, match=f"Choice of type {mismatched_type.__name__} is not valid for a {type_repr.__name__} argument" ): - annotations.with_annotated_args(callback) + annotations.with_annotated_args(callback) # pyright: ignore[reportUnknownArgumentType] def test_with_generic_float_choices(): diff --git a/tests/test_clients.py b/tests/test_clients.py index e95755034..6159fe8e6 100644 --- a/tests/test_clients.py +++ b/tests/test_clients.py @@ -1228,7 +1228,7 @@ class StubClient(tanjun.Client): client = StubClient(mock.Mock()) with pytest.raises(ValueError, match="Missing event argument annotation"): - client.with_listener()(callback) + client.with_listener()(callback) # pyright: ignore[reportUnknownArgumentType] add_listener_.assert_not_called() diff --git a/tests/test_clients_future_annotations.py b/tests/test_clients_future_annotations.py index 9553dd45f..703dd31b8 100644 --- a/tests/test_clients_future_annotations.py +++ b/tests/test_clients_future_annotations.py @@ -54,7 +54,7 @@ class StubClient(tanjun.Client): client = StubClient(mock.Mock()) with pytest.raises(ValueError, match="Missing event argument annotation"): - client.with_listener()(callback) + client.with_listener()(callback) # pyright: ignore[reportUnknownArgumentType] add_listener_.assert_not_called() diff --git a/tests/test_components.py b/tests/test_components.py index 573e4fa70..f905d33d3 100644 --- a/tests/test_components.py +++ b/tests/test_components.py @@ -1201,7 +1201,7 @@ async def callback(foo) -> None: # type: ignore )() with pytest.raises(ValueError, match="Missing event argument annotation"): - component.with_listener()(callback) + component.with_listener()(callback) # pyright: ignore[reportUnknownArgumentType] add_listener.assert_not_called() diff --git a/tests/test_components_future_annotations.py b/tests/test_components_future_annotations.py index d01ba9bd1..e91038b2d 100644 --- a/tests/test_components_future_annotations.py +++ b/tests/test_components_future_annotations.py @@ -53,7 +53,7 @@ async def callback(foo) -> None: # type: ignore )() with pytest.raises(ValueError, match="Missing event argument annotation"): - component.with_listener()(callback) + component.with_listener()(callback) # pyright: ignore[reportUnknownArgumentType] add_listener.assert_not_called() From 039bdddd2eb58aceeee92f58ddb79c9d43364b33 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Wed, 25 Jan 2023 13:01:43 +0000 Subject: [PATCH 30/45] More doc fixes --- tanjun/annotations.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tanjun/annotations.py b/tanjun/annotations.py index abdb81793..ea6861998 100644 --- a/tanjun/annotations.py +++ b/tanjun/annotations.py @@ -339,12 +339,12 @@ def __init__(self, converter: _ConverterSig[typing.Any], /, *other_converters: _ Parameters ---------- - converter : collections.abc.Callable + converter : collections.abc.Callable[[str], collections.Coroutine[Any, Any, Any] | Any] The first converter this argument should use to handle values passed to it during parsing. Only the first converter to pass will be used. - *other_converters : collections.abc.Callable + *other_converters : collections.abc.Callable[[str], collections.Coroutine[Any, Any, Any] | Any] Other first converter(s) this argument should use to handle values passed to it during parsing. From e958beae69ac7c26963d56bcb4c35765b117250f Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Sun, 29 Jan 2023 13:59:38 +0000 Subject: [PATCH 31/45] Don't error on 3.10 and 3.9 --- tanjun/abc.py | 229 ++++++++++++++++++++++----------------- tanjun/commands/slash.py | 21 +++- tanjun/parsing.py | 28 +++-- 3 files changed, 161 insertions(+), 117 deletions(-) diff --git a/tanjun/abc.py b/tanjun/abc.py index 9123276b1..bec930002 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -107,156 +107,181 @@ _MessageCommandT = typing.TypeVar("_MessageCommandT", bound="MessageCommand[typing.Any]") _MetaEventSigT = typing.TypeVar("_MetaEventSigT", bound="MetaEventSig") -_P = typing_extensions.ParamSpec("_P") _T = typing.TypeVar("_T") _AppCommandContextT = typing.TypeVar("_AppCommandContextT", bound="AppCommandContext") +_AutocompleteValueT = typing.TypeVar("_AutocompleteValueT", int, str, float) _ContextT_co = typing.TypeVar("_ContextT_co", covariant=True, bound="Context") _ContextT_contra = typing.TypeVar("_ContextT_contra", bound="Context", contravariant=True) _CoroT = collections.Coroutine[typing.Any, typing.Any, _T] -_MenuValueT = typing.TypeVar("_MenuValueT", hikari.Message, hikari.InteractionMember) _MenuTypeT = typing.TypeVar( "_MenuTypeT", typing.Literal[hikari.CommandType.USER], typing.Literal[hikari.CommandType.MESSAGE] ) +_MenuValueT = typing.TypeVar("_MenuValueT", hikari.Message, hikari.InteractionMember) -_MaybeAwaitable = collections.Callable[_P, _CoroT[_T] | _T] - -_AutocompleteValueT = typing.TypeVar("_AutocompleteValueT", int, str, float) -_AutocompleteSig = collections.Callable[ - typing_extensions.Concatenate["AutocompleteContext", _AutocompleteValueT, _P], _CoroT[None] -] +CommandCallbackSig = collections.Callable[..., _CoroT[None]] +"""Deprecated type hint used to represent any command callback.""" -AutocompleteSig = _AutocompleteSig[_AutocompleteValueT, ...] -"""Type hint of the callback an autocomplete callback should have. +MetaEventSig = collections.Callable[..., _CoroT[None] | None] +"""Type hint of a client callback. -This will be called when handling autocomplete and should be an asynchronous -callback which two positional arguments of type [tanjun.abc.AutocompleteContext][] and -`str` or `int` or `float` (with the 2nd argument type being decided by the -autocomplete type), returns [None][] and may use dependency injection. +The positional arguments this is guaranteed depend on the event name its being +subscribed to (more information the standard client callbacks can be found at +[tanjun.abc.ClientCallbackNames][]) and may be either synchronous or asynchronous but must +return [None][]. """ -AutocompleteCallbackSig = AutocompleteSig -"""Deprecated alias of [tanjun.abc.AutocompleteSig][].""" +# 3.9 and 3.10 just can't handle ending a Paramspec with ... so we lie at runtime about this. +if typing.TYPE_CHECKING: + _P = typing_extensions.ParamSpec("_P") -_CheckSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, _P], bool] -CheckSig = _CheckSig[_ContextT_contra, ...] -"""Type hint of a generic context check used with Tanjun [tanjun.abc.ExecutableCommand][] classes. + _MaybeAwaitable = collections.Callable[_P, _CoroT[_T] | _T] -This may be registered with a [tanjun.abc.ExecutableCommand][] to add a rule -which decides whether it should execute for each context passed to it. + _AutocompleteSig = collections.Callable[ + typing_extensions.Concatenate["AutocompleteContext", _AutocompleteValueT, _P], _CoroT[None] + ] -This should take one positional argument of type [tanjun.abc.Context][] and may -either be a synchronous or asynchronous callback which returns [bool][]. -Returning [False][] or raising [tanjun.FailedCheck][] will indicate that the -current context shouldn't lead to an execution. -""" + AutocompleteSig = _AutocompleteSig[_AutocompleteValueT, ...] + """Type hint of the callback an autocomplete callback should have. -AnyCheckSig = _CheckSig["Context", ...] -"""Type hint of a check callback for any command type.""" + This will be called when handling autocomplete and should be an asynchronous + callback which two positional arguments of type [tanjun.abc.AutocompleteContext][] and + `str` or `int` or `float` (with the 2nd argument type being decided by the + autocomplete type), returns [None][] and may use dependency injection. + """ -CommandCallbackSig = collections.Callable[..., _CoroT[None]] -"""Deprecated type hint used to represent any command callback.""" + AutocompleteCallbackSig = AutocompleteSig + """Deprecated alias of [tanjun.abc.AutocompleteSig][].""" -_ManuCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _MenuValueT, _P], _CoroT[None]] -MenuCallbackSig = _ManuCallbackSig["MenuContext", _MenuValueT, ...] -"""Type hint of a context menu command callback. + _CheckSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, _P], bool] + CheckSig = _CheckSig[_ContextT_contra, ...] + """Type hint of a generic context check used with Tanjun [tanjun.abc.ExecutableCommand][] classes. -This is guaranteed two positional; arguments of type [tanjun.abc.MenuContext][] -and either `hikari.User | hikari.InteractionMember` and/or -[hikari.messages.Message][] dependent on the type(s) of menu this is, -and may use dependency injection. + This may be registered with a [tanjun.abc.ExecutableCommand][] to add a rule + which decides whether it should execute for each context passed to it. -This must be asynchronous and return [None][]. -""" + This should take one positional argument of type [tanjun.abc.Context][] and may + either be a synchronous or asynchronous callback which returns [bool][]. + Returning [False][] or raising [tanjun.FailedCheck][] will indicate that the + current context shouldn't lead to an execution. + """ -MenuCommandCallbackSig = MenuCallbackSig -"""Deprecated alias of [tanjun.abc.MenuCallbackSig][].""" + AnyCheckSig = _CheckSig["Context", ...] + """Type hint of a check callback for any command type.""" -_MenuCallbackSigT = typing.TypeVar("_MenuCallbackSigT", bound=MenuCallbackSig[typing.Any]) + _ManuCallbackSig = collections.Callable[ + typing_extensions.Concatenate[_ContextT_contra, _MenuValueT, _P], _CoroT[None] + ] + MenuCallbackSig = _ManuCallbackSig["MenuContext", _MenuValueT, ...] + """Type hint of a context menu command callback. -_CommandCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _P], _CoroT[None]] + This is guaranteed two positional; arguments of type [tanjun.abc.MenuContext][] + and either `hikari.User | hikari.InteractionMember` and/or + [hikari.messages.Message][] dependent on the type(s) of menu this is, + and may use dependency injection. -MessageCallbackSig = _CommandCallbackSig["MessageContext", ...] -"""Type hint of a message command callback. + This must be asynchronous and return [None][]. + """ -This is guaranteed one positional argument of type [tanjun.abc.MessageContext][] and -may use dependency injection. + MenuCommandCallbackSig = MenuCallbackSig + """Deprecated alias of [tanjun.abc.MenuCallbackSig][].""" -This must be asynchronous and return [None][]. -""" -_MessageCallbackSigT = typing.TypeVar("_MessageCallbackSigT", bound=MessageCallbackSig) + _CommandCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _P], _CoroT[None]] -SlashCallbackSig = _CommandCallbackSig["SlashContext", ...] -"""Type hint of a slash command callback. + MessageCallbackSig = _CommandCallbackSig["MessageContext", ...] + """Type hint of a message command callback. -This is guaranteed one positional argument of type [tanjun.abc.SlashContext][] and -may use dependency injection. + This is guaranteed one positional argument of type [tanjun.abc.MessageContext][] and + may use dependency injection. -This must be asynchronous and return [None][]. -""" -_SlashCallbackSigT = typing.TypeVar("_SlashCallbackSigT", bound=SlashCallbackSig) + This must be asynchronous and return [None][]. + """ -_ErrorHookSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, Exception, _P], bool | None] + SlashCallbackSig = _CommandCallbackSig["SlashContext", ...] + """Type hint of a slash command callback. -ErrorHookSig = _ErrorHookSig[_ContextT_contra, ...] -"""Type hint of the callback used as a unexpected command error hook. + This is guaranteed one positional argument of type [tanjun.abc.SlashContext][] and + may use dependency injection. -This will be called whenever an unexpected [Exception][] is raised during the -execution stage of a command (ignoring [tanjun.ParserError][] and expected -[tanjun.TanjunError][] subclasses). + This must be asynchronous and return [None][]. + """ -This should take two positional arguments - of type [tanjun.abc.Context][] and -[Exception][] - and may be either a synchronous or asynchronous callback which -returns [bool][] or [None][] and may take advantage of dependency injection. + _ErrorHookSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, Exception, _P], bool | None] -[True][] is returned to indicate that the exception should be suppressed and -[False][] is returned to indicate that the exception should be re-raised. -""" + ErrorHookSig = _ErrorHookSig[_ContextT_contra, ...] + """Type hint of the callback used as a unexpected command error hook. -_ParserHookSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, "errors.ParserError", _P], bool | None] + This will be called whenever an unexpected [Exception][] is raised during the + execution stage of a command (ignoring [tanjun.ParserError][] and expected + [tanjun.TanjunError][] subclasses). -ParserHookSig = _ParserHookSig[_ContextT_contra, ...] -"""Type hint of the callback used as a command parser error hook. + This should take two positional arguments - of type [tanjun.abc.Context][] and + [Exception][] - and may be either a synchronous or asynchronous callback which + returns [bool][] or [None][] and may take advantage of dependency injection. -This will be called whenever an parser [ParserError][tanjun.errors.ParserError] -is raised during the execution stage of a command. + [True][] is returned to indicate that the exception should be suppressed and + [False][] is returned to indicate that the exception should be re-raised. + """ -This should take two positional arguments - of type [tanjun.abc.Context][] and -[ParserError][tanjun.errors.ParserError] - and may be either a synchronous or -asynchronous callback which returns [None][] and may take advantage of -dependency injection. + _ParserHookSig = _MaybeAwaitable[ + typing_extensions.Concatenate[_ContextT_contra, "errors.ParserError", _P], bool | None + ] -Parser errors are always suppressed (unlike general errors). -""" + ParserHookSig = _ParserHookSig[_ContextT_contra, ...] + """Type hint of the callback used as a command parser error hook. -_HookSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, _P], None] + This will be called whenever an parser [ParserError][tanjun.errors.ParserError] + is raised during the execution stage of a command. -HookSig = _HookSig[_ContextT_contra, ...] -"""Type hint of the callback used as a general command hook. + This should take two positional arguments - of type [tanjun.abc.Context][] and + [ParserError][tanjun.errors.ParserError] - and may be either a synchronous or + asynchronous callback which returns [None][] and may take advantage of + dependency injection. -!!! note - This may be asynchronous or synchronous, dependency injection is supported - for this callback's keyword arguments and the positional arguments which - are passed dependent on the type of hook this is being registered as. -""" + Parser errors are always suppressed (unlike general errors). + """ -_EventT = typing.TypeVar("_EventT", bound=hikari.Event) -_ListenerCallbackSig = collections.Callable[typing_extensions.Concatenate[_EventT, _P], _CoroT[None]] + _HookSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, _P], None] -ListenerCallbackSig = _ListenerCallbackSig[_EventT, ...] -"""Type hint of a hikari event manager callback. + HookSig = _HookSig[_ContextT_contra, ...] + """Type hint of the callback used as a general command hook. -This is guaranteed one positional arg of type [hikari.events.base_events.Event][] -regardless of implementation and must be a coruotine function which returns [None][]. -""" + !!! note + This may be asynchronous or synchronous, dependency injection is supported + for this callback's keyword arguments and the positional arguments which + are passed dependent on the type of hook this is being registered as. + """ -MetaEventSig = _MaybeAwaitable[..., None] -"""Type hint of a client callback. + _EventT = typing.TypeVar("_EventT", bound=hikari.Event) + _ListenerCallbackSig = collections.Callable[typing_extensions.Concatenate[_EventT, _P], _CoroT[None]] -The positional arguments this is guaranteed depend on the event name its being -subscribed to (more information the standard client callbacks can be found at -[tanjun.abc.ClientCallbackNames][]) and may be either synchronous or asynchronous but must -return [None][]. -""" + ListenerCallbackSig = _ListenerCallbackSig[_EventT, ...] + """Type hint of a hikari event manager callback. + + This is guaranteed one positional arg of type [hikari.events.base_events.Event][] + regardless of implementation and must be a coruotine function which returns [None][]. + """ + +else: + import types + + AutocompleteSig = types.GenericAlias(collections.Callable[..., typing.Any], (_AutocompleteValueT,)) + AutocompleteCallbackSig = AutocompleteSig + CheckSig = types.GenericAlias(collections.Callable[..., typing.Any], (_ContextT_contra,)) + AnyCheckSig = CheckSig + MenuCallbackSig = types.GenericAlias(collections.Callable[..., typing.Any], (_MenuValueT,)) + MenuCommandCallbackSig = MenuCallbackSig + MessageCallbackSig = collections.Callable[..., typing.Any] + SlashCallbackSig = collections.Callable[..., typing.Any] + ErrorHookSig = types.GenericAlias(collections.Callable[..., typing.Any], (_ContextT_contra,)) + ParserHookSig = types.GenericAlias(collections.Callable[..., typing.Any], (_ContextT_contra,)) + HookSig = types.GenericAlias(collections.Callable[..., typing.Any], (_ContextT_contra,)) + _EventT = typing.TypeVar("_EventT", bound=hikari.Event) + ListenerCallbackSig = types.GenericAlias(collections.Callable[..., typing.Any], (_EventT,)) + + +_MenuCallbackSigT = typing.TypeVar("_MenuCallbackSigT", bound=MenuCallbackSig[typing.Any]) +_MessageCallbackSigT = typing.TypeVar("_MessageCallbackSigT", bound=MessageCallbackSig) +_SlashCallbackSigT = typing.TypeVar("_SlashCallbackSigT", bound=SlashCallbackSig) class Context(alluka.Context): diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index 9d9ba8377..990f9c914 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -91,13 +91,22 @@ _SlashCallbackSigT = typing.TypeVar("_SlashCallbackSigT", bound=tanjun.SlashCallbackSig) _ConvertT = typing.TypeVar("_ConvertT", int, float, str) -_P = typing_extensions.ParamSpec("_P") -_ConverterSig = collections.Callable[ - typing_extensions.Concatenate[_ConvertT, _P], collections.Coroutine[typing.Any, typing.Any, typing.Any] | typing.Any -] -ConverterSig = _ConverterSig[_ConvertT, ...] -"""Type hint of a slash command option converter.""" +# 3.9 and 3.10 just can't handle ending a Paramspec with ... so we lie at runtime about this. +if typing.TYPE_CHECKING: + _P = typing_extensions.ParamSpec("_P") + + _ConverterSig = collections.Callable[ + typing_extensions.Concatenate[_ConvertT, _P], + collections.Coroutine[typing.Any, typing.Any, typing.Any] | typing.Any, + ] + ConverterSig = _ConverterSig[_ConvertT, ...] + """Type hint of a slash command option converter.""" + +else: + import types + + ConverterSig = types.GenericAlias(collections.Callable[..., typing.Any], (_ConvertT,)) _EMPTY_DICT: typing.Final[dict[typing.Any, typing.Any]] = {} _EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() diff --git a/tanjun/parsing.py b/tanjun/parsing.py index a8ad8a187..3e235acca 100644 --- a/tanjun/parsing.py +++ b/tanjun/parsing.py @@ -85,17 +85,27 @@ def __len__(self) -> int: _T = typing.TypeVar("_T") -_P = typing_extensions.ParamSpec("_P") -_ConverterSig = collections.Callable[ - typing_extensions.Concatenate[str, _P], collections.Coroutine[typing.Any, typing.Any, _T] | _T -] -ConverterSig = _ConverterSig[..., _T] -"""Type hint of a converter used within a parser instance. +"""Type hint of a slash command option converter.""" +if typing.TYPE_CHECKING: + _P = typing_extensions.ParamSpec("_P") + _ConverterSig = collections.Callable[ + typing_extensions.Concatenate[str, _P], collections.Coroutine[typing.Any, typing.Any, _T] | _T + ] + + ConverterSig = _ConverterSig[..., _T] + """Type hint of a converter used within a parser instance. -This must be a callable or asynchronous callable which takes one position -[str][], argument and returns the resultant value. -""" + This must be a callable or asynchronous callable which takes one position + [str][], argument and returns the resultant value. + """ + +else: + import types + + ConverterSig = types.GenericAlias( + collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, _T] | _T], (_T,) + ) class UndefinedT: From ee38be0012a239704977b22c1fd1bbf845a1c84a Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Mon, 30 Jan 2023 05:21:31 +0000 Subject: [PATCH 32/45] Post-rebase fixes --- dev-requirements/flake8.txt | 321 +------------------------------ tanjun/_internal/__init__.py | 7 +- tanjun/abc.py | 10 +- tanjun/annotations.py | 21 +- tanjun/checks.py | 62 +++--- tanjun/clients.py | 28 +-- tanjun/commands/menu.py | 36 ++-- tanjun/commands/message.py | 22 +-- tanjun/commands/slash.py | 74 +++---- tanjun/components.py | 2 +- tanjun/dependencies/reloaders.py | 10 +- tanjun/hooks.py | 10 +- tanjun/parsing.py | 6 +- tanjun/schedules.py | 4 +- 14 files changed, 152 insertions(+), 461 deletions(-) diff --git a/dev-requirements/flake8.txt b/dev-requirements/flake8.txt index 1d8d813ca..4bbd7e7c2 100644 --- a/dev-requirements/flake8.txt +++ b/dev-requirements/flake8.txt @@ -1,320 +1 @@ -# -# This file is autogenerated by pip-compile-cross-platform -# To update, run: -# -# pip-compile-cross-platform dev-requirements/flake8.in --output-file dev-requirements/flake8.txt --min-python-version 3.10.0,<3.12 -# -astor==0.8.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5 \ - --hash=sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e -attrs==22.2.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836 \ - --hash=sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99 -bandit==1.7.4 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:2d63a8c573417bae338962d4b9b06fbc6080f74ecd955a092849e1e65c717bd2 \ - --hash=sha256:412d3f259dab4077d0e7f0c11f50f650cc7d10db905d98f6520a95a18049658a -black==22.12.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320 \ - --hash=sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351 \ - --hash=sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350 \ - --hash=sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f \ - --hash=sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf \ - --hash=sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148 \ - --hash=sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4 \ - --hash=sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d \ - --hash=sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc \ - --hash=sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d \ - --hash=sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2 \ - --hash=sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f -click==8.1.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \ - --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48 -colorama==0.4.6 ; python_full_version >= "3.10.0" and python_version < "3.12" and platform_system == "Windows" \ - --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ - --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 -eradicate==2.1.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:8bfaca181db9227dc88bdbce4d051a9627604c2243e7d85324f6d6ce0fd08bb2 \ - --hash=sha256:aac7384ab25b1bf21c4c012de9b4bf8398945a14c98c911545b2ea50ab558014 -flake8-async==22.11.14 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:317cf0f882a2f4a09c2250c451acff8358d7faec8a0aa54521b6e69336fe9d0b \ - --hash=sha256:b4db2d55883653b47d4bfd946fdf506e8958bb4ca35974790b8c3e620fc1abff -flake8-bandit==4.1.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:068e09287189cbfd7f986e92605adea2067630b75380c6b5733dab7d87f9a84e \ - --hash=sha256:4c8a53eb48f23d4ef1e59293657181a3c989d0077c9952717e98a0eace43e06d -flake8-black==0.3.6 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:0dfbca3274777792a5bcb2af887a4cad72c72d0e86c94e08e3a3de151bb41c34 \ - --hash=sha256:fe8ea2eca98d8a504f22040d9117347f6b367458366952862ac3586e7d4eeaca -flake8-broken-line==0.6.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:a02268f11a18837c83c59013a36cc00fee9e17a042745cc0c9895f1c9f6acc16 \ - --hash=sha256:c0ab336ff7de228dbffbe56d67b3615bb21fb15f3ed0604fa7bdf9feb72d7d88 -flake8-builtins==2.1.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:12ff1ee96dd4e1f3141141ee6c45a5c7d3b3c440d0949e9b8d345c42b39c51d4 \ - --hash=sha256:469e8f03d6d0edf4b1e62b6d5a97dce4598592c8a13ec8f0952e7a185eba50a1 -flake8-coding==1.3.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:79704112c44d09d4ab6c8965e76a20c3f7073d52146db60303bce777d9612260 \ - --hash=sha256:b8f4d5157a8f74670e6cfea732c3d9f4291a4e994c8701d2c55f787c6e6cb741 -flake8-comments==0.1.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:42250cb4a51dc59e6db25f1291cfb16b78ea233f72dac32a5bc7b09c691235ea \ - --hash=sha256:780b4fc2820ed4ff8a0a98f3fc993f776ede1aecbe0c6cec64d93814b21c9234 -flake8-comprehensions==3.10.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:412052ac4a947f36b891143430fef4859705af11b2572fbb689f90d372cf26ab \ - --hash=sha256:d763de3c74bc18a79c039a7ec732e0a1985b0c79309ceb51e56401ad0a2cd44e -flake8-deprecated==2.0.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:8c61d2cb8d487118b6c20392b25f08ba1ec49c759e4ea562c7a60172912bc7ee \ - --hash=sha256:c7659a530aa76c3ad8be0c1e8331ed56d882ef8bfba074501a545bb3352b0c23 -flake8-docstrings==1.6.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:99cac583d6c7e32dd28bbfbef120a7c0d1b6dde4adb5a9fd441c4227a6534bde \ - --hash=sha256:9fe7c6a306064af8e62a055c2f61e9eb1da55f84bb39caef2b84ce53708ac34b -flake8-eradicate==1.4.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:3088cfd6717d1c9c6c3ac45ef2e5f5b6c7267f7504d5a74b781500e95cb9c7e1 \ - --hash=sha256:e3bbd0871be358e908053c1ab728903c114f062ba596b4d40c852fd18f473d56 -flake8-executable==2.1.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:619fe023e00c3d8e5113521d7200e1ebb04587c12d157f9a2fb167feb8cae66b \ - --hash=sha256:f0a66c97c3b99ce63bc1f01ce602d6bd048e4fc5dc0d7a13be2bfa3deb023a34 -flake8-fixme==1.1.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:226a6f2ef916730899f29ac140bed5d4a17e5aba79f00a0e3ae1eff1997cb1ac \ - --hash=sha256:50cade07d27a4c30d4f12351478df87339e67640c83041b664724bda6d16f33a -flake8-functions==0.0.7 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:40584b05d57e5ab185545bcfa08aa0edca52b04646d0df266e2b1667d6437184 \ - --hash=sha256:f2f75545c2b0df9eeba0ad316e2ac38c101676970b4441300fc07af3226a44f6 -flake8-future-annotations==1.1.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:555f16f51ae24ab4d0683b1ce8d0f59d36259c3a7e776bd5642f58c78ce7d3ab \ - --hash=sha256:df416bd2b9e1eda7ea639a5fd2a083dabb942ffe49d197f836df380d0dcf6608 -flake8-html==0.4.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:8b870299620cc4a06f73644a1b4d457799abeca1cc914c62ae71ec5bf65c79a5 \ - --hash=sha256:8f126748b1b0edd6cd39e87c6192df56e2f8655b0aa2bb00ffeac8cf27be4325 -flake8-if-statements==1.0.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:4de1a05c6840ed7ca419a0de6038a343317fe327401a91c887cd8661730662c9 \ - --hash=sha256:7a247fab5f409e3f2c18c3d92e1f7a9a9d1a8e0cd3aa1d446a17097e16ecddab -flake8-implicit-str-concat==0.3.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:a89ebc50567790fb7b83e032ed4014ae0db70e35d89e269c3323967135023600 \ - --hash=sha256:c0e6ae227e46238e4c87844091f8072892caeccd3bb266576a7d449eadbf53a0 -flake8-isort==5.0.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:0951398c343c67f4933407adbbfb495d4df7c038650c5d05753a006efcfeb390 \ - --hash=sha256:8c4ab431d87780d0c8336e9614e50ef11201bc848ef64ca017532dec39d4bf49 -flake8-mutable==1.2.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:38fd9dadcbcda6550a916197bc40ed76908119dabb37fbcca30873666c31d2d5 \ - --hash=sha256:ee9b77111b867d845177bbc289d87d541445ffcc6029a0c5c65865b42b18c6a6 -flake8-new-union-types==0.4.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:0a9dd421099f2525f8be525977ff6632b13b68719a7b0807cf49028d4287b0aa \ - --hash=sha256:92737a2f598772d5aedd05b5450c5dd200e0f1acd42b3c1f95dbbe3211af2009 -flake8-no-pep420==2.3.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:1b965a18508ac7842de288740aa43627d3a5bb2be64f7d5d70d55cb691c3de84 \ - --hash=sha256:ccba3efa05c50b1c2712d78807cca81e563ab571d6b3bcb90228e87388704cf5 -flake8-pep3101==2.0.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:1d818e1f53c6d26e875714f2f041ec15fbb23c17e2268dbbb024e9c3383541cd \ - --hash=sha256:ae2ee1758734a473ca971b4bf9ff09c961b6099916db91fdb6b9718328dfcacb -flake8-pep585==0.1.6 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:67feae956ccf7ef20c5cfe57bb63f5342e4f7898fd1cb1d3a8a8a52e26393fd2 \ - --hash=sha256:8b7bccfa760c40baedb28dc48b1b514907867b3551a7aec87552d115355a6def -flake8-plugin-utils==1.3.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:1fe43e3e9acf3a7c0f6b88f5338cad37044d2f156c43cb6b080b5f9da8a76f06 \ - --hash=sha256:20fa2a8ca2decac50116edb42e6af0a1253ef639ad79941249b840531889c65a -flake8-print==5.0.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:76915a2a389cc1c0879636c219eb909c38501d3a43cc8dae542081c9ba48bdf9 \ - --hash=sha256:84a1a6ea10d7056b804221ac5e62b1cee1aefc897ce16f2e5c42d3046068f5d8 -flake8-printf-formatting==1.1.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:0f9e1308ac290356e4b271d4f26adfc3f9165680a7b6c221503b0f3e155a2784 \ - --hash=sha256:d908ffabdf08581043a50572744fd60563d82386630b0335445894120089d2df -flake8-pytest-style==1.6.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:5fedb371a950e9fe0e0e6bfc854be7d99151271208f34cd2cc517681ece27780 \ - --hash=sha256:c1175713e9e11b78cd1a035ed0bca0d1e41d09c4af329a952750b61d4194ddac -flake8-pytest==1.4 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:19f543b2d1cc89d61b76f19d0a9e58e9a110a035175f701b3425c363a7732c56 \ - --hash=sha256:97328f258ffad9fe18babb3b0714a16b121505ad3ac87d4e33020874555d0784 -flake8-raise==0.0.5 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:0a9890e16b851402d9b0d4fafe6c34890eab73835a2c2079c3850a25be575623 \ - --hash=sha256:df26e5c542a58c8f8786d978e18ad7e54126a0ef5c6241c35dafaca7e2bbb808 -flake8-simplify==0.19.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:1057320e9312d75849541fee822900d27bcad05b2405edc84713affee635629e \ - --hash=sha256:2fb083bf5142a98d9c9554755cf2f56f8926eb4a33eae30c0809041b1546879e -flake8-typing-imports==1.14.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:0612976976f1e90bd4588a03d9be5a9c408411e5dc46b29cc6b052e5de42277c \ - --hash=sha256:3008214280cd96092e7ebbad87dc62bb0e03020c12e8c342f6565cbddfdd67c7 -flake8-use-fstring==1.4 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:6550bf722585eb97dffa8343b0f1c372101f5c4ab5b07ebf0edd1c79880cdd39 -flake8-use-pathlib==0.3.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:0ef19f255a51601bcf04ff54f25ef8a466dff68210cd95b4f1db36a78ace5223 \ - --hash=sha256:c7b6d71575b575f7d70ebf3f1d7f2dd6685e401d3280208f1db9dbb6bfa32608 -flake8-variables-names==0.0.5 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:30133e14ee2300e13a60393a00f74d98110c76070ac67d1ab91606f02824a7e1 \ - --hash=sha256:e3277031696bbe10b5132b49938cde1d70fcae9561533b7bd7ab8e69cb27addb -flake8==5.0.4 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db \ - --hash=sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248 -gitdb==4.0.10 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a \ - --hash=sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7 -gitpython==3.1.30 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:769c2d83e13f5d938b7688479da374c4e3d49f71549aaf462b646db9602ea6f8 \ - --hash=sha256:cd455b0000615c60e286208ba540271af9fe531fa6a87cc590a7298785ab2882 -isort==5.11.4 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6 \ - --hash=sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b -jinja2==3.1.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ - --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 -markdown-it-py==2.1.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27 \ - --hash=sha256:cf7e59fed14b5ae17c0006eff14a2d9a00ed5f3a846148153899a0224e2c07da -markupsafe==2.1.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed \ - --hash=sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc \ - --hash=sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2 \ - --hash=sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460 \ - --hash=sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7 \ - --hash=sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0 \ - --hash=sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1 \ - --hash=sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa \ - --hash=sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03 \ - --hash=sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323 \ - --hash=sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65 \ - --hash=sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013 \ - --hash=sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036 \ - --hash=sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f \ - --hash=sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4 \ - --hash=sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419 \ - --hash=sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2 \ - --hash=sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619 \ - --hash=sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a \ - --hash=sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a \ - --hash=sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd \ - --hash=sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7 \ - --hash=sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666 \ - --hash=sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65 \ - --hash=sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859 \ - --hash=sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625 \ - --hash=sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff \ - --hash=sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156 \ - --hash=sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd \ - --hash=sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba \ - --hash=sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f \ - --hash=sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1 \ - --hash=sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094 \ - --hash=sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a \ - --hash=sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513 \ - --hash=sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed \ - --hash=sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d \ - --hash=sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3 \ - --hash=sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147 \ - --hash=sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c \ - --hash=sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603 \ - --hash=sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601 \ - --hash=sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a \ - --hash=sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1 \ - --hash=sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d \ - --hash=sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3 \ - --hash=sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54 \ - --hash=sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2 \ - --hash=sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6 \ - --hash=sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58 -mccabe==0.7.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \ - --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e -mdurl==0.1.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ - --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba -more-itertools==8.14.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:1bc4f91ee5b1b31ac7ceacc17c09befe6a40a503907baf9c839c229b5095cfd2 \ - --hash=sha256:c09443cd3d5438b8dafccd867a6bc1cb0894389e90cb53d227456b0b0bccb750 -mr-proper==0.0.7 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:03b517b19e617537f711ce418b125e5f2efd82ec881539cdee83195c78c14a02 \ - --hash=sha256:74a1b60240c46f10ba518707ef72811a01e5c270da0a78b5dd2dd923d99fdb14 -mypy-extensions==0.4.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d \ - --hash=sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8 -pathspec==0.11.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:3a66eb970cbac598f9e5ccb5b2cf58930cd8e3ed86d393d541eaf2d8b1705229 \ - --hash=sha256:64d338d4e0914e91c1792321e6907b5a593f1ab1851de7fc269557a21b30ebbc -pbr==5.11.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b \ - --hash=sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3 -pep8-naming==0.13.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:1705f046dfcd851378aac3be1cd1551c7c1e5ff363bacad707d43007877fa971 \ - --hash=sha256:1a86b8c71a03337c97181917e2b472f0f5e4ccb06844a0d6f0a33522549e7a80 -platformdirs==2.6.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490 \ - --hash=sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2 -pycodestyle==2.9.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785 \ - --hash=sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b -pydocstyle==6.3.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019 \ - --hash=sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1 -pyflakes==2.5.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2 \ - --hash=sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3 -pygments==2.14.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297 \ - --hash=sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717 -pyproject-flake8==5.0.4.post1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:457e52dde1b7a1f84b5230c70d61afa58ced64a44b81a609f19e972319fa68ed \ - --hash=sha256:c2dfdf1064f47efbb2e4faf1a32b0b6a6ea67dc4d1debb98d862b0cdee377941 -pyyaml==6.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ - --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ - --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ - --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ - --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ - --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ - --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ - --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ - --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ - --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ - --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ - --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ - --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ - --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ - --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ - --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ - --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ - --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ - --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ - --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ - --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ - --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ - --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ - --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ - --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ - --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ - --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ - --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ - --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ - --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ - --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ - --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ - --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ - --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ - --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ - --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ - --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ - --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ - --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ - --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 -rich==13.2.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:7c963f0d03819221e9ac561e1bc866e3f95a02248c1234daa48954e6d381c003 \ - --hash=sha256:f1a00cdd3eebf999a15d85ec498bfe0b1a77efe9b34f645768a54132ef444ac5 -setuptools==66.1.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:6f590d76b713d5de4e49fe4fbca24474469f53c83632d5d0fd056f7ff7e8112b \ - --hash=sha256:ac4008d396bc9cd983ea483cb7139c0240a07bbc74ffb6232fceffedc6cf03a8 -smmap==5.0.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94 \ - --hash=sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936 -snowballstemmer==2.2.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1 \ - --hash=sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a -stdlib-list==0.8.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:2ae0712a55b68f3fbbc9e58d6fa1b646a062188f49745b495f94d3310a9fdd3e \ - --hash=sha256:a1e503719720d71e2ed70ed809b385c60cd3fb555ba7ec046b96360d30b16d9f -stevedore==4.1.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:7f8aeb6e3f90f96832c301bff21a7eb5eefbe894c88c506483d355565d88cc1a \ - --hash=sha256:aa6436565c069b2946fe4ebff07f5041e0c8bf18c7376dd29edf80cf7d524e4e -toml==0.10.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ - --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f -tomli==2.0.1 ; python_full_version >= "3.10.0" and python_full_version < "3.11.0a7" \ - --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ - --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f -tryceratops==1.1.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:58e56b33eeb7a9cfd643957069bb1872ebe26c1eeac7abb1877c9535b7e473db \ - --hash=sha256:f4770960782a2ae87cad7a7fd1206476468d0f41383c9fd7a49c6d537534015e +-r ../piped/python/base-requirements/library-flake8.txt diff --git a/tanjun/_internal/__init__.py b/tanjun/_internal/__init__.py index 700a72bbb..ea43e0a60 100644 --- a/tanjun/_internal/__init__.py +++ b/tanjun/_internal/__init__.py @@ -60,7 +60,10 @@ _ContextT = typing.TypeVar("_ContextT", bound=tanjun.Context) _CoroT = collections.Coroutine[typing.Any, typing.Any, _T] - _TreeT = dict["str | _IndexKeys", "_TreeT | list[tuple[list[str], tanjun.MessageCommand[typing.Any]]]"] + _TreeT = dict[ + typing.Union[str, "_IndexKeys"], + typing.Union["_TreeT", list[tuple[list[str], tanjun.MessageCommand[typing.Any]]]], + ] _KeyT = typing.TypeVar("_KeyT") @@ -155,7 +158,7 @@ def __len__(self) -> int: _KEYWORD_TYPES = {inspect.Parameter.KEYWORD_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD} -def get_kwargs(callback: collections.Callable[..., typing.Any], /) -> list[str] | None: +def get_kwargs(callback: collections.Callable[..., typing.Any], /) -> typing.Union[list[str], None]: """Get a list of the keyword argument names for a callback. Parameters diff --git a/tanjun/abc.py b/tanjun/abc.py index bec930002..79e5dcab7 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -121,7 +121,7 @@ CommandCallbackSig = collections.Callable[..., _CoroT[None]] """Deprecated type hint used to represent any command callback.""" -MetaEventSig = collections.Callable[..., _CoroT[None] | None] +MetaEventSig = collections.Callable[..., typing.Union[_CoroT[None], None]] """Type hint of a client callback. The positional arguments this is guaranteed depend on the event name its being @@ -134,7 +134,7 @@ if typing.TYPE_CHECKING: _P = typing_extensions.ParamSpec("_P") - _MaybeAwaitable = collections.Callable[_P, _CoroT[_T] | _T] + _MaybeAwaitable = collections.Callable[_P, typing.Union[_CoroT[_T], _T]] _AutocompleteSig = collections.Callable[ typing_extensions.Concatenate["AutocompleteContext", _AutocompleteValueT, _P], _CoroT[None] @@ -205,7 +205,9 @@ This must be asynchronous and return [None][]. """ - _ErrorHookSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, Exception, _P], bool | None] + _ErrorHookSig = _MaybeAwaitable[ + typing_extensions.Concatenate[_ContextT_contra, Exception, _P], typing.Optional[bool] + ] ErrorHookSig = _ErrorHookSig[_ContextT_contra, ...] """Type hint of the callback used as a unexpected command error hook. @@ -223,7 +225,7 @@ """ _ParserHookSig = _MaybeAwaitable[ - typing_extensions.Concatenate[_ContextT_contra, "errors.ParserError", _P], bool | None + typing_extensions.Concatenate[_ContextT_contra, "errors.ParserError", _P], typing.Optional[bool] ] ParserHookSig = _ParserHookSig[_ContextT_contra, ...] diff --git a/tanjun/annotations.py b/tanjun/annotations.py index ea6861998..c62a8e538 100644 --- a/tanjun/annotations.py +++ b/tanjun/annotations.py @@ -73,7 +73,6 @@ import abc import datetime -import enum import itertools import operator import typing @@ -98,19 +97,19 @@ _T = typing.TypeVar("_T") _P = typing_extensions.ParamSpec("_P") __ConverterSig = collections.Callable[ - typing_extensions.Concatenate[str, _P], collections.Coroutine[typing.Any, typing.Any, _T] | _T, + typing_extensions.Concatenate[str, _P], typing.Union[collections.Coroutine[typing.Any, typing.Any, _T], _T], ] _ConverterSig = __ConverterSig[..., _T] - _ChannelTypeIsh = type[hikari.PartialChannel] | int - _ChoiceUnion = int | float | str + _ChannelTypeIsh = typing.Union[type[hikari.PartialChannel], int] + _ChoiceUnion = typing.Union[int, float, str] _ChoiceT = typing.TypeVar("_ChoiceT", int, float, str) - _CommandUnion = slash.SlashCommand[typing.Any] | message.MessageCommand[typing.Any] + _CommandUnion = typing.Union[slash.SlashCommand[typing.Any], message.MessageCommand[typing.Any]] _CommandUnionT = typing.TypeVar("_CommandUnionT", bound=_CommandUnion) _EnumT = typing.TypeVar("_EnumT", bound=enum.Enum) _NumberT = typing.TypeVar("_NumberT", float, int) -_MentionableUnion = hikari.User | hikari.Role +_MentionableUnion = typing.Union[hikari.User, hikari.Role] class _ConfigIdentifier(abc.ABC): @@ -306,7 +305,7 @@ def set_config(self, config: _ArgConfig, /) -> None: class _ConvertedMeta(abc.ABCMeta): - def __getitem__(cls, converters: _ConverterSig[_T] | tuple[_ConverterSig[_T]], /) -> type[_T]: + def __getitem__(cls, converters: typing.Union[_ConverterSig[_T], tuple[_ConverterSig[_T]]], /) -> type[_T]: if not isinstance(converters, tuple): converters = (converters,) @@ -971,7 +970,7 @@ def __getitem__(cls, type_: type[_T], /) -> type[typing.Union[hikari.Snowflake, descriptor = SnowflakeOr() return typing.cast( - type[typing.Union[hikari.Snowflake, _T]], + "type[typing.Union[hikari.Snowflake, _T]]", typing.Annotated[typing.Union[hikari.Snowflake, type_], descriptor], ) @@ -1154,8 +1153,8 @@ def __init__(self, parameter: inspect.Parameter, /, *, description: typing.Optio self.default: typing.Any = parsing.UNDEFINED if parameter.default is parameter.empty else parameter.default self.description: typing.Optional[str] = description self.empty_value: typing.Union[parsing.UndefinedT, typing.Any] = parsing.UNDEFINED - self.float_converter: collections.Callable[[float], typing.Any] | None = None - self.int_converter: collections.Callable[[int], typing.Any] | None = None + self.float_converter: typing.Optional[collections.Callable[[float], typing.Any]] = None + self.int_converter: typing.Optional[collections.Callable[[int], typing.Any]] = None # The float and int converters are just for Choices[Enum]. self.is_greedy: bool = False self.is_positional: typing.Optional[bool] = None @@ -1169,7 +1168,7 @@ def __init__(self, parameter: inspect.Parameter, /, *, description: typing.Optio self.range_or_slice: typing.Union[range, slice, None] = None self.slash_name: str = parameter.name self.snowflake_converter: typing.Optional[collections.Callable[[str], hikari.Snowflake]] = None - self.str_converters: collections.Sequence[_ConverterSig[typing.Any]] | None = None + self.str_converters: typing.Optional[collections.Sequence[_ConverterSig[typing.Any]]] = None def finalise_slice(self) -> None: if not self.range_or_slice: diff --git a/tanjun/checks.py b/tanjun/checks.py index d591964a2..c8dd85bfc 100644 --- a/tanjun/checks.py +++ b/tanjun/checks.py @@ -74,12 +74,12 @@ class _AnyCallback(typing.Protocol[_ContextT_contra]): async def __call__( - self, ctx: _ContextT_contra, /, *, localiser: dependencies.AbstractLocaliser | None = None + self, ctx: _ContextT_contra, /, *, localiser: typing.Optional[dependencies.AbstractLocaliser] = None ) -> bool: raise NotImplementedError _CommandT = typing.TypeVar("_CommandT", bound=tanjun.ExecutableCommand[typing.Any]) - _CallbackReturnT = _CommandT | collections.Callable[[_CommandT], _CommandT] + _CallbackReturnT = typing.Union[_CommandT, collections.Callable[[_CommandT], _CommandT]] _MenuCommandT = typing.TypeVar("_MenuCommandT", bound=tanjun.MenuCommand[typing.Any, typing.Any]) _MessageCommandT = typing.TypeVar("_MessageCommandT", bound=tanjun.MessageCommand[typing.Any]) _SlashCommandT = typing.TypeVar("_SlashCommandT", bound=tanjun.BaseSlashCommand) @@ -97,8 +97,8 @@ def _add_to_command(command: _CommandT, check: tanjun.AnyCheckSig, follow_wrappe def _optional_kwargs( - command: _CommandT | None, check: tanjun.AnyCheckSig, follow_wrapped: bool -) -> _CommandT | collections.Callable[[_CommandT], _CommandT]: + command: typing.Optional[_CommandT], check: tanjun.AnyCheckSig, follow_wrapped: bool +) -> typing.Union[_CommandT, collections.Callable[[_CommandT], _CommandT]]: if command: return _add_to_command(command, check, follow_wrapped) @@ -1015,12 +1015,12 @@ def with_check( def with_check( check: tanjun.CheckSig[typing.Any], /, *, follow_wrapped: bool = False -) -> ( - collections.Callable[[_CommandT], _CommandT] - | collections.Callable[[_MenuCommandT], _MenuCommandT] - | collections.Callable[[_MessageCommandT], _MessageCommandT] - | collections.Callable[[_SlashCommandT], _SlashCommandT] -): +) -> typing.Union[ + collections.Callable[[_CommandT], _CommandT], + collections.Callable[[_MenuCommandT], _MenuCommandT], + collections.Callable[[_MessageCommandT], _MessageCommandT], + collections.Callable[[_SlashCommandT], _SlashCommandT], +]: """Add a generic check to a command. Parameters @@ -1115,12 +1115,12 @@ def with_all_checks( def with_all_checks( check: tanjun.CheckSig[typing.Any], /, *checks: tanjun.CheckSig[typing.Any], follow_wrapped: bool = False -) -> ( - collections.Callable[[_CommandT], _CommandT] - | collections.Callable[[_MenuCommandT], _MenuCommandT] - | collections.Callable[[_MessageCommandT], _MessageCommandT] - | collections.Callable[[_SlashCommandT], _SlashCommandT] -): +) -> typing.Union[ + collections.Callable[[_CommandT], _CommandT], + collections.Callable[[_MenuCommandT], _MenuCommandT], + collections.Callable[[_MessageCommandT], _MessageCommandT], + collections.Callable[[_SlashCommandT], _SlashCommandT], +]: """Add a check which will pass if all the provided checks pass through a decorator call. This ensures that the callbacks are run in the order they were supplied in @@ -1160,7 +1160,7 @@ def __init__( self._suppress = suppress async def __call__( - self, ctx: _ContextT, /, *, localiser: alluka.Injected[dependencies.AbstractLocaliser | None] = None + self, ctx: _ContextT, /, *, localiser: alluka.Injected[typing.Optional[dependencies.AbstractLocaliser]] = None ) -> bool: for check in self._checks: try: @@ -1240,8 +1240,8 @@ def with_any_checks( check: tanjun.CheckSig[tanjun.MenuContext], /, *checks: tanjun.CheckSig[tanjun.MenuContext], - error: collections.Callable[[], Exception] | None = None, - error_message: str | collections.Mapping[str, str] | None, + error: typing.Optional[collections.Callable[[], Exception]] = None, + error_message: typing.Union[str, collections.Mapping[str, str], None], follow_wrapped: bool = False, halt_execution: bool = False, suppress: tuple[type[Exception], ...] = (errors.CommandError, errors.HaltExecution), @@ -1254,8 +1254,8 @@ def with_any_checks( check: tanjun.CheckSig[tanjun.MessageContext], /, *checks: tanjun.CheckSig[tanjun.MessageContext], - error: collections.Callable[[], Exception] | None = None, - error_message: str | collections.Mapping[str, str] | None, + error: typing.Optional[collections.Callable[[], Exception]] = None, + error_message: typing.Union[str, collections.Mapping[str, str], None], follow_wrapped: bool = False, halt_execution: bool = False, suppress: tuple[type[Exception], ...] = (errors.CommandError, errors.HaltExecution), @@ -1268,8 +1268,8 @@ def with_any_checks( check: tanjun.CheckSig[tanjun.SlashContext], /, *checks: tanjun.CheckSig[tanjun.SlashContext], - error: collections.Callable[[], Exception] | None = None, - error_message: str | collections.Mapping[str, str] | None, + error: typing.Optional[collections.Callable[[], Exception]] = None, + error_message: typing.Union[str, collections.Mapping[str, str], None], follow_wrapped: bool = False, halt_execution: bool = False, suppress: tuple[type[Exception], ...] = (errors.CommandError, errors.HaltExecution), @@ -1281,17 +1281,17 @@ def with_any_checks( check: tanjun.CheckSig[typing.Any], /, *checks: tanjun.CheckSig[typing.Any], - error: collections.Callable[[], Exception] | None = None, - error_message: str | collections.Mapping[str, str] | None, + error: typing.Optional[collections.Callable[[], Exception]] = None, + error_message: typing.Union[str, collections.Mapping[str, str], None], follow_wrapped: bool = False, halt_execution: bool = False, suppress: tuple[type[Exception], ...] = (errors.CommandError, errors.HaltExecution), -) -> ( - collections.Callable[[_CommandT], _CommandT] - | collections.Callable[[_MenuCommandT], _MenuCommandT] - | collections.Callable[[_MessageCommandT], _MessageCommandT] - | collections.Callable[[_SlashCommandT], _SlashCommandT] -): +) -> typing.Union[ + collections.Callable[[_CommandT], _CommandT], + collections.Callable[[_MenuCommandT], _MenuCommandT], + collections.Callable[[_MessageCommandT], _MessageCommandT], + collections.Callable[[_SlashCommandT], _SlashCommandT], +]: """Add a check which'll pass if any of the provided checks pass through a decorator call. This ensures that the callbacks are run in the order they were supplied in diff --git a/tanjun/clients.py b/tanjun/clients.py index 2efacb595..f332e35ec 100644 --- a/tanjun/clients.py +++ b/tanjun/clients.py @@ -76,11 +76,9 @@ from typing_extensions import Self _CheckSigT = typing.TypeVar("_CheckSigT", bound=tanjun.AnyCheckSig) - _AppCmdResponse = ( - hikari.api.InteractionMessageBuilder - | hikari.api.InteractionDeferredBuilder - | hikari.api.InteractionModalBuilder - ) + _AppCmdResponse = typing.Union[ + hikari.api.InteractionMessageBuilder, hikari.api.InteractionDeferredBuilder, hikari.api.InteractionModalBuilder, + ] _EventT = typing.TypeVar("_EventT", bound=hikari.Event) _ListenerCallbackSigT = typing.TypeVar("_ListenerCallbackSigT", bound=tanjun.ListenerCallbackSig[typing.Any]) _MetaEventSigT = typing.TypeVar("_MetaEventSigT", bound=tanjun.MetaEventSig) @@ -492,11 +490,11 @@ async def __call__(self) -> None: def _log_clients( - cache: hikari.api.Cache | None, - events: hikari.api.EventManager | None, - server: hikari.api.InteractionServer | None, + cache: typing.Optional[hikari.api.Cache], + events: typing.Optional[hikari.api.EventManager], + server: typing.Optional[hikari.api.InteractionServer], rest: hikari.api.RESTClient, - shards: hikari.ShardAware | None, + shards: typing.Optional[hikari.ShardAware], event_managed: bool, /, ) -> None: @@ -3079,17 +3077,21 @@ def _try_unsubscribe( pass -@dataclasses.dataclass(slots=True) +@dataclasses.dataclass class _LoadModule: - path: str | pathlib.Path + __slots__ = ("path",) + + path: typing.Union[str, pathlib.Path] def __call__(self) -> types.ModuleType: return importlib.import_module(self.path) if isinstance(self.path, str) else _get_path_module(self.path) -@dataclasses.dataclass(slots=True) +@dataclasses.dataclass class _ReloadModule: - path: types.ModuleType | pathlib.Path + __slots__ = ("path",) + + path: typing.Union[types.ModuleType, pathlib.Path] def __call__(self) -> types.ModuleType: return _get_path_module(self.path) if isinstance(self.path, pathlib.Path) else importlib.reload(self.path) diff --git a/tanjun/commands/menu.py b/tanjun/commands/menu.py index 04fd22e71..2a43efcee 100644 --- a/tanjun/commands/menu.py +++ b/tanjun/commands/menu.py @@ -35,6 +35,8 @@ import typing +import hikari + from .. import _internal from .. import abc as tanjun from .. import components @@ -54,14 +56,12 @@ _MessageCallbackSigT = typing.TypeVar("_MessageCallbackSigT", bound=tanjun.MenuCallbackSig[hikari.Message]) _UserCallbackSigT = typing.TypeVar("_UserCallbackSigT", bound=tanjun.MenuCallbackSig[hikari.InteractionMember]) - _AnyCommandT = ( - tanjun.MenuCommand[_AnyCallbackSigT, typing.Any] - | tanjun.MessageCommand[_AnyCallbackSigT] - | tanjun.SlashCommand[_AnyCallbackSigT] - ) - _CallbackishT = _AnyCallbackSigT | _AnyCommandT[_AnyCallbackSigT] - -import hikari + _AnyCommandT = typing.Union[ + tanjun.MenuCommand[_AnyCallbackSigT, typing.Any], + tanjun.MessageCommand[_AnyCallbackSigT], + tanjun.SlashCommand[_AnyCallbackSigT], + ] + _CallbackishT = typing.Union[_AnyCallbackSigT, _AnyCommandT[_AnyCallbackSigT]] _AnyMenuCallbackSigT = typing.TypeVar("_AnyMenuCallbackSigT", bound=tanjun.MenuCallbackSig[typing.Any]) _MenuTypeT = typing.TypeVar( @@ -336,15 +336,15 @@ def __init__( self: MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]], callback: _UserCallbackSigT, type_: typing.Literal[hikari.CommandType.USER], - name: str | collections.Mapping[str, str], + name: typing.Union[str, collections.Mapping[str, str]], /, *, always_defer: bool = False, - default_member_permissions: hikari.Permissions | int | None = None, - default_to_ephemeral: bool | None = None, - dm_enabled: bool | None = None, + default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, + default_to_ephemeral: typing.Optional[bool] = None, + dm_enabled: typing.Optional[bool] = None, is_global: bool = True, - _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, + _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, ) -> None: ... @@ -372,15 +372,15 @@ def __init__( self: MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]], callback: _MessageCallbackSigT, type_: typing.Literal[hikari.CommandType.MESSAGE], - name: str | collections.Mapping[str, str], + name: typing.Union[str, collections.Mapping[str, str]], /, *, always_defer: bool = False, - default_member_permissions: hikari.Permissions | int | None = None, - default_to_ephemeral: bool | None = None, - dm_enabled: bool | None = None, + default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, + default_to_ephemeral: typing.Optional[bool] = None, + dm_enabled: typing.Optional[bool] = None, is_global: bool = True, - _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, + _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, ) -> None: ... diff --git a/tanjun/commands/message.py b/tanjun/commands/message.py index 502e86a92..63044a531 100644 --- a/tanjun/commands/message.py +++ b/tanjun/commands/message.py @@ -49,12 +49,12 @@ _AnyMessageCommandT = typing.TypeVar("_AnyMessageCommandT", bound=tanjun.MessageCommand[typing.Any]) _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=collections.Callable[..., typing.Any]) - _AnyCommandT = ( - tanjun.MenuCommand[_AnyCallbackSigT, typing.Any] - | tanjun.MessageCommand[_AnyCallbackSigT] - | tanjun.SlashCommand[_AnyCallbackSigT] - ) - _CallbackishT: typing.TypeAlias = "_AnyCommandT[_MessageCallbackSigT] | _MessageCallbackSigT" + _AnyCommandT = typing.Union[ + tanjun.MenuCommand[_AnyCallbackSigT, typing.Any], + tanjun.MessageCommand[_AnyCallbackSigT], + tanjun.SlashCommand[_AnyCallbackSigT], + ] + _CallbackishT = typing.Union[_AnyCommandT["_MessageCallbackSigT"], "_MessageCallbackSigT"] _OtherCallbackSigT = typing.TypeVar("_OtherCallbackSigT", bound=tanjun.MessageCallbackSig) @@ -185,7 +185,7 @@ def __init__( /, *names: str, validate_arg_keys: bool = True, - _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, + _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, ) -> None: ... @@ -197,7 +197,7 @@ def __init__( /, *names: str, validate_arg_keys: bool = True, - _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, + _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, ) -> None: ... @@ -387,7 +387,7 @@ def __init__( *names: str, strict: bool = False, validate_arg_keys: bool = True, - _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, + _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, ) -> None: ... @@ -400,7 +400,7 @@ def __init__( *names: str, strict: bool = False, validate_arg_keys: bool = True, - _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, + _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, ) -> None: ... @@ -505,7 +505,7 @@ def as_sub_command( """ def decorator( - callback: _OtherCallbackSigT | _AnyCommandT[_OtherCallbackSigT], / + callback: typing.Union[_OtherCallbackSigT, _AnyCommandT[_OtherCallbackSigT]], / ) -> MessageCommand[_OtherCallbackSigT]: return self.with_command(as_message_command(name, *names, validate_arg_keys=validate_arg_keys)(callback)) diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index 990f9c914..a64ee12d8 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -76,13 +76,13 @@ _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=collections.Callable[..., typing.Any]) _AnyBaseSlashCommandT = typing.TypeVar("_AnyBaseSlashCommandT", bound=tanjun.BaseSlashCommand) _SlashCommandT = typing.TypeVar("_SlashCommandT", bound="SlashCommand[typing.Any]") - _AnyCommandT = ( - tanjun.MenuCommand[_AnyCallbackSigT, typing.Any] - | tanjun.MessageCommand[_AnyCallbackSigT] - | tanjun.SlashCommand[_AnyCallbackSigT] - ) - _AnyConverterSig: typing.TypeAlias = "ConverterSig[float] | ConverterSig[int] | ConverterSig[str]" - _CallbackishT: typing.TypeAlias = "_SlashCallbackSigT | _AnyCommandT[_SlashCallbackSigT]" + _AnyCommandT = typing.Union[ + tanjun.MenuCommand[_AnyCallbackSigT, typing.Any], + tanjun.MessageCommand[_AnyCallbackSigT], + tanjun.SlashCommand[_AnyCallbackSigT], + ] + _AnyConverterSig = typing.Union["ConverterSig[float]", "ConverterSig[int]", "ConverterSig[str]"] + _CallbackishT = typing.Union["_SlashCallbackSigT", _AnyCommandT["_SlashCallbackSigT"]] _IntAutocompleteSigT = typing.TypeVar("_IntAutocompleteSigT", bound=tanjun.AutocompleteSig[int]) _FloatAutocompleteSigT = typing.TypeVar("_FloatAutocompleteSigT", bound=tanjun.AutocompleteSig[float]) @@ -98,7 +98,7 @@ _ConverterSig = collections.Callable[ typing_extensions.Concatenate[_ConvertT, _P], - collections.Coroutine[typing.Any, typing.Any, typing.Any] | typing.Any, + typing.Union[collections.Coroutine[typing.Any, typing.Any, typing.Any], typing.Any], ] ConverterSig = _ConverterSig[_ConvertT, ...] """Type hint of a slash command option converter.""" @@ -428,9 +428,9 @@ def with_str_slash_option( description: typing.Union[str, collections.Mapping[str, str]], /, *, - autocomplete: tanjun.AutocompleteSig[str] | None = None, + autocomplete: typing.Optional[tanjun.AutocompleteSig[str]] = None, choices: typing.Union[collections.Mapping[str, str], collections.Sequence[str], None] = None, - converters: collections.Sequence[ConverterSig[str]] | ConverterSig[str] = (), + converters: typing.Union[collections.Sequence[ConverterSig[str]], ConverterSig[str]] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_length: typing.Optional[int] = None, @@ -476,9 +476,9 @@ def with_int_slash_option( description: typing.Union[str, collections.Mapping[str, str]], /, *, - autocomplete: tanjun.AutocompleteSig[int] | None = None, + autocomplete: typing.Optional[tanjun.AutocompleteSig[int]] = None, choices: typing.Optional[collections.Mapping[str, int]] = None, - converters: collections.Sequence[ConverterSig[int]] | ConverterSig[int] = (), + converters: typing.Union[collections.Sequence[ConverterSig[int]], ConverterSig[int]] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_value: typing.Optional[int] = None, @@ -525,9 +525,9 @@ def with_float_slash_option( /, *, always_float: bool = True, - autocomplete: tanjun.AutocompleteSig[float] | None = None, + autocomplete: typing.Optional[tanjun.AutocompleteSig[float]] = None, choices: typing.Optional[collections.Mapping[str, float]] = None, - converters: collections.Sequence[ConverterSig[float]] | ConverterSig[float] = (), + converters: typing.Union[collections.Sequence[ConverterSig[float]], ConverterSig[float]] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_value: typing.Optional[float] = None, @@ -782,7 +782,7 @@ def __init__( name: str, option_type: typing.Union[hikari.OptionType, int], always_float: bool = False, - converters: list[_AnyConverterSig] | None = None, + converters: typing.Optional[list[_AnyConverterSig]] = None, only_member: bool = False, default: typing.Any = UNDEFINED_DEFAULT, ) -> None: @@ -1456,18 +1456,18 @@ class SlashCommand(BaseSlashCommand, tanjun.SlashCommand[_SlashCallbackSigT]): def __init__( self, callback: _SlashCallbackSigT, - name: str | collections.Mapping[str, str], - description: str | collections.Mapping[str, str], + name: typing.Union[str, collections.Mapping[str, str]], + description: typing.Union[str, collections.Mapping[str, str]], /, *, always_defer: bool = False, - default_member_permissions: hikari.Permissions | int | None = None, - default_to_ephemeral: bool | None = None, - dm_enabled: bool | None = None, + default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, + default_to_ephemeral: typing.Optional[bool] = None, + dm_enabled: typing.Optional[bool] = None, is_global: bool = True, sort_options: bool = True, validate_arg_keys: bool = True, - _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, + _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, ) -> None: ... @@ -1475,26 +1475,26 @@ def __init__( def __init__( self, callback: _AnyCommandT[_SlashCallbackSigT], - name: str | collections.Mapping[str, str], - description: str | collections.Mapping[str, str], + name: typing.Union[str, collections.Mapping[str, str]], + description: typing.Union[str, collections.Mapping[str, str]], /, *, always_defer: bool = False, - default_member_permissions: hikari.Permissions | int | None = None, - default_to_ephemeral: bool | None = None, - dm_enabled: bool | None = None, + default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, + default_to_ephemeral: typing.Optional[bool] = None, + dm_enabled: typing.Optional[bool] = None, is_global: bool = True, sort_options: bool = True, validate_arg_keys: bool = True, - _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, + _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, ) -> None: ... def __init__( self, callback: _CallbackishT[_SlashCallbackSigT], - name: str | collections.Mapping[str, str], - description: str | collections.Mapping[str, str], + name: typing.Union[str, collections.Mapping[str, str]], + description: typing.Union[str, collections.Mapping[str, str]], /, *, always_defer: bool = False, @@ -1679,7 +1679,7 @@ def _add_option( choices: typing.Union[ collections.Mapping[str, typing.Union[str, int, float]], collections.Sequence[typing.Any], None ] = None, - converters: collections.Sequence[_AnyConverterSig] | _AnyConverterSig = (), + converters: typing.Union[collections.Sequence[_AnyConverterSig], _AnyConverterSig] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_length: typing.Optional[int] = None, @@ -1845,9 +1845,9 @@ def add_str_option( description: typing.Union[str, collections.Mapping[str, str]], /, *, - autocomplete: tanjun.AutocompleteSig[str] | None = None, + autocomplete: typing.Optional[tanjun.AutocompleteSig[str]] = None, choices: typing.Union[collections.Mapping[str, str], collections.Sequence[str], None] = None, - converters: collections.Sequence[ConverterSig[str]] | ConverterSig[str] = (), + converters: typing.Union[collections.Sequence[ConverterSig[str]], ConverterSig[str]] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_length: typing.Optional[int] = None, @@ -1993,9 +1993,9 @@ def add_int_option( description: typing.Union[str, collections.Mapping[str, str]], /, *, - autocomplete: tanjun.AutocompleteSig[int] | None = None, + autocomplete: typing.Optional[tanjun.AutocompleteSig[int]] = None, choices: typing.Optional[collections.Mapping[str, int]] = None, - converters: collections.Sequence[ConverterSig[int]] | ConverterSig[int] = (), + converters: typing.Union[collections.Sequence[ConverterSig[int]], ConverterSig[int]] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_value: typing.Optional[int] = None, @@ -2104,9 +2104,9 @@ def add_float_option( /, *, always_float: bool = True, - autocomplete: tanjun.AutocompleteSig[float] | None = None, + autocomplete: typing.Optional[tanjun.AutocompleteSig[float]] = None, choices: typing.Optional[collections.Mapping[str, float]] = None, - converters: collections.Sequence[ConverterSig[float]] | ConverterSig[float] = (), + converters: typing.Union[collections.Sequence[ConverterSig[float]], ConverterSig[float]] = (), default: typing.Any = UNDEFINED_DEFAULT, key: typing.Optional[str] = None, min_value: typing.Optional[float] = None, @@ -2623,7 +2623,7 @@ def add_mentionable_option( pass_as_kwarg=pass_as_kwarg, ) - def set_float_autocomplete(self, name: str, callback: tanjun.AutocompleteSig[float] | None, /) -> Self: + def set_float_autocomplete(self, name: str, callback: typing.Optional[tanjun.AutocompleteSig[float]], /) -> Self: """Set the autocomplete callback for a float option. Parameters diff --git a/tanjun/components.py b/tanjun/components.py index d0c9e54ea..603dea41c 100644 --- a/tanjun/components.py +++ b/tanjun/components.py @@ -70,7 +70,7 @@ # This errors on earlier 3.9 releases when not quotes cause dumb handling of the [_CommandT] list _WithCommandReturnSig = typing.Union[_CommandT, "collections.Callable[[_CommandT], _CommandT]"] -OnCallbackSig = collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, None] | None] +OnCallbackSig = collections.Callable[..., typing.Optional[collections.Coroutine[typing.Any, typing.Any, None]]] """Type hint of a on_open or on_close component callback. These support dependency injection, should expect no positional arguments and diff --git a/tanjun/dependencies/reloaders.py b/tanjun/dependencies/reloaders.py index 2ef34d229..89f9efe30 100644 --- a/tanjun/dependencies/reloaders.py +++ b/tanjun/dependencies/reloaders.py @@ -547,7 +547,7 @@ def _scan_one(path: pathlib.Path, /) -> typing.Optional[int]: return None # MyPy compat -@dataclasses.dataclass(slots=True) +@dataclasses.dataclass class _ScanResult: py_paths: dict[str, _PyPathInfo] = dataclasses.field(init=False, default_factory=dict) removed_py_paths: list[str] = dataclasses.field(init=False, default_factory=list) @@ -555,10 +555,12 @@ class _ScanResult: sys_paths: dict[pathlib.Path, _PyPathInfo] = dataclasses.field(init=False, default_factory=dict) -@dataclasses.dataclass(slots=True) +@dataclasses.dataclass class _PathScanner(typing.Generic[_PathT]): + __slots__ = ("dead_unloads", "global_paths", "removed_paths", "result_paths") + global_paths: dict[_PathT, _PyPathInfo] - dead_unloads: set[str | pathlib.Path] + dead_unloads: set[typing.Union[str, pathlib.Path]] result_paths: dict[_PathT, _PyPathInfo] removed_paths: list[_PathT] @@ -592,7 +594,7 @@ def process(self) -> None: self.removed_paths.append(path) -@dataclasses.dataclass(slots=True) +@dataclasses.dataclass class _PathLoader(typing.Generic[_PathT]): waiting_for: dict[_PathT, int] paths: dict[_PathT, _PyPathInfo] diff --git a/tanjun/hooks.py b/tanjun/hooks.py index 9b2a8c706..102aac99e 100644 --- a/tanjun/hooks.py +++ b/tanjun/hooks.py @@ -153,7 +153,7 @@ def add_on_error(self, callback: tanjun.ErrorHookSig[_ContextT_contra], /) -> Se self._error_callbacks.append(callback) return self - def set_on_error(self, callback: tanjun.ErrorHookSig[_ContextT_contra] | None, /) -> Self: + def set_on_error(self, callback: typing.Optional[tanjun.ErrorHookSig[_ContextT_contra]], /) -> Self: """Set the error callback for this hook object. !!! note @@ -210,7 +210,7 @@ def add_on_parser_error(self, callback: tanjun.ParserHookSig[_ContextT_contra], self._parser_error_callbacks.append(callback) return self - def set_on_parser_error(self, callback: tanjun.ParserHookSig[_ContextT_contra] | None, /) -> Self: + def set_on_parser_error(self, callback: typing.Optional[tanjun.ParserHookSig[_ContextT_contra]], /) -> Self: """Set the parser error callback for this hook object. Parameters @@ -260,7 +260,7 @@ def add_post_execution(self, callback: tanjun.HookSig[_ContextT_contra], /) -> S self._post_execution_callbacks.append(callback) return self - def set_post_execution(self, callback: tanjun.HookSig[_ContextT_contra] | None, /) -> Self: + def set_post_execution(self, callback: typing.Optional[tanjun.HookSig[_ContextT_contra]], /) -> Self: """Set the post-execution callback for this hook object. Parameters @@ -307,7 +307,7 @@ def add_pre_execution(self, callback: tanjun.HookSig[_ContextT_contra], /) -> Se self._pre_execution_callbacks.append(callback) return self - def set_pre_execution(self, callback: tanjun.HookSig[_ContextT_contra] | None, /) -> Self: + def set_pre_execution(self, callback: typing.Optional[tanjun.HookSig[_ContextT_contra]], /) -> Self: """Set the pre-execution callback for this hook object. Parameters @@ -354,7 +354,7 @@ def add_on_success(self, callback: tanjun.HookSig[_ContextT_contra], /) -> Self: self._success_callbacks.append(callback) return self - def set_on_success(self, callback: tanjun.HookSig[_ContextT_contra] | None, /) -> Self: + def set_on_success(self, callback: typing.Optional[tanjun.HookSig[_ContextT_contra]], /) -> Self: """Set the success callback for this hook object. Parameters diff --git a/tanjun/parsing.py b/tanjun/parsing.py index 3e235acca..59d8bc8ec 100644 --- a/tanjun/parsing.py +++ b/tanjun/parsing.py @@ -80,7 +80,7 @@ def __len__(self) -> int: raise NotImplementedError _CmpProtoT = typing.TypeVar("_CmpProtoT", bound=_CmpProto[typing.Any]) - _MaybeIterable: typing.TypeAlias = "collections.Iterable[_T] | _T" + _MaybeIterable = typing.Union[collections.Iterable["_T"], "_T"] _SizedCmpProtoT = typing.TypeVar("_SizedCmpProtoT", bound=_SizedCmpProto[typing.Any]) @@ -90,7 +90,7 @@ def __len__(self) -> int: if typing.TYPE_CHECKING: _P = typing_extensions.ParamSpec("_P") _ConverterSig = collections.Callable[ - typing_extensions.Concatenate[str, _P], collections.Coroutine[typing.Any, typing.Any, _T] | _T + typing_extensions.Concatenate[str, _P], typing.Union[collections.Coroutine[typing.Any, typing.Any, _T], _T] ] ConverterSig = _ConverterSig[..., _T] @@ -104,7 +104,7 @@ def __len__(self) -> int: import types ConverterSig = types.GenericAlias( - collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, _T] | _T], (_T,) + collections.Callable[..., typing.Union[collections.Coroutine[typing.Any, typing.Any, _T], _T]], (_T,) ) diff --git a/tanjun/schedules.py b/tanjun/schedules.py index 97e39d01c..a3d939eb8 100644 --- a/tanjun/schedules.py +++ b/tanjun/schedules.py @@ -595,8 +595,10 @@ def _to_sequence( return values -@dataclasses.dataclass(slots=True) +@dataclasses.dataclass class _TimeScheduleConfig: + __slots__ = ("current_date", "days", "hours", "is_weekly", "minutes", "months", "seconds", "timezone") + current_date: datetime.datetime days: typing.Optional[collections.Sequence[int]] hours: collections.Sequence[int] From 8d2a52dfb9552fe4a54ae86ff55f469c60c348ea Mon Sep 17 00:00:00 2001 From: "always-on-duty[bot]" <120557446+always-on-duty[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 05:31:06 +0000 Subject: [PATCH 33/45] Freeze PR dependency changes --- dev-requirements/constraints.txt | 4 ++-- dev-requirements/tests.txt | 4 ++-- dev-requirements/type-checking.txt | 20 ++++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/dev-requirements/constraints.txt b/dev-requirements/constraints.txt index a1dcfe872..878e6a76a 100644 --- a/dev-requirements/constraints.txt +++ b/dev-requirements/constraints.txt @@ -269,10 +269,10 @@ multidict==6.0.4 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf \ --hash=sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d \ --hash=sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba -typing-extensions==4.4.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ +typing-extensions==4.4.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa \ --hash=sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e -yarl==1.8.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ +yarl==1.8.2 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:009a028127e0a1755c38b03244c0bea9d5565630db9c4cf9572496e947137a87 \ --hash=sha256:0414fd91ce0b763d4eadb4456795b307a71524dbacd015c657bb2a39db2eab89 \ --hash=sha256:0978f29222e649c351b173da2b9b4665ad1feb8d1daa9d971eb90df08702668a \ diff --git a/dev-requirements/tests.txt b/dev-requirements/tests.txt index a434635bf..1cc9a52ef 100644 --- a/dev-requirements/tests.txt +++ b/dev-requirements/tests.txt @@ -113,7 +113,7 @@ colorama==0.4.6 ; python_full_version >= "3.9.0" and python_version < "3.12" and colorlog==6.7.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662 \ --hash=sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5 -coverage[toml]==7.1.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ +coverage[toml]==7.1.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:04481245ef966fbd24ae9b9e537ce899ae584d521dfbe78f89cad003c38ca2ab \ --hash=sha256:0c45948f613d5d18c9ec5eaa203ce06a653334cf1bd47c783a12d0dd4fd9c851 \ --hash=sha256:10188fe543560ec4874f974b5305cd1a8bdcfa885ee00ea3a03733464c4ca265 \ @@ -165,7 +165,7 @@ coverage[toml]==7.1.0 ; python_full_version >= "3.10.0" and python_version < "3. --hash=sha256:f2cba5c6db29ce991029b5e4ac51eb36774458f0a3b8d3137241b32d1bb91f06 \ --hash=sha256:f5b4198d85a3755d27e64c52f8c95d6333119e49fd001ae5798dac872c95e0f8 \ --hash=sha256:ffeeb38ee4a80a30a6877c5c4c359e5498eec095878f1581453202bfacc8fbc2 -exceptiongroup==1.1.0 ; python_full_version >= "3.10.0" and python_version < "3.11" \ +exceptiongroup==1.1.0 ; python_full_version >= "3.9.0" and python_version < "3.11" \ --hash=sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e \ --hash=sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23 execnet==1.9.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ diff --git a/dev-requirements/type-checking.txt b/dev-requirements/type-checking.txt index 7d7c7c980..ff5f9eeaa 100644 --- a/dev-requirements/type-checking.txt +++ b/dev-requirements/type-checking.txt @@ -116,7 +116,7 @@ colorama==0.4.6 ; python_full_version >= "3.9.0" and python_version < "3.12" and colorlog==6.7.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662 \ --hash=sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5 -coverage[toml]==7.1.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ +coverage[toml]==7.1.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:04481245ef966fbd24ae9b9e537ce899ae584d521dfbe78f89cad003c38ca2ab \ --hash=sha256:0c45948f613d5d18c9ec5eaa203ce06a653334cf1bd47c783a12d0dd4fd9c851 \ --hash=sha256:10188fe543560ec4874f974b5305cd1a8bdcfa885ee00ea3a03733464c4ca265 \ @@ -168,7 +168,7 @@ coverage[toml]==7.1.0 ; python_full_version >= "3.10.0" and python_version < "3. --hash=sha256:f2cba5c6db29ce991029b5e4ac51eb36774458f0a3b8d3137241b32d1bb91f06 \ --hash=sha256:f5b4198d85a3755d27e64c52f8c95d6333119e49fd001ae5798dac872c95e0f8 \ --hash=sha256:ffeeb38ee4a80a30a6877c5c4c359e5498eec095878f1581453202bfacc8fbc2 -distlib==0.3.6 ; python_full_version >= "3.10.0" and python_version < "3.12" \ +distlib==0.3.6 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46 \ --hash=sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e exceptiongroup==1.1.0 ; python_full_version >= "3.9.0" and python_version < "3.11" \ @@ -270,7 +270,7 @@ iniconfig==2.0.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ jinja2==3.1.2 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 -markupsafe==2.1.2 ; python_full_version >= "3.10.0" and python_version < "3.12" \ +markupsafe==2.1.2 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed \ --hash=sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc \ --hash=sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2 \ @@ -321,7 +321,7 @@ markupsafe==2.1.2 ; python_full_version >= "3.10.0" and python_version < "3.12" --hash=sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2 \ --hash=sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6 \ --hash=sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58 -multidict==6.0.4 ; python_full_version >= "3.10.0" and python_version < "3.12" \ +multidict==6.0.4 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9 \ --hash=sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8 \ --hash=sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03 \ @@ -482,10 +482,10 @@ pydantic==1.10.4 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:f2f7eb6273dd12472d7f218e1fef6f7c7c2f00ac2e1ecde4db8824c457300416 \ --hash=sha256:fdf88ab63c3ee282c76d652fc86518aacb737ff35796023fae56a65ced1a5978 \ --hash=sha256:fdf8d759ef326962b4678d89e275ffc55b7ce59d917d9f72233762061fd04a2d -pyright==1.1.291 ; python_full_version >= "3.10.0" and python_version < "3.12" \ +pyright==1.1.291 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:2dbd133ee400e81ff319d0701bc47545a7ab1cd7dcfcf46c7de37d9b0fbbb76f \ --hash=sha256:3946f43f1a99f8e438eee1738ad0649d8bd7ac36dded25849245993ab02671bd -pytest-asyncio==0.20.3 ; python_full_version >= "3.10.0" and python_version < "3.12" \ +pytest-asyncio==0.20.3 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:83cbf01169ce3e8eb71c6c278ccb0574d1a7a3bb8eaaf5e50e0ad342afb33b36 \ --hash=sha256:f129998b209d04fcc65c96fc85c11e5316738358909a8399e93be553d7656442 pytest-cov==4.0.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ @@ -506,10 +506,10 @@ pytest==7.2.1 ; python_full_version >= "3.9.0" and python_version < "3.12" \ python-dateutil==2.8.2 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 -setuptools==66.1.1 ; python_full_version >= "3.10.0" and python_version < "3.12" \ - --hash=sha256:6f590d76b713d5de4e49fe4fbca24474469f53c83632d5d0fd056f7ff7e8112b \ - --hash=sha256:ac4008d396bc9cd983ea483cb7139c0240a07bbc74ffb6232fceffedc6cf03a8 -six==1.16.0 ; python_full_version >= "3.10.0" and python_version < "3.12" \ +setuptools==67.0.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ + --hash=sha256:883131c5b6efa70b9101c7ef30b2b7b780a4283d5fc1616383cdf22c83cbefe6 \ + --hash=sha256:9d790961ba6219e9ff7d9557622d2fe136816a264dd01d5997cfc057d804853d +six==1.16.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 termcolor==2.2.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ From d16f50298066870c5ce37de40074da3f0cbd4b6c Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Mon, 30 Jan 2023 15:41:19 +0000 Subject: [PATCH 34/45] Some more fixes + changelog entry --- CHANGELOG.md | 3 +++ tanjun/abc.py | 1 + tanjun/parsing.py | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13186a1be..820f3d610 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### [2.11.2] - 2023-01-23 ### Changed - [tanjun.clients.Client.from_gateway_bot][] can now also take cache-less `ShardAware` bots. +- Improved the typing of callbacks which support DI to enforce the type of any positionally + passed arguments with a static type. + MyPy doesn't support this and will just behave as before. ### Fixed - [tanjun.clients.Client.set_human_only][] no longer registers the internal check multiple diff --git a/tanjun/abc.py b/tanjun/abc.py index 79e5dcab7..a7d9fa497 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -263,6 +263,7 @@ regardless of implementation and must be a coruotine function which returns [None][]. """ +# 3.9 and 3.10 just can't handle ending a Paramspec with ... so we lie at runtime about this. else: import types diff --git a/tanjun/parsing.py b/tanjun/parsing.py index 59d8bc8ec..fbd14f3ae 100644 --- a/tanjun/parsing.py +++ b/tanjun/parsing.py @@ -86,7 +86,7 @@ def __len__(self) -> int: _T = typing.TypeVar("_T") -"""Type hint of a slash command option converter.""" +# 3.9 and 3.10 just can't handle ending a Paramspec with ... so we lie at runtime about this. if typing.TYPE_CHECKING: _P = typing_extensions.ParamSpec("_P") _ConverterSig = collections.Callable[ From 706069b0fb54a17504cf14d34159dab382e800d7 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Mon, 30 Jan 2023 15:59:26 +0000 Subject: [PATCH 35/45] Another small fixa --- tanjun/components.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tanjun/components.py b/tanjun/components.py index 603dea41c..c2b4bbbc3 100644 --- a/tanjun/components.py +++ b/tanjun/components.py @@ -64,11 +64,10 @@ _OnCallbackSigT = typing.TypeVar("_OnCallbackSigT", bound="OnCallbackSig") _ScheduleT = typing.TypeVar("_ScheduleT", bound=schedules_.AbstractSchedule) + _CommandT = typing.TypeVar("_CommandT", bound="tanjun.ExecutableCommand[typing.Any]") + _WithCommandReturnSig = typing.Union[_CommandT, "collections.Callable[[_CommandT], _CommandT]"] _LOGGER = logging.getLogger("hikari.tanjun.components") -_CommandT = typing.TypeVar("_CommandT", bound="tanjun.ExecutableCommand[typing.Any]") -# This errors on earlier 3.9 releases when not quotes cause dumb handling of the [_CommandT] list -_WithCommandReturnSig = typing.Union[_CommandT, "collections.Callable[[_CommandT], _CommandT]"] OnCallbackSig = collections.Callable[..., typing.Optional[collections.Coroutine[typing.Any, typing.Any, None]]] """Type hint of a on_open or on_close component callback. @@ -107,7 +106,7 @@ def decorator(command: _CommandT, /, *, _recursing: bool = False) -> _CommandT: add_command(target_command) if follow_wrapped and not _recursing: for wrapped in _internal.collect_wrapped(target_command): - decorator(typing.cast(_CommandT, wrapped), _recursing=True) + decorator(typing.cast("_CommandT", wrapped), _recursing=True) return command From f663318a0c29196b9d2c0e507d6ccbfcd22e58f6 Mon Sep 17 00:00:00 2001 From: Lucina Date: Mon, 30 Jan 2023 16:04:56 +0000 Subject: [PATCH 36/45] Remove typing_extensions runtime dep --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 0f28904af..3085ed28b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,7 @@ classifiers = [ "Topic :: Utilities", "Typing :: Typed", ] -dependencies = ["alluka>=0.1.2, <1", "hikari>=2.0.0.dev115, <3", "typing-extensions~=4.4"] +dependencies = ["alluka>=0.1.2, <1", "hikari>=2.0.0.dev115, <3"] dynamic = ["description"] [project.urls] From 4f2d85dff757df26b4a4356f809996ed2bc3cb6e Mon Sep 17 00:00:00 2001 From: Lucina Date: Mon, 30 Jan 2023 16:05:02 +0000 Subject: [PATCH 37/45] Add back typing_extensions test dep --- dev-requirements/tests.in | 1 + 1 file changed, 1 insertion(+) diff --git a/dev-requirements/tests.in b/dev-requirements/tests.in index 384742211..b68f82021 100644 --- a/dev-requirements/tests.in +++ b/dev-requirements/tests.in @@ -5,3 +5,4 @@ freezegun>=1.2.2, <2 pytest-asyncio>=0.20.1, <1 pytest-timeout>=2.1, <3 pytest-xdist>=3.1, <4 +typing-extensions~=4.4 From 8a07a84df38a8b5f7e018180f59d09c9014b0a93 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Mon, 30 Jan 2023 16:07:46 +0000 Subject: [PATCH 38/45] Don't import typing_extensions at runtime --- tanjun/abc.py | 3 ++- tanjun/commands/slash.py | 3 ++- tanjun/parsing.py | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tanjun/abc.py b/tanjun/abc.py index a7d9fa497..8ae06308c 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -73,7 +73,6 @@ from collections import abc as collections import hikari -import typing_extensions from alluka import abc as alluka if typing.TYPE_CHECKING: @@ -132,6 +131,8 @@ # 3.9 and 3.10 just can't handle ending a Paramspec with ... so we lie at runtime about this. if typing.TYPE_CHECKING: + import typing_extensions + _P = typing_extensions.ParamSpec("_P") _MaybeAwaitable = collections.Callable[_P, typing.Union[_CoroT[_T], _T]] diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index a64ee12d8..442b6a470 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -58,7 +58,6 @@ from collections import abc as collections import hikari -import typing_extensions from .. import _internal from .. import abc as tanjun @@ -94,6 +93,8 @@ # 3.9 and 3.10 just can't handle ending a Paramspec with ... so we lie at runtime about this. if typing.TYPE_CHECKING: + import typing_extensions + _P = typing_extensions.ParamSpec("_P") _ConverterSig = collections.Callable[ diff --git a/tanjun/parsing.py b/tanjun/parsing.py index fbd14f3ae..4938ccb49 100644 --- a/tanjun/parsing.py +++ b/tanjun/parsing.py @@ -56,8 +56,6 @@ import typing from collections import abc as collections -import typing_extensions - from . import abc as tanjun from . import conversion from . import errors @@ -88,6 +86,8 @@ def __len__(self) -> int: # 3.9 and 3.10 just can't handle ending a Paramspec with ... so we lie at runtime about this. if typing.TYPE_CHECKING: + import typing_extensions + _P = typing_extensions.ParamSpec("_P") _ConverterSig = collections.Callable[ typing_extensions.Concatenate[str, _P], typing.Union[collections.Coroutine[typing.Any, typing.Any, _T], _T] From 6765b965113773d45cda95d0feaad52d7876ceb0 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Mon, 30 Jan 2023 16:16:49 +0000 Subject: [PATCH 39/45] Some simplifications + restore all --- tanjun/abc.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tanjun/abc.py b/tanjun/abc.py index 8ae06308c..a66d3c937 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -36,6 +36,7 @@ "AnyHooks", "AppCommand", "AppCommandContext", + "AutocompleteCallbackSig", "AutocompleteContext", "AutocompleteSig", "BaseSlashCommand", @@ -43,6 +44,7 @@ "Client", "ClientCallbackNames", "ClientLoader", + "CommandCallbackSig", "Component", "Context", "ErrorHookSig", @@ -52,6 +54,7 @@ "ListenerCallbackSig", "MenuCallbackSig", "MenuCommand", + "MenuCommandCallbackSig", "MenuContext", "MenuHooks", "MessageCommand", @@ -150,9 +153,6 @@ autocomplete type), returns [None][] and may use dependency injection. """ - AutocompleteCallbackSig = AutocompleteSig - """Deprecated alias of [tanjun.abc.AutocompleteSig][].""" - _CheckSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, _P], bool] CheckSig = _CheckSig[_ContextT_contra, ...] """Type hint of a generic context check used with Tanjun [tanjun.abc.ExecutableCommand][] classes. @@ -183,9 +183,6 @@ This must be asynchronous and return [None][]. """ - MenuCommandCallbackSig = MenuCallbackSig - """Deprecated alias of [tanjun.abc.MenuCallbackSig][].""" - _CommandCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _P], _CoroT[None]] MessageCallbackSig = _CommandCallbackSig["MessageContext", ...] @@ -269,11 +266,9 @@ import types AutocompleteSig = types.GenericAlias(collections.Callable[..., typing.Any], (_AutocompleteValueT,)) - AutocompleteCallbackSig = AutocompleteSig CheckSig = types.GenericAlias(collections.Callable[..., typing.Any], (_ContextT_contra,)) AnyCheckSig = CheckSig MenuCallbackSig = types.GenericAlias(collections.Callable[..., typing.Any], (_MenuValueT,)) - MenuCommandCallbackSig = MenuCallbackSig MessageCallbackSig = collections.Callable[..., typing.Any] SlashCallbackSig = collections.Callable[..., typing.Any] ErrorHookSig = types.GenericAlias(collections.Callable[..., typing.Any], (_ContextT_contra,)) @@ -283,6 +278,12 @@ ListenerCallbackSig = types.GenericAlias(collections.Callable[..., typing.Any], (_EventT,)) +AutocompleteCallbackSig = AutocompleteSig +"""Deprecated alias of [tanjun.abc.AutocompleteSig][].""" + +MenuCommandCallbackSig = MenuCallbackSig +"""Deprecated alias of [tanjun.abc.MenuCallbackSig][].""" + _MenuCallbackSigT = typing.TypeVar("_MenuCallbackSigT", bound=MenuCallbackSig[typing.Any]) _MessageCallbackSigT = typing.TypeVar("_MessageCallbackSigT", bound=MessageCallbackSig) _SlashCallbackSigT = typing.TypeVar("_SlashCallbackSigT", bound=SlashCallbackSig) From 0cc054c4289ef1ca5b0b8865657e42d338b97914 Mon Sep 17 00:00:00 2001 From: Lucina Date: Mon, 30 Jan 2023 16:19:10 +0000 Subject: [PATCH 40/45] Remove typing_extensions from generated constraints file --- dev-requirements/constraints.in | 1 - 1 file changed, 1 deletion(-) diff --git a/dev-requirements/constraints.in b/dev-requirements/constraints.in index d2eeac918..0e09a12ec 100644 --- a/dev-requirements/constraints.in +++ b/dev-requirements/constraints.in @@ -1,3 +1,2 @@ alluka>=0.1.2, <1 hikari>=2.0.0.dev115, <3 -typing-extensions~=4.4 From 1907f88d52e2a2dc2da6b6e8459262a2492a4ce7 Mon Sep 17 00:00:00 2001 From: Lucina Date: Mon, 30 Jan 2023 16:19:53 +0000 Subject: [PATCH 41/45] Remove typing_extensions from generated constraints file --- dev-requirements/constraints.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/dev-requirements/constraints.txt b/dev-requirements/constraints.txt index 878e6a76a..cee34ebd5 100644 --- a/dev-requirements/constraints.txt +++ b/dev-requirements/constraints.txt @@ -269,9 +269,6 @@ multidict==6.0.4 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf \ --hash=sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d \ --hash=sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba -typing-extensions==4.4.0 ; python_full_version >= "3.9.0" and python_version < "3.12" \ - --hash=sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa \ - --hash=sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e yarl==1.8.2 ; python_full_version >= "3.9.0" and python_version < "3.12" \ --hash=sha256:009a028127e0a1755c38b03244c0bea9d5565630db9c4cf9572496e947137a87 \ --hash=sha256:0414fd91ce0b763d4eadb4456795b307a71524dbacd015c657bb2a39db2eab89 \ From 2172f0a4ba37462176d4c63b6efdcefde53b16fa Mon Sep 17 00:00:00 2001 From: Lucina Date: Mon, 30 Jan 2023 22:55:54 +0000 Subject: [PATCH 42/45] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 820f3d610..f554b5d6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - [tanjun.MenuHooks][] is now exported top-level. +### Changed +- Improved the typing of callbacks which support DI to enforce the type of any positionally + passed arguments with a static type. + MyPy doesn't support this and will just behave as before. + ### Fixed - [tanjun.annotations.Converted][] now properly overrides the actual type annotation for slash commands. @@ -18,9 +23,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### [2.11.2] - 2023-01-23 ### Changed - [tanjun.clients.Client.from_gateway_bot][] can now also take cache-less `ShardAware` bots. -- Improved the typing of callbacks which support DI to enforce the type of any positionally - passed arguments with a static type. - MyPy doesn't support this and will just behave as before. ### Fixed - [tanjun.clients.Client.set_human_only][] no longer registers the internal check multiple From 8b83f14fd0b239ae196812a213f0fb43683115ce Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Tue, 31 Jan 2023 05:07:32 +0000 Subject: [PATCH 43/45] Doc improvements --- tanjun/abc.py | 71 ++++++++++++++++++-------------------- tanjun/annotations.py | 4 +-- tanjun/clients.py | 17 +++++---- tanjun/commands/message.py | 12 +++---- tanjun/commands/slash.py | 7 +++- tanjun/components.py | 4 +-- tanjun/parsing.py | 4 +-- 7 files changed, 61 insertions(+), 58 deletions(-) diff --git a/tanjun/abc.py b/tanjun/abc.py index a66d3c937..55a7e7826 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -145,25 +145,28 @@ ] AutocompleteSig = _AutocompleteSig[_AutocompleteValueT, ...] - """Type hint of the callback an autocomplete callback should have. + """Type hint of the signature an autocomplete callback should have. - This will be called when handling autocomplete and should be an asynchronous - callback which two positional arguments of type [tanjun.abc.AutocompleteContext][] and - `str` or `int` or `float` (with the 2nd argument type being decided by the - autocomplete type), returns [None][] and may use dependency injection. + This represents the signature + `async def (tanjun.abc.AutocompleteContext, int | str | float) -> None` + where dependency injection is supported. """ _CheckSig = _MaybeAwaitable[typing_extensions.Concatenate[_ContextT_contra, _P], bool] CheckSig = _CheckSig[_ContextT_contra, ...] - """Type hint of a generic context check used with Tanjun [tanjun.abc.ExecutableCommand][] classes. + """Type hint of a generic context check used with Tanjun commands. - This may be registered with a [tanjun.abc.ExecutableCommand][] to add a rule + This may be registered with a command, client or component to add a rule which decides whether it should execute for each context passed to it. - This should take one positional argument of type [tanjun.abc.Context][] and may - either be a synchronous or asynchronous callback which returns [bool][]. - Returning [False][] or raising [tanjun.FailedCheck][] will indicate that the - current context shouldn't lead to an execution. + This represnts the signatures `def (tanjun.abc.Context, ...) -> bool | None` + and `async def (tanjun.abc.Context, ...) -> bool | None` where dependency + injection is supported. + + Check callbacks may either return [False][] to indicate that the current + command(s) don't match the context (without stopping execution) or raise + [tanjun.FailedCheck][] to indicate that command execution should be halted + early and marked as not found. """ AnyCheckSig = _CheckSig["Context", ...] @@ -175,12 +178,10 @@ MenuCallbackSig = _ManuCallbackSig["MenuContext", _MenuValueT, ...] """Type hint of a context menu command callback. - This is guaranteed two positional; arguments of type [tanjun.abc.MenuContext][] - and either `hikari.User | hikari.InteractionMember` and/or - [hikari.messages.Message][] dependent on the type(s) of menu this is, - and may use dependency injection. - - This must be asynchronous and return [None][]. + This represents the signature + `async def (tanjun.abc.MenuContext, hikari.Message, ...) -> None` or + `async def (tanjun.abc.MenuContext, hikari.InteractionMember, ...) -> None` + where dependency injection is supported. """ _CommandCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, _P], _CoroT[None]] @@ -188,19 +189,15 @@ MessageCallbackSig = _CommandCallbackSig["MessageContext", ...] """Type hint of a message command callback. - This is guaranteed one positional argument of type [tanjun.abc.MessageContext][] and - may use dependency injection. - - This must be asynchronous and return [None][]. + This represents the signature `async def (tanjun.abc.MessageContext, ...) -> None` + where dependency injection is supported. """ SlashCallbackSig = _CommandCallbackSig["SlashContext", ...] """Type hint of a slash command callback. - This is guaranteed one positional argument of type [tanjun.abc.SlashContext][] and - may use dependency injection. - - This must be asynchronous and return [None][]. + This represents the signature `async def (tanjun.abc.SlashContext, ...) -> None` + where dependency injection is supported. """ _ErrorHookSig = _MaybeAwaitable[ @@ -214,9 +211,9 @@ execution stage of a command (ignoring [tanjun.ParserError][] and expected [tanjun.TanjunError][] subclasses). - This should take two positional arguments - of type [tanjun.abc.Context][] and - [Exception][] - and may be either a synchronous or asynchronous callback which - returns [bool][] or [None][] and may take advantage of dependency injection. + This represents the signatures `def (tanjun.abc.Context, Exception, ...) -> bool | None` + and `async def (tanjun.abc.Context, Exception, ...) -> bool | None` where + dependency injection is supported. [True][] is returned to indicate that the exception should be suppressed and [False][] is returned to indicate that the exception should be re-raised. @@ -232,10 +229,9 @@ This will be called whenever an parser [ParserError][tanjun.errors.ParserError] is raised during the execution stage of a command. - This should take two positional arguments - of type [tanjun.abc.Context][] and - [ParserError][tanjun.errors.ParserError] - and may be either a synchronous or - asynchronous callback which returns [None][] and may take advantage of - dependency injection. + This represents the signatures `def (tanjun.abc.Context, tanjun.ParserError, ...) -> None` + and `async def (tanjun.abc.Context, tanjun.ParserError, ...) -> None` where + dependency injection is supported. Parser errors are always suppressed (unlike general errors). """ @@ -245,10 +241,9 @@ HookSig = _HookSig[_ContextT_contra, ...] """Type hint of the callback used as a general command hook. - !!! note - This may be asynchronous or synchronous, dependency injection is supported - for this callback's keyword arguments and the positional arguments which - are passed dependent on the type of hook this is being registered as. + This represents the signatures `def (tanjun.abc.Context, ...) -> None` and + `async def (tanjun.abc.Context, ...) -> None` where dependency injection is + supported. """ _EventT = typing.TypeVar("_EventT", bound=hikari.Event) @@ -257,8 +252,8 @@ ListenerCallbackSig = _ListenerCallbackSig[_EventT, ...] """Type hint of a hikari event manager callback. - This is guaranteed one positional arg of type [hikari.events.base_events.Event][] - regardless of implementation and must be a coruotine function which returns [None][]. + This represents the signature `async def (hikari.Event, ...) -> None` where + dependency injection is supported. """ # 3.9 and 3.10 just can't handle ending a Paramspec with ... so we lie at runtime about this. diff --git a/tanjun/annotations.py b/tanjun/annotations.py index c62a8e538..8dc4ff714 100644 --- a/tanjun/annotations.py +++ b/tanjun/annotations.py @@ -338,12 +338,12 @@ def __init__(self, converter: _ConverterSig[typing.Any], /, *other_converters: _ Parameters ---------- - converter : collections.abc.Callable[[str], collections.Coroutine[Any, Any, Any] | Any] + converter : collections.abc.Callable[[str, ...], collections.Coroutine[Any, Any, Any] | Any] The first converter this argument should use to handle values passed to it during parsing. Only the first converter to pass will be used. - *other_converters : collections.abc.Callable[[str], collections.Coroutine[Any, Any, Any] | Any] + *other_converters : collections.abc.Callable[[str, ...], collections.Coroutine[Any, Any, Any] | Any] Other first converter(s) this argument should use to handle values passed to it during parsing. diff --git a/tanjun/clients.py b/tanjun/clients.py index f332e35ec..c1b575c43 100644 --- a/tanjun/clients.py +++ b/tanjun/clients.py @@ -143,15 +143,18 @@ class _GatewayBotProto(hikari.EventManagerAware, hikari.RESTAware, hikari.ShardA """Protocol of a cacheless Hikari Gateway bot.""" -PrefixGetterSig = collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, collections.Iterable[str]]] -"""Type hint of a callable used to get the prefix(es) for a specific guild. +# 3.9 and 3.10 just can't handle ending a Paramspec with ... so we lie at runtime about this. +if typing.TYPE_CHECKING: + _PrefixGetterSig = collections.Callable[typing_extensions.Concatenate[tanjun.MessageContext, _P], collections.Coroutine[typing.Any, typing.Any, collections.Iterable[str]]] + PrefixGetterSig = _PrefixGetterSig[...] + """Type hint of a callable used to get the prefix(es) for a specific guild. -This should be an asynchronous callable which returns an iterable of strings. + This represents the callback `async def (tanjun.abc.MessageContext, ...) -> collections.Iterable[str]` + where dependency injection is supported. + """ -!!! note - While dependency injection is supported for this, the first positional - argument will always be a [tanjun.abc.MessageContext][]. -""" +else: + PrefixGetterSig = collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, collections.Iterable[str]]] _LOGGER: typing.Final[logging.Logger] = logging.getLogger("hikari.tanjun.clients") _MENU_TYPES = frozenset((hikari.CommandType.MESSAGE, hikari.CommandType.USER)) diff --git a/tanjun/commands/message.py b/tanjun/commands/message.py index 63044a531..113187e95 100644 --- a/tanjun/commands/message.py +++ b/tanjun/commands/message.py @@ -83,7 +83,7 @@ def as_message_command(name: str, /, *names: str, validate_arg_keys: bool = True name The command name. *names - Variable positional arguments of other names for the command. + Other names for the command. validate_arg_keys Whether to validate that option keys match the command callback's signature. @@ -135,7 +135,7 @@ def as_message_command_group( name The command name. *names - Variable positional arguments of other names for the command. + Other names for the command. strict Whether this command group should only allow commands without spaces in their names. @@ -223,7 +223,7 @@ def __init__( name The command name. *names - Variable positional arguments of other names for the command. + Other names for the command. validate_arg_keys Whether to validate that option keys match the command callback's signature. """ @@ -427,7 +427,7 @@ def __init__( name The command name. *names - Variable positional arguments of other names for the command. + Other names for the command. strict Whether this command group should only allow commands without spaces in their names. @@ -491,7 +491,7 @@ def as_sub_command( name The command name. *names - Variable positional arguments of other names for the command. + Other names for the command. validate_arg_keys Whether to validate that option keys match the command callback's signature. @@ -521,7 +521,7 @@ def as_sub_group( name The command name. *names - Variable positional arguments of other names for the command. + Other names for the command. strict Whether this command group should only allow commands without spaces in their names. diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index 442b6a470..b1fd12783 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -102,7 +102,12 @@ typing.Union[collections.Coroutine[typing.Any, typing.Any, typing.Any], typing.Any], ] ConverterSig = _ConverterSig[_ConvertT, ...] - """Type hint of a slash command option converter.""" + """Type hint of a slash command option converter. + + This represents the signatures `def (int | float | str, ...) -> Any` and + `async def (int | float | str, ...) -> None` where dependency injection is + supported. + """ else: import types diff --git a/tanjun/components.py b/tanjun/components.py index c2b4bbbc3..a310f4994 100644 --- a/tanjun/components.py +++ b/tanjun/components.py @@ -72,8 +72,8 @@ OnCallbackSig = collections.Callable[..., typing.Optional[collections.Coroutine[typing.Any, typing.Any, None]]] """Type hint of a on_open or on_close component callback. -These support dependency injection, should expect no positional arguments and -should return [None][]. +This represents the signatures `def (...) -> None` and `async def (...) -> None` +where dependency injection is supported. """ diff --git a/tanjun/parsing.py b/tanjun/parsing.py index 4938ccb49..f14d5f4ad 100644 --- a/tanjun/parsing.py +++ b/tanjun/parsing.py @@ -96,8 +96,8 @@ def __len__(self) -> int: ConverterSig = _ConverterSig[..., _T] """Type hint of a converter used within a parser instance. - This must be a callable or asynchronous callable which takes one position - [str][], argument and returns the resultant value. + This represents the signatures `def (str, ...) -> Any` and + `async def (str, ...) -> Any` where dependency injection is supported. """ else: From 4b7e4f1ffc8e359ba2e8738f738c5c85076a26eb Mon Sep 17 00:00:00 2001 From: "always-on-duty[bot]" <120557446+always-on-duty[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 05:11:00 +0000 Subject: [PATCH 44/45] Reformat PR code --- tanjun/clients.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tanjun/clients.py b/tanjun/clients.py index c1b575c43..14e0dcb54 100644 --- a/tanjun/clients.py +++ b/tanjun/clients.py @@ -145,7 +145,10 @@ class _GatewayBotProto(hikari.EventManagerAware, hikari.RESTAware, hikari.ShardA # 3.9 and 3.10 just can't handle ending a Paramspec with ... so we lie at runtime about this. if typing.TYPE_CHECKING: - _PrefixGetterSig = collections.Callable[typing_extensions.Concatenate[tanjun.MessageContext, _P], collections.Coroutine[typing.Any, typing.Any, collections.Iterable[str]]] + _PrefixGetterSig = collections.Callable[ + typing_extensions.Concatenate[tanjun.MessageContext, _P], + collections.Coroutine[typing.Any, typing.Any, collections.Iterable[str]], + ] PrefixGetterSig = _PrefixGetterSig[...] """Type hint of a callable used to get the prefix(es) for a specific guild. @@ -154,7 +157,9 @@ class _GatewayBotProto(hikari.EventManagerAware, hikari.RESTAware, hikari.ShardA """ else: - PrefixGetterSig = collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, collections.Iterable[str]]] + PrefixGetterSig = collections.Callable[ + ..., collections.Coroutine[typing.Any, typing.Any, collections.Iterable[str]] + ] _LOGGER: typing.Final[logging.Logger] = logging.getLogger("hikari.tanjun.clients") _MENU_TYPES = frozenset((hikari.CommandType.MESSAGE, hikari.CommandType.USER)) From f4621e2408d5eac9b69353b29ddca20cb7382d55 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Tue, 31 Jan 2023 05:11:46 +0000 Subject: [PATCH 45/45] Typo fix --- tanjun/abc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tanjun/abc.py b/tanjun/abc.py index 55a7e7826..0ab38bfdb 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -159,7 +159,7 @@ This may be registered with a command, client or component to add a rule which decides whether it should execute for each context passed to it. - This represnts the signatures `def (tanjun.abc.Context, ...) -> bool | None` + This represents the signatures `def (tanjun.abc.Context, ...) -> bool | None` and `async def (tanjun.abc.Context, ...) -> bool | None` where dependency injection is supported.