diff --git a/.pylintrc b/.pylintrc index a6aa8fde01..bad78ecaac 100644 --- a/.pylintrc +++ b/.pylintrc @@ -50,7 +50,7 @@ confidence= # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" -disable=ungrouped-imports,bad-continuation,duplicate-code +disable=ungrouped-imports,bad-continuation,duplicate-code,consider-using-f-string # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option diff --git a/RELEASE.md b/RELEASE.md index fff6d9153a..616ba97219 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,3 +1,15 @@ +# Upcoming Release 0.17.6 + +## Major features and improvements + +## Bug fixes and other changes + +## Minor breaking changes to the API + +## Upcoming deprecations for Kedro 0.18.0 + +## Thanks for supporting contributions + # Release 0.17.5 ## Major features and improvements @@ -22,8 +34,6 @@ * Imports are now refactored at `kedro pipeline package` and `kedro pipeline pull` time, so that _aliasing_ a modular pipeline doesn't break it. * Pinned `dynaconf` to `<3.1.6` because the method signature for `_validate_items` changed which is used in Kedro. -## Minor breaking changes to the API - ## Upcoming deprecations for Kedro 0.18.0 * `kedro pipeline list` and `kedro pipeline describe` are being deprecated in favour of new commands `kedro registry list ` and `kedro registry describe`. * `kedro install` is being deprecated in favour of using `pip install -r src/requirements.txt` to install project dependencies. diff --git a/features/environment.py b/features/environment.py index 5f8463ff7e..b934cfe2aa 100644 --- a/features/environment.py +++ b/features/environment.py @@ -149,7 +149,7 @@ def _install_project_requirements(context): Path( "kedro/templates/project/{{ cookiecutter.repo_name }}/src/requirements.txt" ) - .read_text() + .read_text(encoding="utf-8") .splitlines() ) install_reqs = [req for req in install_reqs if "{" not in req] diff --git a/features/steps/cli_steps.py b/features/steps/cli_steps.py index ec7af0be30..14a7c5c0b9 100644 --- a/features/steps/cli_steps.py +++ b/features/steps/cli_steps.py @@ -669,7 +669,7 @@ def check_jupyter_nb_proc_on_port(context: behave.runner.Context, port: int): port: Port to check """ - url = "http://localhost:%d" % int(port) + url = f"http://localhost:{int(port)}" try: util.wait_for( func=_check_service_up, diff --git a/kedro/extras/extensions/ipython.py b/kedro/extras/extensions/ipython.py index 1b3bcb6a15..b7be81ddec 100644 --- a/kedro/extras/extensions/ipython.py +++ b/kedro/extras/extensions/ipython.py @@ -122,7 +122,7 @@ def load_ipython_extension(ipython): """Main entry point when %load_ext is executed""" global project_path - global startup_path + global startup_path # pylint:disable=global-variable-not-assigned ipython.register_magic_function(init_kedro, "line") ipython.register_magic_function(reload_kedro, "line", "reload_kedro") diff --git a/kedro/framework/cli/utils.py b/kedro/framework/cli/utils.py index 0db4cbe432..55ee432c26 100644 --- a/kedro/framework/cli/utils.py +++ b/kedro/framework/cli/utils.py @@ -241,7 +241,7 @@ def get_pkg_version(reqs_path: (Union[str, Path]), package_name: str) -> str: raise KedroCliError(f"Given path `{reqs_path}` is not a regular file.") pattern = re.compile(package_name + r"([^\w]|$)") - with reqs_path.open("r") as reqs_file: + with reqs_path.open("r", encoding="utf-8") as reqs_file: for req_line in reqs_file: req_line = req_line.strip() if pattern.search(req_line): diff --git a/kedro/io/core.py b/kedro/io/core.py index e5fdcf1cc7..a55e727319 100644 --- a/kedro/io/core.py +++ b/kedro/io/core.py @@ -171,8 +171,8 @@ def from_config( ) except Exception as exc: raise DataSetError( - "An exception occurred when parsing config " - "for DataSet `{}`:\n{}".format(name, str(exc)) + f"An exception occurred when parsing config " + f"for DataSet `{name}`:\n{str(exc)}" ) from exc try: diff --git a/kedro/io/data_catalog.py b/kedro/io/data_catalog.py index 8f40970885..2baf24dd23 100644 --- a/kedro/io/data_catalog.py +++ b/kedro/io/data_catalog.py @@ -135,7 +135,7 @@ def __init__(self, datasets): # Don't allow users to add/change attributes on the fly def __setattr__(self, key, value): msg = "Operation not allowed! " - if key in self.__dict__.keys(): + if key in self.__dict__: msg += "Please change datasets through configuration." else: msg += "Please use DataCatalog.add() instead." @@ -218,9 +218,7 @@ def _check_and_normalize_transformers(self): if excess_transformers: raise DataSetNotFoundError( - "Unexpected transformers for missing data_sets {}".format( - ", ".join(excess_transformers) - ) + f"Unexpected transformers for missing data_sets {', '.join(excess_transformers)}" ) for data_set_name in missing_transformers: @@ -624,9 +622,7 @@ def add_transformer( if not isinstance(transformer, AbstractTransformer): raise TypeError( - "Object of type {} is not an instance of AbstractTransformer".format( - type(transformer) - ) + f"Object of type {type(transformer)} is not an instance of AbstractTransformer" ) if data_set_names is None: self._default_transformers.append(transformer) diff --git a/tests/framework/cli/pipeline/test_pipeline.py b/tests/framework/cli/pipeline/test_pipeline.py index 3ec5be0934..a1818243b3 100644 --- a/tests/framework/cli/pipeline/test_pipeline.py +++ b/tests/framework/cli/pipeline/test_pipeline.py @@ -92,12 +92,7 @@ def pipelines_dict(): class TestPipelineCreateCommand: @pytest.mark.parametrize("env", [None, "local"]) def test_create_pipeline( # pylint: disable=too-many-locals - self, - fake_repo_path, - fake_project_cli, - fake_metadata, - env, - fake_package_path, + self, fake_repo_path, fake_project_cli, fake_metadata, env, fake_package_path ): """Test creation of a pipeline""" pipelines_dir = fake_package_path / "pipelines" @@ -419,9 +414,7 @@ def test_bad_pipeline_name( ): """Test error message when bad pipeline name was provided.""" result = CliRunner().invoke( - fake_project_cli, - ["pipeline", "delete", "-y", bad_name], - obj=fake_metadata, + fake_project_cli, ["pipeline", "delete", "-y", bad_name], obj=fake_metadata ) assert result.exit_code assert error_message in result.output @@ -547,9 +540,7 @@ def test_describe_pipeline( pipelines_dict, ): result = CliRunner().invoke( - fake_project_cli, - ["pipeline", "describe", pipeline_name], - obj=fake_metadata, + fake_project_cli, ["pipeline", "describe", pipeline_name], obj=fake_metadata ) assert not result.exit_code @@ -569,16 +560,10 @@ def test_not_found_pipeline(self, fake_project_cli, fake_metadata): assert expected_output in result.output def test_describe_pipeline_default( - self, - fake_project_cli, - fake_metadata, - yaml_dump_mock, - pipelines_dict, + self, fake_project_cli, fake_metadata, yaml_dump_mock, pipelines_dict ): result = CliRunner().invoke( - fake_project_cli, - ["pipeline", "describe"], - obj=fake_metadata, + fake_project_cli, ["pipeline", "describe"], obj=fake_metadata ) assert not result.exit_code @@ -597,7 +582,7 @@ def source(self, tmp_path) -> Path: source_dir.mkdir() (source_dir / "existing").mkdir() (source_dir / "existing" / "source_file").touch() - (source_dir / "existing" / "common").write_text("source") + (source_dir / "existing" / "common").write_text("source", encoding="utf-8") (source_dir / "new").mkdir() (source_dir / "new" / "source_file").touch() return source_dir @@ -608,7 +593,7 @@ def test_sync_target_exists(self, source, tmp_path): target.mkdir() (target / "existing").mkdir() (target / "existing" / "target_file").touch() - (target / "existing" / "common").write_text("target") + (target / "existing" / "common").write_text("target", encoding="utf-8") _sync_dirs(source, target) @@ -618,7 +603,7 @@ def test_sync_target_exists(self, source, tmp_path): assert (source / "new" / "source_file").is_file() assert (target / "existing" / "source_file").is_file() - assert (target / "existing" / "common").read_text() == "target" + assert (target / "existing" / "common").read_text(encoding="utf-8") == "target" assert (target / "existing" / "target_file").exists() assert (target / "new" / "source_file").is_file() @@ -634,6 +619,6 @@ def test_sync_no_target(self, source, tmp_path): assert (source / "new" / "source_file").is_file() assert (target / "existing" / "source_file").is_file() - assert (target / "existing" / "common").read_text() == "source" + assert (target / "existing" / "common").read_text(encoding="utf-8") == "source" assert not (target / "existing" / "target_file").exists() assert (target / "new" / "source_file").is_file() diff --git a/tests/framework/cli/test_starters.py b/tests/framework/cli/test_starters.py index c2abc462e9..64aa57115c 100644 --- a/tests/framework/cli/test_starters.py +++ b/tests/framework/cli/test_starters.py @@ -93,9 +93,11 @@ def _assert_template_ok( assert len(generated_files) == FILES_IN_TEMPLATE assert full_path.exists() assert (full_path / ".gitignore").is_file() - assert project_name in (full_path / "README.md").read_text() - assert "KEDRO" in (full_path / ".gitignore").read_text() - assert kedro_version in (full_path / "src" / "requirements.txt").read_text() + assert project_name in (full_path / "README.md").read_text(encoding="utf-8") + assert "KEDRO" in (full_path / ".gitignore").read_text(encoding="utf-8") + assert kedro_version in (full_path / "src" / "requirements.txt").read_text( + encoding="utf-8" + ) assert (full_path / "src" / python_package / "__init__.py").is_file() @@ -110,8 +112,12 @@ def test_starter_list(fake_kedro_cli): def test_cookiecutter_json_matches_prompts_yml(): """Validate the contents of the default config file.""" - cookiecutter_json = json.loads((TEMPLATE_PATH / "cookiecutter.json").read_text()) - prompts_yml = yaml.safe_load((TEMPLATE_PATH / "prompts.yml").read_text()) + cookiecutter_json = json.loads( + (TEMPLATE_PATH / "cookiecutter.json").read_text(encoding="utf-8") + ) + prompts_yml = yaml.safe_load( + (TEMPLATE_PATH / "prompts.yml").read_text(encoding="utf-8") + ) assert set(cookiecutter_json) == set(prompts_yml) | {"kedro_version"} @@ -245,7 +251,7 @@ def test_prompt_no_title(self, fake_kedro_cli): def test_prompt_bad_yaml(self, fake_kedro_cli): shutil.copytree(TEMPLATE_PATH, "template") - (Path("template") / "prompts.yml").write_text("invalid\tyaml") + (Path("template") / "prompts.yml").write_text("invalid\tyaml", encoding="utf-8") result = CliRunner().invoke(fake_kedro_cli, ["new", "--starter", "template"]) assert result.exit_code != 0 assert "Failed to generate project: could not load prompts.yml" in result.output @@ -380,7 +386,7 @@ def test_config_empty(self, fake_kedro_cli): def test_config_bad_yaml(self, fake_kedro_cli): """Check the error if config YAML is invalid.""" - Path("config.yml").write_text("invalid\tyaml") + Path("config.yml").write_text("invalid\tyaml", encoding="utf-8") result = CliRunner().invoke(fake_kedro_cli, ["new", "-v", "-c", "config.yml"]) assert result.exit_code != 0 assert "Failed to generate project: could not load config" in result.output diff --git a/tests/framework/session/test_session.py b/tests/framework/session/test_session.py index 749117f8a5..dcee20906f 100644 --- a/tests/framework/session/test_session.py +++ b/tests/framework/session/test_session.py @@ -222,11 +222,11 @@ def fake_project(tmp_path, local_logging_config, mock_package_name): } } toml_str = toml.dumps(payload) - pyproject_toml_path.write_text(toml_str) + pyproject_toml_path.write_text(toml_str, encoding="utf-8") env_logging = fake_project_dir / "conf" / "base" / "logging.yml" env_logging.parent.mkdir(parents=True) - env_logging.write_text(json.dumps(local_logging_config)) + env_logging.write_text(json.dumps(local_logging_config), encoding="utf-8") (fake_project_dir / "conf" / "local").mkdir() return fake_project_dir