Nobody is following the metadata_directory promise in PEP 517

We don’t have a consensus on that question yet, as far as I can tell. There seem to be more use cases for your second option (callers can manipulate the data and backends must respect that) but the PEP currently prohibits such manipulation:

The directory passed in by the build frontend MUST be identical to the directory created by prepare_metadata_for_build_wheel

So that would definitely require a PEP (and consideration of backward compatibility) to implement.

The first option, on the other hand, could be implemented now, but requiring that backends MUST implement a check goes beyond what the current PEP says, and so would at least require a clarification to the PEP. I don’t personally see the point of making the check mandatory rather than optional, so IMO status quo wins here (callers can’t change the data, backends may check but don’t have to and can ignore the parameter).

Personally, I don’t have a need for either behaviour here, though, so I’m fine with whatever the community decides.

I have an implementation of zipfile.pop() somewhere that removes files from the end of a zip. You can rewrite distinfo without rewriting the entire archive.

In my build system and possibly also in setuptools it is not convenient to follow the metadata promise. Setuptools can put arbitrary files in there with its plugin mechanism for example.

Could we loosen the requirement to “should but if it doesn’t match nothing will break” or if it is really important the only way would be to check in the caller.

After rereading the PEP and the comments here several times I come to the conclusion that the backend must ensure that the resulting wheels doesn’t differ between in the case build_wheel is called without metadata_directory and in case build_wheel is called with metadata_directory pointing to the dist info folder previously created by prepare_metadata_for_build_wheel.

It is not responsible to ensure that the metadata is equal. According to the PEP the front end is allowed only to pass in the unchanged metadata directory previously created by prepare_metadata_for_build_wheel. Whether this restriction is good or not is debatible. But the important point as a backend developer is: If metadata_directory is given, use it.

Note that it is not necessarily the frontend that modifies metadata_directory. An extending backend that wraps an existing one, as mentioned above, is still a backend. PEP 517 does not prohibit such an implementation to modify metadata_directory, but a mandatory check in build_wheel will render it impossible.

1 Like

It seems to me that PEP 517 is based on a model that frontends (and only frontends) call backends[1], and that’s the real issue here. Because that model doesn’t cater for the case of backends wrapping other backends[2].

What I’ve been doing is reading PEP 517 as talking about the responsibilities of callers and implementers rather than frontends and backends. Maybe that was never the intention, and there’s a way to read the PEP to understand the responsibilities of a caller that isn’t a frontend (such a caller might be a wrapper backend, or it might be something else like a utility library or an introspection tool) without concluding that the PEP says nothing about that case, but if so I’m missing it. If others can infer such an interpretation, I’d love to see a clarification to the PEP to help people like me understand better[3].

Note that I’m fine with the idea that callers might want to modify the metadata and see that reflected in the built wheel. That seems like a perfectly good use case that we’d simply not thought much about until now. But before we start insisting that existing backends change to support that, I’d like the standard to clarify that they are expected to do so, and to explain how an arbitrary caller should decide whether it’s a frontend (and so mustn’t change the metadata) or not (so it can).

To be clear, though, I’m not a backend developer, so I don’t have a stake in this. My only interest is to make sure our standards are precise enough for people to rely on them for interoperability.


  1. That’s certainly how I recall thinking about it when PEP 517 was being developed. ↩︎

  2. Yes, I know wrapper backends are mentioned in the section about of in-tree backends but they were a later addition. ↩︎

  3. I know I’ve said this before, sorry for repeating myself. ↩︎

It seems GitHub has begun implementing support for modern Python dependency metadata, so Hatchling now implements the metadata methods Implement minimal versions of metadata preparation methods by ofek · Pull Request #466 · pypa/hatch · GitHub

As I mentioned in this thread and here and elsewhere, any builder that has build-time hooks like Hatchling and setuptools cannot technically keep PEP 517’s promise e.g. C extensions would require different tags in the WHEEL file.

I now consider the methods as mostly being for non-frontend tools like tox and Dependabot. So Hatchling only writes the METADATA file to the metadata directory and continues to ignore that directory itself.