Control: retitle -1 python-npe2: FTBFS: importlib.metadata.MetadataNotFound: No 
package metadata was found

On Fri, Oct 23, 2026 at 04:27:46PM +0000, Santiago Vila wrote:
   from pydantic_core import __version__ as __pydantic_core_version__
 File "/usr/lib/python3/dist-packages/pydantic_core/__init__.py", line 8, in 
<module>
   from ._pydantic_core import (
   ...<21 lines>...
   )
ImportError: cannot import name 'ArgsKwargs' from 
'pydantic_core._pydantic_core' (unknown location)

Now that pydantic-core has been rebuilt against Python 3.15, this fails in a different way. The Python 3.14 tests are fine. I haven't debugged this further.

I: pybuild base:383: cd 
/build/reproducible-path/python-npe2-0.8.3/.pybuild/cpython3_3.15_npe2/build; python3.15 
-m pytest -k "not fetch and not test_cli_convert_svg and not test_conversion and not 
test_render_docs and not test_setuptools_plugin and not test_compile and not 
test_cli_convert_package_name" tests
============================= test session starts ==============================
platform linux -- Python 3.15.1, pytest-9.1.1, pluggy-1.6.0
rootdir: /build/reproducible-path/python-npe2-0.8.3
configfile: pyproject.toml
plugins: npe2-0.8.3, napari-plugin-engine-0.2.1, pretty-1.3.0
collected 265 items / 59 deselected / 1 skipped / 206 selected

tests/test__io_utils.py ..................................               [ 16%]
tests/test_cli.py ...................................                    [ 33%]
tests/test_config_contribution.py ................                       [ 41%]
tests/test_contributions.py .....................                        [ 51%]
tests/test_docs.py .                                                     [ 51%]
tests/test_implements.py ....                                            [ 53%]
tests/test_manifest.py ....F                                             [ 56%]
.pybuild/cpython3_3.15_npe2/build/tests/test_manifest.py:46 test_discover_errors
tests/test_manifest.py ............                                      [ 62%]
tests/test_npe1_adapter.py ........                                      [ 66%]
tests/test_package_meta.py ...                                           [ 67%]
tests/test_plugin_manager.py ................                            [ 75%]
tests/test_pm_module.py .                                                [ 75%]
tests/test_pytest_plugin.py F                                            [ 76%]
.pybuild/cpython3_3.15_npe2/build/tests/test_pytest_plugin.py:60 
test_npe2pm_fixture[\nfrom npe2._pytest_plugin import TestPluginManager\nfrom 
npe2 import PluginManager\n\ndef test_something_1(npe2pm):\n    assert 
isinstance(npe2pm, TestPluginManager)\n    assert PluginManager.instance() is 
npe2pm\n]
tests/test_pytest_plugin.py .....                                        [ 78%]
tests/test_tmp_plugin.py ...                                             [ 80%]
tests/test_utils.py ....                                                 [ 82%]
tests/test_validations.py .....................................          [100%]

=================================== FAILURES ===================================
_____________________________ test_discover_errors _____________________________

cls = <class 'npe2.manifest.schema.PluginManifest'>
paths = [PosixPath('/tmp/pytest-of-sbuild/pytest-0/test_discover_errors0')]

    @classmethod
    def discover(cls, paths: Sequence[str | Path] = ()) -> 
Iterator[DiscoverResults]:
        """Discover manifests in the environment.

        This function searches for installed python packages with a matching
        entry point group and then attempts to resolve the manifest file.

        The manifest file should be specified in the plugin's ``setup.cfg`` or
        ``setup.py`` file using the [entry point group][1]: "napari.manifest".
        For example, this would be the section for a plugin "npe-tester" with
        "napari.yaml" as the manifest file:

        .. code-block:: cfg

            [options.entry_points]
            napari.manifest =
                npe2-tester = npe2_tester:napari.yaml

        The manifest file is specified relative to the submodule root path.
        So for the example it will be loaded from:
        ``<path/to/npe2-tester>/napari.yaml``.

        [1]: https://packaging.python.org/specifications/entry-points/

        Parameters
        ----------
        paths : Sequence[str], optional
            paths to add to sys.path while discovering.

        Yields
        ------
        DiscoverResults: (3 namedtuples: manifest, entrypoint, error)
            3-tuples with either manifest or (entrypoint and error) being None.
        """
        with _temporary_path_additions(paths):
            for dist in metadata.distributions():
                try:
                  pm = _from_dist(dist)
                         ^^^^^^^^^^^^^^^^

npe2/manifest/schema.py:367:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
npe2/manifest/schema.py:554: in _from_dist
    return PluginManifest._from_entrypoint(_npe2, dist)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

