Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

API incompatibility with `importlib.metadata` (or at least the API is not type-safe?)

Aperta
#486 9 commenti 8 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
35/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Ferma
Stack tecnologico
python

Direzione di ricerca

Inizia riproducendo l'esempio documentato con il MetaPathFinder personalizzato e l'ambiente Python 3.8 descritto nell'issue. Esamina Distribution.discover e il relativo flusso di discovery, quindi esegui i type checker rispetto alla baseline supportata per verificare che le distribuzioni di terze parti di importlib.metadata e i relativi risultati di entry_points vengano gestiti in modo coerente.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

When 3rd-party MetaPathFinder are implemented using importlib.metadata, the return types in importlib_metadata are not respected, which causes the API to behave in an unexpected way (with unexpected errors).

This is an example similar to the one identified in https://github.com/pypa/pyproject-hooks/pull/195#issuecomment-2088695300 and https://github.com/pypa/setuptools/issues/4338:

mkdir -p /tmp/stash/private_path/_test-0.0.1.dist-info
cat <<EOF > /tmp/stash/private_path/_test-0.0.1.dist-info/METADATA
Name: _test
Version: 0.0.1
EOF

cat <<EOF > /tmp/stash/private_path/_test-0.0.1.dist-info/entry_points.txt
[_test.importlib_metadata]
hello = world
EOF

cat <<EOF > /tmp/stash/install_finder.py
import sys
from importlib.machinery import PathFinder
from importlib.metadata import DistributionFinder, MetadataPathFinder


class _ExampleFinder:
    def __init__(self, private_path):
        self.private_path = private_path


    def find_spec(self, fullname, _path, _target=None):
        if "." in fullname:
            # Rely on importlib to find nested modules based on parent's path
            return None

        # Ignore other items in _path or sys.path and use private_path instead:
        return PathFinder.find_spec(fullname, path=self.private_path)

    def find_distributions(self, context=None):
        context = DistributionFinder.Context(path=self.private_path)
        return MetadataPathFinder.find_distributions(context=context)


sys.meta_path.insert(0, _ExampleFinder(["/tmp/stash/private_path"]))
EOF

cd /tmp/stash/
python3.8 -m venv .venv
.venv/bin/python -m pip install -U importlib-metadata
.venv/bin/python
>>> import install_finder
>>> from importlib_metadata import distribution
>>> distribution("_test").entry_points.select(group="_test.importlib_metadata")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'select'

The expected behaviour as per API documentation would be:

>>> distribution("_test").entry_points.select(group="_test.importlib_metadata")
EntryPoints((EntryPoint(name='hello', value='world', group='_test.importlib_metadata'),))

It seems that the origin of this problem is a little "lie" in the API definition:

Instead of

importlib_metadata.Distribution.discover(...) -> Iterable[importlib_metadata.Distribution]

what actually happens is:

importlib_metadata.Distribution.discover(...) -> Iterable[importlib_metadata.Distribution | importlib.metadata.Distribution]

and that propagates throughout the whole API.

I haven't tested, but there is potential for other internal errors too, if internally importlib_metadata is relying that the objects will have type importlib_metadata.Distribution to call newer APIs.

It is probably worthy to change the return type of importlib_metadata.Distribution.discover(...) to Iterable[importlib_metadata.Distribution | importlib.metadata.Distribution] and then run the type checkers on the lowest Python supported (I suppose Python 3.8), to see if everything is OK.

It also means that consumers of importlib_metadata cannot rely on the newer APIs (unless they are sure that 3r-party packages installed in their environment are not using importlib.metadata).

Lingua principale
Python
Stelle
142
Fork
97
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di python/importlib_metadata

Tutte le issue di python/importlib_metadata

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.