diff --git a/CITATION.cff b/CITATION.cff index a8b2d2e073..df74d7372d 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -44,6 +44,6 @@ authors: - family-names: Brugman given-names: Simon title: Kedro -version: 0.19.6 -date-released: 2024-05-23 +version: 0.19.7 +date-released: 2024-08-01 url: https://github.com/kedro-org/kedro diff --git a/RELEASE.md b/RELEASE.md index 32a47371f6..cbb3a9f3a0 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,17 +1,30 @@ -# Upcoming Release 0.19.7 +# Upcoming Release 0.19.8 + +## Major features and improvements + +## Bug fixes and other changes + +## Breaking changes to the API + +## Documentation changes + +## Community contributions + +# Release 0.19.7 ## Major features and improvements * Exposed `load` and `save` publicly for each dataset in the core `kedro` library, and enabled other datasets to do the same. If a dataset doesn't expose `load` or `save` publicly, Kedro will fall back to using `_load` or `_save`, respectively. * Kedro commands are now lazily loaded to add performance gains when running Kedro commands. +* Implemented key completion support for accessing datasets in the `DataCatalog`. +* Implemented dataset pretty printing. +* Implemented `DataCatalog` pretty printing. +* Moved to an opt-out model for telemetry, enabling it by default without requiring prior consent. ## Bug fixes and other changes * Updated error message for invalid catalog entries. * Updated error message for catalog entries when the dataset class is not found with hints on how to resolve the issue. * Fixed a bug in the `DataCatalog` `shallow_copy()` method to ensure it returns the type of the used catalog and doesn't cast it to `DataCatalog`. -* Implemented key completion support for accessing datasets in the `DataCatalog`. * Made [kedro-telemetry](https://github.com/kedro-org/kedro-plugins/tree/main/kedro-telemetry) a core dependency. -* Implemented dataset pretty printing. -* Implemented `DataCatalog` pretty printing. * Fixed a bug when `OmegaConfigLoader` is printed, there are few missing arguments. * Fixed a bug when where iterating `OmegaConfigLoader`'s `keys` return empty dictionary. @@ -25,6 +38,9 @@ * Extended documentation with an example of logging customisation at runtime ## Community contributions +Many thanks to the following Kedroids for contributing PRs to this release: +* [nickolasrm](https://github.com/nickolasrm) +* [yury-fedotov](https://github.com/yury-fedotov) # Release 0.19.6 diff --git a/docs/source/development/commands_reference.md b/docs/source/development/commands_reference.md index 37de75d44d..41c1fa2300 100644 --- a/docs/source/development/commands_reference.md +++ b/docs/source/development/commands_reference.md @@ -109,7 +109,7 @@ Returns output similar to the following, depending on the version of Kedro used | |/ / _ \/ _` | '__/ _ \ | < __/ (_| | | | (_) | |_|\_\___|\__,_|_| \___/ -v0.19.6 +v0.19.7 Kedro is a Python framework for creating reproducible, maintainable diff --git a/docs/source/robots.txt b/docs/source/robots.txt index 962c08cfc9..e8527497df 100644 --- a/docs/source/robots.txt +++ b/docs/source/robots.txt @@ -1,6 +1,7 @@ User-agent: * Disallow: / Allow: /en/stable/ +Allow: /en/0.19.7* Allow: /en/0.19.6* Allow: /en/0.19.5* Allow: /en/0.19.4* diff --git a/kedro/__init__.py b/kedro/__init__.py index b3ab28979a..a5cab8cf56 100644 --- a/kedro/__init__.py +++ b/kedro/__init__.py @@ -6,7 +6,7 @@ import sys import warnings -__version__ = "0.19.6" +__version__ = "0.19.7" class KedroDeprecationWarning(DeprecationWarning): diff --git a/kedro/framework/cli/cli.py b/kedro/framework/cli/cli.py index 87bd5c4505..0892deed35 100644 --- a/kedro/framework/cli/cli.py +++ b/kedro/framework/cli/cli.py @@ -5,6 +5,7 @@ from __future__ import annotations import importlib +import logging import sys import traceback from collections import defaultdict @@ -38,6 +39,9 @@ v{version} """ +logger = logging.getLogger(__name__) +logger.addHandler(logging.StreamHandler(sys.stderr)) + @click.group(context_settings=CONTEXT_SETTINGS, name="Kedro") @click.version_option(version, "--version", "-V", help="Show version and exit") @@ -154,6 +158,9 @@ def main( self._cli_hook_manager.hook.before_command_run( project_metadata=self._metadata, command_args=args ) + + hook_called = False + try: super().main( args=args, @@ -169,6 +176,8 @@ def main( self._cli_hook_manager.hook.after_command_run( project_metadata=self._metadata, command_args=args, exit_code=exc.code ) + hook_called = True + # When CLI is run outside of a project, project_groups are not registered catch_exception = "click.exceptions.UsageError: No such command" # click convert exception handles to error message @@ -198,7 +207,19 @@ def main( ) click.echo(message) click.echo(hint) - sys.exit(exc.code) + sys.exit(exc.code) + except Exception as error: + logger.error(f"An error has occurred: {error}") + 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]: diff --git a/kedro/io/lambda_dataset.py b/kedro/io/lambda_dataset.py index 126bef6632..9c6ee10498 100644 --- a/kedro/io/lambda_dataset.py +++ b/kedro/io/lambda_dataset.py @@ -49,7 +49,7 @@ def _to_str(func: Any) -> str | None: return descr - def load(self) -> Any: + def _load(self) -> Any: if not self.__load: raise DatasetError( "Cannot load data set. No 'load' function " @@ -57,7 +57,7 @@ def load(self) -> Any: ) return self.__load() - def save(self, data: Any) -> None: + def _save(self, data: Any) -> None: if not self.__save: raise DatasetError( "Cannot save to data set. No 'save' function " diff --git a/tests/framework/cli/test_cli.py b/tests/framework/cli/test_cli.py index 317a596924..b9144ebc1b 100644 --- a/tests/framework/cli/test_cli.py +++ b/tests/framework/cli/test_cli.py @@ -2,6 +2,7 @@ from itertools import cycle from os import rename from pathlib import Path +from unittest.mock import MagicMock, patch import click from click.testing import CliRunner @@ -432,6 +433,37 @@ def test_kedro_cli_with_project(self, mocker, fake_metadata): assert "Global commands from Kedro" in result.output assert "Project specific commands from Kedro" in result.output + @patch("sys.exit") + def test_main_hook_exception_handling(self, fake_metadata): + kedro_cli = KedroCLI(fake_metadata.project_path) + kedro_cli._cli_hook_manager.hook.after_command_run = MagicMock() + + with patch.object( + click.CommandCollection, "main", side_effect=Exception("Test Exception") + ): + result = CliRunner().invoke(kedro_cli, []) + + kedro_cli._cli_hook_manager.hook.after_command_run.assert_called_once_with( + project_metadata=kedro_cli._metadata, command_args=[], exit_code=1 + ) + + assert "An error has occurred: Test Exception" in result.output + + @patch("sys.exit") + def test_main_hook_finally_block(self, fake_metadata): + kedro_cli = KedroCLI(fake_metadata.project_path) + kedro_cli._cli_hook_manager.hook.after_command_run = MagicMock() + + # No exception is raised, so it should go to the finally block and call the hook + with patch.object(click.CommandCollection, "main"): + result = CliRunner().invoke(kedro_cli, []) + + kedro_cli._cli_hook_manager.hook.after_command_run.assert_called_once_with( + project_metadata=kedro_cli._metadata, command_args=[], exit_code=0 + ) + + assert "An error has occurred:" not in result.output + @mark.usefixtures("chdir_to_dummy_project") class TestRunCommand: diff --git a/tests/framework/cli/test_starters.py b/tests/framework/cli/test_starters.py index b114c818de..ec8c9ff9a3 100644 --- a/tests/framework/cli/test_starters.py +++ b/tests/framework/cli/test_starters.py @@ -825,9 +825,11 @@ def test_alias(self, fake_kedro_cli, mock_determine_repo_dir, mock_cookiecutter) ) kwargs = { "template": "git+https://github.com/kedro-org/kedro-starters.git", - "checkout": version, "directory": "spaceflights-pandas", } + starters_version = mock_determine_repo_dir.call_args[1].pop("checkout", None) + + assert starters_version in [version, "main"] assert kwargs.items() <= mock_determine_repo_dir.call_args[1].items() assert kwargs.items() <= mock_cookiecutter.call_args[1].items() @@ -853,11 +855,14 @@ def test_git_repo(self, fake_kedro_cli, mock_determine_repo_dir, mock_cookiecutt ["new", "--starter", "git+https://github.com/fake/fake.git"], input=_make_cli_prompt_input(), ) + kwargs = { "template": "git+https://github.com/fake/fake.git", - "checkout": version, "directory": None, } + starters_version = mock_determine_repo_dir.call_args[1].pop("checkout", None) + + assert starters_version in [version, "main"] assert kwargs.items() <= mock_determine_repo_dir.call_args[1].items() del kwargs["directory"] assert kwargs.items() <= mock_cookiecutter.call_args[1].items() @@ -899,11 +904,14 @@ def test_git_repo_custom_directory( ], input=_make_cli_prompt_input(), ) + kwargs = { "template": "git+https://github.com/fake/fake.git", - "checkout": version, "directory": "my_directory", } + starters_version = mock_determine_repo_dir.call_args[1].pop("checkout", None) + + assert starters_version in [version, "main"] assert kwargs.items() <= mock_determine_repo_dir.call_args[1].items() assert kwargs.items() <= mock_cookiecutter.call_args[1].items()