From 41b33239e70c6556ff87ef5f948fd63f545f6124 Mon Sep 17 00:00:00 2001 From: Yossi <54272821+Apakottur@users.noreply.github.com> Date: Tue, 6 Aug 2024 14:05:54 +0000 Subject: [PATCH] Add test --- .gitignore | 2 +- linters/cspell/words.txt | 2 +- src/updater.py | 17 ++++--- tests/test_updater.py | 107 ++++++++++++++++++++++++++++----------- 4 files changed, 90 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index 761c115..02f090d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,4 @@ .tmp __pycache__ .venv -.cspellcache \ No newline at end of file +.cspellcache diff --git a/linters/cspell/words.txt b/linters/cspell/words.txt index dc106c9..cce14d2 100644 --- a/linters/cspell/words.txt +++ b/linters/cspell/words.txt @@ -26,4 +26,4 @@ shellcheck pydantic ignorelist docstrings -biomejs \ No newline at end of file +biomejs diff --git a/src/updater.py b/src/updater.py index 006e1fe..22a5b92 100644 --- a/src/updater.py +++ b/src/updater.py @@ -50,7 +50,9 @@ def _run_updater_in_path(path: str) -> None: for details in current_poetry_section.values(): if "path" in details: - file_path_to_deps[file_path.resolve()].append((Path(root) / details["path"] / name).resolve()) + file_path_to_deps[file_path.resolve()].append( + (Path(root) / details["path"] / name).resolve() + ) # Order the projects based on interdependencies, where dependencies go first. def cmp(x: Path, y: Path) -> int: @@ -62,7 +64,11 @@ def cmp(x: Path, y: Path) -> int: file_paths_in_order = sorted(file_path_to_deps, key=functools.cmp_to_key(cmp)) - # Second iteration - run updates in order. + # Second iteration - make sure all projects have lock files. + for file_path in file_paths_in_order: + shpyx.run("poetry lock", exec_dir=file_path.parent) + + # Third iteration - run updates in order. for file_path in file_paths_in_order: # Get the contents of the configuration file. file_contents = Path(file_path).read_text() @@ -71,9 +77,6 @@ def cmp(x: Path, y: Path) -> int: print(f"TOML contents of {file_path}: {parsed_contents}") - # Update the lock file, creating it if needed. - shpyx.run("poetry update --lock", exec_dir=file_path.parent) - # Get all the outdated packages. results = shpyx.run("poetry show -o --no-ansi", exec_dir=file_path.parent) @@ -111,7 +114,9 @@ def cmp(x: Path, y: Path) -> int: if isinstance(package_details, str): current_poetry_section[original_package_name] = new_version else: - current_poetry_section[original_package_name]["version"] = new_version + current_poetry_section[original_package_name]["version"] = ( + new_version + ) # Write the updated configuration file. Path(file_path).write_text(parsed_contents.as_string()) diff --git a/tests/test_updater.py b/tests/test_updater.py index 65184bf..6431e23 100644 --- a/tests/test_updater.py +++ b/tests/test_updater.py @@ -24,7 +24,12 @@ class Project: path: str = "" -def _run_updater(projects: list[Project], *, add_tool_poetry: bool = True, tmp_dir: str | None = None) -> None: +def _run_updater( + projects: list[Project], + *, + add_tool_poetry: bool = True, + tmp_dir: str | None = None, +) -> None: """ Run the updater and verify the result. @@ -92,13 +97,13 @@ def test_poetry_deps() -> None: Project( """ [tool.poetry.dependencies] - python = "^3.10" + python = "~3.12" shpyx = "0.0.13" """, """ [tool.poetry.dependencies] - python = "^3.10" - shpyx = "0.0.25" + python = "~3.12" + shpyx = "0.0.28" """, ) ] @@ -113,17 +118,17 @@ def test_poetry_dev_deps() -> None: Project( """ [tool.poetry.dependencies] - python = "^3.10" + python = "~3.12" [tool.poetry.dev-dependencies] shpyx = "0.0.13" """, """ [tool.poetry.dependencies] - python = "^3.10" + python = "~3.12" [tool.poetry.dev-dependencies] - shpyx = "0.0.25" + shpyx = "0.0.28" """, ) ] @@ -135,17 +140,17 @@ def test_poetry_dev_deps() -> None: Project( """ [tool.poetry.dependencies] - python = "^3.10" + python = "~3.12" [tool.poetry.group.dev.dependencies] shpyx = "0.0.13" """, """ [tool.poetry.dependencies] - python = "^3.10" + python = "~3.12" [tool.poetry.group.dev.dependencies] - shpyx = "0.0.25" + shpyx = "0.0.28" """, ) ] @@ -159,7 +164,7 @@ def test_multiline_deps() -> None: Project( """ [tool.poetry.dependencies] - python = "^3.10" + python = "~3.12" sqlalchemy = { extras = [ "postgresql", "postgresql_asyncpg" @@ -167,11 +172,11 @@ def test_multiline_deps() -> None: """, """ [tool.poetry.dependencies] - python = "^3.10" + python = "~3.12" sqlalchemy = { extras = [ "postgresql", "postgresql_asyncpg" - ], version = "2.0.25" } + ], version = "2.0.32" } """, ) ] @@ -185,13 +190,13 @@ def test_no_changes() -> None: Project( """ [tool.poetry.dependencies] - python = "^3.10" - shpyx = "0.0.25" + python = "~3.12" + shpyx = "0.0.28" """, """ [tool.poetry.dependencies] - python = "^3.10" - shpyx = "0.0.25" + python = "~3.12" + shpyx = "0.0.28" """, ) ] @@ -205,13 +210,13 @@ def test_casing() -> None: Project( """ [tool.poetry.dependencies] - python = "^3.10" - sHpYx = "0.0.13" + python = "~3.12" + sHpYx = "0.0.28" """, """ [tool.poetry.dependencies] - python = "^3.10" - sHpYx = "0.0.25" + python = "~3.12" + sHpYx = "0.0.28" """, ) ] @@ -226,7 +231,9 @@ def test_path_dependency_run_order(mocker: MockerFixture) -> None: tmp_dir = tempfile.TemporaryDirectory() # Make sure the results of `os.walk` are NOT in the correct update order. - def _os_walk(path: str, *args: Any, **kwargs: Any) -> list[tuple[str, list[str], list[str]]]: + def _os_walk( + path: str, *args: Any, **kwargs: Any + ) -> list[tuple[str, list[str], list[str]]]: assert (path, args, kwargs) == (tmp_dir.name, (), {}) return [ (tmp_dir, ["outer", "inner_1", "inner_2"], []), @@ -242,13 +249,13 @@ def _os_walk(path: str, *args: Any, **kwargs: Any) -> list[tuple[str, list[str], Project( """ [tool.poetry.dependencies] - python = "^3.10" + python = "~3.12" inner_1 = { path = "../inner_1", develop = true } inner_2 = { path = "../inner_2", develop = false } """, """ [tool.poetry.dependencies] - python = "^3.10" + python = "~3.12" inner_1 = { path = "../inner_1", develop = true } inner_2 = { path = "../inner_2", develop = false } """, @@ -257,12 +264,12 @@ def _os_walk(path: str, *args: Any, **kwargs: Any) -> list[tuple[str, list[str], Project( """ [tool.poetry.dependencies] - python = "^3.10" + python = "~3.12" inner_2 = { path = "../inner_2", develop = false } """, """ [tool.poetry.dependencies] - python = "^3.10" + python = "~3.12" inner_2 = { path = "../inner_2", develop = false } """, "inner_1", @@ -270,13 +277,13 @@ def _os_walk(path: str, *args: Any, **kwargs: Any) -> list[tuple[str, list[str], Project( """ [tool.poetry.dependencies] - python = "^3.10" + python = "~3.12" shpyx = "0.0.13" """, """ [tool.poetry.dependencies] - python = "^3.10" - shpyx = "0.0.25" + python = "~3.12" + shpyx = "0.0.28" """, "inner_2", ), @@ -287,7 +294,10 @@ def _os_walk(path: str, *args: Any, **kwargs: Any) -> list[tuple[str, list[str], tmp_dir.cleanup() # Verify that the updates were called in the correct order. - cmd_runs = [(mock_call.args[0], Path(mock_call.kwargs["exec_dir"]).name) for mock_call in shpyx_run_spy.mock_calls] + cmd_runs = [ + (mock_call.args[0], Path(mock_call.kwargs["exec_dir"]).name) + for mock_call in shpyx_run_spy.mock_calls + ] assert cmd_runs == [ ("poetry update --lock", "inner_2"), ("poetry show -o --no-ansi", "inner_2"), @@ -297,3 +307,40 @@ def _os_walk(path: str, *args: Any, **kwargs: Any) -> list[tuple[str, list[str], ("poetry update --lock", "outer"), ("poetry show -o --no-ansi", "outer"), ] + + +def test_path_dependency_duplicates_dependency() -> None: + """Verify that the update succeeds when both the main project and the path dependency have the same dependency""" + + _run_updater( + [ + Project( + """ + [tool.poetry.dependencies] + python = "~3.12" + inner = { path = "../inner", develop = true } + shpyx = "0.0.13" + """, + """ + [tool.poetry.dependencies] + python = "~3.12" + inner = { path = "../inner", develop = true } + shpyx = "0.0.28" + """, + "outer", + ), + Project( + """ + [tool.poetry.dependencies] + python = "~3.12" + shpyx = "0.0.13" + """, + """ + [tool.poetry.dependencies] + python = "~3.12" + shpyx = "0.0.28" + """, + "inner", + ), + ], + )