Skip to content

Conversation

@thatguylah
Copy link
Contributor

@thatguylah thatguylah commented Jul 25, 2023

closes #3798

CommandHandler allows an optional has_args argument that defaults to None, but can optionally accept either True, False or any int.

  • Used an Enum for mapping this logic inside an internal method _check_correct_args of class CommandHandler
  • In check_update method, right before sending to filters for filters parsing, it _check_correct_args and if _valid then it does nothing and passes to filters
  • if however _valid is False, it early returns None before it hits filters parsing.
  • Implemented test cases in test_commandhandler.py for has_args
  • All test cases passed. 👍

Let me know if i need to refactor or add to more documentation that i am not aware about. ☺️

@thatguylah
Copy link
Contributor Author

Also, do you perhaps think instead of returning None in check_update we should raise an Exception instead? @Bibo-Joshi

@harshil21 harshil21 added the 📋 pending-review work status: pending-review label Jul 26, 2023
Copy link
Member

@Bibo-Joshi Bibo-Joshi left a comment

Choose a reason for hiding this comment

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

Hi. Thakks for the PR! The overall gist of the changes look good :) I left some comments below.

Also, do you perhaps think instead of returning None in check_update we should raise an Exception instead?

No, that is not desired. This method it designed to determine whether the handler should handle the update and the return value must indicate that. Raising an exception would mean that it can not be determined whether the update should be handled.

Comment on lines +92 to +97
has_args (:obj:`bool` | :obj:`int`, optional):
Determines whether the command handler should process the update or not.
If :obj:`True`, the handler will process any non-zero number of args.
If :obj:`False`, the handler will only process if there are no args.
if :obj:`int`, the handler will only process if there are exactly that many args.
Defaults to :obj:`None`, which means the handler will process any or no args.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
has_args (:obj:`bool` | :obj:`int`, optional):
Determines whether the command handler should process the update or not.
If :obj:`True`, the handler will process any non-zero number of args.
If :obj:`False`, the handler will only process if there are no args.
if :obj:`int`, the handler will only process if there are exactly that many args.
Defaults to :obj:`None`, which means the handler will process any or no args.
has_args (:obj:`bool` | :obj:`int`, optional):
Specifies criteria on the arguments of the command that this handler should check for.
If :obj:`True`, the handler will process the update if the command has any non-zero number of arguments.
If :obj:`False`, the handler will only process the update if there are no arguments following the command.
If a non-negative :obj:`int` is passed, the handler will only process the update if there are exactly that many arguments specified for the command.
Defaults to :obj:`None`, which means the handler will not check the number of arguments.
.. versionadded:: NEXT.VERSION

Comment on lines +110 to +112
has_args (:obj:`bool` | :obj:`int` | None):
Optional argument, otherwise all implementations of :class:`CommandHandler` will break.
Defaults to :obj:`None`, which means the handler will process any args or no args.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
has_args (:obj:`bool` | :obj:`int` | None):
Optional argument, otherwise all implementations of :class:`CommandHandler` will break.
Defaults to :obj:`None`, which means the handler will process any args or no args.
has_args (:obj:`bool` | :obj:`int`):
Optional. Only allow commands whose arguments satisfy this criterion. See :param:`has_args` for details.
.. versionadded:: NEXT.VERSION

Comment on lines +158 to +169
condition = (
ArgsCondition.HAS_ARGS_NONE
if (self.has_args is None)
else ArgsCondition.HAS_ARGS_TRUE_ARGS_PRESENT
if (self.has_args is True and args)
# Must specify is True, otherwise if has_args is int, it will default to Truthy value.
else ArgsCondition.HAS_ARGS_FALSE_ARGS_ABSENT
if (self.has_args is False and not args)
else ArgsCondition.HAS_ARGS_NUM
if (isinstance(self.has_args, int) and len(args) == self.has_args)
else ArgsCondition.HAS_INVALID_ARGS
)
Copy link
Member

Choose a reason for hiding this comment

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

The enum is a nice idea, but it seems like rather heavy overkill for this use case :D especially since there are only 2 values that the enums are mapped to.
The important part are the if-clauses you specified and those look good to me. I suggest to simplify this method to something like this:

if (cond 1) or (cond 2) or (cond 3) or (cond 4):
    return True
return False

Comment on lines +206 to +208
_valid = self._check_correct_args(args)
if _valid is False:
return None
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
_valid = self._check_correct_args(args)
if _valid is False:
return None
if not self._check_correct_args(args):
return None

assert not is_match(handler_false, make_command_update("/test helloworld", bot=bot))

assert is_match(handler_int_one, make_command_update("/test helloworld", bot=bot))
assert not is_match(handler_int_one, make_command_update("/test hello world", bot=bot))
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
assert not is_match(handler_int_one, make_command_update("/test hello world", bot=bot))
assert not is_match(handler_int_one, make_command_update("/test hello world", bot=bot))
assert not is_match(handler_int_one, make_command_update("/test", bot=bot))

same for hander_int_two :)

filters if filters is not None else filters_module.UpdateType.MESSAGES
)

self.has_args = has_args
Copy link
Member

Choose a reason for hiding this comment

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

it would be good to check if has_args is negative and raise a ValueError if it is. We'd also need a corresponding unit test

@harshil21 harshil21 added enhancement and removed 📋 pending-review work status: pending-review labels Jul 27, 2023
@Bibo-Joshi Bibo-Joshi added the 📋 pending-reply work status: pending-reply label Jul 28, 2023
@Bibo-Joshi
Copy link
Member

Closing due to inactivity

@Bibo-Joshi Bibo-Joshi closed this Aug 11, 2023
@Bibo-Joshi Bibo-Joshi reopened this Aug 12, 2023
@Bibo-Joshi Bibo-Joshi closed this Aug 21, 2023
@github-actions github-actions bot locked and limited conversation to collaborators Aug 29, 2023
@Bibo-Joshi Bibo-Joshi added 🔌 enhancement pr description: enhancement and removed enhancement labels Nov 3, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

🔌 enhancement pr description: enhancement 📋 pending-reply work status: pending-reply

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Add args present argument to command filter

3 participants