Repository: kedro-org/kedro

Issue:
Unhide cookiecutter errors in `kedro new`
## Description
Somehow the opposite of gh-2401: when cookiecutter fails, `kedro new` prompts you to re-run with `--verbose`:

```
> kedro new --starter=spaceflights

Project Name
============
Please enter a human readable name for your new project.
Spaces, hyphens, and underscores are allowed.
 [Spaceflights]: 
kedro.framework.cli.utils.KedroCliError: Failed to generate project when running cookiecutter.
Run with --verbose to see the full exception
Error: Failed to generate project when running cookiecutter.
```

## Context
In my case, the issue was quite silly: the directory already existed.

```
> kedro new --starter=spaceflights --verbose

Project Name
============
Please enter a human readable name for your new project.
Spaces, hyphens, and underscores are allowed.
 [Spaceflights]: 
Traceback (most recent call last):
  File "/Users/juan_cano/.micromamba/envs/_test310/lib/python3.10/site-packages/kedro/framework/cli/starters.py", line 351, in _create_project
    result_path = cookiecutter(template=template_path, **cookiecutter_args)
  File "/Users/juan_cano/.micromamba/envs/_test310/lib/python3.10/site-packages/cookiecutter/main.py", line 114, in cookiecutter
    result = generate_files(
  File "/Users/juan_cano/.micromamba/envs/_test310/lib/python3.10/site-packages/cookiecutter/generate.py", line 291, in generate_files
    project_dir, output_directory_created = render_and_create_dir(
  File "/Users/juan_cano/.micromamba/envs/_test310/lib/python3.10/site-packages/cookiecutter/generate.py", line 223, in render_and_create_dir
    raise OutputDirExistsException(msg)
cookiecutter.exceptions.OutputDirExistsException: Error: "/private/tmp/spaceflights" directory already exists

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/juan_cano/.micromamba/envs/_test310/lib/python3.10/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "/Users/juan_cano/.micromamba/envs/_test310/lib/python3.10/site-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/Users/juan_cano/.micromamba/envs/_test310/lib/python3.10/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/Users/juan_cano/.micromamba/envs/_test310/lib/python3.10/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "/Users/juan_cano/.micromamba/envs/_test310/lib/python3.10/site-packages/kedro/framework/cli/starters.py", line 233, in new
    _create_project(template_path, cookiecutter_args)
  File "/Users/juan_cano/.micromamba/envs/_test310/lib/python3.10/site-packages/kedro/framework/cli/starters.py", line 353, in _create_project
    raise KedroCliError(
kedro.framework.cli.utils.KedroCliError: Failed to generate project when running cookiecutter.
Error: Failed to generate project when running cookiecutter.
```

## Possible Implementation
Capture the error and show it. Something like this:

```
> kedro new --starter=spaceflights --verbose                                                                                                                                (_test310) 

Project Name
============
Please enter a human readable name for your new project.
Spaces, hyphens, and underscores are allowed.
 [Spaceflights]: 
cookiecutter.exceptions.OutputDirExistsException: Error: "/private/tmp/spaceflights" directory already exists
Run with --verbose to see the full exception
Error: Failed to generate project when running cookiecutter.
```

## Possible Alternatives
Just display the full traceback on error. But I don't think it's optimal in its current form, since the actual error is hidden in the middle.



Discussion:

Patch:
diff --git a/RELEASE.md b/RELEASE.md
index e22d9f9a47..c534720754 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -1,6 +1,7 @@
 # Upcoming Release 0.19.4
 
 ## Major features and improvements
+* Cookiecutter errors are shown in short format without the `--verbose` flag.
 * Kedro commands now work from any subdirectory within a Kedro project.
 * Kedro CLI now provides a better error message when project commands are run outside of a project i.e. `kedro run`
 
diff --git a/kedro/framework/cli/utils.py b/kedro/framework/cli/utils.py
index 46fc5bdc62..194b244b5f 100644
--- a/kedro/framework/cli/utils.py
+++ b/kedro/framework/cli/utils.py
@@ -265,15 +265,21 @@ class KedroCliError(click.exceptions.ClickException):
 
     VERBOSE_ERROR = False
     VERBOSE_EXISTS = True
+    COOKIECUTTER_EXCEPTIONS_PREFIX = "cookiecutter.exceptions"
 
     def show(self, file: IO | None = None) -> None:
         if self.VERBOSE_ERROR:
             click.secho(traceback.format_exc(), nl=False, fg="yellow")
         elif self.VERBOSE_EXISTS:
-            etype, value, _ = sys.exc_info()
+            etype, value, tb = sys.exc_info()
             formatted_exception = "".join(traceback.format_exception_only(etype, value))
+            cookiecutter_exception = ""
+            for ex_line in traceback.format_exception(etype, value, tb):
+                if self.COOKIECUTTER_EXCEPTIONS_PREFIX in ex_line:
+                    cookiecutter_exception = ex_line
+                    break
             click.secho(
-                f"{formatted_exception}Run with --verbose to see the full exception",
+                f"{cookiecutter_exception}{formatted_exception}Run with --verbose to see the full exception",
                 fg="yellow",
             )
         else:


Test patch:
diff --git a/tests/framework/cli/test_cli.py b/tests/framework/cli/test_cli.py
index c1e5ce51ec..d147a6a0d1 100644
--- a/tests/framework/cli/test_cli.py
+++ b/tests/framework/cli/test_cli.py
@@ -691,6 +691,7 @@ def test_run_with_invalid_config(
             "Key `node-names` in provided configuration is not valid. \n\nDid you mean one of "
             "these?\n    node_names\n    to_nodes\n    namespace" in result.stdout
         )
+        KedroCliError.VERBOSE_EXISTS = True
 
     @mark.parametrize(
         "fake_run_config_with_params,expected",
diff --git a/tests/framework/cli/test_starters.py b/tests/framework/cli/test_starters.py
index d89270f862..09ae542fd3 100644
--- a/tests/framework/cli/test_starters.py
+++ b/tests/framework/cli/test_starters.py
@@ -490,6 +490,15 @@ def test_fail_if_dir_exists(self, fake_kedro_cli):
         assert result.exit_code != 0
         assert "directory already exists" in result.output
 
+    def test_cookiecutter_exception_if_no_verbose(self, fake_kedro_cli):
+        """Check if the original cookiecutter exception is present in the output
+        if no verbose flag is provided."""
+        Path("new-kedro-project").mkdir()
+        result = CliRunner().invoke(
+            fake_kedro_cli, ["new"], input=_make_cli_prompt_input()
+        )
+        assert "cookiecutter.exceptions" in result.output
+
     def test_prompt_no_title(self, fake_kedro_cli):
         shutil.copytree(TEMPLATE_PATH, "template")
         _write_yaml(Path("template") / "prompts.yml", {"repo_name": {}})