pypa / build

A simple, correct Python build frontend

Home Page:https://build.pypa.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Confusing return type of `build.util.project_wheel_metadata`

astrojuanlu opened this issue · comments

I'm falling down a rabbit hole trying to find the "accepted" way of doing the equivalent of pep517.meta.load, which is deprecated as per pypa/pyproject-hooks#142 (comment) (because reading https://pypi.org/project/pep517/#deprecated-high-level did not make it clear to me that pep517.meta was deprecated).

I somehow got that the modern replacement for it would be build.util.project_wheel_metadata, which is supposed to returns PackageMetadata:

https://pypa-build.readthedocs.io/en/stable/api.html#build.util.project_wheel_metadata

However, when actually using it, I got an email.message.Message:

In [9]: type(project_wheel_metadata(Path(".").resolve()))
Out[9]: email.message.Message

Searching for PackageMetadata in the official Python docs got me to this mysterious warning:

The actual type of the object returned by metadata() is an implementation detail and should be accessed only through the interface described by the PackageMetadata protocol.

So, I went to see such protocol, and see there's supposed to be a json property:

https://importlib-metadata.readthedocs.io/en/latest/api.html#importlib_metadata.PackageMetadata.json

...but naturally email.message.Message doesn't have it:

In [10]: package_metadata = project_wheel_metadata(Path(".").resolve())

In [11]: package_metadata.json
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[11], line 1
----> 1 package_metadata.json

AttributeError: 'Message' object has no attribute 'json'
commented

Presumably you are using an older version of importlib_metadata from the stdlib (Python 3.8 or 3.9) which doesn't doesn't have json. The typeshed stubs correctly indicate that json is only available from Python 3.10 onwards. The build docs are built using Python 3.10; I don't know if there's any way to have sphinx show that the types vary by Python version.

This was changed in importlib_metadata 4: https://importlib-metadata.readthedocs.io/en/latest/history.html. If you look at the stdlib version: https://docs.python.org/3/library/importlib.metadata.html#distribution-metadata you’ll see the json property was added in 3.10. So 3.8-3.9 won’t have .json. 3.7 will depend on the version of importlib-metadata you have.

The implementation is at https://github.com/python/importlib_metadata/blob/a12a34537aa9566011ad8d9386e5c22d5425e6a5/importlib_metadata/_adapters.py#L77.

Thanks both for the fast response.

Presumably you are using an older version of importlib_metadata from the stdlib (Python 3.8 or 3.9)

Indeed, I was on 3.8, thanks.

So 3.8-3.9 won’t have .json. 3.7 will depend on the version of importlib-metadata you have.

That's weird, wouldn't it be better if 3.8-3.9 could also benefit from the backported importlib-metadata? In any case, that's a question separate from this issue.

I don't have specific suggestions on how this path could have been easier or more clear. I understand that things are in flux and that the docs are optimized for folks that live on the latest stable versions.

Closing this for now.

commented

That's weird, wouldn't it be better if 3.8-3.9 could also benefit from the backported importlib-metadata?

They can, but it’s up to you to depend on importlib-metadata and import importlib_metadata rather than stdlib importlib.metadata.

commented

build will always use the stdlib version in Python 3.8 and above, even if importlib_metadata is available.