|
8 | 8 | import re |
9 | 9 | import ssl |
10 | 10 | import subprocess |
| 11 | +import tomllib |
| 12 | +from collections import defaultdict |
11 | 13 | from datetime import datetime, timedelta, timezone |
12 | 14 | from functools import partial |
13 | 15 | from html.parser import HTMLParser |
| 16 | +from importlib.metadata import PackageNotFoundError, distribution, entry_points |
14 | 17 | from pathlib import Path |
15 | 18 | from typing import TYPE_CHECKING |
16 | 19 | from urllib.parse import parse_qs, urljoin, urlparse |
@@ -686,3 +689,63 @@ def handle_starttag(self, tag, attrs): |
686 | 689 |
|
687 | 690 | # This should have redirected to the DiracX page that shows the login is complete |
688 | 691 | assert "Please close the window" in r.text |
| 692 | + |
| 693 | + |
| 694 | +def get_installed_entry_points(): |
| 695 | + """Retrieve the installed entry points from the environment.""" |
| 696 | + entry_pts = entry_points() |
| 697 | + diracx_eps = defaultdict(dict) |
| 698 | + for group in entry_pts.groups: |
| 699 | + if "diracx" in group: |
| 700 | + for ep in entry_pts.select(group=group): |
| 701 | + diracx_eps[group][ep.name] = ep.value |
| 702 | + return dict(diracx_eps) |
| 703 | + |
| 704 | + |
| 705 | +def get_entry_points_from_toml(toml_file): |
| 706 | + """Parse entry points from pyproject.toml.""" |
| 707 | + with open(toml_file, "rb") as f: |
| 708 | + pyproject = tomllib.load(f) |
| 709 | + package_name = pyproject["project"]["name"] |
| 710 | + return package_name, pyproject.get("project", {}).get("entry-points", {}) |
| 711 | + |
| 712 | + |
| 713 | +def get_current_entry_points(repo_base) -> bool: |
| 714 | + """Create current entry points dict for comparison.""" |
| 715 | + current_eps = {} |
| 716 | + for toml_file in repo_base.glob("diracx-*/pyproject.toml"): |
| 717 | + package_name, entry_pts = get_entry_points_from_toml(f"{toml_file}") |
| 718 | + # Ignore packages that are not installed |
| 719 | + try: |
| 720 | + distribution(package_name) |
| 721 | + except PackageNotFoundError: |
| 722 | + continue |
| 723 | + # Merge the entry points |
| 724 | + for key, value in entry_pts.items(): |
| 725 | + current_eps[key] = current_eps.get(key, {}) | value |
| 726 | + return current_eps |
| 727 | + |
| 728 | + |
| 729 | +@pytest.fixture(scope="session", autouse=True) |
| 730 | +def verify_entry_points(request, pytestconfig): |
| 731 | + try: |
| 732 | + ini_toml_name = tomllib.loads(pytestconfig.inipath.read_text())["project"][ |
| 733 | + "name" |
| 734 | + ] |
| 735 | + except tomllib.TOMLDecodeError: |
| 736 | + return |
| 737 | + if ini_toml_name == "diracx": |
| 738 | + repo_base = pytestconfig.inipath.parent |
| 739 | + elif ini_toml_name.startswith("diracx-"): |
| 740 | + repo_base = pytestconfig.inipath.parent.parent |
| 741 | + else: |
| 742 | + return |
| 743 | + |
| 744 | + installed_eps = get_installed_entry_points() |
| 745 | + current_eps = get_current_entry_points(repo_base) |
| 746 | + |
| 747 | + if installed_eps != current_eps: |
| 748 | + pytest.fail( |
| 749 | + "Project and installed entry-points are not consistent. " |
| 750 | + "You should run `pip install -r requirements-dev.txt`", |
| 751 | + ) |
0 commit comments