Skip to content

Commit 8bda95d

Browse files
authored
wip(hatch hook): add support for exclude patterns as paths with wildcards (#341)
* feat(hatch hook): add support for exclude patterns as paths with wildcards * bump Hatch hook to 1.5.0 * bump PDM hooks to 1.3.0 * bump CLI to 1.30.0
1 parent 1787a35 commit 8bda95d

File tree

6 files changed

+68
-18
lines changed

6 files changed

+68
-18
lines changed

components/polylith/hatch/hooks/bricks.py

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import shutil
22
from pathlib import Path
3-
from typing import Any, Dict, List
3+
from typing import Any, Dict, List, Set
44

55
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
66
from polylith import parsing, repo, toml
@@ -43,6 +43,21 @@ def collect_configured_exclude_patterns(data: dict, target_name: str) -> set:
4343
return set(exclude)
4444

4545

46+
def copy_bricks(bricks: dict, work_dir: Path, exclude_patterns: Set[str]) -> List[Path]:
47+
return [
48+
parsing.copy_brick(source, brick, work_dir, exclude_patterns)
49+
for source, brick in bricks.items()
50+
]
51+
52+
53+
def rewrite_modules(paths: List[Path], ns: str, top_ns: str) -> None:
54+
for path in paths:
55+
rewritten_bricks = parsing.rewrite_modules(path, ns, top_ns)
56+
57+
for item in rewritten_bricks:
58+
print(f"Updated {item} with new top namespace for local imports.")
59+
60+
4661
class PolylithBricksHook(BuildHookInterface):
4762
PLUGIN_NAME = "polylith-bricks"
4863

@@ -58,24 +73,24 @@ def initialize(self, version: str, build_data: Dict[str, Any]) -> None:
5873
if not bricks or not found_bricks:
5974
return
6075

76+
ns = parsing.parse_brick_namespace_from_path(bricks)
6177
top_ns = core.get_top_namespace(data, self.config)
6278
work_dir = core.get_work_dir(self.config)
79+
exclude_patterns = collect_configured_exclude_patterns(data, self.target_name)
6380

64-
if not top_ns:
81+
if not top_ns and not exclude_patterns:
6582
build_data[include_key] = bricks
6683
return
6784

68-
ns = parsing.parse_brick_namespace_from_path(bricks)
69-
exclude_patterns = collect_configured_exclude_patterns(data, self.target_name)
85+
key = work_dir.as_posix()
86+
paths = copy_bricks(bricks, work_dir, exclude_patterns)
7087

71-
for source, brick in bricks.items():
72-
path = parsing.copy_brick(source, brick, work_dir, exclude_patterns)
73-
rewritten_bricks = parsing.rewrite_modules(path, ns, top_ns)
88+
if not top_ns:
89+
build_data[include_key] = {f"{key}/{ns}": ns}
90+
return
7491

75-
for item in rewritten_bricks:
76-
print(f"Updated {item} with new top namespace for local imports.")
92+
rewrite_modules(paths, ns, top_ns)
7793

78-
key = work_dir.as_posix()
7994
build_data[include_key][key] = top_ns
8095

8196
def finalize(self, *args, **kwargs) -> None:

components/polylith/parsing/core.py

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import fnmatch
12
import shutil
23
from pathlib import Path
3-
from typing import Union
4+
from typing import List, Set, Union
45

56
default_patterns = {
67
"*.pyc",
@@ -12,13 +13,47 @@
1213
".pytest_cache",
1314
"node_modules",
1415
".git",
16+
".pixi",
1517
}
1618

1719

18-
def copy_tree(source: str, destination: str, patterns: set) -> Path:
19-
ignore = shutil.ignore_patterns(*patterns)
20+
def is_match(root: Path, pattern: str, name: str, current: Path) -> bool:
21+
path_name = (current / name).relative_to(root).as_posix()
2022

21-
res = shutil.copytree(source, destination, ignore=ignore, dirs_exist_ok=True)
23+
return any(fnmatch.fnmatch(n, pattern) for n in [path_name, name])
24+
25+
26+
def any_match(root: Path, patterns: set, name: str, current: Path) -> bool:
27+
return any(is_match(root, pattern, name, current) for pattern in patterns)
28+
29+
30+
def ignore_paths(root: Path, patterns: Set[str]):
31+
def fn(current_path: str, names: List[str]):
32+
current = Path(current_path).resolve()
33+
34+
return {name for name in names if any_match(root, patterns, name, current)}
35+
36+
return fn
37+
38+
39+
def calculate_root(current_path: str) -> Path:
40+
relative = Path(current_path)
41+
42+
parts = [p for p in relative.parts if p != ".."]
43+
relative_path = "/".join(parts)
44+
45+
root = relative.resolve().as_posix().replace(relative_path, "")
46+
47+
return Path(root)
48+
49+
50+
def copy_tree(source: str, destination: str, patterns: Set[str]) -> Path:
51+
root = calculate_root(source)
52+
53+
is_paths = any("/" in p for p in patterns)
54+
fn = ignore_paths(root, patterns) if is_paths else shutil.ignore_patterns(*patterns)
55+
56+
res = shutil.copytree(source, destination, ignore=fn, dirs_exist_ok=True)
2257

2358
return Path(res)
2459

projects/hatch_polylith_bricks/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "hatch-polylith-bricks"
3-
version = "1.4.0"
3+
version = "1.5.0"
44
description = "Hatch build hook plugin for Polylith"
55
authors = ['David Vujic']
66
homepage = "https://davidvujic.github.io/python-polylith-docs/"

projects/pdm_polylith_bricks/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "pdm-polylith-bricks"
3-
version = "1.2.0"
3+
version = "1.3.0"
44
description = "a PDM build hook for Polylith"
55
authors = ["David Vujic"]
66
homepage = "https://davidvujic.github.io/python-polylith-docs/"

projects/pdm_polylith_workspace/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "pdm-polylith-workspace"
3-
version = "1.2.0"
3+
version = "1.3.0"
44
description = "a PDM build hook for a Polylith workspace"
55
homepage = "https://davidvujic.github.io/python-polylith-docs/"
66
repository = "https://github.com/davidvujic/python-polylith"

projects/polylith_cli/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "polylith-cli"
3-
version = "1.29.0"
3+
version = "1.30.0"
44
description = "Python tooling support for the Polylith Architecture"
55
authors = ['David Vujic']
66
homepage = "https://davidvujic.github.io/python-polylith-docs/"

0 commit comments

Comments
 (0)