Skip to content

Commit

Permalink
Use click features for project creation prompts (#4387)
Browse files Browse the repository at this point in the history
* Test prompt change

Signed-off-by: Laura Couto <[email protected]>

* Test adding default value

Signed-off-by: Laura Couto <[email protected]>

* Change other prompts

Signed-off-by: Laura Couto <[email protected]>

* Move prompting logic to the inside of new function

Signed-off-by: Laura Couto <[email protected]>

* fix name default

Signed-off-by: Laura Couto <[email protected]>

* Add auxiliary function for converting numbers to tools

Signed-off-by: Laura Couto <[email protected]>

* Normalize whitespaces in test outputs

Signed-off-by: Laura Couto <[email protected]>

* Prevent prompts from happening when a config file is used

Signed-off-by: Laura Couto <[email protected]>

* move click prompting to replace cookiecutter's

Signed-off-by: Laura Couto <[email protected]>

* Remove reduntant variables

Signed-off-by: Laura Couto <[email protected]>

* Fix more tests

Signed-off-by: Laura Couto <[email protected]>

* All unit tests passing

Signed-off-by: Laura Couto <[email protected]>

* Revert unnecessary changes on tests

Signed-off-by: Laura Couto <[email protected]>

* remove reduntant leftover code

Signed-off-by: Laura Couto <[email protected]>

* remove reduntant leftover code

Signed-off-by: Laura Couto <[email protected]>

* Set up prompt appearance

Signed-off-by: Laura Couto <[email protected]>

* Revert default to unformatted

Signed-off-by: Laura Couto <[email protected]>

* Switch yes/no CLI prompts to click validation

Signed-off-by: Laura Couto <[email protected]>

* Lint

Signed-off-by: Laura Couto <[email protected]>

* Use click.Choice for telemetry, rest as our own function

Signed-off-by: Laura Couto <[email protected]>

* Change example validation back to what it was initially

Signed-off-by: Laura Couto <[email protected]>

* Revert verification to _Prompt.validate

Signed-off-by: Laura Couto <[email protected]>

---------

Signed-off-by: Laura Couto <[email protected]>
  • Loading branch information
lrcouto authored Jan 27, 2025
1 parent 46259b9 commit a960558
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 22 deletions.
65 changes: 48 additions & 17 deletions kedro/framework/cli/starters.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ def _kedro_version_equal_or_lower_to_starters(version: str) -> bool:
"pyspark": "6",
"viz": "7",
}

