Skip to content

Regression: importlib.metadata.PathDistribution.requires raises AttributeError, name/version raises TypeError #143387

Description

@hroncok

Bug report

Bug description:

Python 3.14.2

>>> from importlib import metadata
>>> d = metadata.PathDistribution.at('/tmp')
>>> d.requires
>>> d.requires is None
True

Python 3.15.0a3

>>> from importlib import metadata
>>> d = metadata.PathDistribution.at('/tmp')
>>> d.requires
Traceback (most recent call last):
  File "<python-input-2>", line 1, in <module>
    d.requires
  File "/usr/lib64/python3.15/importlib/metadata/__init__.py", line 660, in requires
    reqs = self._read_dist_info_reqs() or self._read_egg_info_reqs()
           ~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/usr/lib64/python3.15/importlib/metadata/__init__.py", line 664, in _read_dist_info_reqs
    return self.metadata.get_all('Requires-Dist')
           ^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'get_all'

I believe this is a regression from 9b38c66 where the metadata property changed the type from _meta.PackageMetadata to _meta.PackageMetadata | None but other properties (here the requires property) do not account for it being None.

This was discovered as a failure of tests of rpmlint in Fedora's continuous testing of Python pre-releases: https://bugzilla.redhat.com/show_bug.cgi?id=2424585

CPython versions tested on:

3.15

Operating systems tested on:

Linux

Linked PRs

