Skip to content

Commit

Permalink
Merge pull request #20 from seapagan/subclass_rich_prompt
Browse files Browse the repository at this point in the history
subclass the Rich prompt locally
  • Loading branch information
seapagan authored Jul 25, 2023
2 parents d5b88b0 + 681a9c7 commit 344150a
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 13 deletions.
16 changes: 6 additions & 10 deletions poetry.lock

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

65 changes: 65 additions & 0 deletions py_maker/prompt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""Subclass the Prompt class from Rich to add a few features.
Currently only makes the choices case-insensitive.
"""
from rich.prompt import Confirm as RichConfirm
from rich.prompt import InvalidResponse
from rich.prompt import Prompt as RichPrompt
from rich.prompt import PromptType


class Confirm(RichConfirm):
"""Just so we can import it from the same place as IPrompt.
Saves importing from the Rich library.
"""


class Prompt(RichPrompt):
"""Override the Prompt class to make choices case-insensitive."""

def check_choice(self, value: str) -> bool:
"""Check value is in the list of valid choices.
Args:
value (str): Value entered by user.
Returns:
bool: True if choice was valid, otherwise False.
"""
assert self.choices is not None # nosec
return value.strip().lower() in [
choice.lower() for choice in self.choices
]

def process_response(self, value: str) -> PromptType: # type: ignore
"""Process response from user, convert to prompt type.
Args:
value (str): String typed by user.
Raises:
InvalidResponse: If ``value`` is invalid.
Returns:
PromptType: The value to be returned from ask method.
"""
value = value.strip()
try:
return_value: PromptType = self.response_type(value) # type: ignore
except ValueError as exc:
raise InvalidResponse(self.validate_error_message) from exc

if self.choices is not None:
if not self.check_choice(value):
raise InvalidResponse(self.illegal_choice_message)

# return the original choice, not the lower case version
return_value = self.response_type( # type: ignore
self.choices[
[choice.lower() for choice in self.choices].index(
value.lower()
)
]
)
return return_value
3 changes: 1 addition & 2 deletions py_maker/pymaker.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
from git.repo import Repo
from jinja2 import Environment, FileSystemLoader
from rich import print # pylint: disable=W0622
from rich.prompt import Confirm, Prompt

from py_maker import template
from py_maker.constants import ExitErrors, license_names
from py_maker.prompt import Confirm, Prompt
from py_maker.schema import ProjectValues


Expand Down Expand Up @@ -277,7 +277,6 @@ def run(self) -> None:
"Application License?",
choices=license_names,
default="MIT",
case_insensitive=True,
)

if not self.confirm_values():
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ pymaker = "py_maker.main:app"
[tool.poetry.dependencies]
python = ">=3.9,<4.0"
typer = {extras = ["all"], version = "^0.9.0"}
rich = {git = "https://github.com/seapagan/rich.git", rev = "case-insensitive-prompt-choices"}
jinja2 = "^3.1.2"
gitpython = "^3.1.32"
tomli = "^2.0.1"
pydantic = "^2.0"
rich = "^13.4.2"

[build-system]
requires = ["poetry-core"]
Expand Down

0 comments on commit 344150a

Please sign in to comment.