Skip to content
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

feat: build[uv] #1856

Merged
merged 15 commits into from
Jun 9, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ jobs:
with:
python-version: ${{ matrix.python_version }}

- uses: yezz123/setup-uv@v4

# Install podman on this CI instance for podman tests on linux
# Snippet from: https://github.com/redhat-actions/podman-login/blob/main/.github/workflows/example.yml
- name: Install latest podman
Expand All @@ -69,7 +71,7 @@ jobs:

- name: Install dependencies
run: |
python -m pip install ".[test]"
uv pip install --system ".[test]"

- name: Generate a sample project
run: |
Expand All @@ -82,6 +84,7 @@ jobs:
output-dir: wheelhouse
env:
CIBW_ARCHS_MACOS: x86_64 universal2 arm64
CIBW_BUILD_FRONTEND: 'build[uv]'

- name: Run a sample build (GitHub Action, only)
uses: ./
Expand Down Expand Up @@ -159,7 +162,7 @@ jobs:
with:
python-version: "3.x"
- name: Install dependencies
run: python -m pip install ".[test]"
run: python -m pip install ".[test,uv]"

- name: Set up QEMU
id: qemu
Expand Down
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ repos:
- types-jinja2
- types-pyyaml
- types-requests
- uv
- validate-pyproject
- id: mypy
name: mypy 3.12
Expand Down
8 changes: 5 additions & 3 deletions bin/generate_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,21 @@
type: string_array
build-frontend:
default: default
description: Set the tool to use to build, either "pip" (default for now) or "build"
description: Set the tool to use to build, either "pip" (default for now), "build", or "build[uv]"
oneOf:
- enum: [pip, build, default]
- enum: [pip, build, "build[uv]", default]
- type: string
pattern: '^pip; ?args:'
- type: string
pattern: '^build; ?args:'
- type: string
pattern: '^build\[uv\]; ?args:'
- type: object
additionalProperties: false
required: [name]
properties:
name:
enum: [pip, build]
enum: [pip, build, "build[uv]"]
args:
type: array
items:
Expand Down
55 changes: 37 additions & 18 deletions cibuildwheel/linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ def build_in_container(
log.build_start(config.identifier)
build_options = options.build_options(config.identifier)
build_frontend = build_options.build_frontend or BuildFrontendConfig("pip")
use_uv = build_frontend.name == "build[uv]" and Version(config.version) >= Version("3.8")
pip = ["uv", "pip"] if use_uv else ["pip"]

dependency_constraint_flags: list[PathOrStr] = []

Expand Down Expand Up @@ -229,13 +231,22 @@ def build_in_container(
)
sys.exit(1)

which_pip = container.call(["which", "pip"], env=env, capture_output=True).strip()
if PurePosixPath(which_pip) != python_bin / "pip":
print(
"cibuildwheel: pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it.",
file=sys.stderr,
)
sys.exit(1)
if use_uv:
which_uv = container.call(["which", "uv"], env=env, capture_output=True).strip()
if not which_uv:
print(
"cibuildwheel: uv not found on PATH. You must use a supported manylinux or musllinux environment with uv.",
file=sys.stderr,
)
sys.exit(1)
else:
which_pip = container.call(["which", "pip"], env=env, capture_output=True).strip()
if PurePosixPath(which_pip) != python_bin / "pip":
print(
"cibuildwheel: pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it.",
file=sys.stderr,
)
sys.exit(1)

compatible_wheel = find_compatible_wheel(built_wheels, config.identifier)
if compatible_wheel:
Expand Down Expand Up @@ -279,10 +290,12 @@ def build_in_container(
],
env=env,
)
elif build_frontend.name == "build":
elif build_frontend.name == "build" or build_frontend.name == "build[uv]":
henryiii marked this conversation as resolved.
Show resolved Hide resolved
if not 0 <= build_options.build_verbosity < 2:
msg = f"build_verbosity {build_options.build_verbosity} is not supported for build frontend. Ignoring."
log.warning(msg)
if use_uv:
extra_flags += ["--installer=uv"]
container.call(
[
"python",
Expand Down Expand Up @@ -327,26 +340,32 @@ def build_in_container(

# set up a virtual environment to install and test from, to make sure
# there are no dependencies that were pulled in at build time.
container.call(["pip", "install", "virtualenv", *dependency_constraint_flags], env=env)
if not use_uv:
container.call(
["pip", "install", "virtualenv", *dependency_constraint_flags], env=env
)

testing_temp_dir = PurePosixPath(
container.call(["mktemp", "-d"], capture_output=True).strip()
)
venv_dir = testing_temp_dir / "venv"

# Use embedded dependencies from virtualenv to ensure determinism
venv_args = ["--no-periodic-update", "--pip=embed"]
# In Python<3.12, setuptools & wheel are installed as well
if Version(config.version) < Version("3.12"):
venv_args.extend(("--setuptools=embed", "--wheel=embed"))
container.call(["python", "-m", "virtualenv", *venv_args, venv_dir], env=env)
if use_uv:
container.call(["uv", "venv", venv_dir], env=env)
else:
# Use embedded dependencies from virtualenv to ensure determinism
venv_args = ["--no-periodic-update", "--pip=embed"]
# In Python<3.12, setuptools & wheel are installed as well
if Version(config.version) < Version("3.12"):
venv_args.extend(("--setuptools=embed", "--wheel=embed"))
container.call(["python", "-m", "virtualenv", *venv_args, venv_dir], env=env)

virtualenv_env = env.copy()
virtualenv_env["PATH"] = f"{venv_dir / 'bin'}:{virtualenv_env['PATH']}"
virtualenv_env["VIRTUAL_ENV"] = str(venv_dir)

# TODO remove me once virtualenv provides pip>=24.1b1
if config.version == "3.13":
if config.version == "3.13" and not use_uv:
container.call(["pip", "install", "pip>=24.1b1"], env=virtualenv_env)

if build_options.before_test:
Expand All @@ -365,13 +384,13 @@ def build_in_container(
# Let's just pick the first one.
wheel_to_test = repaired_wheels[0]
container.call(
["pip", "install", str(wheel_to_test) + build_options.test_extras],
[*pip, "install", str(wheel_to_test) + build_options.test_extras],
env=virtualenv_env,
)

# Install any requirements to run the tests
if build_options.test_requires:
container.call(["pip", "install", *build_options.test_requires], env=virtualenv_env)
container.call([*pip, "install", *build_options.test_requires], env=virtualenv_env)

# Run the tests from a different directory
test_command_prepared = prepare_command(
Expand Down
Loading
Loading