-
Notifications
You must be signed in to change notification settings - Fork 187
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
refactor: nextcord.Interaction subclassing #970
base: master
Are you sure you want to change the base?
Conversation
Creat first classes + Create PR
class creation
* Check and Use Interaction type in Client.py * Import Interaction subclasses in Client.py * Transfer SlashApplicationInteraction specific data from Base to subclass * Copy SlashApplicationInteraction contents to ApplicationAutocompleteInteraction (use same data)
* Check and use correct Interaction type in Client.py * Add imports for Interaction subclasses in Client.py * Transfer SlashApplicationInteraction specific data from Interaction (parent class) * Transfer ApplicationAutocompleteInteraction specific data from Interaction (parent class) * Add subclass refined properties to SlashApplicationInteraction * Add subclass refined properties to ApplicationAutocompleteInteraction * Create PartialInteractionOption (will contain options data for SlashApplicationInteraction and ApplicationAutocompleteInteraction)
* Check and use correct Interaction type in Client.py * Add imports for new Interaction subclasses * Transfer SlashApplicationInteraction specific data from Interaction (parent class) * Transfer ApplicationAutocompleteInteraction specific data from Interaction (parent class) * Add properties for SlashApplicationInteraction refined data * Add properties for ApplicationAutocompleteInteraction refined data
…ubclasses * Add parameters to get_interaction to support custom Interaction subclasses in Client.py * Create SlashOptionData to hold recieved SlashOptionData - to be used in Interaction classes (Interactions.py) * Rename SlashApplicationCommand subinteraction class to SlashApplicationInteraction * Add option data handling in SlashApplicationInteraction (using SlashOptionData) (new .options attribute) * Add option data handlin in ApplicationAutocompleteInteraction (using SlashOptionData) (new .options attribute) * Add ocused_option attribute to ApplicationAutocompleteInteraction (fast way to get Slashoption invoking Autocomplete)
Stop double Initialization for focused slash options - instead append the first initialization to collection list
…ubclasses * Add parameters to get_interaction to support custom Interaction subclasses in Client.py * Create SlashOptionData to hold recieved SlashOptionData - to be used in Interaction classes (Interactions.py) * Rename SlashApplicationCommand subinteraction class to SlashApplicationInteraction * Add option data handling in SlashApplicationInteraction (using SlashOptionData) (new .options attribute) * Add option data handlin in ApplicationAutocompleteInteraction (using SlashOptionData) (new .options attribute) * Add ocused_option attribute to ApplicationAutocompleteInteraction (fast way to get Slashoption invoking Autocomplete)
…subclasses * Copy Interaction.edit() method to ViewInteraction * Copy Intenteraction.edit() to ModalSubmitInteraction * Remove Interaction.edit() from Interaction * Remove .message attribute from Interaction * Add .message attribute to ViewInteraction * Add .message attribute to ModalSubmitInteraction * Add attributes for ModalSubmit refined data (ModalSubmitInteraction) * add attributes for MessageComponent refined data (ViewInteraction) * Add comments for questioning changes
* Fixed ViewInteraction.edit() method - can now also edit ephemeral messages * Fixed ModalSubmitInteraction.edit() method - can now also edit ephemeral messages Refactor: * Remove prints from testing * Add comments for future changes * Add __repr__ method to SlashOptionData class
* Add classes to __all__ (interactions.py) * removed prints from testing
…updates * Change SlashApplicationInteraction name to ApplicationCommandInteraction * Type the correct Interaction subclass in client.py * Add class Descriptions to Interaction Subclasses * Correct __slots__ in Interaction class * Ad __slots__ to Interaction subclasses * Change some attribute names to have more appropriate name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two more things that I decided to leave out of individual review comments:
- The rest of the library isn't typed to use these new subclasses.
- It would be a lot cleaner imo if the interaction subclasses were split into multiple files under an
interactions
folder. This also includes the base interaction class.
FYI, some of the review comments I specifically made on ApplicationCommandInteraction
apply to the rest of the subclasses, I didn't want to copy all of those review comments over and over again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also i'm unsure whether should we keep documenting Interaction -- as it doesn't have any real-world usage now.
i think it's a bit breaking but fine, acceptable
* Remove parent attributes from Interaction subclass descriptions (suggestion from PR comments) * Remove 'version added' in Interaction subclasses (suggestion from PR comments) * Correct spelling and punctuation in Interaction subclass descriptions (suggestion from PR comments) * ApplicationAutocompleteInteraction now inherits from ApplicationCommandInteraction * Correct list typehinting for application options list in ApplicationCommandInteraction
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would need to add backward compatibilities or fix pyright error
i actually prefer add backward compatibilities bcuz it would not take much time
but you also need to re-typehint the whole lib where just use interactions, thx =))
🦅 |
nextcord/application_command.py
Outdated
|
||
__slots__: Tuple[str, ...] = ("data", "value", "type", "name", "focused") | ||
|
||
def __init__(self, data) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please type the data
parameter with ApplicationCommandInteractionDataOption
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type doesn't exist - Are you suggesting I should make a new type for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nextcord/nextcord/types/interactions.py
Lines 128 to 135 in 5d2eff1
ApplicationCommandInteractionDataOption = Union[ | |
_ApplicationCommandInteractionDataOptionString, | |
_ApplicationCommandInteractionDataOptionInteger, | |
_ApplicationCommandInteractionDataOptionSubcommand, | |
_ApplicationCommandInteractionDataOptionBoolean, | |
_ApplicationCommandInteractionDataOptionSnowflake, | |
_ApplicationCommandInteractionDataOptionNumber, | |
] |
It does exist, and it's already imported in this module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Must have missed that somehow. Either way, as part of that list, is the class _ApplicationCommandInteractionDataOptionSubcommand
, which the SlashOptionData class doesn't use. (It may possibly not use Snowflake either but I can't say this for sure). Would it be worth making a new dedicated type for this? or is there some typehinting approach I can take, to reassure pyright, that this class does, indeed, not get used (other than using something like isinstance - which would be redundant since the library simply doesn't use this class for any other purpose)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it does get used to tell Pyright what keys and types of values a specific dictionary has. You could make a new union without the subcommand one, but I'm not sure what to call it.
nextcord/application_command.py
Outdated
__slots__: Tuple[str, ...] = ("data", "value", "type", "name", "focused") | ||
|
||
def __init__(self, data) -> None: | ||
self.data: dict = data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
|
||
Warns | ||
-------- | ||
~FutureWarning |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's worth documenting this warning, considering that other functions throughout the library do not either.
if slot == "type" and getattr(self, slot, None) is not None: | ||
# nextcord/issues/1103 | ||
continue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't this fixed by #1104?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possibly? I haven't been keeping track on more recent PRs. Please let me know what I should do with this code, provided changes are in order :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All that PR did when it was merged was remove "type"
from the __slots__
of the Component
class. As long as your fork is up to date with the upstream and you remove this code I commented on, all should be good.
Co-authored-by: Emre Terzioglu <50607143+EmreTech@users.noreply.github.com>
Co-authored-by: Emre Terzioglu <50607143+EmreTech@users.noreply.github.com>
Co-authored-by: Emre Terzioglu <50607143+EmreTech@users.noreply.github.com>
Co-authored-by: Emre Terzioglu <50607143+EmreTech@users.noreply.github.com>
Co-authored-by: Emre Terzioglu <50607143+EmreTech@users.noreply.github.com>
Co-authored-by: Emre Terzioglu <50607143+EmreTech@users.noreply.github.com>
Co-authored-by: Emre Terzioglu <50607143+EmreTech@users.noreply.github.com>
Co-authored-by: Emre Terzioglu <50607143+EmreTech@users.noreply.github.com>
Co-authored-by: Emre Terzioglu <50607143+EmreTech@users.noreply.github.com>
Co-authored-by: Emre Terzioglu <50607143+EmreTech@users.noreply.github.com>
Co-authored-by: Emre Terzioglu <50607143+EmreTech@users.noreply.github.com>
self.options: List[SlashOptionData] = ( | ||
self._get_application_options(options) if options else [] | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
preview is broken for some reason, but what Emre said.
self.options: List[SlashOptionData] = ( | |
self._get_application_options(options) if options else [] | |
) | |
options = self.data.get("options", []) | |
self.options: List[SlashOptionData] = ( | |
self._get_application_options(options) | |
) |
def _get_application_options(self, data): | ||
options = data | ||
|
||
if len(options) == 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forgot to apply this
SlashOptionData, | ||
) | ||
|
||
return [SlashOptionData(option) for option in options] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pyright is not happy with this because you are changing the type of an already assigned variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what variable this is referring to
self._parent._state.store_modal(modal, self._parent.user.id) # type: ignore | ||
|
||
|
||
class ApplicationAutocompleteInteraction(Interaction): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested. Only issues were the warning and button type error mentioned in these comments. https://paste.nextcord.dev/?id=1702153210128711
nextcord.interactions | ||
~~~~~~~~~~~~~~~~~~ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nextcord.interactions | |
~~~~~~~~~~~~~~~~~~ | |
nextcord.interactions | |
~~~~~~~~~~~~~~~~~~~~~ |
from ..application_command import ( # Importing here due to circular import issues | ||
SlashOptionData, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from ..application_command import ( # Importing here due to circular import issues | |
SlashOptionData, | |
) | |
# Importing here due to circular import issues | |
from ..application_command import SlashOptionData |
If you put the comment above, this wouldn't wrap the line like that
SlashOptionData, | ||
) | ||
|
||
return [SlashOptionData(option) for option in options] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what variable this is referring to
return super().get_interaction( | ||
data, | ||
application_interaction=CustomApplicationCommandInteraction, | ||
application_autocomplete_interaction=CustomApplicationAutocompleteInteraction, | ||
message_component_interaction=MessageComponentInteraction, | ||
modal_submit_interaction=CustomModalSubmitInteraction, | ||
|
||
# If you want a custom Interaction object to fall back to if interaction type wasn't recognized: | ||
cls=CustomInteraction | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return super().get_interaction( | |
data, | |
application_interaction=CustomApplicationCommandInteraction, | |
application_autocomplete_interaction=CustomApplicationAutocompleteInteraction, | |
message_component_interaction=MessageComponentInteraction, | |
modal_submit_interaction=CustomModalSubmitInteraction, | |
# If you want a custom Interaction object to fall back to if interaction type wasn't recognized: | |
cls=CustomInteraction | |
) | |
def get_interaction(self, data): | |
return super().get_interaction( | |
data, | |
application_interaction=CustomApplicationCommandInteraction, | |
application_autocomplete_interaction=CustomApplicationAutocompleteInteraction, | |
message_component_interaction=MessageComponentInteraction, | |
modal_submit_interaction=CustomModalSubmitInteraction, | |
# If you want a custom Interaction object to fall back to if interaction type wasn't recognized: | |
cls=CustomInteraction | |
) |
Warns | ||
-------- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Warns | |
-------- | |
Warns | |
----- |
@@ -2068,10 +2084,14 @@ def scheduled_events(self) -> List[ScheduledEvent]: | |||
""" | |||
return [event for guild in self.guilds for event in guild.scheduled_events] | |||
|
|||
async def on_interaction(self, interaction: Interaction) -> None: | |||
async def on_interaction( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be all types however, process_application_commands
ignores the types it doesn't want.
in the event that defining this parameter was a mistake, and other parameters were to be defined instead. | ||
""" | ||
# check if they are creating custom interaction subclasses | ||
if cls is not Interaction: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This warning seems a bit weird, the signature for get_interaction
seems to imply you should pass a custom interaction when passing other custom interaction classes. The better check would be to look at the other classes and if none are custom, but that just seems a bit excessive IMO.
class Client(nextcord.Client):
def get_interaction(self, data: InteractionPayload):
return super().get_interaction(
data,
application_autocomplete_interaction=CustomAutocompleteInteraction,
application_interaction=CustomAppCmdInteraction,
message_component_interaction=CustomComponentInteraction,
modal_submit_interaction=CustomModalSubmitInteraction,
cls=CustomInteraction,
)
from ..interactions import ClientT, Interaction | ||
from ..interactions.base import ClientT, Interaction | ||
from ..interactions.message_component import MessageComponentInteraction | ||
from ..interactions.modal_submit import ModalSubmitInteraction |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ItemCallbackType
should probably use the component interaction class not the base one:
Argument of type "(self: Self@View, button: Button[Unknown], interaction: CustomComponentInteraction) -> Coroutine[Any, Any, None]" cannot be assigned to parameter of type "ItemCallbackType[Button[V@button], ClientT@button]"
Type "(self: Self@View, button: Button[Unknown], interaction: CustomComponentInteraction) -> Coroutine[Any, Any, None]" cannot be assigned to type "ItemCallbackType[Button[V@button], ClientT@button]"
Parameter 3: type "Interaction[ClientT@button]" cannot be assigned to type "CustomComponentInteraction"
"Interaction[ClientT@button]" is incompatible with "CustomComponentInteraction"Pylance[reportGeneralTypeIssues](https://github.com/microsoft/pyright/blob/main/docs/configuration.md#reportGeneralTypeIssues)
Summary
PR for #952
Create Subclasses for
nextcord.Interaction
Subclasses will include:
ApplicationCommandInteraction
Interaction object for application commands
ApplicationAutocompleteInteraction
Interaction object for slash command autocomplete
ViewInteraction
Interaction object for message components
ModalSubmitInteraction
Interaction object for Modal submits
Following object names will/may still change:
ApplicationAutocompleteInteraction
ViewInteraction
toMessageComponentInteraction
Checklist (currently incomplete)
nextcord.types.interactions
__all__
Set in interactions.py__slots__
, type hints, bugs, ...)