diff --git a/components/polylith/project/get.py b/components/polylith/project/get.py index c9102f7f..da4f5f07 100644 --- a/components/polylith/project/get.py +++ b/components/polylith/project/get.py @@ -1,7 +1,7 @@ import re from functools import lru_cache from pathlib import Path -from typing import List +from typing import Any, List import tomlkit from polylith import repo, workspace @@ -13,12 +13,38 @@ def transform_to_package(namespace: str, include: str) -> dict: return {"include": f"{namespace}/{brick}", "from": path} +def find_by_key(data: dict, key: str) -> Any: + if key in data.keys(): + return data[key] + + filtered = {k: v for k, v in data.items() if isinstance(data[k], dict)} + + res = (find_by_key(data[k], key) for k in filtered.keys()) + + return next((r for r in res if r), None) + + +def get_hatch_project_packages(data) -> dict: + hatch_data = data["tool"]["hatch"] + build_data = hatch_data.get("build", {}) if isinstance(hatch_data, dict) else {} + + force_included = build_data.get("force-include") + + if force_included: + return force_included + + found = find_by_key(build_data, "polylith") + bricks = found.get("bricks", {}) if isinstance(found, dict) else {} + + return bricks if isinstance(bricks, dict) else {} + + def get_project_package_includes(namespace: str, data) -> List[dict]: if repo.is_poetry(data): return data["tool"]["poetry"].get("packages", []) if repo.is_hatch(data): - includes = data["tool"]["hatch"].get("build", {}).get("force-include", {}) + includes = get_hatch_project_packages(data) return [transform_to_package(namespace, key) for key in includes.keys()] diff --git a/test/components/polylith/project/test_project_get.py b/test/components/polylith/project/test_project_get.py index 7e31e218..0514161b 100644 --- a/test/components/polylith/project/test_project_get.py +++ b/test/components/polylith/project/test_project_get.py @@ -1,37 +1,82 @@ -from polylith import project import tomlkit +from polylith import project namespace = "unittest" poetry_toml = """\ [tool.poetry] packages = [ - {include = "unittest/one",from = "../../components"} + {include = "unittest/one",from = "../../bases"}, + {include = "unittest/two",from = "../../components"} ] """ - hatch_toml = """\ [tool.hatch.build.force-include] "../../bases/unittest/one" = "unittest/one" "../../components/unittest/two" = "unittest/two" """ +hatch_toml_alternative = """\ +[tool.hatch.build.hooks.targets.wheel.polylith.bricks] +"../../bases/unittest/one" = "unittest/one" +"../../components/unittest/two" = "unittest/two" +""" + +hatch_toml_combined = """\ +[tool.hatch.build.force-include] +"../../bases/unittest/one" = "unittest/one" +"../../components/unittest/two" = "unittest/two" + +[tool.hatch.build.hooks.targets.wheel.polylith.bricks] +"something" = "else" +""" + +expected = [ + {"include": "unittest/one", "from": "../../bases"}, + {"include": "unittest/two", "from": "../../components"}, +] + def test_get_poetry_package_includes(): data = tomlkit.loads(poetry_toml) res = project.get.get_project_package_includes(namespace, data) - assert res == [{"include": "unittest/one", "from": "../../components"}] + assert res == expected -def test_get_pep_621_includes(): +def test_get_hatch_package_includes(): data = tomlkit.loads(hatch_toml) res = project.get.get_project_package_includes(namespace, data) - assert res == [ - {"include": "unittest/one", "from": "../../bases"}, - {"include": "unittest/two", "from": "../../components"}, - ] + assert res == expected + + +def test_get_hatch_package_includes_in_build_hook(): + data = tomlkit.loads(hatch_toml_alternative) + + res = project.get.get_project_package_includes(namespace, data) + + assert res == expected + + +def test_get_hatch_package_includes_from_default_when_in_both(): + data = tomlkit.loads(hatch_toml_combined) + + res = project.get.get_project_package_includes(namespace, data) + + assert res == expected + + +def test_get_hatch_package_includes_lookup_with_unexpected_format(): + unexpected = """\ +[tool.hatch.build.hooks.targets.wheel] +"polylith" = "this-is-unexpected" +""" + data = tomlkit.loads(unexpected) + + res = project.get.get_project_package_includes(namespace, data) + + assert res == []