Activity

  1. added
    type-bugAn unexpected behavior, bug, or error
    on Jan 3, 2026
  2. hroncok commented on Jan 3, 2026

    @hroncok
    ContributorAuthor

    Upstream commit is python/importlib_metadata@57f31d7 from python/importlib_metadata#519 -- unfortunately, neither the commit nor the PR provide rationale for this change.

  3. hroncok commented on Jan 3, 2026

    @hroncok
    ContributorAuthor

    Similarly, before:

    >>> d = metadata.PathDistribution.at('/tmp')
    >>> d.name
    >>> d.version
    >>> 

    After:

    >>> from importlib import metadata
    >>> d = metadata.PathDistribution.at('/tmp')
    >>> d.name
    Traceback (most recent call last):
      File "<python-input-2>", line 1, in <module>
        d.name
      File "/usr/lib64/python3.15/importlib/metadata/__init__.py", line 542, in name
        return md_none(self.metadata)['Name']
               ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
    TypeError: 'NoneType' object is not subscriptable
    >>> d.version
    Traceback (most recent call last):
      File "<python-input-3>", line 1, in <module>
        d.version
      File "/usr/lib64/python3.15/importlib/metadata/__init__.py", line 552, in version
        return md_none(self.metadata)['Version']
               ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
    TypeError: 'NoneType' object is not subscriptable
  4. changed the title [-]Regression: importlib.metadata.PathDistribution.requires raises AttributeError[/-] [+]Regression: importlib.metadata.PathDistribution.requires raises AttributeError, name/version raises TypeError[/+] on Jan 3, 2026
  5. a12k commented on Jan 3, 2026

    @a12k
    Contributor

    Agreed the regression seems to stem from the change in PathDistribution.metadata to return None. It does correctly return None, but downstream properties like .name, .version, and .requires weren't updated to handle the NoneType return.

    I’d be happy to patch this if it is indeed a regression.

  6. added
    stdlibStandard Library Python modules in the Lib/ directory
    on Jan 3, 2026
  7. tomasr8 commented on Jan 3, 2026

    @tomasr8
    Member
  8. hroncok commented on Jan 5, 2026

    @hroncok
    ContributorAuthor

    What is the deal here? Do I need to report this to https://github.com/python/importlib_metadata/ ?

    Note that, based on tox-dev/pipdeptree#530 I think that .metadata being None is a regression of its own.

  9. arunkumargururaj07-star commented on Jan 7, 2026

    @arunkumargururaj07-star

    Hi, I'd like to work on this regression fix. I can see the issue is in PathDistribution where requires, name, and version methods don't handle self.metadata being None. I'll add proper None checks to all three methods.

  10. hroncok commented on Jan 8, 2026

    @hroncok
    ContributorAuthor

    I am not quite sure this is a proper fix. Considering self.metadata being None is a breaking change, I think the best way forward is to revert it.

  11. hroncok commented on Feb 9, 2026

    @hroncok
    ContributorAuthor

    How can I move this forward?

  12. hroncok commented on Mar 3, 2026

    @hroncok
    ContributorAuthor

    @hugovk As the release manager of 3.15, could you please help me determine what the best way forward is here? This change seems to violate PEP 387 – Backwards Compatibility Policy.

  13. hugovk commented on Mar 4, 2026

    @hugovk
    Member

    I talked with @jaraco and he'll take a look at this towards the end of the week.

  14. jaraco commented on Mar 6, 2026

    @jaraco
    Member

    This change was an intentional one, and I apologize for it not being clearly traceable to the rationale.

    I only had to go one level deeper from python/importlib_metadata#519 to python/importlib_metadata#493 to see the rationale.

    Instead, I would expect dist.metadata to be None when no metadata file is present, and to return an empty PackageMetadata object when a metadata file is present but empty.

    And one layer deeper python/importlib_metadata#489 (comment) describes where the Python 3.14 behavior missed expectations (and conflated the absence of metadata with a degenerate, empty metadata).

    I am not quite sure this is a proper fix. Considering self.metadata being None is a breaking change, I think the best way forward is to revert it.

    I was assuming, perhaps incorrectly, that there would be little if any reliance on reading Distribution.metadata from invalid sources, so this change while technically incompatible was also refining the behavior around previously-unsupported edge cases, adding fidelity where the previous behavior was undefined and incidental. As mentioned in the referenced comments, I'd have expected email.message_from_string(None) to have raised an Exception and not produced a degenerate result, so it was an accident (and a bug) that this edge case didn't fail.

    Based on those assumptions, I was treating this change as a (technically incompatible, but acceptable) bugfix.

    [From PEP 387, API compatibility includes: ] Given a set of arguments, the return value, side effects, and raised exceptions of a function. This does not preclude changes from reasonable bug fixes.

    Seeing the examples above, I'm now more concerned about the uses resulting from Hyrum's law.

    I did release this behavior early in order to gather feedback, and based on this feedback, it does deserve some reconsideration. I don't want to simply revert the behavior, as I'd like to understand what is the proper design moving forward and whether or not that change deserves a deprecation period.

    Regarding the .metadata property, I do feel as if the None value better reflects the reality of the situation, and my instinct was that downstream consumers not handling None should crash (including cases that hit internal use as reported above). Or maybe better would be to throw an exception (MetadataNotFound) and avoid the None return type altogether. I do feel it's important to help consumers distinguish between a metadata folder with a missing METADATA file (but potentially containing other metadata) and one with an empty METADATA file.

    Let's not revert this quite yet.

    @hugovk Based on my explanation above and the fact that this use case was only viable due to an accident in the underlying APIs, do you want to retroactively support the behavior and demand a deprecation period for the change?

    To everyone else, what should be the desired behavior when resolving "metadata" (i.e. the fields) for a folder that lacks the METADATA file? Exception, None, or something else (maybe a DegeneratePackageMetadata object that's distinct from actual PackageMetadata)? My instinct now is it should raise an Exception (and keep the API pure).

  15. 51 remaining items

  16. added a commit that references this issue on May 20, 2026
  17. jaraco commented on May 20, 2026

    @jaraco
    Member

    Thanks Miro.

    Hugo, let me know if I should add the note in What's New, or if that's something someone else will do (in the past, that's generally been handled by someone other than me).

  18. hugovk commented on May 20, 2026

    @hugovk
    Member

    @jaraco Please add it to What's New.

    Nowadays we prefer contributors to update it directly (when needed), and then we might do some editing later.

  19. added 2 commits that reference this issue on May 20, 2026
  20. hroncok commented on Jun 2, 2026

    @hroncok
    ContributorAuthor

    FTR another one: Pylons/plaster#38

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

stdlibStandard Library Python modules in the Lib/ directorytopic-importlibtype-bugAn unexpected behavior, bug, or error

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions