From 67a4df06c996b8f09e49d095780a234b6fb829d2 Mon Sep 17 00:00:00 2001 From: Nok Lam Chan Date: Tue, 2 Apr 2024 10:40:06 +0100 Subject: [PATCH] Resolve all path in Kedro (#3742) * Kedro need more uv Signed-off-by: Nok * remove docker Signed-off-by: Nok * fix broken type hint and resolve project path Signed-off-by: Nok Lam Chan * fix type hint Signed-off-by: Nok Lam Chan * remove duplicate logic Signed-off-by: Nok Lam Chan * adding nok.py is definitely an accident Signed-off-by: Nok Lam Chan * fix test Signed-off-by: Nok Lam Chan * remove print Signed-off-by: Nok Lam Chan * add test Signed-off-by: Nok --------- Signed-off-by: Nok Signed-off-by: Nok Lam Chan --- .gitignore | 2 ++ kedro/framework/startup.py | 11 +++++++---- tests/framework/test_startup.py | 15 ++++++++++++++- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 3565128a49..7c54bb352a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ + +tmp/ # CMake cmake-build-debug/ diff --git a/kedro/framework/startup.py b/kedro/framework/startup.py index 0dcaeb4a27..8649bbc8a7 100644 --- a/kedro/framework/startup.py +++ b/kedro/framework/startup.py @@ -1,8 +1,10 @@ """This module provides metadata for a Kedro project.""" +from __future__ import annotations + import os import sys from pathlib import Path -from typing import NamedTuple, Union +from typing import NamedTuple import toml @@ -34,7 +36,7 @@ def _version_mismatch_error(kedro_init_version: str) -> str: ) -def _get_project_metadata(project_path: Union[str, Path]) -> ProjectMetadata: +def _get_project_metadata(project_path: Path) -> ProjectMetadata: """Read project metadata from `/pyproject.toml` config file, under the `[tool.kedro]` section. @@ -50,7 +52,6 @@ def _get_project_metadata(project_path: Union[str, Path]) -> ProjectMetadata: Returns: A named tuple that contains project metadata. """ - project_path = Path(project_path).expanduser().resolve() pyproject_toml = project_path / _PYPROJECT if not pyproject_toml.is_file(): @@ -144,10 +145,12 @@ def _add_src_to_path(source_dir: Path, project_path: Path) -> None: os.environ["PYTHONPATH"] = f"{str(source_dir)}{sep}{python_path}" -def bootstrap_project(project_path: Path) -> ProjectMetadata: +def bootstrap_project(project_path: str | Path) -> ProjectMetadata: """Run setup required at the beginning of the workflow when running in project mode, and return project metadata. """ + + project_path = Path(project_path).expanduser().resolve() metadata = _get_project_metadata(project_path) _add_src_to_path(metadata.source_dir, project_path) configure_project(metadata.package_name) diff --git a/tests/framework/test_startup.py b/tests/framework/test_startup.py index d135afc25f..bdda3380f1 100644 --- a/tests/framework/test_startup.py +++ b/tests/framework/test_startup.py @@ -70,7 +70,7 @@ def test_toml_invalid_format(self, tmp_path): toml_path.write_text("!!") # Invalid TOML pattern = "Failed to parse 'pyproject.toml' file" with pytest.raises(RuntimeError, match=re.escape(pattern)): - _get_project_metadata(str(tmp_path)) + _get_project_metadata(tmp_path) def test_valid_toml_file(self, mocker): mocker.patch.object(Path, "is_file", return_value=True) @@ -275,6 +275,19 @@ def test_non_existent_source_path(self, tmp_path): with pytest.raises(NotADirectoryError, match=pattern): _validate_source_path(source_path, tmp_path.resolve()) + @pytest.mark.parametrize( + "source_dir", [".", "src", "./src", "src/nested", "src/nested/nested"] + ) + def test_symlink_source_path(self, tmp_path, source_dir): + source_path = (tmp_path / source_dir).resolve() + source_path.mkdir(parents=True, exist_ok=True) + + fake_path = tmp_path / "../" / ".path_does_not_exist" + fake_path.symlink_to(source_path) + + _validate_source_path(fake_path, tmp_path.resolve()) + os.remove(fake_path) + class TestBootstrapProject: def test_bootstrap_project(self, monkeypatch, tmp_path):