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

✨ feat: Interactive CLI input #947

Merged
merged 2 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@ dependencies = [
"solc-select>=1.0.4,<2",
"filelock>=3.15.1,<4",
"ethereum-types>=0.2.1,<0.3",
"pyyaml>=6.0.2",
"types-pyyaml>=6.0.12.20240917",
"pyyaml>=6.0.2,<7",
"types-pyyaml>=6.0.12.20240917,<7",
"pytest-json-report>=1.5.0,<2",
"questionary>=2.0.1,<3",
]

[project.urls]
Expand Down
75 changes: 75 additions & 0 deletions src/cli/input/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"""
A standard interface for interactive CLI inputs.
"""

from .questionary_input_repository import QuestionaryInputRepository

# Instantiate the input repository
input_repository = QuestionaryInputRepository()


def input_text(question: str) -> str:
"""
Ask a simple text input question.

Args:
question (str): The question to ask.

Returns:
str: The user's response.
"""
return input_repository.input_text(question)


def input_password(question: str) -> str:
"""
Ask a password input question (hidden text).

Args:
question (str): The question to ask.

Returns:
str: The user's response (password).
"""
return input_repository.input_password(question)


def input_select(question: str, choices: list) -> str:
"""
Ask a single-choice question from a list of options.

Args:
question (str): The question to ask.
choices (list): A list of options for the user to choose from.

Returns:
str: The selected choice.
"""
return input_repository.input_select(question, choices)


def input_checkbox(question: str, choices: list) -> list:
"""
Ask a multi-choice question and return a list of selected choices.

Args:
question (str): The question to ask.
choices (list): A list of options for the user to choose from.

Returns:
list: The list of selected choices.
"""
return input_repository.input_checkbox(question, choices)


def input_confirm(question: str) -> bool:
"""
Ask a yes/no confirmation question.

Args:
question (str): The question to ask.

Returns:
bool: True for 'yes', False for 'no'.
"""
return input_repository.input_confirm(question)
38 changes: 38 additions & 0 deletions src/cli/input/input_repository.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""
An abstract base class for handling interactive CLI inputs.
"""

from abc import ABC, abstractmethod
from typing import List


class InputRepository(ABC):
"""
Abstract base class for input handling.
This class defines the interface for different input types that can be swapped out.
"""

@abstractmethod
def input_text(self, question: str) -> str:
"""Ask a text input question."""
pass

@abstractmethod
def input_password(self, question: str) -> str:
"""Ask a password input question (hidden)."""
pass

@abstractmethod
def input_select(self, question: str, choices: List[str]) -> str:
"""Ask a single-choice selection question."""
pass

@abstractmethod
def input_checkbox(self, question: str, choices: List[str]) -> List[str]:
"""Ask a multi-choice question."""
pass

@abstractmethod
def input_confirm(self, question: str) -> bool:
"""Ask a yes/no confirmation question."""
pass
42 changes: 42 additions & 0 deletions src/cli/input/questionary_input_repository.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""
Interactive CLI inputs using questionary library.
See: https://questionary.readthedocs.io/
"""

from questionary import checkbox, confirm, password, select, text

from .input_repository import InputRepository


class QuestionaryInputRepository(InputRepository):
"""Repository for handling various types of user inputs using the Questionary library."""

def input_text(self, question: str) -> str:
"""Ask a text input question.
See: https://questionary.readthedocs.io/en/stable/api.html#questionary.text
"""
return text(message=question).ask()

def input_password(self, question: str) -> str:
"""Ask a password input question (hidden).
See: https://questionary.readthedocs.io/en/stable/api.html#questionary.password
"""
return password(message=question).ask()

def input_select(self, question: str, choices: list) -> str:
"""Ask a single-choice selection question.
See: https://questionary.readthedocs.io/en/stable/api.html#questionary.select
"""
return select(message=question, choices=choices).ask()

def input_checkbox(self, question: str, choices: list) -> list:
"""Ask a multi-choice question.
See: https://questionary.readthedocs.io/en/stable/api.html#questionary.checkbox
"""
return checkbox(message=question, choices=choices).ask()

def input_confirm(self, question: str) -> bool:
"""Ask a yes/no confirmation question.
See: https://questionary.readthedocs.io/en/stable/api.html#questionary.confirm
"""
return confirm(message=question).ask()
35 changes: 35 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions whitelist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ Pytest
pytest's
pytestArgs
qGpsxSA
questionary
quickstart
radd
randao
Expand Down