Repository: kedro-org/kedro
File: kedro/framework/cli/cli.py (Python)

Code before:
                    fg=ORANGE,
                    bold=True,
                )
                result = (
                    click.style("Project specific commands such as ")
                    + click.style("'run' ", fg="cyan")
                    + "or "
                    + click.style("'jupyter' ", fg="cyan")
                    + "are only available within a project directory."
                )
                message = warn + result
                hint = (
                    click.style(
                        "\nHint: Kedro is looking for a file called ", fg=BRIGHT_BLACK
                    )
                    + click.style("'pyproject.toml", fg="magenta")
                    + click.style(
                        ", is one present in your current working directory?",
                        fg=BRIGHT_BLACK,
                    )
                )
                click.echo(message)
                click.echo(hint)
                sys.exit(exc.code)
        except Exception as error:
            logger.error(f"An error has occurred: {error}")
            logger.error(f"{traceback.format_exc()}")

            self._cli_hook_manager.hook.after_command_run(
                project_metadata=self._metadata, command_args=args, exit_code=1
            )
            hook_called = True
            sys.exit(1)
        finally:
            if not hook_called:
                self._cli_hook_manager.hook.after_command_run(
                    project_metadata=self._metadata, command_args=args, exit_code=0
                )

    @property
    def global_groups(self) -> Sequence[click.MultiCommand]:
        """Property which loads all global command groups from plugins and
        combines them with the built-in ones (eventually overriding the
        built-in ones if they are redefined by plugins).
        """
        return [*load_entry_points("global"), cli, global_commands]

    @property
    def project_groups(self) -> Sequence[click.MultiCommand]:
        """Property which loads all project command groups from the
        project and the plugins, then combines them with the built-in ones.

Review comment (suggestion):
This message was introduced in 0.19.7; however, if we want to spit out the full trace, why is this necessary? Why can't you just doing something like

```python
            self._cli_hook_manager.hook.after_command_run(
                project_metadata=self._metadata, command_args=args, exit_code=1
            )
            hook_called = True
            raise
```

?

This would be closer to the previous behavior.

In case you're unsure, your `finally` block will still be called:

```pycon
>>> try:
...    print("do or do not")
...    raise Exception("oh no")
... except Exception as exc:
...    print("there is no try")
...    raise
... finally:
...    print("rip")
... 
do or do not
there is no try
rip
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
Exception: oh no
>>> 
```

Code after:
                    click.style("Project specific commands such as ")
                    + click.style("'run' ", fg="cyan")
                    + "or "
                    + click.style("'jupyter' ", fg="cyan")
                    + "are only available within a project directory."
                )
                message = warn + result
                hint = (
                    click.style(
                        "\nHint: Kedro is looking for a file called ", fg=BRIGHT_BLACK
                    )
                    + click.style("'pyproject.toml", fg="magenta")
                    + click.style(
                        ", is one present in your current working directory?",
                        fg=BRIGHT_BLACK,
                    )
                )
                click.echo(message)
                click.echo(hint)
                sys.exit(exc.code)
        except Exception:
            self._cli_hook_manager.hook.after_command_run(
                project_metadata=self._metadata, command_args=args, exit_code=1
            )
            hook_called = True
            raise
        finally:
            if not hook_called:
                self._cli_hook_manager.hook.after_command_run(
                    project_metadata=self._metadata, command_args=args, exit_code=0
                )

    @property
    def global_groups(self) -> Sequence[click.MultiCommand]:
        """Property which loads all global command groups from plugins and
        combines them with the built-in ones (eventually overriding the
        built-in ones if they are redefined by plugins).
        """
        return [*load_entry_points("global"), cli, global_commands]

    @property
    def project_groups(self) -> Sequence[click.MultiCommand]:
        """Property which loads all project command groups from the
        project and the plugins, then combines them with the built-in ones.
        Built-in commands can be overridden by plugins, which can be
        overridden by a custom project cli.py.
        See https://docs.kedro.org/en/stable/extend_kedro/common_use_cases.html#use-case-3-how-to-add-or-modify-cli-commands
        on how to add this.
        """
        if not self._metadata:
            return []