Skip to content

Return type annotation for importlib.metadata.version is incorrect #7513

@DMRobertson

Description

@DMRobertson

To my surprise, I discovered in matrix-org/synapse#12223 that it is possible for importlib.metadata.version("foo") to return None. However, the stub suggests version and Distribution.version will always return a string:

def version(self) -> str: ...

def version(distribution_name: str) -> str: ...

To prove that version sometimes returns None:

  1. Create a new virtual environment. I'm using CPython 3.10.2 as my interpreter.
  2. Within the venv, pip install bottle. (Any package will do; I choose bottle because it's small and doesn't have any dependencies).
  3. The version of bottle agrees with what you've just installed:
    $ python -c "import importlib.metadata as m; print(repr(m.version('bottle')))"
    '0.12.19'
  4. Here's the dirty bit: remove the metadata files for that package but keep the metadata directory.
    • Use pip show bottle to find the site-packages location
    • From there, remove all files in the bottle-VERSION-.dist-info directory: `rm /path/to/site-packages/bottle-VERSION.dist-info/*'.
  5. The version of bottle is now judged to be None:
    $ python -c "import importlib.metadata as m; print(repr(m.version('bottle')))"
    None

A few other notes:

  • For a package foo that's not installed, version("foo") raises a PackageNotFoundError.
  • I don't know if this ought to be considered a bug in the library rather than the annotations?
  • I haven't dug much into the internals of importlib.metadata but it looks like the version is retrieved by looking inside a metadata attribute on a Distribution. I think other lookups are vulnerable to a similar problem; the only example I could find is Distribution.name.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions