-
Notifications
You must be signed in to change notification settings - Fork 6k
use sets instead of lists to store CH and PH commands #2890
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
Conversation
…t#2612) Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
Co-authored-by: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
Signed-off-by: starry69 <starry369126@outlook.com> Co-authored-by: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
…m-bot#2634) Co-authored-by: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com> Co-authored-by: poolitzer <25934244+Poolitzer@users.noreply.github.com>
Co-authored-by: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com> Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com> Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
|
Hi, are you working on #2885 with this? |
yes |
Bibo-Joshi
left a comment
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.
Hi. thanks for the PR! IISC so far you have only allowed for the PrefixHandler.prefix/command setters to accept sets.
I think I should clarify a bit what the intention of #2885 was:
- The main idea of the issue was to rename
CommandHandler.commandtoCommandHandler.commands(plural) since that attribute is currently actually always a list. Extending this toPrefixHandlers.prefixis surely reasonable. - Since I noticed that we only ever need
x in self.command, my idea was to makeCommandHandler.commandsa set instead of a list. Accepting sets as input in addition is surely a logical extension. So
Additionally, while reviewing your PR, I noticed that unlike PrefixHandler.command, CommandHandler.command doesn't have a setter. I.e. if you do command_handler.command = 'NewCommand', it won't be converted to [newcommand]. I think we should fix that. So what I would ask you to do is:
- Make sure that sets are accepted as input for
Prefix/CommandHandler.commandandPrefixHandler.prefix- this includes type hints & documentation - rename
CommandHandler.commandtoCommandHandler._commandsand add getter + setter proprtiesCommandHandler.commands. The getter should provide access to the setCH._commandsand the setter should accept a single string or tuple/list/set and convert it as it is converted on__init__ - Apply analogous changes to
PrefixHandler
telegram/ext/_commandhandler.py
Outdated
| Attributes: | ||
| command (:obj:`str` | Tuple[:obj:`str`] | List[:obj:`str`]): | ||
| command (:obj:`str` | Tuple[:obj:`str`] | List[:obj:`str`] | Set[:obj:`str`]): |
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.
In the current implementation, CommandHandler.command is actually always a List …
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.
Hi. thanks for the PR! IISC so far you have only allowed for the
PrefixHandler.prefix/commandsetters to accept sets. I think I should clarify a bit what the intention of #2885 was:
- The main idea of the issue was to rename
CommandHandler.commandtoCommandHandler.commands(plural) since that attribute is currently actually always a list. Extending this toPrefixHandlers.prefixis surely reasonable.- Since I noticed that we only ever need
x in self.command, my idea was to makeCommandHandler.commandsa set instead of a list. Accepting sets as input in addition is surely a logical extension. SoAdditionally, while reviewing your PR, I noticed that unlike
PrefixHandler.command,CommandHandler.commanddoesn't have a setter. I.e. if you docommand_handler.command = 'NewCommand', it won't be converted to[newcommand]. I think we should fix that. So what I would ask you to do is:
- Make sure that sets are accepted as input for
Prefix/CommandHandler.commandandPrefixHandler.prefix- this includes type hints & documentation- rename
CommandHandler.commandtoCommandHandler._commandsand add getter + setter proprtiesCommandHandler.commands. The getter should provide access to the setCH._commandsand the setter should accept a single string or tuple/list/set and convert it as it is converted on__init__- Apply analogous changes to
PrefixHandler
Thanks for the review, I'm working on it. should I change the name in arguments from command to commands too?
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.
should I change the name in arguments from command to commands too?
no need IMO, since either way the arguments will have to accept both single strings or colletcions of strings.
Bibo-Joshi
left a comment
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.
hi, thanks for the updates! I left a few comments below
Also please add a .. versionchanged:: directive just before the Args: of CommandHandler saying that command was replaced by commands
telegram/ext/_commandhandler.py
Outdated
| commands (Set[:obj:`str`]): | ||
| The set of command(s) this handler should listen for. |
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.
the property already has a docstring, so you can remove this documentation of the attribute
telegram/ext/_commandhandler.py
Outdated
| .. versionchanged:: 14.0 | ||
| :attr:`commands` is now a set and can be assinged after construction of model. |
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.
see above
telegram/ext/_commandhandler.py
Outdated
| if isinstance(command, str): | ||
| self._commands = {command.lower()} | ||
| else: | ||
| self._commands = {i.lower() for i in command} |
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 is the same logic that's used on __init__. Could you extract it to a new protected method (e.g. _parse_commands()) that you call both here and on __init__? Then you can also move the regexing from __init__ to that function. THat will make sure that also the setter only accepts valid bot commands (please add a unit test 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.
Sure, I first tried to do it like this
self.commands = command
But it wouldn't work when PrefixHandler tried to call it because it has a different setter than CommandHandler with the same name. But I'll make a function for it.
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 noticed we don't have CommandHandler command limitations for PrefixHandler, so illegal commands in prefixhandler should work properly shouldn't they?
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 noticed we don't have CommandHandler command limitations for PrefixHandler, so illegal commands in prefixhandler should work properly shouldn't they?
yes, since PrefixHandler is not limited to the commands recognized by Telegram. Actually the fact that PrefixHandler is a subclass of CommandHandler is more or less an implementation detail …
| Args: | ||
| command (:obj:`str` | Tuple[:obj:`str`] | List[:obj:`str`]): | ||
| command (:obj:`str` | Tuple[:obj:`str`] | List[:obj:`str`] | Set[:obj:`str`]): |
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 add a "versionchanged" directive saying that it now also accepts sets
telegram/ext/_commandhandler.py
Outdated
| .. versionchanged:: 14.0 | ||
| :attr:`prefix` has been changed to :attr:`prefixes` and accepts sets as well. | ||
| :attr:`command` has been changed to :attr:`commands` and accepts sets as well. |
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 move the "changed to" notes to a versionchanged directive right before the Args:. Please move the "now accepts sets" to a versionchanged directive in the documentation of the respective arguments
telegram/ext/_commandhandler.py
Outdated
| @property # type: ignore[override] | ||
| def command(self) -> List[str]: # type: ignore[override] | ||
| @property | ||
| def commands(self) -> Set[str]: |
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.
Is this override still necessary? IISC, this does exatly the same as CommandHandler.commands
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.
yes, because this class uses a different setter than the parent one and needs a property to set it.
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.
IIRC using @CommandHandler.commands.setter instead of @commands.setter should do the trick and then you don't need to re-implement the property
| handler = CommandHandler(['test', 'star'], self.callback_basic) | ||
| assert is_match(handler, make_command_update('/test')) | ||
| handler.commands = "help" | ||
| assert is_match(handler, make_command_update('/help')) |
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.
| assert is_match(handler, make_command_update('/help')) | |
| assert is_match(handler, make_command_update('/help')) | |
| assert not is_match(handler, make_command_update('/test)) |
| handler.commands = "help" | ||
| assert is_match(handler, make_command_update('/help')) | ||
| handler.commands = ['exit', 'happy'] | ||
| assert is_match(handler, make_command_update('/happy')) |
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.
| assert is_match(handler, make_command_update('/happy')) | |
| assert is_match(handler, make_command_update('/happy')) | |
| assert not is_match(handler, make_command_update('/help')) |
| .. versionchanged:: 14.0 | ||
| :attr:`commands` is now a set and can be assinged after construction of model. | ||
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 remove
| attributes to :class:`telegram.ext.CallbackContext`. See its docs for more info. | ||
| .. versionchanged:: 14.0 | ||
| :attr:`commands` is now a set and can be assinged after construction of model. |
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.
The attribute command was replaced by :attr:commands
| and message.get_bot() | ||
| ): | ||
| command = message.text[1 : message.entities[0].length] | ||
| command = message.text[1: message.entities[0].length] |
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 revert - this is the reason the pre-commit test is failing
| for comm in self._commands: | ||
| if not re.match(r'^[\da-z_]{1,32}$', comm): | ||
| raise ValueError(f'Command `{comm}` is not a valid bot command') |
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.
when this is raised, self._commands has already been changed - it should be the other way around. You can even add a unit test along the lines
- bulid commandhandler with valid commands
- try to assign invalid commands
- assert that the commands where not changed
what we can do to make this easier here & also make the init a bit cleaner is:
- make
_parse_commandsreturn the parsed commands instead of assigning them directly toself._commands. It can be converted into a static method - apply the regexing for valid commands directly within
_parse_commands - do
self._commands = self._parse_commands(command)both here and in__init__.
| self._command = command | ||
| @CommandHandler.commands.setter # type: ignore[attr-defined,misc] | ||
| def commands(self, command: SLTS) -> None: | ||
| self._parse_commands(command) |
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.
IISC this doesn't rebuilt self._combinations, but that's needed. I guess it should be self._build_commands instead. If you want to reduce code duplication some more, you can add a method _slts_to_set that returns {arg.lower()} if isinstance(arg, str) else {item.lower() for item in arg}. This can be a static method of CommandHandler or even just a module level function. You can then use it in CH._parse_commands, in the setter of prefixes and here.
| :attr:`prefixes` and :attr:`commands` are always a set and can be | ||
| assigned with sets as well. |
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.
| :attr:`prefixes` and :attr:`commands` are always a set and can be | |
| assigned with sets as well. | |
| The attributes ``prefix`` and ``command`` where replaced by :attr:`prefixes` and :attr:`commands`, respectively. |
fix CommandHandler and PrefixHandler to use lists instead of sets
.. versionadded:: version,.. versionchanged:: versionor.. deprecated:: versionto the docstrings for user facing changes (for methods/class descriptions, arguments and attributes)AUTHORS.rst(optional)Closes Rename CommandHandler.command to CH.commands (plural) … #2885