From f250258b7534392b61d69d270f5dfc73f5960d04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Sun, 17 Mar 2024 15:26:46 +0000 Subject: [PATCH] Avoid conflicts between test-requirements and local repo --- bin/oca_list_addons_to_test_as_url_reqs | 28 +++++++-- tests/common.py | 8 +++ tests/test_list_addons_to_test_as_url_reqs.py | 58 +++++++++++++++++++ 3 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 tests/test_list_addons_to_test_as_url_reqs.py diff --git a/bin/oca_list_addons_to_test_as_url_reqs b/bin/oca_list_addons_to_test_as_url_reqs index 51874e3..c200387 100755 --- a/bin/oca_list_addons_to_test_as_url_reqs +++ b/bin/oca_list_addons_to_test_as_url_reqs @@ -1,8 +1,13 @@ #!/usr/bin/env python -"""Print addons to test as pip requirements pointing to local directories.""" +"""Print addons to test as pip requirements pointing to local directories. +Addons that are referenced as direct URLs in test-requirements.txt are ignored +because they are going to be installed from there, as test-requirements.txt +must have priority over the local repo, when there are PR references in it. +""" import argparse import os +import re import subprocess from pathlib import Path @@ -35,9 +40,21 @@ def _list_addons_to_test(): ) -parser = argparse.ArgumentParser( - description=__doc__ -) +def _addons_in_test_requirements(addons_dir): + """Return a set of addon names that have direct URL requirements in test-requirements.txt.""" + test_requirements_path = addons_dir / "test-requirements.txt" + if not test_requirements_path.exists(): + return set() + url_addon_regex = re.compile(r"^odoo\d*-addon-(?P[a-zA-Z0-9_-]+) *@") + res = set() + for line in test_requirements_path.read_text().splitlines(): + match = url_addon_regex.match(line) + if match: + res.add(match.group("addon_name").replace("-", "_")) + return res + + +parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( "--editable", action="store_true", @@ -46,7 +63,10 @@ parser.add_argument( args = parser.parse_args() addons_dir = Path(os.getenv("ADDONS_DIR", ".")) +addons_to_skip = _addons_in_test_requirements(addons_dir) for addon_name in _list_addons_to_test(): + if addon_name in addons_to_skip: + continue pyproject_path = addons_dir / addon_name / "pyproject.toml" if pyproject_path.exists(): print(_make_addon_req(pyproject_path.parent, args.editable)) diff --git a/tests/common.py b/tests/common.py index cd37280..b485a62 100644 --- a/tests/common.py +++ b/tests/common.py @@ -87,3 +87,11 @@ def did_run_test_module(output, test_module): test_module is the full name of the test (addon_name.tests.test_module). """ return "odoo.addons." + test_module in output + + +def make_addon_dist_name(addon_name): + odoo_series = int(os.getenv("ODOO_VERSION").partition(".")[0]) + return "odoo{odoo_series}-addon-{name}".format( + name=addon_name, + odoo_series=odoo_series if odoo_series < 15 else "", + ) diff --git a/tests/test_list_addons_to_test_as_url_reqs.py b/tests/test_list_addons_to_test_as_url_reqs.py new file mode 100644 index 0000000..5e7d4c5 --- /dev/null +++ b/tests/test_list_addons_to_test_as_url_reqs.py @@ -0,0 +1,58 @@ +import subprocess +import textwrap + +from .common import make_addons_dir, make_addon_dist_name + + +def test_oca_list_addons_to_test_as_url_reqs__basic(): + """Basic successful test.""" + with make_addons_dir( + ["addon_success", "addon_with_deb_dep", "uninstallable_addon"] + ) as addons_dir: + result = subprocess.check_output( + ["oca_list_addons_to_test_as_url_reqs"], cwd=addons_dir, text=True + ) + assert result == textwrap.dedent( + f"""\ + {make_addon_dist_name('addon_success')} @ {addons_dir.as_uri()}/addon_success + {make_addon_dist_name('addon_with_deb_dep')} @ {addons_dir.as_uri()}/addon_with_deb_dep + """ + ) + + +def test_oca_list_addons_to_test_as_url_reqs__editable(): + """Basic successful test with editables.""" + with make_addons_dir( + ["addon_success", "addon_with_deb_dep", "uninstallable_addon"] + ) as addons_dir: + result = subprocess.check_output( + ["oca_list_addons_to_test_as_url_reqs", "--editable"], + cwd=addons_dir, + text=True, + ) + assert result == textwrap.dedent( + f"""\ + -e {addons_dir.as_uri()}/addon_success#egg={make_addon_dist_name('addon_success')} + -e {addons_dir.as_uri()}/addon_with_deb_dep#egg={make_addon_dist_name('addon_with_deb_dep')} + """ + ) + + +def test_oca_list_addons_to_test_as_url_reqs__skip_test_requirement(): + """Basic successful test.""" + with make_addons_dir( + ["addon_success", "addon_with_deb_dep", "uninstallable_addon"] + ) as addons_dir: + # add URL reference to addon_success + addons_dir.joinpath("test-requirements.txt").write_text( + f"{make_addon_dist_name('addon_success')} @ git+https://github.com/oca/dummy@refs/pull/123/head" + ) + result = subprocess.check_output( + ["oca_list_addons_to_test_as_url_reqs"], cwd=addons_dir, text=True + ) + # addon_success should not be in result because it is already in test-requirements.txt + assert result == textwrap.dedent( + f"""\ + {make_addon_dist_name('addon_with_deb_dep')} @ {addons_dir.as_uri()}/addon_with_deb_dep + """ + )