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

Exceptions from class-based validators #39

Open
irons opened this issue Feb 5, 2022 · 2 comments
Open

Exceptions from class-based validators #39

irons opened this issue Feb 5, 2022 · 2 comments
Labels
documentation Improvements or additions to documentation

Comments

@irons
Copy link

irons commented Feb 5, 2022

I'm trying to migrate code from PyInquirer, which leans on class-based validators. Here's an example, borrowing from https://inquirerpy.readthedocs.io/en/latest/pages/validator.html:

#!/usr/bin/env python3 

from InquirerPy import prompt
from prompt_toolkit.validation import ValidationError, Validator

class EmptyInputValidator(Validator):
    def validate(self, document):
        if not len(document.text) > 0:
            raise ValidationError(
                message="Input cannot be empty.",
                cursor_position=document.cursor_position,
            )

questions = [
    {
        'type': 'input',
        'name': 'color',
        'message': f"How do you feel?",
        'validate': EmptyInputValidator
    }
]

result = prompt(questions)
print(result)

This approach crashes InquirerPy, whether the prompt response is empty or not:

Unhandled exception in event loop:
  File "/Users/whomever/.pyenv/versions/3.9.10/lib/python3.9/asyncio/events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
  File "/Users/whomever/.pyenv/versions/3.9.10/lib/python3.9/site-packages/prompt_toolkit/input/vt100.py", line 170, in callback_wrapper
    callback()
  File "/Users/whomever/.pyenv/versions/3.9.10/lib/python3.9/site-packages/prompt_toolkit/application/application.py", line 708, in read_from_input
    self.key_processor.process_keys()
  File "/Users/whomever/.pyenv/versions/3.9.10/lib/python3.9/site-packages/prompt_toolkit/key_binding/key_processor.py", line 271, in process_keys
    self._process_coroutine.send(key_press)
  File "/Users/whomever/.pyenv/versions/3.9.10/lib/python3.9/site-packages/prompt_toolkit/key_binding/key_processor.py", line 186, in _process
    self._call_handler(matches[-1], key_sequence=buffer[:])
  File "/Users/whomever/.pyenv/versions/3.9.10/lib/python3.9/site-packages/prompt_toolkit/key_binding/key_processor.py", line 321, in _call_handler
    handler.call(event)
  File "/Users/whomever/.pyenv/versions/3.9.10/lib/python3.9/site-packages/prompt_toolkit/key_binding/key_bindings.py", line 124, in call
    result = self.handler(event)
  File "/Users/whomever/.pyenv/versions/3.9.10/lib/python3.9/site-packages/InquirerPy/base/simple.py", line 240, in executable
    func(event)
  File "/Users/whomever/.pyenv/versions/3.9.10/lib/python3.9/site-packages/InquirerPy/base/simple.py", line 142, in _
    method["func"](event, *method.get("args", []))
  File "/Users/whomever/.pyenv/versions/3.9.10/lib/python3.9/site-packages/InquirerPy/prompts/input.py", line 188, in _handle_enter
    self._session.validator.validate(self._session.default_buffer)  # type: ignore
  File "/Users/whomever/.pyenv/versions/3.9.10/lib/python3.9/site-packages/prompt_toolkit/validation.py", line 120, in validate
    if not self.func(document.text):

Exception EmptyInputValidator() takes no arguments

The outcome and stack trace are identical on python versions 3.7.10, 3.8.12, 3.9.10, and 3.10.2, all running on macOS 11.6.3 (under pyenv) with inquirerpy 0.3.3.

I can fix the exception's complaint by adding a stub __init__ method:

class EmptyInputValidator(Validator):
    def __init__(self, document):
      pass

This no longer crashes, but the validator never fires. It also breaks the contract from prompt_toolkit about only needing to override the validate function.

For the record, the subclass approach succeeds in PyInquirer, until python 3.10, where it falls victim to the removal of Mapping from the collections interface. And though validators using from_callable succeed in InquirerPy, this is not a good fit for my purposes, unless I'm overlooking how it can be used to return distinct error messages for different kinds of validation failure.

Do you have any guidance for class-based validators with InquirerPy? Thanks for your time.

@kazhala
Copy link
Owner

kazhala commented Feb 5, 2022

Hi @irons ,

Thanks for reporting. This seems like another difference with PyInquirer that I didn't catch. You'll need to initialise the validator before providing it to the prompt.

questions = [
    {
        'type': 'input',
        'name': 'color',
        'message': f"How do you feel?",
        'validate': EmptyInputValidator()  # initialise here
    }
]

I'll update the doc to note this.

Thanks,
Kevin

@kazhala kazhala added the documentation Improvements or additions to documentation label Feb 5, 2022
@irons
Copy link
Author

irons commented Feb 6, 2022

Thanks for the rapid response. Easy change on my end, looks to be working well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

2 participants