Spaces:
Sleeping
Sleeping
"""This module contains the classic entrypoint for creating prompts. | |
A `PyInquirer <https://github.com/CITGuru/PyInquirer>`_ compatible entrypoint :func:`.prompt`. | |
""" | |
from typing import Any, Dict, List, Optional, Tuple, Union | |
from InquirerPy.exceptions import InvalidArgument, RequiredKeyNotFound | |
from InquirerPy.prompts.checkbox import CheckboxPrompt | |
from InquirerPy.prompts.confirm import ConfirmPrompt | |
from InquirerPy.prompts.expand import ExpandPrompt | |
from InquirerPy.prompts.filepath import FilePathPrompt | |
from InquirerPy.prompts.fuzzy import FuzzyPrompt | |
from InquirerPy.prompts.input import InputPrompt | |
from InquirerPy.prompts.list import ListPrompt | |
from InquirerPy.prompts.number import NumberPrompt | |
from InquirerPy.prompts.rawlist import RawlistPrompt | |
from InquirerPy.prompts.secret import SecretPrompt | |
from InquirerPy.utils import ( | |
InquirerPyKeybindings, | |
InquirerPyQuestions, | |
InquirerPySessionResult, | |
get_style, | |
) | |
__all__ = ["prompt", "prompt_async"] | |
question_mapping = { | |
"confirm": ConfirmPrompt, | |
"filepath": FilePathPrompt, | |
"password": SecretPrompt, | |
"input": InputPrompt, | |
"list": ListPrompt, | |
"checkbox": CheckboxPrompt, | |
"rawlist": RawlistPrompt, | |
"expand": ExpandPrompt, | |
"fuzzy": FuzzyPrompt, | |
"number": NumberPrompt, | |
} | |
def _get_questions(questions: InquirerPyQuestions) -> List[Dict[str, Any]]: | |
"""Process and validate questions. | |
Args: | |
questions: List of questions to create prompt. | |
Returns: | |
List of validated questions. | |
""" | |
if isinstance(questions, dict): | |
questions = [questions] | |
if not isinstance(questions, list): | |
raise InvalidArgument("argument questions should be type of list or dictionary") | |
return questions | |
def _get_question( | |
original_question: Dict[str, Any], result: InquirerPySessionResult, index: int | |
) -> Tuple[Optional[Dict[str, Any]], str, Union[str, int], str]: | |
"""Get information from individual question. | |
Args: | |
original_question: Original question dictionary. | |
result: Current prompt session result. | |
index: Question index. | |
Returns: | |
A tuple containing question information in the order of | |
question dictionary, type of question, name of question, message of question. | |
""" | |
question = original_question.copy() | |
question_type = question.pop("type") | |
question_name = question.pop("name", index) | |
message = question.pop("message") | |
question_when = question.pop("when", None) | |
if question_when and not question_when(result): | |
result[question_name] = None | |
question = None | |
return question, question_type, question_name, message | |
async def prompt_async( | |
questions: InquirerPyQuestions, | |
style: Optional[Dict[str, str]] = None, | |
vi_mode: bool = False, | |
raise_keyboard_interrupt: bool = True, | |
keybindings: Optional[InquirerPyKeybindings] = None, | |
style_override: bool = True, | |
) -> InquirerPySessionResult: | |
"""Classic syntax entrypoint to create a prompt session via asynchronous method. | |
Refer to :func:`InquirerPy.resolver.prompt` for detailed documentations. | |
""" | |
result: InquirerPySessionResult = {} | |
if not keybindings: | |
keybindings = {} | |
questions = _get_questions(questions=questions) | |
question_style = get_style(style, style_override) | |
for index, original_question in enumerate(questions): | |
try: | |
question, question_type, question_name, message = _get_question( | |
original_question=original_question, result=result, index=index | |
) | |
if question is None: | |
continue | |
args = { | |
"message": message, | |
"style": question_style, | |
"vi_mode": vi_mode, | |
"raise_keyboard_interrupt": raise_keyboard_interrupt, | |
"session_result": result, | |
"keybindings": {**keybindings, **question.pop("keybindings", {})}, | |
} | |
result[question_name] = await question_mapping[question_type]( | |
**args, **question | |
).execute_async() | |
except KeyError: | |
raise RequiredKeyNotFound | |
return result | |
def prompt( | |
questions: InquirerPyQuestions, | |
style: Optional[Dict[str, str]] = None, | |
vi_mode: bool = False, | |
raise_keyboard_interrupt: bool = True, | |
keybindings: Optional[InquirerPyKeybindings] = None, | |
style_override: bool = True, | |
) -> InquirerPySessionResult: | |
"""Classic syntax entrypoint to create a prompt session. | |
Resolve user provided list of questions, display prompts and get the results. | |
Args: | |
questions: A list of :ref:`pages/prompt:question` to ask. Refer to documentation for more info. | |
style: A :class:`dict` containing the style specification for the prompt. Refer to :ref:`pages/style:Style` for more info. | |
vi_mode: Use vim keybindings for the prompt instead of the default emacs keybindings. | |
Refer to :ref:`pages/kb:Keybindings` for more info. | |
raise_keyboard_interrupt: Raise the :class:`KeyboardInterrupt` exception when `ctrl-c` is pressed. If false, the result | |
will be `None` and the question is skiped. | |
keybindings: List of custom :ref:`pages/kb:Keybindings` to apply. Refer to documentation for more info. | |
style_override: Override all default styles. When providing any style customisation, all default styles are removed when this is True. | |
Returns: | |
A dictionary containing all of the question answers. The key is the name of the question and the value is the | |
user answer. If the `name` key is not present as part of the question, then the question index will be used | |
as the key. | |
Raises: | |
RequiredKeyNotFound: When the question is missing required keys. | |
InvalidArgument: When the provided `questions` argument is not a type of :class:`list` nor :class:`dictionary`. | |
Examples: | |
>>> from InquirerPy import prompt | |
>>> from InquirerPy.validator import NumberValidator | |
>>> questions = [ | |
... { | |
... "type": "input", | |
... "message": "Enter your age:", | |
... "validate": NumberValidator(), | |
... "invalid_message": "Input should be number.", | |
... "default": "18", | |
... "name": "age", | |
... "filter": lambda result: int(result), | |
... "transformer": lambda result: "Adult" if int(result) >= 18 else "Youth", | |
... }, | |
... { | |
... "type": "rawlist", | |
... "message": "What drinks would you like to buy:", | |
... "default": 2, | |
... "choices": lambda result: ["Soda", "Cidr", "Water", "Milk"] | |
... if result["age"] < 18 | |
... else ["Wine", "Beer"], | |
... "name": "drink", | |
... }, | |
... { | |
... "type": "list", | |
... "message": "Would you like a bag:", | |
... "choices": ["Yes", "No"], | |
... "when": lambda result: result["drink"] in {"Wine", "Beer"}, | |
... }, | |
... {"type": "confirm", "message": "Confirm?", "default": True}, | |
... ] | |
>>> result = prompt(questions=questions) | |
""" | |
result: InquirerPySessionResult = {} | |
if not keybindings: | |
keybindings = {} | |
questions = _get_questions(questions=questions) | |
question_style = get_style(style, style_override) | |
for index, original_question in enumerate(questions): | |
try: | |
question, question_type, question_name, message = _get_question( | |
original_question=original_question, result=result, index=index | |
) | |
if question is None: | |
continue | |
args = { | |
"message": message, | |
"style": question_style, | |
"vi_mode": vi_mode, | |
"raise_keyboard_interrupt": raise_keyboard_interrupt, | |
"session_result": result, | |
"keybindings": {**keybindings, **question.pop("keybindings", {})}, | |
} | |
result[question_name] = question_mapping[question_type]( | |
**args, **question | |
).execute() | |
except KeyError: | |
raise RequiredKeyNotFound | |
return result | |