From 3806b3979ec4f4d9568cef00b54afeae01d81bc1 Mon Sep 17 00:00:00 2001 From: Robert Bikar Date: Wed, 11 Feb 2026 15:39:05 +0100 Subject: [PATCH 1/2] Fix importlib for py39 and older * use importlib-metadata; python_version < "3.10" * remove setuptools requirement * fix related test for python3.9 and older * added GH worklows for py39 Assisted-by: Cursor --- .github/workflows/tox-tests.yml | 17 +++++++++ requirements.txt | 2 +- src/pubtools/_impl/pluggy.py | 7 +++- tests/hooks/test_entry_points.py | 63 ++++++++++++++++++-------------- tox.ini | 3 ++ 5 files changed, 61 insertions(+), 31 deletions(-) diff --git a/.github/workflows/tox-tests.yml b/.github/workflows/tox-tests.yml index 46e75e2..6c9422c 100644 --- a/.github/workflows/tox-tests.yml +++ b/.github/workflows/tox-tests.yml @@ -67,3 +67,20 @@ jobs: run: pip install tox - name: Run Tox run: tox -e py3-bandit + test-py39: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Setup Python + uses: actions/setup-python@v2 + with: + python-version: "3.9" + - name: Install OS packages + run: | + sudo apt-get -y update + sudo apt-get install -y libkrb5-dev + - name: Install Tox + run: pip install tox + - name: Run Tox + run: tox -e py39 + diff --git a/requirements.txt b/requirements.txt index c0ec2d3..22304f7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ pluggy -setuptools +importlib-metadata; python_version < "3.10" diff --git a/src/pubtools/_impl/pluggy.py b/src/pubtools/_impl/pluggy.py index 32acda0..0a81764 100644 --- a/src/pubtools/_impl/pluggy.py +++ b/src/pubtools/_impl/pluggy.py @@ -1,8 +1,11 @@ import logging import sys from contextlib import contextmanager -from importlib.metadata import entry_points - +if sys.version_info >= (3, 10): + from importlib.metadata import entry_points +else: # pragma: no cover + # for older python use non-standard compatible module + from importlib_metadata import entry_points import pluggy LOG = logging.getLogger("pubtools") diff --git a/tests/hooks/test_entry_points.py b/tests/hooks/test_entry_points.py index 97f8d5a..3947ea5 100644 --- a/tests/hooks/test_entry_points.py +++ b/tests/hooks/test_entry_points.py @@ -1,42 +1,49 @@ import sys -from importlib import metadata -from importlib.metadata import EntryPoint +if sys.version_info >= (3, 10): + from importlib.metadata import EntryPoint +else: + from importlib_metadata import EntryPoint + +from pubtools._impl import pluggy from pubtools.pluggy import task_context def test_task_context_loads_entry_points(monkeypatch): """task_context eagerly resolves console_scripts and pubtools.hooks entry points.""" - target_mod = "pydoc" - - # Define the mock entry points EntryPoint(name, value, group) - ep1 = EntryPoint( - name="some-script", value="pubtools.pluggy", group="console_scripts" - ) - ep2 = EntryPoint(name="anything", value=target_mod, group="pubtools.hooks") - - mock_entry_points = [ep1, ep2] - - # Monkeypatch metadata.entry_points globally - # In the new API, mock the function that task_context() will call - def mock_eps(**kwargs): - group = kwargs.get("group") - if group: - return [ep for ep in mock_entry_points if ep.group == group] - return metadata.EntryPoints(mock_entry_points) - - monkeypatch.setattr(metadata, "entry_points", mock_eps) - - # "un-import" these modules (Ensure they are in sys.modules first so del doesn't fail, - # though usually they are already there from imports above) - for mod in ["pubtools.pluggy", target_mod]: - if mod in sys.modules: - del sys.modules[mod] + # importlib.metadata.entry_points() reads from installed package metadata; + # there is no mutable entry map to patch. Patch entry_points in the pluggy + # module so it returns our custom entry points by group. + console_scripts = [ + # This one is pubtools.*, so it should be loaded by resolve_hooks. + EntryPoint("some-script", "pubtools.pluggy", "console_scripts"), + # This should be ignored (module does not start with "pubtools"). + EntryPoint("other-script", "something.non.existent", "console_scripts"), + ] + pubtools_hooks = [ + EntryPoint("anything", "pytest", "pubtools.hooks"), + ] + + def fake_entry_points(group=None): + if group == "console_scripts": + return console_scripts + if group == "pubtools.hooks": + return pubtools_hooks + return [] + + monkeypatch.setattr(pluggy, "entry_points", fake_entry_points) + + # Effectively "un-import" these modules so we can observe that task_context + # has the side-effect of importing them. + assert "pubtools.pluggy" in sys.modules + assert "pytest" in sys.modules + del sys.modules["pubtools.pluggy"] + del sys.modules["pytest"] with task_context(): # As soon as we've entered the task context, the modules referenced from # those entry points should be imported, ensuring we can now use hooks with # everything registered assert "pubtools.pluggy" in sys.modules - assert target_mod in sys.modules + assert "pytest" in sys.modules \ No newline at end of file diff --git a/tox.ini b/tox.ini index 2c1194d..9a8f1b5 100644 --- a/tox.ini +++ b/tox.ini @@ -6,6 +6,9 @@ deps=-rtest-requirements.txt commands=pytest -v {posargs} whitelist_externals=sh +[testenv:py39] +deps=-rtest-requirements.in + [testenv:cov] usedevelop=true commands= From 7e65d05dda50c6e4702a906cd7106defd349747a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 16 Feb 2026 10:33:20 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/pubtools/_impl/pluggy.py | 3 ++- tests/hooks/test_entry_points.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pubtools/_impl/pluggy.py b/src/pubtools/_impl/pluggy.py index 0a81764..b825694 100644 --- a/src/pubtools/_impl/pluggy.py +++ b/src/pubtools/_impl/pluggy.py @@ -1,9 +1,10 @@ import logging import sys from contextlib import contextmanager + if sys.version_info >= (3, 10): from importlib.metadata import entry_points -else: # pragma: no cover +else: # pragma: no cover # for older python use non-standard compatible module from importlib_metadata import entry_points import pluggy diff --git a/tests/hooks/test_entry_points.py b/tests/hooks/test_entry_points.py index 3947ea5..6c0f093 100644 --- a/tests/hooks/test_entry_points.py +++ b/tests/hooks/test_entry_points.py @@ -46,4 +46,4 @@ def fake_entry_points(group=None): # those entry points should be imported, ensuring we can now use hooks with # everything registered assert "pubtools.pluggy" in sys.modules - assert "pytest" in sys.modules \ No newline at end of file + assert "pytest" in sys.modules