Skip to content

build: implement metadata preparation hook #217

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Feb 17, 2021

Conversation

uranusjr
Copy link
Member

Fix #130.

I make the function signature require the user to pass in "wheel" explicitly. This is of course redundant, but I have a feeling we’re going to have a prepare_metadata_for_sdist at some point and it’s better to leave room now than having to change things later. And prepare("wheel") is arguably more consistent with build("wheel") anyway.

Due to the issues mentioned in #130 (comment), I’m not using the build_wheel fallback provided by pep517, and instead return None when the backend does not implement prepare_metadata_for_wheel. The returned result is stored in a member attribute and popped out when build_wheel is called.

@uranusjr uranusjr marked this pull request as draft January 29, 2021 15:09
@layday
Copy link
Member

layday commented Jan 29, 2021

I like that prepare follows the same pattern as build. Why is the metadata path discarded during the build?

@uranusjr
Copy link
Member Author

uranusjr commented Jan 30, 2021

PEP 517 does not say whether the prepared metadata directory may be reused across multiple build_wheel call, only that it should be reused, so I took the safe route and use it only exactly once.

It also just occured to me that the PEP says the frontend should only pass the metadata directory into build_whell [if the frontend] depends on the wheel resulting from this call to have metadata matching this earlier call, so an option should be provided for the frontend to have a choice to not do it. So maybe it’s not that good an idea to store the prepare result as a state after all, and we should just add a metadata_directory argument to build and let the user choose what to they want.

@layday
Copy link
Member

layday commented Jan 30, 2021

Yes, I don't think we need to do anything fancy with the metadata path, nor do I expect that anybody will actually want to pipe the metadata path into build_wheel. I'm not sure if it was intended as an optimisation should you need to look at the metadata before building the wheel or a guarantee that the source tree has not changed between the two calls, but nobody seems to have sought to use the metadata_directory argument of build_wheel, that I can tell. That might be because none of the three major backends support it:

@uranusjr
Copy link
Member Author

uranusjr commented Jan 30, 2021

nobody seems to have sought to use the metadata_directory argument of build_wheel, that I can tell.

pip does. And arguably all major backends are implemented incorrectly. According to PEP 517, if a backend implements prepare_metadata_for_wheel, it MUST ensure the resulting wheel contains identical metadata to the prepared metadata directory (IOW it must use the metadata_directory argument to either generate the wheel directly from it, or use it to verify the built wheel contains identical metadata). setuptools actually fails to meet the promise in at least one situation, leading to numerous pip bug reports.

@layday
Copy link
Member

layday commented Jan 30, 2021

setuptools actually fails to meet the promise in at least one situation, leading to numerous pip bug reports.

Is that because the prepared metadata becomes stale (e.g. when editing a package locally) or because the prepared metadata is simply incorrect?

@uranusjr
Copy link
Member Author

The prepared metadata is incorrect in the particular case (pypa/pip#9446).

@layday
Copy link
Member

layday commented Jan 30, 2021

We could check with backend devs to see why this wasn't implemented, if the PEP needs to be modified and if pip wouldn't be better off comparing prepared and built wheel metadata on their end.

@uranusjr
Copy link
Member Author

There are issue filed to those backends now (I filed one for Flit just a moment ago): pypa/setuptools#1825 python-poetry/poetry#1078 pypa/flit#389

@uranusjr
Copy link
Member Author

uranusjr commented Feb 1, 2021

I raised the issue on discussion.python.org, and from the response, I think we should still implement the metadata_directory argument because it is the right thing to do. Backends don’t use it, but that’s an issue they should fix.

@FFY00
Copy link
Member

FFY00 commented Feb 1, 2021

I agree. I think a backend simply ignoring the argument is fine, though I think they should all verify if it's the same metadata if they're gonna rebuild it anyway.

@uranusjr uranusjr force-pushed the prepare-metadata-for-build-wheel branch from 5a511d9 to 07aeb1f Compare February 1, 2021 15:25
@uranusjr uranusjr marked this pull request as ready for review February 1, 2021 15:47
@uranusjr uranusjr force-pushed the prepare-metadata-for-build-wheel branch 2 times, most recently from 8efe23a to 195f416 Compare February 1, 2021 15:50
except pep517.wrappers.BackendUnavailable:
raise BuildException("Backend '{}' is not available.".format(self._backend))
except pep517.wrappers.HookMissing:
return None
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prepare('wheel') currently returns None if prepare_metadata_for_build_wheel is not implemented. Should an exception be raised instead?

Copy link
Member

@layday layday Feb 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly - would that mean exposing pep517's exceptions or creating our own equivalents?

Copy link
Member

@layday layday Feb 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is to say, I don't think a generic Build(Backend)Exception is satisfactory.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. The exception raised here need to be different, otherwise the caller won’t be able to distinguish an expected code path (prepare_metadata_for_build_wheel not implemented by the backend) from a legistimate error in the backend (BuildBackendException) or the build process (BuildException). So a new exception will be needed if we raise here.

raise BuildBackendException('Backend operation failed: {!r}'.format(e))
return path

def build(self, distribution, outdir, metadata_directory=None, config_settings=None):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

metadata_directory -> metadatadir or outdir -> output_directory for consistency.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PEP 517 names the arguments wheel_directory and metadata_directory. Would that work?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, build works both with wheels and sdists, hence 'out' or 'output'.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m going with output_directory.

@uranusjr uranusjr force-pushed the prepare-metadata-for-build-wheel branch 4 times, most recently from 51a7884 to 3c131e6 Compare February 1, 2021 16:24
@uranusjr uranusjr force-pushed the prepare-metadata-for-build-wheel branch from 3c131e6 to 02bf104 Compare February 9, 2021 13:36
@gaborbernat gaborbernat force-pushed the prepare-metadata-for-build-wheel branch 2 times, most recently from 2dc409a to 4af72f9 Compare February 13, 2021 08:10
Copy link
Contributor

@gaborbernat gaborbernat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@uranusjr made some changes to reduce code duplication, but now looks 👍🏻

@gaborbernat gaborbernat force-pushed the prepare-metadata-for-build-wheel branch 2 times, most recently from 7443b1b to ae1fa87 Compare February 13, 2021 08:35
@gaborbernat gaborbernat changed the title Implement metadata preparation hook build: implement metadata preparation hook Feb 13, 2021
@gaborbernat gaborbernat force-pushed the prepare-metadata-for-build-wheel branch 4 times, most recently from 370dc6e to 2d50531 Compare February 13, 2021 17:03
Signed-off-by: Bernát Gábor <[email protected]>
@gaborbernat gaborbernat force-pushed the prepare-metadata-for-build-wheel branch from 2d50531 to aa3b220 Compare February 13, 2021 18:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for metadata hook
4 participants