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'
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.
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
.
build will always use the stdlib version in Python 3.8 and above, even if importlib_metadata
is available.