Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate using Tanjun contexts as DI contexts take 2 #977

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,36 @@ 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
- Support for Alluka's local contexts feature in the command and autocomplete
flows.

### Changed
- Bumped the minimum Alluka version to `v0.4.0`.
- Renamed the `case_sensntive` argument to `case_sensitive` in `MessageCommand.find_command`.

### Deprecated
- The old `case_sensntive` argument alias in `MessageCommand.find_command`.
- Using Tanjun's command and autocomplete contexts as Alluka contexts.
This includes deprecating the relevant methods inherited from
[alluka.abc.Context][] and [alluka.BasicContext][].
- Providing the following classes as global type-dependencies:
* [hikari.impl.RESTClientImpl][]
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reformat these

* [hikari.impl.CacheImpl][]
* [hikari.impl.EventManagerImpl][]
* [hikari.impl.InteractionServer][]
* [hikari.impl.GatewayShardImpl][]
* [hikari.impl.VoiceComponentImpl][]

The relevant ABCs should be used instead.
- Setting subclasses of [tanjun.Client][] as global type-dependencies.
- Providing the following classes as context-specific type-dependencies:
* [tanjun.AutocompleteContext][tanjun.context.AutocompleteContext]
* [tanjun.MessageContext][tanjun.context.MessageContext]
* [tanjun.MenuContext][tanjun.context.MenuContext]
* [tanjun.SlashContext][tanjun.context.SlashContext]

The relevant ABCs should be used instead.

## [2.17.7] - 2024-11-24
### Fixed
Expand Down
9 changes: 5 additions & 4 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -385,13 +385,14 @@ The following types are registered globally as type dependencies:
The following type dependencies are available in specific contexts:

* [tanjun.abc.AutocompleteContext][]: slash command autocomplete execution
* [tanjun.abc.AppCommandContext][]: both slash and menu command execution (excluding any checks)
* [tanjun.abc.Context][] for all command execution (not autocomplete)
* [tanjun.abc.AppCommandContext][]: both slash and menu command execution
* [tanjun.abc.MenuContext][]: menu command execution
* [tanjun.abc.MessageContext][]: message command execution
* [tanjun.abc.SlashContext][]: slash command execution
<!-- * [tanjun.abc.MenuCommand][]: menu command execution (excluding any checks)
* [tanjun.abc.MessageCommand][]: message command execution (excluding any checks)
* [tanjun.abc.SlashCommand][]: slash command execution (excluding any checks)
<!-- * [tanjun.abc.MenuCommand][]: menu command execution (excluding component and client checks)
* [tanjun.abc.MessageCommand][]: message command execution (excluding component and clientchecks)
* [tanjun.abc.SlashCommand][]: slash command execution (excluding component and clientchecks)
TODO: this needs a consistency fix before being documented -->
* [tanjun.abc.Component][]: Command execution (excluding client checks)
<!-- * [hikari.Event][hikari.events.base_events.Event] TODO: implement this-->
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ classifiers = [
"Topic :: Utilities",
"Typing :: Typed",
]
dependencies = ["alluka>=0.2.0, <1", "hikari>=2.0.0.dev115, <3", "typing-extensions>=4.5, <5"]
dependencies = ["alluka>=0.4, <1", "hikari>=2.0.0.dev115, <3", "typing-extensions>=4.5, <5"]
dynamic = ["description"]

[project.urls]
Expand Down
20 changes: 16 additions & 4 deletions tanjun/_internal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import typing
from collections import abc as collections

import alluka
import hikari

from tanjun import errors
Expand Down Expand Up @@ -78,14 +79,22 @@ class _DefaultEnum(enum.Enum):
"""The type of `DEFAULT`."""


async def _execute_check(ctx: _ContextT, callback: tanjun.CheckSig[_ContextT], /) -> bool:
if result := await ctx.call_with_async_di(callback, ctx):
async def _execute_check(
alluka_ctx: alluka.abc.Context, ctx: _ContextT, callback: tanjun.CheckSig[_ContextT], /
) -> bool:
if result := await alluka_ctx.call_with_async_di(callback, ctx):
return result

raise errors.FailedCheck


async def gather_checks(ctx: _ContextT, checks: collections.Iterable[tanjun.CheckSig[_ContextT]], /) -> bool:
async def gather_checks(
ctx: _ContextT,
checks: collections.Iterable[tanjun.CheckSig[_ContextT]],
/,
*,
alluka_ctx: alluka.abc.Context | None = None,
) -> bool:
"""Gather a collection of checks.

Parameters
Expand All @@ -94,14 +103,17 @@ async def gather_checks(ctx: _ContextT, checks: collections.Iterable[tanjun.Chec
The context to check.
checks : collections.abc.Iterable[tanjun.abc.CheckSig]
An iterable of injectable checks.
alluka_ctx : alluka.abc.Context
The Alluka context to use for dependency injection.

Returns
-------
bool
Whether all the checks passed or not.
"""
alluka_ctx = alluka_ctx or alluka.local.get_context(default=None) or ctx.injection_client.make_context()
try:
await asyncio.gather(*(_execute_check(ctx, check) for check in checks))
await asyncio.gather(*(_execute_check(alluka_ctx, ctx, check) for check in checks))

except errors.FailedCheck:
return False
Expand Down
161 changes: 155 additions & 6 deletions tanjun/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
from collections import abc as collections

import hikari
import typing_extensions
from alluka import abc as alluka

if typing.TYPE_CHECKING:
Expand Down Expand Up @@ -263,7 +264,12 @@ class _DefaultFlag(enum.Enum):


class Context(alluka.Context):
"""Interface for the context of a command execution."""
"""Interface for the context of a command execution.

!!! warning "deprecated"
Using Tanjun contexts as an Alluka context is
deprecated behaviour and may not behave as expected.
"""

