From 5c3d8ca96565e36171ba91f2605f6e73ade8f94a Mon Sep 17 00:00:00 2001 From: David Vujic Date: Tue, 3 Dec 2024 21:02:46 +0100 Subject: [PATCH] fix: Hatchling dev-mode and editable installations (#308) * fix(hatchling): filter project-specific bricks when in editable mode and with dev-mode-dirs enabled * bump Hatch hook to 1.3.1 --- components/polylith/hatch/hooks/bricks.py | 33 +++++++++++++-- projects/hatch_polylith_bricks/pyproject.toml | 2 +- test/components/polylith/hatch/test_hook.py | 41 +++++++++++++++++++ 3 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 test/components/polylith/hatch/test_hook.py diff --git a/components/polylith/hatch/hooks/bricks.py b/components/polylith/hatch/hooks/bricks.py index 2d3149ba..ae8233d1 100644 --- a/components/polylith/hatch/hooks/bricks.py +++ b/components/polylith/hatch/hooks/bricks.py @@ -1,22 +1,49 @@ import shutil from pathlib import Path -from typing import Any, Dict +from typing import Any, Dict, List from hatchling.builders.hooks.plugin.interface import BuildHookInterface from polylith import parsing, repo, toml from polylith.hatch import core +def get_build_section(data: dict) -> dict: + return data.get("tool", {}).get("hatch", {}).get("build", {}) + + +def is_in_path(key: str, paths: List[str]) -> bool: + return any(key.startswith(p) for p in paths) + + +def filter_dev_mode_bricks(data: dict, bricks: dict) -> dict: + build_section = get_build_section(data) + dev_mode_dirs = build_section.get("dev-mode-dirs") + + if not dev_mode_dirs: + return bricks + + return {k: v for k, v in bricks.items() if not is_in_path(k, dev_mode_dirs)} + + +def filtered_bricks(data: dict, version: str) -> dict: + bricks = toml.get_project_packages_from_polylith_section(data) + + if version == "editable": + return filter_dev_mode_bricks(data, bricks) + + return bricks + + class PolylithBricksHook(BuildHookInterface): PLUGIN_NAME = "polylith-bricks" def initialize(self, version: str, build_data: Dict[str, Any]) -> None: - include_key = "force_include_editable" if version == "editable" else "force_include" + include_key = "force_include" root = self.root pyproject = Path(f"{root}/{repo.default_toml}") data = toml.read_toml_document(pyproject) - bricks = toml.get_project_packages_from_polylith_section(data) + bricks = filtered_bricks(data, version) found_bricks = {k: v for k, v in bricks.items() if Path(f"{root}/{k}").exists()} if not bricks or not found_bricks: diff --git a/projects/hatch_polylith_bricks/pyproject.toml b/projects/hatch_polylith_bricks/pyproject.toml index 60517265..38a1a638 100644 --- a/projects/hatch_polylith_bricks/pyproject.toml +++ b/projects/hatch_polylith_bricks/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "hatch-polylith-bricks" -version = "1.3.0" +version = "1.3.1" description = "Hatch build hook plugin for Polylith" authors = ['David Vujic'] homepage = "https://davidvujic.github.io/python-polylith-docs/" diff --git a/test/components/polylith/hatch/test_hook.py b/test/components/polylith/hatch/test_hook.py new file mode 100644 index 00000000..0c47f048 --- /dev/null +++ b/test/components/polylith/hatch/test_hook.py @@ -0,0 +1,41 @@ +import tomlkit +from polylith.hatch.hooks.bricks import filtered_bricks + +project_toml = """\ +[tool.polylith.bricks] +"../../bases/unittest/one" = "unittest/one" +"../../components/unittest/two" = "unittest/two" +""" + +project_toml_dev_mode = """\ +[tool.hatch.build] +dev-mode-dirs = ["../../components", "../../bases"] + +[tool.polylith.bricks] +"../../bases/unittest/one" = "unittest/one" +"../../components/unittest/two" = "unittest/two" +""" + + +def test_filtered_bricks(): + data = tomlkit.loads(project_toml) + + expected = data["tool"]["polylith"]["bricks"] + + first = filtered_bricks(data, version="standard") + second = filtered_bricks(data, version="editable") + + assert first == expected + assert second == expected + + +def test_filtered_bricks_in_project_with_dev_mode_dirs(): + data = tomlkit.loads(project_toml_dev_mode) + + expected = data["tool"]["polylith"]["bricks"] + + first = filtered_bricks(data, version="standard") + second = filtered_bricks(data, version="editable") + + assert first == expected + assert second == {}