Skip to content

Commit e2fafae

Browse files
Add the ability to package addons by name and path
1 parent c41daf4 commit e2fafae

File tree

10 files changed

+87
-30
lines changed

10 files changed

+87
-30
lines changed

src/hatch_odoo/build_hook.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,21 @@ def initialize(self, version: str, build_data: Dict[str, Any]) -> None:
2626
hatch_odoo_config = load_hatch_odoo_config(self.root)
2727
if version == "standard":
2828
force_include = build_data["force_include"]
29-
for addon_dir in iter_addon_dirs(
29+
for addon_dir, addon_name in iter_addon_dirs(
3030
self.root,
3131
hatch_odoo_config,
3232
# We force-include addons that are installable False to avoid that the
3333
# default hatch behaviour adds them at the wrong place in the wheel.
3434
allow_not_installable=True,
3535
):
36-
addon_name = addon_dir.name
3736
force_include[addon_dir] = f"odoo/addons/{addon_name}"
3837
elif version == "editable" and self.config.get("editable_symlinks", True):
3938
editable_path = Path(self.root) / "build" / "__editable_odoo_addons__"
4039
if editable_path.is_dir():
4140
shutil.rmtree(editable_path)
4241
editable_odoo_addons_path = editable_path / "odoo" / "addons"
4342
has_editable_symlinks = False
44-
for addon_dir in iter_addon_dirs(
43+
for addon_dir, addon_name in iter_addon_dirs(
4544
self.root,
4645
hatch_odoo_config,
4746
allow_not_installable=False,
@@ -50,7 +49,6 @@ def initialize(self, version: str, build_data: Dict[str, Any]) -> None:
5049
if not has_editable_symlinks:
5150
editable_odoo_addons_path.mkdir(parents=True)
5251
has_editable_symlinks = True
53-
addon_name = addon_dir.name
5452
editable_addon_path = editable_odoo_addons_path / addon_name
5553
editable_addon_path.symlink_to(addon_dir)
5654
# Add .pth to build/__editable_odoo_addons__ in wheel.

src/hatch_odoo/config.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import sys
66
from pathlib import Path
7-
from typing import Iterator
7+
from typing import Iterator, Tuple
88

99
if sys.version_info < (3, 11):
1010
import tomli as tomllib
@@ -40,8 +40,22 @@ def iter_addon_dirs(
4040
root: str,
4141
config: dict,
4242
allow_not_installable: bool,
43-
) -> Iterator[Path]:
44-
for addons_dir in iter_addons_dirs(root, config):
45-
for addon_dir in addons_dir.iterdir():
46-
if is_addon_dir(addon_dir, allow_not_installable=allow_not_installable):
47-
yield addon_dir
43+
) -> Iterator[Tuple[Path, str]]:
44+
addon_dirs = config.get("addon_dirs")
45+
if addon_dirs:
46+
with open("/tmp/log", "w") as log:
47+
for addon_name in addon_dirs:
48+
log.write(f"addon name = {addon_name}\n")
49+
addon_dir_path = Path(root, addon_dirs[addon_name])
50+
if is_addon_dir(
51+
addon_dir_path, allow_not_installable=allow_not_installable
52+
):
53+
log.write("is an addon\n")
54+
yield addon_dir_path, addon_name
55+
else:
56+
log.write("NOT AN addon\n")
57+
else:
58+
for addons_dir in iter_addons_dirs(root, config):
59+
for addon_dir in addons_dir.iterdir():
60+
if is_addon_dir(addon_dir, allow_not_installable=allow_not_installable):
61+
yield addon_dir, addon_dir.name

src/hatch_odoo/metadata_hook.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,15 @@ def _get_odooo_addons_dependencies(self) -> List[str]:
2929
)
3030
)
3131
depends_override = hatch_odoo_config.get("depends_override", {})
32-
for addon_dir in addon_dirs:
33-
addon_name = addon_dir.name
32+
for addon_dir, addon_name in addon_dirs:
3433
# Do not add dependencies on addons that are in the project.
3534
depends_override[addon_name] = None
3635
options = dict(
3736
hatch_odoo_config,
3837
depends_override=depends_override,
3938
post_version_strategy_override=POST_VERSION_STRATEGY_NONE,
4039
)
41-
for addon_dir in addon_dirs:
40+
for addon_dir, _ in addon_dirs:
4241
try:
4342
addon_metadata = metadata_from_addon_dir(addon_dir, options)
4443
except Exception as e:

tests/data/project7/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# project7
2+
3+
A basic project where the root directory is an odoo addon.
4+
5+
This layout can be used when using whool is not possible.

tests/data/project7/__init__.py

Whitespace-only changes.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "a",
3+
"depends": ["mis-builder"],
4+
"external_dependencies": {
5+
"python": ["wrapt"],
6+
},
7+
}

