From 6c71eb23eb5b70f6b513f3d8820feb22ba900096 Mon Sep 17 00:00:00 2001 From: jiqing-feng Date: Wed, 16 Sep 2026 14:35:07 +0800 Subject: [PATCH] Fix `egg_info.writers` entry point module path (#829) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With `kernels` installed, any setuptools source build in the same environment fails, including builds of unrelated packages: ``` File "setuptools/command/egg_info.py", line 304, in run writer = ep.load() ModuleNotFoundError: No module named 'kernels.lockfile' ``` Reproducer: ```bash pip install kernels==0.17.0 printf 'from setuptools import setup\nsetup(name="smoke", version="0.1")\n' > setup.py python setup.py egg_info ``` `kernels/pyproject.toml` registers a setuptools entry point pointing at a module that is not shipped: ```toml [project.entry-points."egg_info.writers"] "kernels.lock" = "kernels.lockfile:write_egg_lockfile" ``` `write_egg_lockfile` lives in `kernels/locking.py`; there is no `kernels/lockfile.py` in the wheel. The entry point was not updated when `lockfile.py` was renamed to `locking.py`. setuptools loads **all** registered `egg_info.writers` on every `egg_info` run, so a broken writer from any installed distribution takes down unrelated builds. PEP 517 isolated builds are unaffected; `--no-build-isolation` builds reuse the ambient setuptools and always hit it. Present in 0.17.0 and on `main`; 0.16.2 is the last good release. Point the entry point at `kernels.locking`, and add a regression test that loads it the way setuptools does — nothing covered this path, which is why the rename regressed silently. Built a wheel from this branch and installed it: - `ep.load()` resolves to the real function. - The reproducer above succeeds. - The new test passes, and fails when reverted to `kernels.lockfile`. --- kernels/pyproject.toml | 2 +- kernels/tests/test_entry_points.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 kernels/tests/test_entry_points.py diff --git a/kernels/pyproject.toml b/kernels/pyproject.toml index fc946bc4..739c31ac 100644 --- a/kernels/pyproject.toml +++ b/kernels/pyproject.toml @@ -63,7 +63,7 @@ docs = [ kernels = "kernels.cli:main" [project.entry-points."egg_info.writers"] -"kernels.lock" = "kernels.lockfile:write_egg_lockfile" +"kernels.lock" = "kernels.locking:write_egg_lockfile" [tool.maturin] module-name = "kernels._rust" diff --git a/kernels/tests/test_entry_points.py b/kernels/tests/test_entry_points.py new file mode 100644 index 00000000..553d4c37 --- /dev/null +++ b/kernels/tests/test_entry_points.py @@ -0,0 +1,19 @@ +from importlib.metadata import distribution + +import pytest + + +def test_egg_info_writer_entry_point_is_importable(): + """The `egg_info.writers` entry point is loaded by setuptools during *any* + `egg_info` run in an environment where `kernels` is installed, including + builds of unrelated packages. If it points at a module that is not shipped, + every such build fails with `ModuleNotFoundError`.""" + entry_points = [ep for ep in distribution("kernels").entry_points if ep.group == "egg_info.writers"] + assert entry_points, "no egg_info.writers entry point registered" + + for ep in entry_points: + try: + writer = ep.load() + except ModuleNotFoundError as e: + pytest.fail(f"entry point {ep.name} = {ep.value!r} is not importable: {e}") + assert callable(writer)