* chore: faster mypy This makes mypy around 26% faster from a cold cache. Signed-off-by: Henry Schreiner <henryfs@princeton.edu> * chore: enable more mypy error codes Turn on possibly-undefined, exhaustive-match, and other strict flags, and fix what they report. Two real bugs: pyodide never set `repaired_wheel` when it reused a compatible wheel, so the test step failed with a NameError; the OCI shell read loop spun forever if the shell exited. Assisted-by: ClaudeCode:claude-opus-5 * test: carry default OCI runtime into podman vfs test config Podman ignores its usual config files when CONTAINERS_CONF is set, so it falls back to the first runtime found on PATH. On current GitHub Ubuntu runner images that is crun 1.14.1, which cannot parse the OCI spec v1.2.x config that podman 5.8.4 generates ("crun: unknown version specified"). Query the default runtime path and set it in the generated config. Assisted-by: ClaudeCode:claude-fable-5 * fix: annotate vfs config dict so mypy passes on Linux mypy on macOS marks the rest of the function unreachable after the darwin pytest.skip, so the strict index error only appears on Linux. Assisted-by: ClaudeCode:claude-fable-5 * chore: minor cleanup of variable name Signed-off-by: Henry Schreiner <henryfs@princeton.edu> * test: cover container shell exiting during call Assisted-by: ClaudeCode:claude-opus-5 --------- Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
438 lines
13 KiB
Python
Executable File
438 lines
13 KiB
Python
Executable File
#!/usr/bin/env -S uv run --script
|
|
|
|
# /// script
|
|
# dependencies = ["pyyaml"]
|
|
# ///
|
|
|
|
import argparse
|
|
import copy
|
|
import json
|
|
from typing import Any
|
|
|
|
import yaml
|
|
|
|
parser = argparse.ArgumentParser(allow_abbrev=False)
|
|
parser.add_argument("--schemastore", action="store_true", help="Generate schema_store version")
|
|
args = parser.parse_args()
|
|
|
|
# The defaults in the schema are used by external tools for validation and IDE support. They
|
|
# should match the values in defaults.toml, which are used by cibuildwheel itself.
|
|
starter = """
|
|
$schema: http://json-schema.org/draft-07/schema#
|
|
$id: https://github.com/pypa/cibuildwheel/blob/main/cibuildwheel/resources/cibuildwheel.schema.json
|
|
$defs:
|
|
inherit:
|
|
enum:
|
|
- none
|
|
- prepend
|
|
- append
|
|
default: none
|
|
description: How to inherit the parent's value.
|
|
enable:
|
|
enum:
|
|
- cpython-prerelease
|
|
- graalpy
|
|
- pyodide-prerelease
|
|
- pypy
|
|
- pypy-eol
|
|
description: A Python version or flavor to enable.
|
|
additionalProperties: false
|
|
description: cibuildwheel's settings.
|
|
type: object
|
|
properties:
|
|
audit-command:
|
|
description: Execute a shell command to audit each wheel after it is repaired. Use {wheel} for each wheel path, or {abi3_wheel} to only audit abi3 wheels.
|
|
type: string_array
|
|
audit-requires:
|
|
description: Install Python dependencies for the audit step.
|
|
type: string_array
|
|
archs:
|
|
description: Change the architectures built on your machine by default.
|
|
type: string_array
|
|
before-all:
|
|
description: Execute a shell command on the build system before any wheels are built.
|
|
type: string_array
|
|
before-build:
|
|
description: Execute a shell command preparing each wheel's build.
|
|
type: string_array
|
|
before-test:
|
|
description: Execute a shell command before testing each wheel.
|
|
type: string_array
|
|
build:
|
|
default: ['*']
|
|
description: Choose the Python versions to build.
|
|
type: string_array
|
|
build-frontend: {} # filled in by build_frontend_schema below
|
|
build-verbosity:
|
|
type: integer
|
|
minimum: -3
|
|
maximum: 3
|
|
default: 0
|
|
description: Increase/decrease the output of pip wheel.
|
|
config-settings:
|
|
description: Specify config-settings for the build backend.
|
|
type: string_table_array
|
|
container-engine:
|
|
oneOf:
|
|
- enum: [docker, podman]
|
|
- type: string
|
|
pattern: '^docker; ?(create_args|disable_host_mount):'
|
|
- type: string
|
|
pattern: '^podman; ?(create_args|disable_host_mount):'
|
|
- type: object
|
|
additionalProperties: false
|
|
required: [name]
|
|
properties:
|
|
name:
|
|
enum: [docker, podman]
|
|
create-args:
|
|
type: array
|
|
items:
|
|
type: string
|
|
disable-host-mount:
|
|
type: boolean
|
|
dependency-versions:
|
|
default: pinned
|
|
description: Specify how cibuildwheel controls the versions of the tools it uses
|
|
oneOf:
|
|
- enum: [pinned, latest]
|
|
- type: string
|
|
description: Path to a file containing dependency versions, or inline package specifications, starting with "packages:"
|
|
not:
|
|
enum: [pinned, latest]
|
|
- type: object
|
|
additionalProperties: false
|
|
properties:
|
|
file:
|
|
type: string
|
|
- type: object
|
|
additionalProperties: false
|
|
properties:
|
|
packages:
|
|
type: array
|
|
items:
|
|
type: string
|
|
enable:
|
|
description: Enable or disable certain builds.
|
|
oneOf:
|
|
- $ref: "#/$defs/enable"
|
|
- type: array
|
|
items:
|
|
$ref: "#/$defs/enable"
|
|
environment:
|
|
description: Set environment variables needed during the build.
|
|
type: string_table
|
|
environment-pass:
|
|
description: Set environment variables on the host to pass-through to the container
|
|
during the build.
|
|
type: string_array
|
|
manylinux-aarch64-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
manylinux-armv7l-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
manylinux-i686-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
manylinux-ppc64le-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
manylinux-pypy_aarch64-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
manylinux-pypy_i686-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
manylinux-pypy_x86_64-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
manylinux-riscv64-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
manylinux-s390x-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
manylinux-x86_64-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
musllinux-aarch64-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
musllinux-armv7l-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
musllinux-i686-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
musllinux-ppc64le-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
musllinux-riscv64-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
musllinux-s390x-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
musllinux-x86_64-image:
|
|
type: string
|
|
description: Specify alternative manylinux / musllinux container images
|
|
xbuild-tools:
|
|
description: Binaries on the path that should be included in an isolated cross-build environment
|
|
type: string_array
|
|
xbuild-files:
|
|
description: Platform-specific files in the build environment
|
|
type: string_table_array
|
|
pyodide-version:
|
|
type: string
|
|
description: Specify the version of Pyodide to use
|
|
repair-wheel-command:
|
|
description: Execute a shell command to repair each built wheel.
|
|
type: string_array
|
|
skip:
|
|
description: Choose the Python versions to skip.
|
|
type: string_array
|
|
test-command:
|
|
description: Execute a shell command to test each built wheel.
|
|
type: string_array
|
|
test-extras:
|
|
description: Install your wheel for testing using `extras_require`
|
|
type: string_array
|
|
test-sources:
|
|
description: Test files that are required by the test environment
|
|
type: string_array
|
|
test-groups:
|
|
description: Install extra groups when testing
|
|
type: string_array
|
|
test-requires:
|
|
description: Install Python dependencies before running the tests
|
|
type: string_array
|
|
test-skip:
|
|
description: Skip running tests on some builds.
|
|
type: string_array
|
|
test-environment:
|
|
description: Set environment variables for the test environment
|
|
type: string_table
|
|
test-runtime:
|
|
description: Additional configuration for the test runner
|
|
oneOf:
|
|
- type: string
|
|
pattern: '^$'
|
|
- type: object
|
|
additionalProperties: false
|
|
- type: string
|
|
pattern: 'args:'
|
|
- type: object
|
|
additionalProperties: false
|
|
required: [args]
|
|
properties:
|
|
args:
|
|
type: array
|
|
items:
|
|
type: string
|
|
|
|
"""
|
|
|
|
schema = yaml.safe_load(starter)
|
|
|
|
string_array = yaml.safe_load(
|
|
"""
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
"""
|
|
)
|
|
|
|
string_table_array = yaml.safe_load(
|
|
"""
|
|
- type: string
|
|
- type: object
|
|
additionalProperties: false
|
|
patternProperties:
|
|
.+:
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
"""
|
|
)
|
|
|
|
string_table = yaml.safe_load(
|
|
"""
|
|
- type: string
|
|
- type: object
|
|
additionalProperties: false
|
|
patternProperties:
|
|
.+:
|
|
type: string
|
|
"""
|
|
)
|
|
|
|
FRONTENDS = ["pip", "build", "build[uv]", "uv"]
|
|
|
|
|
|
def build_frontend_schema(
|
|
names: list[str], description: str, default: str = "default"
|
|
) -> dict[str, Any]:
|
|
"""
|
|
A frontend is a name, a "name; args: ..." string, or a table with a name and args.
|
|
"""
|
|
# Only the brackets in "build[uv]" need escaping
|
|
patterns = [name.replace("[", r"\[").replace("]", r"\]") for name in names]
|
|
return {
|
|
"default": default,
|
|
"description": description,
|
|
"oneOf": [
|
|
{"enum": [*names, "default"]},
|
|
*({"type": "string", "pattern": f"^{pattern}; ?args:"} for pattern in patterns),
|
|
{
|
|
"type": "object",
|
|
"additionalProperties": False,
|
|
"required": ["name"],
|
|
"properties": {
|
|
"name": {"enum": names},
|
|
"args": {"type": "array", "items": {"type": "string"}},
|
|
},
|
|
},
|
|
],
|
|
"title": "CIBW_BUILD_FRONTEND",
|
|
}
|
|
|
|
|
|
schema["properties"]["build-frontend"] = build_frontend_schema(
|
|
[*FRONTENDS, "pyodide-build"],
|
|
'Set the tool to use to build, either "build" (default), "build[uv]", "uv", or "pip"'
|
|
' ("pyodide-build" for pyodide)',
|
|
)
|
|
|
|
for value in schema["properties"].values():
|
|
match value:
|
|
case {"type": "string_array"}:
|
|
del value["type"]
|
|
value["oneOf"] = string_array
|
|
case {"type": "string_table"}:
|
|
del value["type"]
|
|
value["oneOf"] = string_table
|
|
case {"type": "string_table_array"}:
|
|
del value["type"]
|
|
value["oneOf"] = string_table_array
|
|
case _:
|
|
pass
|
|
|
|
overrides = yaml.safe_load(
|
|
"""
|
|
type: array
|
|
description: An overrides array
|
|
items:
|
|
type: object
|
|
required: ["select"]
|
|
minProperties: 2
|
|
additionalProperties: false
|
|
properties:
|
|
select: {}
|
|
inherit:
|
|
type: object
|
|
additionalProperties: false
|
|
properties:
|
|
audit-command: {"$ref": "#/$defs/inherit"}
|
|
audit-requires: {"$ref": "#/$defs/inherit"}
|
|
before-all: {"$ref": "#/$defs/inherit"}
|
|
before-build: {"$ref": "#/$defs/inherit"}
|
|
xbuild-tools: {"$ref": "#/$defs/inherit"}
|
|
xbuild-files: {"$ref": "#/$defs/inherit"}
|
|
before-test: {"$ref": "#/$defs/inherit"}
|
|
config-settings: {"$ref": "#/$defs/inherit"}
|
|
container-engine: {"$ref": "#/$defs/inherit"}
|
|
environment: {"$ref": "#/$defs/inherit"}
|
|
environment-pass: {"$ref": "#/$defs/inherit"}
|
|
repair-wheel-command: {"$ref": "#/$defs/inherit"}
|
|
test-command: {"$ref": "#/$defs/inherit"}
|
|
test-extras: {"$ref": "#/$defs/inherit"}
|
|
test-sources: {"$ref": "#/$defs/inherit"}
|
|
test-requires: {"$ref": "#/$defs/inherit"}
|
|
test-environment: {"$ref": "#/$defs/inherit"}
|
|
test-runtime: {"$ref": "#/$defs/inherit"}
|
|
"""
|
|
)
|
|
|
|
for key, value in schema["properties"].items():
|
|
value["title"] = f"CIBW_{key.replace('-', '_').upper()}"
|
|
|
|
non_global_options = {k: {"$ref": f"#/properties/{k}"} for k in schema["properties"]}
|
|
del non_global_options["build"]
|
|
del non_global_options["skip"]
|
|
del non_global_options["test-skip"]
|
|
del non_global_options["enable"]
|
|
|
|
overrides["items"]["properties"]["select"]["oneOf"] = string_array
|
|
overrides["items"]["properties"] |= non_global_options.copy()
|
|
|
|
del overrides["items"]["properties"]["archs"]
|
|
|
|
not_linux = non_global_options.copy()
|
|
|
|
del not_linux["environment-pass"]
|
|
del not_linux["container-engine"]
|
|
for key in list(not_linux):
|
|
if "linux-" in key:
|
|
del not_linux[key]
|
|
|
|
|
|
def as_object(d: dict[str, Any]) -> dict[str, Any]:
|
|
return {
|
|
"type": "object",
|
|
"additionalProperties": False,
|
|
"properties": copy.deepcopy(d),
|
|
}
|
|
|
|
|
|
oses = {
|
|
"linux": as_object(non_global_options),
|
|
"windows": as_object(not_linux),
|
|
"macos": as_object(not_linux),
|
|
"pyodide": as_object(not_linux),
|
|
"android": as_object(not_linux),
|
|
"ios": as_object(not_linux),
|
|
}
|
|
|
|
for os_name, command in [
|
|
("linux", "auditwheel repair -w {dest_dir} {wheel}"),
|
|
("windows", "delvewheel repair -w {dest_dir} -v {wheel}"),
|
|
("macos", "delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel}"),
|
|
("android", "auditwheel repair --ldpaths {ldpaths} -w {dest_dir} {wheel}"),
|
|
]:
|
|
oses[os_name]["properties"]["repair-wheel-command"] = {
|
|
**schema["properties"]["repair-wheel-command"],
|
|
"default": command,
|
|
}
|
|
|
|
del oses["linux"]["properties"]["dependency-versions"]
|
|
|
|
|
|
schema["$defs"]["build-frontend-no-pyodide"] = build_frontend_schema(
|
|
FRONTENDS,
|
|
'Set the tool to use to build, either "build" (default), "build[uv]", "uv", or "pip"',
|
|
)
|
|
|
|
for os_val in oses.values():
|
|
os_val["properties"]["build-frontend"] = {"$ref": "#/$defs/build-frontend-no-pyodide"}
|
|
|
|
oses["pyodide"]["properties"]["build-frontend"] = build_frontend_schema(
|
|
["pyodide-build"],
|
|
'On the pyodide platform, the build frontend must be "pyodide-build"',
|
|
default="pyodide-build",
|
|
)
|
|
|
|
schema["properties"]["overrides"] = overrides
|
|
schema["properties"] |= oses
|
|
|
|
if args.schemastore:
|
|
schema["$id"] = "https://json.schemastore.org/partial-cibuildwheel.json"
|
|
schema["description"] = (
|
|
"cibuildwheel's settings. Generated with ./bin/generate_schema.py --schemastore from cibuildwheel."
|
|
)
|
|
|
|
print(json.dumps(schema, indent=2))
|