NUMBER_TO_TOOLS_NAME = {
"1": "Linting",
"2": "Testing",
Expand Down Expand Up @@ -311,10 +312,31 @@ def starter() -> None:
@click.option("--starter", "-s", "starter_alias", help=STARTER_ARG_HELP)
@click.option("--checkout", help=CHECKOUT_ARG_HELP)
@click.option("--directory", help=DIRECTORY_ARG_HELP)
@click.option("--tools", "-t", "selected_tools", help=TOOLS_ARG_HELP)
@click.option("--name", "-n", "project_name", help=NAME_ARG_HELP)
@click.option("--example", "-e", "example_pipeline", help=EXAMPLE_ARG_HELP)
@click.option("--telemetry", "-tc", "telemetry_consent", help=TELEMETRY_ARG_HELP)
@click.option(
"--name",
"-n",
"project_name",
help=NAME_ARG_HELP,
)
@click.option(
"--tools",
"-t",
"selected_tools",
help=TOOLS_ARG_HELP,
)
@click.option(
"--example",
"-e",
"example_pipeline",
help=EXAMPLE_ARG_HELP,
)
@click.option(
"--telemetry",
"-tc",
"telemetry_consent",
help=TELEMETRY_ARG_HELP,
type=click.Choice(["yes", "no", "y", "n"], case_sensitive=False),
)
def new( # noqa: PLR0913
config_path: str,
starter_alias: str,
Expand All @@ -337,6 +359,7 @@ def new( # noqa: PLR0913
"example": example_pipeline,
"telemetry_consent": telemetry_consent,
}

_validate_flag_inputs(flag_inputs)
starters_dict = _get_starters_dict()

Expand Down Expand Up @@ -381,6 +404,7 @@ def new( # noqa: PLR0913
shutil.rmtree(tmpdir, onerror=_remove_readonly) # type: ignore[arg-type]

# Obtain config, either from a file or from interactive user prompts.

extra_context = _get_extra_context(
prompts_required=prompts_required,
config_path=config_path,
Expand All @@ -399,7 +423,6 @@ def new( # noqa: PLR0913
)

if telemetry_consent is not None:
_validate_input_with_regex_pattern("yes_no", telemetry_consent)
telemetry_consent = (
"true" if _parse_yes_no_to_bool(telemetry_consent) else "false"
)
Expand Down Expand Up @@ -727,7 +750,8 @@ def _fetch_validate_parse_config_from_file(


def _fetch_validate_parse_config_from_user_prompts(
prompts: dict[str, Any], cookiecutter_context: OrderedDict | None
prompts: dict[str, Any],
cookiecutter_context: OrderedDict | None,
) -> dict[str, str]:
"""Interactively obtains information from user prompts.
Expand All @@ -739,9 +763,6 @@ def _fetch_validate_parse_config_from_user_prompts(
Configuration for starting a new project. This is passed as ``extra_context``
to cookiecutter and will overwrite the cookiecutter.json defaults.
"""
from cookiecutter.environment import StrictEnvironment
from cookiecutter.prompt import read_user_variable, render_variable

if not cookiecutter_context:
raise Exception("No cookiecutter context available.")

Expand All @@ -751,14 +772,16 @@ def _fetch_validate_parse_config_from_user_prompts(
prompt = _Prompt(**prompt_dict)

# render the variable on the command line
cookiecutter_variable = render_variable(
env=StrictEnvironment(context=cookiecutter_context),
raw=cookiecutter_context.get(variable_name),
cookiecutter_dict=config,
)
default_value = cookiecutter_context.get(variable_name) or ""

# read the user's input for the variable
user_input = read_user_variable(str(prompt), cookiecutter_variable)
user_input = click.prompt(
str(prompt),
default=default_value,
show_default=True,
type=str,
).strip()

if user_input:
prompt.validate(user_input)
config[variable_name] = user_input
Expand Down Expand Up @@ -997,9 +1020,17 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
self.error_message = kwargs.get("error_message", "")

def __str__(self) -> str:
# Format the title with optional color
title = self.title.strip().title()
title = click.style(title + "\n" + "=" * len(title), bold=True)
prompt_lines = [title, self.text]
title = click.style(title, fg="cyan", bold=True)
title_line = "=" * len(self.title)
title_line = click.style(title_line, fg="cyan", bold=True)

# Format the main text
text = self.text.strip()

# Combine everything
prompt_lines = [title, title_line, text]
prompt_text = "\n".join(str(line).strip() for line in prompt_lines)
return f"\n{prompt_text}\n"

Expand Down
7 changes: 2 additions & 5 deletions tests/framework/cli/test_starters.py
Original file line number Diff line number Diff line change
Expand Up @@ -1676,12 +1676,9 @@ def test_flag_value_is_invalid(self, fake_kedro_cli):
)

repo_name = "new-kedro-project"
assert result.exit_code == 1
assert result.exit_code == 2

assert (
"'wrong' is an invalid value for example pipeline. It must contain only y, n, YES, or NO (case insensitive)."
in result.output
)
assert "'wrong' is not one of 'yes', 'no', 'y', 'n'" in result.output

telemetry_file_path = Path(repo_name + "/.telemetry")
assert not telemetry_file_path.exists()
Expand Down

0 comments on commit a960558

Please sign in to comment.