PEP 517: update backend example (#310)
- update hook names and signatures - clearly separate sdist building & wheel building - add support for out-of-tree wheel builds - clarify build_wheel spec based on updated example - be explicit that out-of-tree builds should match the results of building via sdist
This commit is contained in:
parent
20c110f591
commit
0189da7b60
112
pep-0517.txt
112
pep-0517.txt
|
@ -190,25 +190,38 @@ metadata. The directory passed in by the build frontend MUST be
|
|||
identical to the directory created by ``prepare_wheel_metadata``,
|
||||
including any unrecognized files it created.
|
||||
|
||||
If build_directory is not None, it is a unicode string containing the
|
||||
path to a directory where intermediate build artifacts may be stored.
|
||||
This may be empty, or it may contain artifacts from a previous build to
|
||||
be used as a cache. The backend is responsible for determining whether
|
||||
any cached artifacts are outdated. When a build_directory is provided,
|
||||
the backend should not create or modify any files in the source
|
||||
directory (the working directory where the hook is called). If the
|
||||
backend cannot reliably avoid modifying the directory it builds from, it
|
||||
should copy any files it needs to build_directory and perform the build
|
||||
there.
|
||||
Backends which do not provide the ``prepare_wheel_metadata`` hook may either
|
||||
silently ignore the ``metadata_directory`` parameter to ``build_wheel``, or
|
||||
else raise an exception when it is set to anything other than ``None``.
|
||||
|
||||
If build_directory is None, the backend may do an 'in place' build which
|
||||
modifies the source directory. The semantics of this are not specified
|
||||
here.
|
||||
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
|
||||
the hook is called) where intermediate build artifacts may be stored.
|
||||
|
||||
Whatever the value of build_directory, the backend may also store intermediates
|
||||
in other cache locations or temporary directories, which it is responsible for
|
||||
managing. The presence or absence of any caches should not make a
|
||||
material difference to the final result of the build.
|
||||
These out-of-tree builds should have the same result as first building an sdist
|
||||
and then building a wheel from that sdist. If the backend cannot otherwise
|
||||
ensure that unexpected files won't end up in the built wheel archive, it should
|
||||
copy any essential input files it needs to ``build_directory`` and perform the
|
||||
build there.
|
||||
|
||||
The provided build directory may be empty, or it may contain artifacts from a
|
||||
previous build to be used as a cache. The backend is responsible for determining
|
||||
whether any cached artifacts are outdated.
|
||||
|
||||
If ``build_directory`` is None, the backend may do an 'in place' build which
|
||||
modifies the source directory and may produce different results from those that
|
||||
would be obtained by exporting an sdist first. The exact semantics of this will
|
||||
depend on the build system in use, and hence are not specified here.
|
||||
|
||||
To guard against frontends that are not fully compliant with this specification,
|
||||
defensively coded backends may treat
|
||||
``os.path.samefile(build_directory, os.getcwd())`` as a request for an in place
|
||||
build.
|
||||
|
||||
Whatever the value of ``build_directory``, the backend may also store
|
||||
intermediate artifacts in other cache locations or temporary directories, which
|
||||
it is responsible for managing. The presence or absence of any caches should not
|
||||
make a material difference to the final result of the build.
|
||||
|
||||
build_sdist
|
||||
-----------
|
||||
|
@ -618,16 +631,15 @@ build backend::
|
|||
# mypackage_custom_build_backend.py
|
||||
import os.path
|
||||
import pathlib
|
||||
import shutil
|
||||
|
||||
def get_build_requires(config_settings, config_directory):
|
||||
return ["wheel"]
|
||||
SDIST_NAME = "mypackage-0.1"
|
||||
SDIST_FILENAME = SDIST_NAME + ".tar.gz"
|
||||
WHEEL_FILENAME = "mypackage-0.1-py2.py3-none-any.whl"
|
||||
|
||||
def build_wheel(wheel_directory, config_settings, config_directory=None):
|
||||
from wheel.archive import archive_wheelfile
|
||||
filename = "mypackage-0.1-py2.py3-none-any"
|
||||
path = os.path.join(wheel_directory, filename)
|
||||
archive_wheelfile(path, "src/")
|
||||
return filename
|
||||
#################
|
||||
# sdist creation
|
||||
#################
|
||||
|
||||
def _exclude_hidden_and_special_files(archive_entry):
|
||||
"""Tarfile filter to exclude hidden and special files from the archive"""
|
||||
|
@ -636,14 +648,54 @@ build backend::
|
|||
return archive_entry
|
||||
return None
|
||||
|
||||
def build_sdist(sdist_dir, config_settings):
|
||||
sdist_subdir = "mypackage-0.1"
|
||||
sdist_path = pathlib.Path(sdist_dir) / (sdist_subdir + ".tar.gz")
|
||||
def _make_sdist(sdist_dir):
|
||||
"""Make an sdist and return both the Python object and its filename"""
|
||||
sdist_path = pathlib.Path(sdist_dir) / SDIST_FILENAME
|
||||
sdist = tarfile.open(sdist_path, "w:gz", format=tarfile.PAX_FORMAT)
|
||||
# Tar up the whole directory, minus hidden and special files
|
||||
sdist.add(os.getcwd(), arcname=sdist_subdir,
|
||||
sdist.add(os.getcwd(), arcname=SDIST_NAME,
|
||||
filter=_exclude_hidden_and_special_files)
|
||||
return sdist_subdir + ".tar.gz"
|
||||
return sdist, SDIST_FILENAME
|
||||
|
||||
def build_sdist(sdist_dir, config_settings):
|
||||
"""PEP 517 sdist creation hook"""
|
||||
sdist, sdist_filename = _make_sdist(sdist_dir)
|
||||
return sdist_filename
|
||||
|
||||
#################
|
||||
# wheel creation
|
||||
#################
|
||||
|
||||
def get_requires_for_build_wheel(config_settings):
|
||||
"""PEP 517 wheel building dependency definition hook"""
|
||||
# As a simple static requirement, this could also just be
|
||||
# listed in the project's build system dependencies instead
|
||||
return ["wheel"]
|
||||
|
||||
def _prepare_out_of_tree_build(build_directory):
|
||||
"""Prepare out-of-tree build by way of unpacking the sdist"""
|
||||
sdist, sdist_filename = _make_sdist(build_directory)
|
||||
os.chdir(build_directory)
|
||||
if os.path.exists(SDIST_NAME):
|
||||
# Prevent caching of stale input files
|
||||
shutil.rmtree(SDIST_NAME)
|
||||
sdist.extractall()
|
||||
os.remove(sdist_filename)
|
||||
os.chdir(SDIST_NAME)
|
||||
|
||||
def build_wheel(wheel_directory, build_directory=None,
|
||||
metadata_directory=None, config_settings=None):
|
||||
"""PEP 517 wheel creation hook"""
|
||||
# First check if the frontend has requested an out-of-tree build
|
||||
out_of_tree_build = (build_directory is not None and
|
||||
not os.path.samefile(build_directory, os.getcwd())
|
||||
if out_of_tree_build:
|
||||
_prepare_out_of_tree_build(build_directory)
|
||||
# Continue with assembling the wheel archive
|
||||
from wheel.archive import archive_wheelfile
|
||||
path = os.path.join(wheel_directory, WHEEL_FILENAME)
|
||||
archive_wheelfile(path, "src/")
|
||||
return WHEEL_FILENAME
|
||||
|
||||
Of course, this is a *terrible* build backend: it requires the user to
|
||||
have manually set up the wheel metadata in
|
||||
|
|
Loading…
Reference in New Issue