PEP 517: remove prepare_wheel_metadata references (#311)

- replace with prepare_metadata_for_build_wheel where appropriate
- update the API evolution example to be based on build_sdist
  rather than prepare_wheel_metadata
- also clarified the frontend example code covering one way to
  handle prepare_metadata_for_build_wheel being optional
This commit is contained in:
Nick Coghlan 2017-07-20 22:12:48 +10:00 committed by GitHub
parent 1a92d6ea0d
commit 83ae4a58a6
1 changed files with 39 additions and 34 deletions

View File

@ -181,18 +181,18 @@ Must build a .whl file, and place it in the specified ``wheel_directory``. It
must return the basename (not the full path) of the ``.whl`` file it creates, must return the basename (not the full path) of the ``.whl`` file it creates,
as a unicode string. as a unicode string.
If the build frontend has previously called ``prepare_wheel_metadata`` and If the build frontend has previously called ``prepare_metadata_for_build_wheel``
depends on the wheel resulting from this call to have metadata and depends on the wheel resulting from this call to have metadata
matching this earlier call, then it should provide the path to the created matching this earlier call, then it should provide the path to the created
``.dist-info`` directory as the ``metadata_directory`` argument. If this ``.dist-info`` directory as the ``metadata_directory`` argument. If this
argument is provided, then ``build_wheel`` MUST produce a wheel with identical argument is provided, then ``build_wheel`` MUST produce a wheel with identical
metadata. The directory passed in by the build frontend MUST be metadata. The directory passed in by the build frontend MUST be
identical to the directory created by ``prepare_wheel_metadata``, identical to the directory created by ``prepare_metadata_for_build_wheel``,
including any unrecognized files it created. including any unrecognized files it created.
Backends which do not provide the ``prepare_wheel_metadata`` hook may either Backends which do not provide the ``prepare_metadata_for_build_wheel`` hook may
silently ignore the ``metadata_directory`` parameter to ``build_wheel``, or either silently ignore the ``metadata_directory`` parameter to ``build_wheel``,
else raise an exception when it is set to anything other than ``None``. or else raise an exception when it is set to anything other than ``None``.
If ``build_directory`` is not None, it is a unicode string containing the If ``build_directory`` is not None, it is a unicode string containing the
path to a directory other than the source directory (the working directory where path to a directory other than the source directory (the working directory where
@ -744,12 +744,13 @@ across the ecosystem.
more powerful options for evolving this specification in the future. more powerful options for evolving this specification in the future.
For concreteness, imagine that next year we add a new For concreteness, imagine that next year we add a new
``prepare_wheel_metadata2`` hook, which replaces the current ``build_sdist_from_vcs`` hook, which provides an alternative to the current
``prepare_wheel_metadata`` hook with something that produces more data, or a ``build_sdist`` hook where the frontend is responsible for passing
different metadata format. In order to version control tracking metadata to backends (including indicating when all
manage the transition, we want it to be possible for build frontends on disk files are tracked), rather than individual backends having to query that
to transparently use ``prepare_wheel_metadata2`` when available and fall information themselves. In order to manage the transition, we'd want it to be
back onto ``prepare_wheel_metadata`` otherwise; and we want it to be possible for build frontends to transparently use ``build_sdist_from_vcs`` when
available and fall back onto ``build_sdist`` otherwise; and we'd want it to be
possible for build backends to define both methods, for compatibility possible for build backends to define both methods, for compatibility
with both old and new build frontends. with both old and new build frontends.
@ -767,11 +768,11 @@ achieve. Because ``pip`` controls the code that runs inside the child
process, it can easily write it to do something like:: process, it can easily write it to do something like::
command, backend, args = parse_command_line_args(...) command, backend, args = parse_command_line_args(...)
if command == "prepare_wheel_metadata": if command == "build_sdist":
if hasattr(backend, "prepare_wheel_metadata2"): if hasattr(backend, "build_sdist_from_vcs"):
backend.prepare_wheel_metadata2(...) backend.build_sdist_from_vcs(...)
elif hasattr(backend, "prepare_wheel_metadata"): elif hasattr(backend, "build_sdist"):
backend.prepare_wheel_metadata(...) backend.build_sdist(...)
else: else:
# error handling # error handling
@ -786,28 +787,32 @@ any change can go live, and that any changes will necessarily be
restricted to new releases. restricted to new releases.
One specific consequence of this is that in this PEP, we're able to One specific consequence of this is that in this PEP, we're able to
make the ``prepare_wheel_metadata`` command optional. In our design, this make the ``prepare_metadata_for_build_wheel`` command optional. In our design,
can easily be worked around by a tool like ``pip``, which can put code this can be readily handled by build frontends, which can put code in
in its subprocess runner like:: their subprocess runner like::
def prepare_wheel_metadata(output_dir, config_settings): def dump_wheel_metadata(backend, output_dir, config_settings):
if hasattr(backend, "prepare_wheel_metadata"): if hasattr(backend, "prepare_metadata_for_build_wheel"):
backend.prepare_wheel_metadata(output_dir, config_settings) backend.prepare_metadata_for_build_wheel(output_dir, config_settings)
else: else:
backend.build_wheel(output_dir, config_settings) wheel_fname = backend.build_wheel(output_dir, config_settings)
touch(output_dir / "PIP_ALREADY_BUILT_WHEELS") (output_dir / "ALREADY_BUILT_WHEEL").write_text(wheel_fname)
unzip_metadata(output_dir/*.whl) unzip_metadata(output_dir / wheel_fname)
def build_wheel(output_dir, config_settings, metadata_dir): def ensure_wheel_is_built(backend, output_dir, config_settings, metadata_dir):
if os.path.exists(metadata_dir.parent / "PIP_ALREADY_BUILT_WHEELS"): already_built = metadata_dir.parent / "ALREADY_BUILT_WHEEL"
copy(metadata_dir.parent / *.whl, output_dir) if already_built.exists():
wheel_fname = already_built.read_text()
copy(metadata_dir.parent / wheel_fname, output_dir)
else: else:
backend.build_wheel(output_dir, config_settings, metadata_dir) backend.build_wheel(output_dir, config_settings, metadata_dir)
and thus expose a totally uniform interface to the rest of ``pip``, and thus expose a totally uniform interface to the rest of the frontend,
with no extra subprocess calls, no duplicated builds, etc. But with no extra subprocess calls, no duplicated builds, etc. But
obviously this is the kind of code that you only want to write as part obviously this is the kind of code that you only want to write as part
of a private, within-project interface. of a private, within-project interface (e.g. the given example assumes that
all filesystem paths are supplied as ``pathlib.Path`` instances, rather than
as plain strings).
(And, of course, making the ``metadata`` command optional is one piece (And, of course, making the ``metadata`` command optional is one piece
of lowering the barrier to entry, as discussed above.) of lowering the barrier to entry, as discussed above.)