2024-09-24 19:23:17 +02:00
|
|
|
|
"""
|
|
|
|
|
|
Python shims for the PEP 517 and PEP 660 build backend.
|
|
|
|
|
|
|
|
|
|
|
|
Major imports in this module are required to be lazy:
|
|
|
|
|
|
```
|
|
|
|
|
|
$ hyperfine \
|
|
|
|
|
|
"/usr/bin/python3 -c \"print('hi')\"" \
|
|
|
|
|
|
"/usr/bin/python3 -c \"from subprocess import check_call; print('hi')\""
|
|
|
|
|
|
Base: Time (mean ± σ): 11.0 ms ± 1.7 ms [User: 8.5 ms, System: 2.5 ms]
|
|
|
|
|
|
With import: Time (mean ± σ): 15.2 ms ± 2.0 ms [User: 12.3 ms, System: 2.9 ms]
|
|
|
|
|
|
Base 1.38 ± 0.28 times faster than with import
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
The same thing goes for the typing module, so we use Python 3.10 type annotations that
|
|
|
|
|
|
don't require importing typing but then quote them so earlier Python version ignore
|
|
|
|
|
|
them while IDEs and type checker can see through the quotes.
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
2025-01-10 07:27:15 -05:00
|
|
|
|
TYPE_CHECKING = False
|
|
|
|
|
|
if TYPE_CHECKING:
|
2025-01-13 13:34:17 -05:00
|
|
|
|
from collections.abc import Mapping, Sequence # noqa:I001
|
2025-01-10 07:27:15 -05:00
|
|
|
|
from typing import Any # noqa:I001
|
2024-09-24 19:23:17 +02:00
|
|
|
|
|
2025-04-22 09:20:00 -04:00
|
|
|
|
# Use the `uv build-backend` command rather than `uv-build`. This option is provided
|
2025-04-22 13:46:42 +02:00
|
|
|
|
# for downstream distributions who provide `uv` and wish to avoid building a partially
|
|
|
|
|
|
# overlapping `uv-build` executable.
|
|
|
|
|
|
USE_UV_EXECUTABLE = False
|
|
|
|
|
|
|
2025-01-10 07:27:15 -05:00
|
|
|
|
|
2025-01-13 13:34:17 -05:00
|
|
|
|
def warn_config_settings(config_settings: "Mapping[Any, Any] | None" = None) -> None:
|
2024-09-24 19:23:17 +02:00
|
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
|
|
if config_settings:
|
|
|
|
|
|
print("Warning: Config settings are not supported", file=sys.stderr)
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-01-13 13:34:17 -05:00
|
|
|
|
def call(
|
|
|
|
|
|
args: "Sequence[str]", config_settings: "Mapping[Any, Any] | None" = None
|
|
|
|
|
|
) -> str:
|
2024-09-24 19:23:17 +02:00
|
|
|
|
"""Invoke a uv subprocess and return the filename from stdout."""
|
2024-12-20 10:15:24 +01:00
|
|
|
|
import shutil
|
2024-09-24 19:23:17 +02:00
|
|
|
|
import subprocess
|
|
|
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
|
|
warn_config_settings(config_settings)
|
2025-04-22 13:46:42 +02:00
|
|
|
|
|
|
|
|
|
|
uv_bin_name = "uv" if USE_UV_EXECUTABLE else "uv-build"
|
2024-12-20 10:15:24 +01:00
|
|
|
|
# Unlike `find_uv_bin`, this mechanism must work according to PEP 517
|
2025-04-22 13:46:42 +02:00
|
|
|
|
uv_bin = shutil.which(uv_bin_name)
|
2024-12-20 10:15:24 +01:00
|
|
|
|
if uv_bin is None:
|
2025-04-22 13:46:42 +02:00
|
|
|
|
raise RuntimeError(f"{uv_bin_name} was not properly installed")
|
|
|
|
|
|
build_backend_args = ["build-backend"] if USE_UV_EXECUTABLE else []
|
2024-09-24 19:23:17 +02:00
|
|
|
|
# Forward stderr, capture stdout for the filename
|
2025-04-22 13:46:42 +02:00
|
|
|
|
result = subprocess.run(
|
|
|
|
|
|
[uv_bin, *build_backend_args, *args], stdout=subprocess.PIPE
|
|
|
|
|
|
)
|
2024-09-24 19:23:17 +02:00
|
|
|
|
if result.returncode != 0:
|
|
|
|
|
|
sys.exit(result.returncode)
|
|
|
|
|
|
# If there was extra stdout, forward it (there should not be extra stdout)
|
2024-10-03 15:05:01 +03:00
|
|
|
|
stdout = result.stdout.decode("utf-8").strip().splitlines(keepends=True)
|
|
|
|
|
|
sys.stdout.writelines(stdout[:-1])
|
2024-09-24 19:23:17 +02:00
|
|
|
|
# Fail explicitly instead of an irrelevant stacktrace
|
2024-10-03 15:05:01 +03:00
|
|
|
|
if not stdout:
|
2025-04-22 13:46:42 +02:00
|
|
|
|
print(
|
|
|
|
|
|
f"{uv_bin_name} subprocess did not return a filename on stdout",
|
|
|
|
|
|
file=sys.stderr,
|
|
|
|
|
|
)
|
2024-09-24 19:23:17 +02:00
|
|
|
|
sys.exit(1)
|
2024-10-03 15:05:01 +03:00
|
|
|
|
return stdout[-1].strip()
|
2024-09-24 19:23:17 +02:00
|
|
|
|
|
|
|
|
|
|
|
2025-01-10 07:27:15 -05:00
|
|
|
|
def build_sdist(
|
2025-01-13 13:34:17 -05:00
|
|
|
|
sdist_directory: str, config_settings: "Mapping[Any, Any] | None" = None
|
2025-01-10 07:27:15 -05:00
|
|
|
|
) -> str:
|
2024-09-24 19:23:17 +02:00
|
|
|
|
"""PEP 517 hook `build_sdist`."""
|
2025-03-07 23:40:53 +01:00
|
|
|
|
args = ["build-sdist", sdist_directory]
|
2024-09-24 19:23:17 +02:00
|
|
|
|
return call(args, config_settings)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def build_wheel(
|
|
|
|
|
|
wheel_directory: str,
|
2025-01-13 13:34:17 -05:00
|
|
|
|
config_settings: "Mapping[Any, Any] | None" = None,
|
2024-09-24 19:23:17 +02:00
|
|
|
|
metadata_directory: "str | None" = None,
|
2025-01-10 07:27:15 -05:00
|
|
|
|
) -> str:
|
2024-09-24 19:23:17 +02:00
|
|
|
|
"""PEP 517 hook `build_wheel`."""
|
2025-03-07 23:40:53 +01:00
|
|
|
|
args = ["build-wheel", wheel_directory]
|
2024-09-24 19:23:17 +02:00
|
|
|
|
if metadata_directory:
|
2025-03-07 23:40:53 +01:00
|
|
|
|
args.extend([metadata_directory])
|
2024-09-24 19:23:17 +02:00
|
|
|
|
return call(args, config_settings)
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-01-10 07:27:15 -05:00
|
|
|
|
def get_requires_for_build_sdist(
|
2025-01-13 13:34:17 -05:00
|
|
|
|
config_settings: "Mapping[Any, Any] | None" = None,
|
|
|
|
|
|
) -> "Sequence[str]":
|
2024-09-24 19:23:17 +02:00
|
|
|
|
"""PEP 517 hook `get_requires_for_build_sdist`."""
|
|
|
|
|
|
warn_config_settings(config_settings)
|
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-01-10 07:27:15 -05:00
|
|
|
|
def get_requires_for_build_wheel(
|
2025-01-13 13:34:17 -05:00
|
|
|
|
config_settings: "Mapping[Any, Any] | None" = None,
|
|
|
|
|
|
) -> "Sequence[str]":
|
2024-09-24 19:23:17 +02:00
|
|
|
|
"""PEP 517 hook `get_requires_for_build_wheel`."""
|
|
|
|
|
|
warn_config_settings(config_settings)
|
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def prepare_metadata_for_build_wheel(
|
2025-01-13 13:34:17 -05:00
|
|
|
|
metadata_directory: str, config_settings: "Mapping[Any, Any] | None" = None
|
2025-01-10 07:27:15 -05:00
|
|
|
|
) -> str:
|
2024-09-24 19:23:17 +02:00
|
|
|
|
"""PEP 517 hook `prepare_metadata_for_build_wheel`."""
|
2025-03-07 23:40:53 +01:00
|
|
|
|
args = ["prepare-metadata-for-build-wheel", metadata_directory]
|
2024-09-24 19:23:17 +02:00
|
|
|
|
return call(args, config_settings)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def build_editable(
|
|
|
|
|
|
wheel_directory: str,
|
2025-01-13 13:34:17 -05:00
|
|
|
|
config_settings: "Mapping[Any, Any] | None" = None,
|
2024-09-24 19:23:17 +02:00
|
|
|
|
metadata_directory: "str | None" = None,
|
2025-01-10 07:27:15 -05:00
|
|
|
|
) -> str:
|
2024-09-24 19:23:17 +02:00
|
|
|
|
"""PEP 660 hook `build_editable`."""
|
2025-03-07 23:40:53 +01:00
|
|
|
|
args = ["build-editable", wheel_directory]
|
2024-09-24 19:23:17 +02:00
|
|
|
|
if metadata_directory:
|
2025-03-07 23:40:53 +01:00
|
|
|
|
args.extend([metadata_directory])
|
2024-09-24 19:23:17 +02:00
|
|
|
|
return call(args, config_settings)
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-01-10 07:27:15 -05:00
|
|
|
|
def get_requires_for_build_editable(
|
2025-01-13 13:34:17 -05:00
|
|
|
|
config_settings: "Mapping[Any, Any] | None" = None,
|
|
|
|
|
|
) -> "Sequence[str]":
|
2024-09-24 19:23:17 +02:00
|
|
|
|
"""PEP 660 hook `get_requires_for_build_editable`."""
|
|
|
|
|
|
warn_config_settings(config_settings)
|
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def prepare_metadata_for_build_editable(
|
2025-01-13 13:34:17 -05:00
|
|
|
|
metadata_directory: str, config_settings: "Mapping[Any, Any] | None" = None
|
2025-01-10 07:27:15 -05:00
|
|
|
|
) -> str:
|
2024-09-24 19:23:17 +02:00
|
|
|
|
"""PEP 660 hook `prepare_metadata_for_build_editable`."""
|
2025-03-07 23:40:53 +01:00
|
|
|
|
args = ["prepare-metadata-for-build-editable", metadata_directory]
|
2024-09-24 19:23:17 +02:00
|
|
|
|
return call(args, config_settings)
|