__slots__ = ()

Expand Down Expand Up @@ -893,9 +899,73 @@ async def respond(
If an internal error occurs on Discord while handling the request.
"""

@property
@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def injection_client(self) -> alluka.Client: ...

@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def cache_result(self, callback: alluka.CallbackSig[_T], value: _T, /) -> None: ...

@typing.overload
@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def call_with_di(
self, callback: collections.Callable[..., _CoroT[typing.Any]], *args: typing.Any, **kwargs: typing.Any
) -> typing.NoReturn: ...

@typing.overload
@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def call_with_di(self, callback: collections.Callable[..., _T], *args: typing.Any, **kwargs: typing.Any) -> _T: ...

@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def call_with_di(self, callback: collections.Callable[..., _T], *args: typing.Any, **kwargs: typing.Any) -> _T: ...

@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
async def call_with_async_di(
self, callback: alluka.CallbackSig[_T], *args: typing.Any, **kwargs: typing.Any
) -> _T: ...

@typing.overload
@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def get_cached_result(self, callback: alluka.CallbackSig[_T], /) -> _T: ...

@typing.overload
@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def get_cached_result(self, callback: alluka.CallbackSig[_T], /, *, default: _DefaultT) -> _T | _DefaultT: ...

@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def get_cached_result(self, callback: alluka.CallbackSig[_T], /, *, default: _DefaultT = ...) -> _T | _DefaultT: ...

@typing.overload
@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def get_type_dependency(self, type_: type[_T], /) -> _T: ...

@typing.overload
@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def get_type_dependency(self, type_: type[_T], /, *, default: _DefaultT) -> _T | _DefaultT: ...

@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def get_type_dependency(self, type_: type[_T], /, *, default: _DefaultT = ...) -> _T | _DefaultT: ...


class MessageContext(Context, abc.ABC):
"""Interface of a message command specific context."""
"""Interface of a message command specific context.

!!! warning "deprecated"
Using Tanjun contexts as an Alluka context is
deprecated behaviour and may not behave as expected.
"""

__slots__ = ()

Expand Down Expand Up @@ -1301,7 +1371,12 @@ def resolve_to_user(self) -> hikari.User | hikari.Member:


class AppCommandContext(Context, abc.ABC):
"""Base class for application command contexts."""
"""Base class for application command contexts.

!!! warning "deprecated"
Using Tanjun contexts as an Alluka context is
deprecated behaviour and may not behave as expected.
"""

__slots__ = ()

Expand Down Expand Up @@ -1684,7 +1759,12 @@ async def create_modal_response(


class MenuContext(AppCommandContext, abc.ABC):
"""Interface of a menu command context."""
"""Interface of a menu command context.

!!! warning "deprecated"
Using Tanjun contexts as an Alluka context is
deprecated behaviour and may not behave as expected.
"""

__slots__ = ()

Expand Down Expand Up @@ -1784,7 +1864,12 @@ def resolve_to_user(self) -> hikari.User | hikari.Member:


class SlashContext(AppCommandContext, abc.ABC):
"""Interface of a slash command specific context."""
"""Interface of a slash command specific context.

!!! warning "deprecated"
Using Tanjun contexts as an Alluka context is
deprecated behaviour and may not behave as expected.
"""

__slots__ = ()

Expand Down Expand Up @@ -1821,7 +1906,12 @@ def set_command(self, command: BaseSlashCommand | None, /) -> Self:


class AutocompleteContext(alluka.Context):
"""Interface of an autocomplete context."""
"""Interface of an autocomplete context.

!!! warning "deprecated"
Using Tanjun contexts as an Alluka context is
deprecated behaviour and may not behave as expected.
"""

__slots__ = ()

Expand Down Expand Up @@ -2062,6 +2152,65 @@ async def set_choices(
If more than 25 choices are passed.
"""

@property
@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def injection_client(self) -> alluka.Client: ...

@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def cache_result(self, callback: alluka.CallbackSig[_T], value: _T, /) -> None: ...

@typing.overload
@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def call_with_di(
self, callback: collections.Callable[..., _CoroT[typing.Any]], *args: typing.Any, **kwargs: typing.Any
) -> typing.NoReturn: ...

@typing.overload
@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def call_with_di(self, callback: collections.Callable[..., _T], *args: typing.Any, **kwargs: typing.Any) -> _T: ...

@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def call_with_di(self, callback: collections.Callable[..., _T], *args: typing.Any, **kwargs: typing.Any) -> _T: ...

@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
async def call_with_async_di(
self, callback: alluka.CallbackSig[_T], *args: typing.Any, **kwargs: typing.Any
) -> _T: ...

@typing.overload
@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def get_cached_result(self, callback: alluka.CallbackSig[_T], /) -> _T: ...

@typing.overload
@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def get_cached_result(self, callback: alluka.CallbackSig[_T], /, *, default: _DefaultT) -> _T | _DefaultT: ...

@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def get_cached_result(self, callback: alluka.CallbackSig[_T], /, *, default: _DefaultT = ...) -> _T | _DefaultT: ...

@typing.overload
@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def get_type_dependency(self, type_: type[_T], /) -> _T: ...

@typing.overload
@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def get_type_dependency(self, type_: type[_T], /, *, default: _DefaultT) -> _T | _DefaultT: ...

@abc.abstractmethod
@typing_extensions.deprecated("Using a Tanjun context as an Alluka context is deprecated")
def get_type_dependency(self, type_: type[_T], /, *, default: _DefaultT = ...) -> _T | _DefaultT: ...


class Hooks(abc.ABC, typing.Generic[_ContextT_contra]):
"""Interface of a collection of callbacks called during set stage of command execution."""
Expand Down
Loading
Loading