示例#1
0
def test_validator_instance():
    def validate(t):
        return len(t) == 3

    validator = Validator.from_callable(validate)

    validator = build_validator(validator)
    assert validator.validate(Document("foo")) is None  # should not raise
示例#2
0
def test_validator_bool_function_fails():
    def validate(t):
        return len(t) == 3

    validator = build_validator(validate)
    with pytest.raises(ValidationError) as e:
        validator.validate(Document("fooooo"))

    assert e.value.message == "Invalid input"
示例#3
0
def text(message: Text,
         default: Text = "",
         validate: Union[Type[Validator],
                         Callable[[Text], bool],
                         None] = None,  # noqa
         qmark: Text = DEFAULT_QUESTION_PREFIX,
         style: Optional[Style] = None,
         **kwargs: Any) -> Question:
    """Prompt the user to enter a free text message.

       This question type can be used to prompt the user for some text input.

       Args:
           message: Question text

           default: Default value will be returned if the user just hits
                    enter.

           validate: Require the entered value to pass a validation. The
                     value can not be submited until the validator accepts
                     it (e.g. to check minimum password length).

                     This can either be a function accepting the input and
                     returning a boolean, or an class reference to a
                     subclass of the prompt toolkit Validator class.

           qmark: Question prefix displayed in front of the question.
                  By default this is a `?`

           style: A custom color and style for the question parts. You can
                  configure colors as well as font types for different elements.

       Returns:
           Question: Question instance, ready to be prompted (using `.ask()`).
    """

    merged_style = merge_styles([DEFAULT_STYLE, style])

    validator = build_validator(validate)

    def get_prompt_tokens():
        return [("class:qmark", qmark),
                ("class:question", ' {} '.format(message))]

    p = PromptSession(get_prompt_tokens,
                      style=merged_style,
                      validator=validator,
                      **kwargs)
    p.default_buffer.reset(Document(default))

    return Question(p.app)
示例#4
0
def test_validator_bool_function():
    def validate(t):
        return len(t) == 3

    validator = build_validator(validate)
    assert validator.validate(Document("foo")) is None  # should not raise
示例#5
0
def path(
    message: str,
    default: str = "",
    qmark: str = DEFAULT_QUESTION_PREFIX,
    validate: Any = None,
    style: Optional[Style] = None,
    only_directories: bool = False,
    file_filter: Optional[Callable[[str], bool]] = None,
    complete_style: CompleteStyle = CompleteStyle.MULTI_COLUMN,
    **kwargs: Any,
) -> Question:
    """A text input for a file or directory path with autocompletion enabled.

    Example:
        >>> import questionary
        >>> questionary.path("What's the path to the projects version file?").ask()
        ? What's the path to the projects version file? ./pyproject.toml
        './pyproject.toml'

    .. image:: ../images/path.gif

    This is just a really basic example, the prompt can be customised using the
    parameters.

    Args:
        message: Question text.

        default: Default return value (single value).

        qmark: Question prefix displayed in front of the question.
               By default this is a ``?``.

        complete_style: How autocomplete menu would be shown, it could be ``COLUMN``
                        ``MULTI_COLUMN`` or ``READLINE_LIKE`` from
                        :class:`prompt_toolkit.shortcuts.CompleteStyle`.

        validate: Require the entered value to pass a validation. The
                  value can not be submitted until the validator accepts
                  it (e.g. to check minimum password length).

                  This can either be a function accepting the input and
                  returning a boolean, or an class reference to a
                  subclass of the prompt toolkit Validator class.

        style: A custom color and style for the question parts. You can
               configure colors as well as font types for different elements.

        only_directories: Only show directories in auto completion

        file_filter: Optional callable to filter suggested paths. Only paths
                     where the passed callable evaluates to ``True`` will show up in
                     the suggested paths. This does not validate the typed path, e.g.
                     it is still possible for the user to enter a path manually, even
                     though this filter evaluates to ``False``. If in addition to
                     filtering suggestions you also want to validate the result, use
                     ``validate`` in combination with the ``file_filter``.

    Returns:
        :class:`Question`: Question instance, ready to be prompted (using ``.ask()``).
    """

    merged_style = merge_styles([DEFAULT_STYLE, style])

    def get_prompt_tokens() -> List[Tuple[str, str]]:
        return [("class:qmark", qmark),
                ("class:question", " {} ".format(message))]

    validator = build_validator(validate)

    bindings = KeyBindings()

    @bindings.add(Keys.ControlM, eager=True)
    def set_answer(event: KeyPressEvent):
        if event.current_buffer.complete_state is not None:
            event.current_buffer.complete_state = None
        elif event.app.current_buffer.validate(set_cursor=True):
            # When the validation succeeded, accept the input.
            result_path = event.app.current_buffer.document.text
            if result_path.endswith(os.path.sep):
                result_path = result_path[:-1]

            event.app.exit(result=result_path)
            event.app.current_buffer.append_to_history()

    @bindings.add(os.path.sep, eager=True)
    def next_segment(event: KeyPressEvent):
        b = event.app.current_buffer

        if b.complete_state:
            b.complete_state = None

        current_path = b.document.text
        if not current_path.endswith(os.path.sep):
            b.insert_text(os.path.sep)

        b.start_completion(select_first=False)

    p = PromptSession(
        get_prompt_tokens,
        lexer=SimpleLexer("class:answer"),
        style=merged_style,
        completer=GreatUXPathCompleter(only_directories=only_directories,
                                       file_filter=file_filter,
                                       expanduser=True),
        validator=validator,
        complete_style=complete_style,
        key_bindings=bindings,
        **kwargs,
    )
    p.default_buffer.reset(Document(default))

    return Question(p.app)