cls = <class 'npe2.manifest.schema.PluginManifest'>
entry_point = EntryPoint(name='my-plugin', value='asdfsad:blahblahblah.yaml', 
group='napari.manifest')
distribution = <importlib.metadata.PathDistribution object at 0x7ff488cd5130>

    @classmethod
    def _from_entrypoint(
        cls,
        entry_point: metadata.EntryPoint,
        distribution: metadata.Distribution | None = None,
    ) -> PluginManifest:
        module_match = entry_point.pattern.match(entry_point.value)
        assert module_match is not None
        module = module_match.group("module")

        spec = util.find_spec(module or "")
        if not spec:  # pragma: no cover
          raise ValueError(
                f"Cannot find module {module!r} declared in "
                f"entrypoint: {entry_point.value!r}"
            )
E           ValueError: Cannot find module 'asdfsad' declared in entrypoint: 
'asdfsad:blahblahblah.yaml'

npe2/manifest/schema.py:399: ValueError

During handling of the above exception, another exception occurred:

tmp_path = PosixPath('/tmp/pytest-of-sbuild/pytest-0/test_discover_errors0')

    @pytest.mark.filterwarnings("ignore:Implicit None on return values is 
deprecated")
    def test_discover_errors(tmp_path: Path):
        """testing various discovery errors"""
        # package with proper `napari.manifest` entry_point, but invalid 
pointer to
        # a manifest should yield an error in results
        a = tmp_path / "a"
        a.mkdir()
        a_ep = a / "entry_points.txt"
        bad_value = "asdfsad:blahblahblah.yaml"
        a_ep.write_text(f"[napari.manifest]\n{SAMPLE_PLUGIN_NAME} = 
{bad_value}")

        # package with proper `napari.manifest` entry_point, but invalid 
manifest
        b = tmp_path / "b"
        b.mkdir()
        b_ep = b / "entry_points.txt"
        b_ep.write_text("[napari.manifest]\nsome_plugin = module:napari.yaml")
        module = tmp_path / "module"
        module.mkdir()
        (module / "napari.yaml").write_text("name: hi??")

        # a regular package, with out napari.manifest entry_point should just 
be skipped
        c = tmp_path / "c"
        c.mkdir()
        c_ep = c / "entry_points.txt"
        c_ep.write_text("[console.scripts]\nsomething = something")

        dists = [
            metadata.PathDistribution(a),
            metadata.PathDistribution(b),
            metadata.PathDistribution(c),
        ]

        with patch.object(metadata, "distributions", return_value=dists):
          discover_results = list(PluginManifest.discover(paths=[tmp_path]))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/test_manifest.py:80:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/conftest.py:62: in wrapper
    yield from _discover(*args, **kwargs)
npe2/manifest/schema.py:382: in discover
    ENTRY_POINT, dist.metadata["Name"], e
                 ^^^^^^^^^^^^^
/usr/lib/python3.15/importlib/metadata/__init__.py:543: in metadata
    return self._assemble_message(self._ensure_metadata_present(text))
                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <importlib.metadata.PathDistribution object at 0x7ff488cd5130>
text = None

    def _ensure_metadata_present(self, text: str | None) -> str:
        if text is not None:
            return text

      raise MetadataNotFound('No package metadata was found.')
E       importlib.metadata.MetadataNotFound: No package metadata was found.

/usr/lib/python3.15/importlib/metadata/__init__.py:556: MetadataNotFound
_ test_npe2pm_fixture[\nfrom npe2._pytest_plugin import TestPluginManager\nfrom 
npe2 import PluginManager\n\ndef test_something_1(npe2pm):\n    assert 
isinstance(npe2pm, TestPluginManager)\n    assert PluginManager.instance() is 
npe2pm\n] _

pytester_pretty = <pytest_pretty.PytesterWrapper object at 0x7ff486d0a7b0>
case = '\nfrom npe2._pytest_plugin import TestPluginManager\nfrom npe2 import 
PluginManager\n\ndef test_something_1(npe2pm):\n    assert isinstance(npe2pm, 
TestPluginManager)\n    assert PluginManager.instance() is npe2pm\n'

    @pytest.mark.parametrize("case", [CASE1, CASE2, CASE3, CASE4, CASE5, CASE6])
    def test_npe2pm_fixture(pytester_pretty: pytest.Pytester, case):
        """Make sure that the npe2pm fixture works."""

        # create a temporary pytest test file
        pytester_pretty.makepyfile(case)
      pytester_pretty.runpytest().assert_outcomes(passed=1)
E       AssertionError: assert {'passed': 0,...rors': 0, ...} == {'passed': 
1,...rors': 0, ...}
E
E         Omitting 5 identical items, use -vv to show
E         Differing items:
E         {'passed': 0} != {'passed': 1}
E         Use -v to get more diff

/build/reproducible-path/python-npe2-0.8.3/.pybuild/cpython3_3.15_npe2/build/tests/test_pytest_plugin.py:67:
 AssertionError
----------------------------- Captured stdout call -----------------------------
============================= test session starts ==============================
platform linux -- Python 3.15.1, pytest-9.1.1, pluggy-1.6.0
rootdir: /tmp/pytest-of-sbuild/pytest-0/test_npe2pm_fixture0
plugins: npe2-0.8.3, napari-plugin-engine-0.2.1, pretty-1.3.0
collected 1 item / 1 error

==================================== ERRORS ====================================
___________________ ERROR collecting test_npe2pm_fixture.py ____________________
/usr/lib/python3/dist-packages/_pytest/runner.py:361: in from_call
    result: TResult | None = func()
                             ^^^^^^
/usr/lib/python3/dist-packages/_pytest/runner.py:406: in collect
    return list(collector.collect())
                ^^^^^^^^^^^^^^^^^^^
/usr/lib/python3/dist-packages/_pytest/python.py:762: in collect
    self.warn(
/usr/lib/python3/dist-packages/_pytest/nodes.py:263: in warn
    warnings.warn_explicit(
E   pytest.PytestCollectionWarning: cannot collect test class 
'TestPluginManager' because it has a __init__ constructor (from: 
test_npe2pm_fixture.py)
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
Results (0.07s):
         1 error
============================= slowest 10 durations =============================
0.11s call     
.pybuild/cpython3_3.15_npe2/build/tests/test_cli.py::test_cli_validate_load_err
0.08s call     
.pybuild/cpython3_3.15_npe2/build/tests/test_pytest_plugin.py::test_npe2pm_fixture[\nfrom
 npe2._pytest_plugin import TestPluginManager\nfrom npe2 import 
PluginManager\n\ndef test_something_1(npe2pm):\n    assert isinstance(npe2pm, 
TestPluginManager)\n    assert PluginManager.instance() is npe2pm\n]
0.04s call     
.pybuild/cpython3_3.15_npe2/build/tests/test_npe1_adapter.py::test_npe1_adapter_cache
0.03s call     
.pybuild/cpython3_3.15_npe2/build/tests/test_pytest_plugin.py::test_npe2pm_fixture[\nimport
 pytest\n\ndef test_something_6(npe2pm):\n    with 
pytest.raises(FileNotFoundError):\n        
npe2pm.tmp_plugin(manifest='some_path.yaml')\n]
0.03s call     
.pybuild/cpython3_3.15_npe2/build/tests/test_cli.py::test_cli_parse[False-toml]
0.03s call     
.pybuild/cpython3_3.15_npe2/build/tests/test_cli.py::test_cli_parse[False-yaml]
0.03s call     
.pybuild/cpython3_3.15_npe2/build/tests/test_cli.py::test_cli_parse[True-yaml]
0.03s call     
.pybuild/cpython3_3.15_npe2/build/tests/test_contributions.py::test_writer_priority
0.02s call     
.pybuild/cpython3_3.15_npe2/build/tests/test_npe1_adapter.py::test_npe1_adapter
0.02s call     
.pybuild/cpython3_3.15_npe2/build/tests/test__io_utils.py::test_read_uses_correct_passed_plugin
                              Summary of Failures
┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃               �               ┃  Function     ┃              ┃               ┃
┃  File         ┃  Function     ┃  Line         ┃  Error Line  ┃  Error        ┃
┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│  .pybuild/c…  │  test_disco…  │  47           │  80          │  MetadataNo…  │
│  .pybuild/c…  │  test_npe2p…  │  61           │  67          │  AssertionE…  │
│               │  npe2._pyte…  │               │              │               │
│               │  import       │               │              │               │
│               │  TestPlugin…  │               │              │               │
│               │  npe2 import  │               │              │               │
│               │  PluginMana…  │               │              │               │
│               │  test_somet…  │               │              │               │
│               │  assert       │               │              │               │
│               │  isinstance…  │               │              │               │
│               │  TestPlugin…  │               │              │               │
│               │  assert       │               │              │               │
│               │  PluginMana…  │               │              │               │
│               │  is           │               │              │               │
│               │  npe2pm\n]    │               │              │               │
└───────────────┴───────────────┴───────────────┴──────────────┴───────────────┘
Results (0.32s):
         2 failed
       204 passed
         1 skipped
        59 deselected
E: pybuild pybuild:485: test: plugin pyproject failed with: exit code=1: cd 
/build/reproducible-path/python-npe2-0.8.3/.pybuild/cpython3_3.15_npe2/build; python3.15 
-m pytest -k "not fetch and not test_cli_convert_svg and not test_conversion and not 
test_render_docs and not test_setuptools_plugin and not test_compile and not 
test_cli_convert_package_name" tests

--
Colin Watson (he/him)                              [[email protected]]

Reply via email to