tests/data/project7/pyproject.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[build-system]
2+
requires = ["hatchling", "hatch-odoo"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "project7"
7+
version = "1.0"
8+
readme = "README.md"
9+
dynamic = ["dependencies"]
10+
11+
[tool.hatch.metadata.hooks.odoo-addons-dependencies]
12+
13+
[tool.hatch.build.hooks.odoo-addons-dirs]
14+
15+
[tool.hatch-odoo]
16+
odoo_version_override = "15.0"
17+
dependencies = ["click-odoo-contrib"]
18+
19+
[tool.hatch-odoo.addon_dirs]
20+
project7 = "."

tests/test_build.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
11
# SPDX-FileCopyrightText: 2022-present Stéphane Bidoul <stephane.bidoul@acsone.eu>
22
# SPDX-FileCopyrightText: 2022-present ACSONE <https://acsone.eu>
3+
# SPDX-FileCopyrightText: 2025-present XCG SAS <https://orbeet.io>
34
#
45
# SPDX-License-Identifier: MIT
56

67
import subprocess
78
import sys
89
import zipfile
910
from pathlib import Path
11+
from typing import Tuple
1012

1113
import pytest
1214

1315

1416
@pytest.mark.parametrize(
15-
"project, addons_only",
17+
"project, addons_only, addon_names",
1618
[
17-
("project1", False),
18-
("project2", False),
19-
("project3", False),
20-
("project4", False),
21-
("project5", False),
22-
("project6", True),
19+
("project1", False, ("addona", "addonb", "addon_uninstallable")),
20+
("project2", False, ("addona", "addonb", "addon_uninstallable")),
21+
("project3", False, ("addona", "addonb", "addon_uninstallable")),
22+
("project4", False, ("addona", "addonb", "addon_uninstallable")),
23+
("project5", False, ("addona", "addonb", "addon_uninstallable")),
24+
("project6", True, ("addona", "addonb", "addon_uninstallable")),
25+
("project7", True, ("project7",)),
2326
],
2427
)
2528
@pytest.mark.parametrize("build_via_sdist", [True, False])
2629
def test_build(
2730
project: str,
2831
addons_only: bool,
32+
addon_names: Tuple[str],
2933
build_via_sdist: bool,
3034
data_path: Path,
3135
tmp_path: Path,
@@ -48,7 +52,7 @@ def test_build(
4852
wheel_file = next(tmp_path.glob(f"{project}-*.whl"))
4953
with zipfile.ZipFile(wheel_file) as zip_file:
5054
files = set(zip_file.namelist())
51-
for addon_name in ("addona", "addonb", "addon_uninstallable"):
55+
for addon_name in addon_names:
5256
assert f"odoo/addons/{addon_name}/__init__.py" in files
5357
assert f"odoo/addons/{addon_name}/__manifest__.py" in files
5458
assert addons_only or f"{project}/__init__.py" in files

tests/test_editable.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# SPDX-FileCopyrightText: 2022-present Stéphane Bidoul <stephane.bidoul@acsone.eu>
22
# SPDX-FileCopyrightText: 2022-present ACSONE <https://acsone.eu>
3+
# SPDX-FileCopyrightText: 2025-present XCG SAS <https://orbeet.io>
34
#
45
# SPDX-License-Identifier: MIT
56

@@ -19,19 +20,21 @@
1920

2021

2122
@pytest.mark.parametrize(
22-
"project_name,expected_editable_pth_lines",
23+
"project_name,expected_editable_pth_lines,expected_editable_addon_names",
2324
[
24-
("project1", ["src"]),
25-
("project2", ["src", "build/__editable_odoo_addons__"]),
26-
("project3", [""]),
27-
("project4", ["src", "addons_group1", "addons_group2"]),
28-
("project5", ["", "build/__editable_odoo_addons__"]),
29-
("project6", ["build/__editable_odoo_addons__"]),
25+
("project1", ["src"], ["addona", "addonb"]),
26+
("project2", ["src", "build/__editable_odoo_addons__"], ["addona", "addonb"]),
27+
("project3", [""], ["addona", "addonb"]),
28+
("project4", ["src", "addons_group1", "addons_group2"], ["addona", "addonb"]),
29+
("project5", ["", "build/__editable_odoo_addons__"], ["addona", "addonb"]),
30+
("project6", ["build/__editable_odoo_addons__"], ["addona", "addonb"]),
31+
("project7", ["build/__editable_odoo_addons__"], ["project7"]),
3032
],
3133
)
3234
def test_odoo_addons_dependencies(
3335
project_name: str,
3436
expected_editable_pth_lines: List[str],
37+
expected_editable_addon_names: List[str],
3538
data_path: Path,
3639
tmp_path: Path,
3740
) -> None:
@@ -64,7 +67,6 @@ def test_odoo_addons_dependencies(
6467
str(data_path / project_name / line) for line in expected_editable_pth_lines
6568
}
6669
# Check all addons are in the editable paths.
67-
expected_editable_addon_names = ["addona", "addonb"]
6870
editable_addon_names = []
6971
for pth_line in pth_lines:
7072
addons_dir = Path(pth_line) / "odoo" / "addons"

tests/test_metadata.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,15 @@
1212

1313
@pytest.mark.parametrize(
1414
"project_name",
15-
["project1", "project2", "project3", "project4", "project5", "project6"],
15+
[
16+
"project1",
17+
"project2",
18+
"project3",
19+
"project4",
20+
"project5",
21+
"project6",
22+
"project7",
23+
],
1624
)
1725
def test_odoo_addons_dependencies(
1826
project_name: str, data_path: Path, tmp_path: Path

0 commit comments

Comments
 (0)