From ce27c2dd781cf21a9cb2263fad35c57bff9b3b78 Mon Sep 17 00:00:00 2001 From: Ahdra Merali <90615669+AhdraMeraliQB@users.noreply.github.com> Date: Thu, 11 Jan 2024 17:35:32 +0000 Subject: [PATCH] Check if starter is used before printing tools message (#3484) * Add check for if starter is used Signed-off-by: Ahdra Merali * Move messages to access starter_alias Signed-off-by: Ahdra Merali * Lint Signed-off-by: Ahdra Merali * Lint again Signed-off-by: Ahdra Merali * Alternative: pass through starter in config Signed-off-by: Ahdra Merali * Resolve quick TODO Signed-off-by: Ahdra Merali * Lint Signed-off-by: Ahdra Merali * Move flag input validation into separate function Signed-off-by: Ahdra Merali * Remove redundant condition Signed-off-by: Ahdra Merali * Change latest docs links to point to stable Signed-off-by: Ahdra Merali * Avoid merge conflict with 3490 Signed-off-by: Ahdra Merali * Add return type hints Signed-off-by: Ahdra Merali * Apply suggestions from code review - consolidate printing Signed-off-by: Ahdra Merali --------- Signed-off-by: Ahdra Merali --- kedro/framework/cli/starters.py | 122 +++++++++++++++++---------- kedro/framework/project/__init__.py | 2 +- tests/framework/cli/test_starters.py | 3 + 3 files changed, 82 insertions(+), 45 deletions(-) diff --git a/kedro/framework/cli/starters.py b/kedro/framework/cli/starters.py index 2d1d31aad3..7fbe4f5ad6 100644 --- a/kedro/framework/cli/starters.py +++ b/kedro/framework/cli/starters.py @@ -31,7 +31,6 @@ command_with_verbosity, ) -# TODO(lrcouto): Insert actual link to the documentation (Visit: kedro.org/{insert-documentation} to find out more about these tools.). TOOLS_ARG_HELP = """ Select which tools you'd like to include. By default, none are included.\n @@ -48,6 +47,8 @@ kedro new --tools=lint,test,log,docs,data,pyspark,viz (or any subset of these options)\n kedro new --tools=all\n kedro new --tools=none + +For more information on using tools, see https://docs.kedro.org/en/stable/starters/new_project_tools.html """ CONFIG_ARG_HELP = """Non-interactive mode, using a configuration yaml file. This file must supply the keys required by the template's prompts.yml. When not using a starter, @@ -130,6 +131,23 @@ class KedroStarterSpec: # noqa: too-few-public-methods } +def _validate_flag_inputs(flag_inputs: dict[str, Any]) -> None: + if flag_inputs.get("checkout") and not flag_inputs.get("starter"): + raise KedroCliError("Cannot use the --checkout flag without a --starter value.") + + if flag_inputs.get("directory") and not flag_inputs.get("starter"): + raise KedroCliError( + "Cannot use the --directory flag without a --starter value." + ) + + if (flag_inputs.get("tools") or flag_inputs.get("example")) and flag_inputs.get( + "starter" + ): + raise KedroCliError( + "Cannot use the --starter flag with the --example and/or --tools flag." + ) + + def _validate_regex(pattern_name, text): VALIDATION_PATTERNS = { "yes_no": { @@ -187,6 +205,39 @@ def _validate_selected_tools(selected_tools): sys.exit(1) +def _print_selection_and_prompt_info( + selected_tools: str | None, example_pipeline: bool | None, interactive: bool +) -> None: + # Confirm tools selection + if selected_tools is not None: + if selected_tools == "['None']": + click.secho( + "You have selected no project tools", + fg="green", + ) + else: + click.secho( + f"You have selected the following project tools: {selected_tools}", + fg="green", + ) + + # Confirm example selection + if example_pipeline is not None: + if example_pipeline: + click.secho( + "It has been created with an example pipeline.", + fg="green", + ) + + # Give hint for skipping interactive flow + if interactive: + click.secho( + "\nTo skip the interactive flow you can run `kedro new` with" + "\nkedro new --name= --tools= --example=", + fg="green", + ) + + # noqa: missing-function-docstring @click.group(context_settings=CONTEXT_SETTINGS, name="Kedro") def create_cli(): # pragma: no cover @@ -223,19 +274,16 @@ def new( # noqa: PLR0913 **kwargs, ): """Create a new kedro project.""" - if checkout and not starter_alias: - raise KedroCliError("Cannot use the --checkout flag without a --starter value.") - - if directory and not starter_alias: - raise KedroCliError( - "Cannot use the --directory flag without a --starter value." - ) - - if (selected_tools or example_pipeline) and starter_alias: - raise KedroCliError( - "Cannot use the --starter flag with the --example and/or --tools flag." - ) - + flag_inputs = { + "config": config_path, + "starter": starter_alias, + "tools": selected_tools, + "name": project_name, + "checkout": checkout, + "directory": directory, + "example": example_pipeline, + } + _validate_flag_inputs(flag_inputs) starters_dict = _get_starters_dict() if starter_alias in starters_dict: @@ -283,7 +331,7 @@ def new( # noqa: PLR0913 extra_context = _get_extra_context( prompts_required=prompts_required, config_path=config_path, - cookiecutter_context=cookiecutter_context, + cookiecutter_context=cookiecutter_context, # type: ignore selected_tools=selected_tools, project_name=project_name, example_pipeline=example_pipeline, @@ -299,12 +347,15 @@ def new( # noqa: PLR0913 _create_project(project_template, cookiecutter_args) - if prompts_required and not config_path and not starter_alias: - click.secho( - "\nTo skip the interactive flow you can run `kedro new` with" - "\nkedro new --name= --tools= --example=", - fg="green", - ) + # If not a starter, print tools and example selection + if not starter_alias: + # If interactive flow used, print hint + interactive_flow = prompts_required and not config_path + _print_selection_and_prompt_info( + extra_context.get("tools"), + extra_context.get("example_pipeline"), + interactive_flow, + ) # type: ignore @starter.command("list") @@ -485,6 +536,10 @@ def _get_extra_context( # noqa: PLR0913 or None in case the flag wasn't used. project_name: a string containing the value for the --name flag, or None in case the flag wasn't used. + example_pipeline: a string containing the value for the --example flag, + or None in case the flag wasn't used + starter_alias: a string containing the value for the --starter flag, or + None in case the flag wasn't used Returns: the prompts_required dictionary, with all the redundant information removed. @@ -824,7 +879,7 @@ def _create_project(template_path: str, cookiecutter_args: dict[str, Any]): template_path: The path to the cookiecutter template to create the project. It could either be a local directory or a remote VCS repository supported by cookiecutter. For more details, please see: - https://cookiecutter.readthedocs.io/en/latest/usage.html#generate-your-project + https://cookiecutter.readthedocs.io/en/stable/usage.html#generate-your-project cookiecutter_args: Arguments to pass to cookiecutter. Raises: @@ -843,34 +898,13 @@ def _create_project(template_path: str, cookiecutter_args: dict[str, Any]): _clean_pycache(Path(result_path)) extra_context = cookiecutter_args["extra_context"] project_name = extra_context.get("project_name", "New Kedro Project") - tools = extra_context.get("tools") - example_pipeline = extra_context.get("example_pipeline") + # Print success message click.secho( "\nCongratulations!" f"\nYour project '{project_name}' has been created in the directory \n{result_path}\n" ) - # we can use starters without tools: - if tools is not None: - if tools == "['None']": # TODO: This should be a list - click.secho( - "You have selected no project tools", - fg="green", - ) - else: - click.secho( - f"You have selected the following project tools: {tools}", - fg="green", - ) - - if example_pipeline is not None: - if example_pipeline: - click.secho( - "It has been created with an example pipeline.", - fg="green", - ) - class _Prompt: """Represent a single CLI prompt for `kedro new`""" diff --git a/kedro/framework/project/__init__.py b/kedro/framework/project/__init__.py index 85eafc37c9..8f507df5e4 100644 --- a/kedro/framework/project/__init__.py +++ b/kedro/framework/project/__init__.py @@ -327,7 +327,7 @@ def find_pipelines() -> dict[str, Pipeline]: # noqa: PLR0912 can modify the mapping generated by the ``find_pipelines`` function. For more information on the pipeline registry and autodiscovery, see - https://kedro.readthedocs.io/en/latest/nodes_and_pipelines/pipeline_registry.html + https://kedro.readthedocs.io/en/stable/nodes_and_pipelines/pipeline_registry.html Returns: A generated mapping from pipeline names to ``Pipeline`` objects. diff --git a/tests/framework/cli/test_starters.py b/tests/framework/cli/test_starters.py index b9cff3fac5..d35beb7dd1 100644 --- a/tests/framework/cli/test_starters.py +++ b/tests/framework/cli/test_starters.py @@ -220,6 +220,8 @@ def _assert_template_ok( if "y" in example_pipeline.lower(): assert "It has been created with an example pipeline." in result.output + else: + assert "It has been created with an example pipeline." not in result.output generated_files = [ p for p in full_path.rglob("*") if p.is_file() and p.name != ".DS_Store" @@ -865,6 +867,7 @@ def test_no_hint(self, fake_kedro_cli): "To skip the interactive flow you can run `kedro new` with\nkedro new --name= --tools= --example=" not in result.output ) + assert "You have selected" not in result.output _assert_template_ok(result) _clean_up_project(Path("./new-kedro-project"))