示例#6
0
def autocomplete(
    message: str,
    choices: List[str],
    default: str = "",
    qmark: str = DEFAULT_QUESTION_PREFIX,
    completer: Optional[Completer] = None,
    meta_information: Optional[Dict[str, Any]] = None,
    ignore_case: bool = True,
    match_middle: bool = True,
    complete_style: CompleteStyle = CompleteStyle.COLUMN,
    validate: Any = None,
    style: Optional[Style] = None,
    **kwargs: Any,
) -> Question:
    """Prompt the user to enter a message with autocomplete help.

    Example:
        >>> import questionary
        >>> questionary.autocomplete(
        ...    'Choose ant specie',
        ...    choices=[
        ...         'Camponotus pennsylvanicus',
        ...         'Linepithema humile',
        ...         'Eciton burchellii',
        ...         "Atta colombica",
        ...         'Polyergus lucidus',
        ...         'Polyergus rufescens',
        ...    ]).ask()
        ? Choose ant specie Atta colombica
        'Atta colombica'

    .. image:: ../images/autocomplete.gif

    This is just a realy basic example, the prompt can be customised using the
    parameters.


    Args:
        message: Question text

        choices: Items shown in the selection, this contains items as strings

        default: Default return value (single value).

        qmark: Question prefix displayed in front of the question.
               By default this is a ``?``

        completer: A prompt_toolkit :class:`prompt_toolkit.completion.Completion`
                   implementation. If not set, a questionary completer implementation
                   will be used.

        meta_information: A dictionary with information/anything about choices.

        ignore_case: If true autocomplete would ignore case.

        match_middle: If true autocomplete would search in every string position
                      not only in string begin.

        complete_style: How autocomplete menu would be shown, it could be ``COLUMN``
                        ``MULTI_COLUMN`` or ``READLINE_LIKE`` from
                        :class:`prompt_toolkit.shortcuts.CompleteStyle`.

        validate: Require the entered value to pass a validation. The
                  value can not be submitted until the validator accepts
                  it (e.g. to check minimum password length).

                  This can either be a function accepting the input and
                  returning a boolean, or an class reference to a
                  subclass of the prompt toolkit Validator class.

        style: A custom color and style for the question parts. You can
               configure colors as well as font types for different elements.

    Returns:
        :class:`Question`: Question instance, ready to be prompted (using ``.ask()``).
    """

    merged_style = merge_styles([DEFAULT_STYLE, style])

    def get_prompt_tokens() -> List[Tuple[str, str]]:
        return [("class:qmark", qmark), ("class:question", " {} ".format(message))]

    def get_meta_style(meta: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
        if meta:
            for key in meta:
                meta[key] = HTML("<text>{}</text>").format(meta[key])

        return meta

    validator = build_validator(validate)

    if completer is None:
        if not choices:
            raise ValueError("No choices is given, you should use Text question.")
        # use the default completer
        completer = WordCompleter(
            choices,
            ignore_case=ignore_case,
            meta_information=get_meta_style(meta_information),
            match_middle=match_middle,
        )

    p = PromptSession(
        get_prompt_tokens,
        lexer=SimpleLexer("class:answer"),
        style=merged_style,
        completer=completer,
        validator=validator,
        complete_style=complete_style,
        **kwargs,
    )
    p.default_buffer.reset(Document(default))

    return Question(p.app)
示例#7
0
def text(
    message: Text,
    default: Text = "",
    validate: Any = None,
    qmark: Text = DEFAULT_QUESTION_PREFIX,
    style: Optional[Style] = None,
    multiline: bool = False,
    instruction: Optional[Text] = None,
    **kwargs: Any,
) -> Question:
    """Prompt the user to enter a free text message.

    This question type can be used to prompt the user for some text input.

    Args:
        message: Question text

        default: Default value will be returned if the user just hits
                 enter.

        validate: Require the entered value to pass a validation. The
                  value can not be submited until the validator accepts
                  it (e.g. to check minimum password length).

                  This can either be a function accepting the input and
                  returning a boolean, or an class reference to a
                  subclass of the prompt toolkit Validator class.

        qmark: Question prefix displayed in front of the question.
               By default this is a `?`

        style: A custom color and style for the question parts. You can
               configure colors as well as font types for different elements.

        multiline: If `True`, multiline input will be enabled.

        instruction: Write instructions for the user if needed. If `None`
                     and `multiline=True`, some instructions will appear.

    Returns:
        Question: Question instance, ready to be prompted (using `.ask()`).
    """

    merged_style = merge_styles([DEFAULT_STYLE, style])

    validator = build_validator(validate)

    if instruction is None and multiline:
        instruction = INSTRUCTION_MULTILINE

    def get_prompt_tokens() -> List[Tuple[Text, Text]]:
        result = [("class:qmark", qmark),
                  ("class:question", " {} ".format(message))]
        if instruction:
            result.append(("class:instruction", " {} ".format(instruction)))
        return result

    p = PromptSession(
        get_prompt_tokens,
        style=merged_style,
        validator=validator,
        lexer=SimpleLexer("class:answer"),
        multiline=multiline,
        **kwargs,
    )
    p.default_buffer.reset(Document(default))

    return Question(p.app)
示例#8
0
def text(message: Text,
         default: Text = "",
         validate: Union[Validator,
                         Callable[[Text], bool],
                         None] = None,  # noqa
         qmark: Text = DEFAULT_QUESTION_PREFIX,
         style: Optional[Style] = None,
         path_autocomplete=False,
         exec_autocomplete=False,
         custom_autocomplete=None,
         ** kwargs: Any) -> Question:
    """Prompt the user to enter a free text message.

       This question type can be used to prompt the user for some text input.

       Args:
           message: Question text

           default: Default value will be returned if the user just hits
                    enter.

           validate: Require the entered value to pass a validation. The
                     value can not be submited until the validator accepts
                     it (e.g. to check minimum password length).

                     This can either be a function accepting the input and
                     returning a boolean, or an class reference to a
                     subclass of the prompt toolkit Validator class.

           qmark: Question prefix displayed in front of the question.
                  By default this is a `?`

           style: A custom color and style for the question parts. You can
                  configure colors as well as font types for different elements.

       Returns:
           Question: Question instance, ready to be prompted (using `.ask()`).
    """

    merged_style = merge_styles([DEFAULT_STYLE, style])

    validator = build_validator(validate)

    def get_prompt_tokens():
        return [("class:qmark", qmark),
                ("class:question", ' {} '.format(message))]
    promptArgs = dict({
        'style': merged_style,
        'validator': validator,
        'complete_style': CompleteStyle.READLINE_LIKE,
    })
    if path_autocomplete:
        promptArgs['completer'] = PathCompleter(
            expanduser=True, delimiters=' \t\n;,')
    elif exec_autocomplete:
        promptArgs['completer'] = ExecutableCompleter(delimiters=' \t\n;,')
    elif custom_autocomplete is not None and len(custom_autocomplete):
        promptArgs['completer'] = WordCompleter(
            custom_autocomplete, ignore_case=True, sentence=True)
    p = PromptSession(get_prompt_tokens,
                      **promptArgs,
                      **kwargs)
    p.default_buffer.reset(Document(default))

    return Question(p.app)
示例#9
0
def autocomplete(
    message: Text,
    choices: List[Text],
    default: Text = "",
    qmark: Text = DEFAULT_QUESTION_PREFIX,
    completer: Optional[Completer] = None,
    meta_information: Optional[Dict[Text, Any]] = None,
    ignore_case: bool = True,
    match_middle: bool = True,
    complete_style: CompleteStyle = CompleteStyle.COLUMN,
    validate: Any = None,
    style: Optional[Style] = None,
    **kwargs: Any,
) -> Question:
    """Prompt the user to enter a message with autocomplete help.

    Args:
        message: Question text

        choices: Items shown in the selection, this contains items as strings

        default: Default return value (single value).

        qmark: Question prefix displayed in front of the question.
               By default this is a `?`

        completer: A prompt_toolkit `Completer` implementation. If not set, a
                questionary completer implementation will be used.

        meta_information: A dictionary with information/anything about choices.

        ignore_case: If true autocomplete would ignore case.

        match_middle: If true autocomplete would search in every string position
                      not only in string begin.

        complete_style: How autocomplete menu would be shown, it could be
                        COLUMN, MULTI_COLUMN or READLINE_LIKE

        validate: Require the entered value to pass a validation. The
                  value can not be submitted until the validator accepts
                  it (e.g. to check minimum password length).

                  This can either be a function accepting the input and
                  returning a boolean, or an class reference to a
                  subclass of the prompt toolkit Validator class.

        style: A custom color and style for the question parts. You can
               configure colors as well as font types for different elements.

    Returns:
        Question: Question instance, ready to be prompted (using `.ask()`).
    """

    merged_style = merge_styles([DEFAULT_STYLE, style])

    def get_prompt_tokens() -> List[Tuple[Text, Text]]:
        return [("class:qmark", qmark),
                ("class:question", " {} ".format(message))]

    def get_meta_style(
            meta: Optional[Dict[Text, Any]]) -> Optional[Dict[Text, Any]]:
        if meta:
            for key in meta:
                meta[key] = HTML("<text>{}</text>").format(meta[key])

        return meta

    validator = build_validator(validate)

    if completer is None:
        if not choices:
            raise ValueError(
                "No choices is given, you should use Text question.")
        # use the default completer
        completer = WordCompleter(
            choices,
            ignore_case=ignore_case,
            meta_information=get_meta_style(meta_information),
            match_middle=match_middle,
        )

    p = PromptSession(
        get_prompt_tokens,
        lexer=SimpleLexer("class:answer"),
        style=merged_style,
        completer=completer,
        validator=validator,
        complete_style=complete_style,
        **kwargs,
    )
    p.default_buffer.reset(Document(default))

    return Question(p.app)
示例#10
0
def text(
    message: str,
    default: str = "",
    validate: Any = None,
    qmark: str = DEFAULT_QUESTION_PREFIX,
    style: Optional[Style] = None,
    multiline: bool = False,
    instruction: Optional[str] = None,
    lexer: Optional[Lexer] = None,
    **kwargs: Any,
) -> Question:
    """Prompt the user to enter a free text message.

    This question type can be used to prompt the user for some text input.

    Example:
        >>> import questionary
        >>> questionary.text("What's your first name?").ask()
        ? What's your first name? Tom
        'Tom'

    .. image:: ../images/text.gif

    This is just a really basic example, the prompt can be customised using the
    parameters.

    Args:
        message: Question text.

        default: Default value will be returned if the user just hits
                 enter.

        validate: Require the entered value to pass a validation. The
                  value can not be submitted until the validator accepts
                  it (e.g. to check minimum password length).

                  This can either be a function accepting the input and
                  returning a boolean, or an class reference to a
                  subclass of the prompt toolkit Validator class.

        qmark: Question prefix displayed in front of the question.
               By default this is a ``?``.

        style: A custom color and style for the question parts. You can
               configure colors as well as font types for different elements.

        multiline: If ``True``, multiline input will be enabled.

        instruction: Write instructions for the user if needed. If ``None``
                     and ``multiline=True``, some instructions will appear.

        lexer: Supply a valid lexer to style the answer. Leave empty to
               use a simple one by default.

        kwargs: Additional arguments, they will be passed to prompt toolkit.

    Returns:
        :class:`Question`: Question instance, ready to be prompted (using ``.ask()``).
    """

    merged_style = merge_styles([DEFAULT_STYLE, style])
    lexer = lexer or SimpleLexer("class:answer")
    validator = build_validator(validate)

    if instruction is None and multiline:
        instruction = INSTRUCTION_MULTILINE

    def get_prompt_tokens() -> List[Tuple[str, str]]:
        result = [("class:qmark", qmark),
                  ("class:question", " {} ".format(message))]
        if instruction:
            result.append(("class:instruction", " {} ".format(instruction)))
        return result

    p = PromptSession(
        get_prompt_tokens,
        style=merged_style,
        validator=validator,
        lexer=lexer,
        multiline=multiline,
        **kwargs,
    )
    p.default_buffer.reset(Document(default))

    return Question(p.app)