Skip to content

Commit

Permalink
Add a print question type (#244)
Browse files Browse the repository at this point in the history
  • Loading branch information
RhetTbull committed Aug 15, 2022
1 parent 6643fe0 commit 87a891c
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 3 deletions.
18 changes: 17 additions & 1 deletion examples/advanced_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@

def ask_dictstyle(**kwargs):
questions = [
{
# just print a message, don't ask a question
# does not require a name (but if provided, is ignored) and does not return a value
"type": "print",
"name": "intro",
"message": "This example demonstrates advanced features! 🦄",
"style": "bold italic",
},
{
"type": "confirm",
"name": "conditional_step",
Expand All @@ -27,6 +35,14 @@ def ask_dictstyle(**kwargs):
"message": "Select item",
"choices": ["item1", "item2", Separator(), "other"],
},
{
# just print a message, don't ask a question
# does not require a name and does not return a value
"type": "print",
"message": "Please enter a value for 'other'",
"style": "bold italic fg:darkred",
"when": lambda x: x["second_question"] == "other",
},
{
"type": "text",
# intentionally overwrites result from previous question
Expand All @@ -35,7 +51,7 @@ def ask_dictstyle(**kwargs):
"when": lambda x: x["second_question"] == "other",
},
]
return prompt(questions)
return prompt(questions, **kwargs)


if __name__ == "__main__":
Expand Down
22 changes: 20 additions & 2 deletions questionary/prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from questionary.constants import DEFAULT_KBI_MESSAGE
from questionary.prompts import AVAILABLE_PROMPTS
from questionary.prompts import prompt_by_name
from questionary.prompts.common import print_formatted_text


class PromptParameterException(ValueError):
Expand Down Expand Up @@ -143,15 +144,16 @@ def unsafe_prompt(
# import the question
if "type" not in question_config:
raise PromptParameterException("type")
if "name" not in question_config:
# every type except 'print' needs a name
if "name" not in question_config and question_config["type"] != "print":
raise PromptParameterException("name")

_kwargs = kwargs.copy()
_kwargs.update(question_config)

_type = _kwargs.pop("type")
_filter = _kwargs.pop("filter", None)
name = _kwargs.pop("name")
name = _kwargs.pop("name", None) if _type == "print" else _kwargs.pop("name")
when = _kwargs.pop("when", None)

if true_color:
Expand All @@ -172,6 +174,22 @@ def unsafe_prompt(
"'when' needs to be function that accepts a dict argument"
)

# handle 'print' type
if _type == "print":
try:
message = _kwargs.pop("message")
except KeyError as e:
raise PromptParameterException("message") from e

# questions can take 'input' arg but print_formatted_text does not
# Remove 'input', if present, to avoid breaking during tests
_kwargs.pop("input", None)

print_formatted_text(message, **_kwargs)
if name:
answers[name] = None
continue

choices = question_config.get("choices")
if choices is not None and callable(choices):
calculated_choices = choices(answers)
Expand Down
25 changes: 25 additions & 0 deletions tests/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,28 @@ def test_autocomplete_example():

assert result_dict == {"ants": "Polyergus lucidus"}
assert result_py == "Polyergus lucidus"


def test_advanced_workflow_example():
from examples.advanced_workflow import ask_dictstyle

text = (
KeyInputs.ENTER
+ "questionary"
+ KeyInputs.ENTER
+ KeyInputs.DOWN
+ KeyInputs.DOWN
+ KeyInputs.ENTER
+ "Hello World"
+ KeyInputs.ENTER
+ "\r"
)

result_dict = ask_with_patched_input(ask_dictstyle, text)

assert result_dict == {
"intro": None,
"conditional_step": True,
"next_question": "questionary",
"second_question": "Hello World",
}
29 changes: 29 additions & 0 deletions tests/test_prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from questionary.prompt import PromptParameterException
from questionary.prompt import prompt
from tests.utils import patched_prompt


def test_missing_message():
Expand Down Expand Up @@ -47,3 +48,31 @@ def test_invalid_question_type():
}
]
)


def test_missing_print_message():
"""Test 'print' raises exception if missing 'message'"""
with pytest.raises(PromptParameterException):
prompt(
[
{
"name": "test",
"type": "print",
}
]
)


def test_print_no_name():
"""'print' type doesn't require a name so it
should not throw PromptParameterException"""
questions = [{"type": "print", "message": "Hello World"}]
result = patched_prompt(questions, "")
assert result == {}


def test_print_with_name():
"""'print' type should return {name: None} when name is provided"""
questions = [{"name": "hello", "type": "print", "message": "Hello World"}]
result = patched_prompt(questions, "")
assert result == {"hello": None}

0 comments on commit 87a891c

Please sign in to comment.