diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e8a668c5..fee90128 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,9 +35,10 @@ repos: hooks: - id: mypy name: mypy 3.8 on cibuildwheel/ - exclude: ^cibuildwheel/resources/.*py$ + exclude: ^cibuildwheel/resources/.*py|bin/generate_schema.py$ args: ["--python-version=3.8"] additional_dependencies: &mypy-dependencies + - bracex - nox - packaging - pygithub @@ -49,7 +50,7 @@ repos: - types-jinja2 - types-pyyaml - types-requests - - bracex + - validate-pyproject - id: mypy name: mypy 3.11 exclude: ^cibuildwheel/resources/.*py$ diff --git a/bin/generate_schema.py b/bin/generate_schema.py new file mode 100755 index 00000000..64245c01 --- /dev/null +++ b/bin/generate_schema.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python + +import copy +import json +from typing import Any + +import yaml + +starter = """ +$id: https://github.com/pypa/cibuildwheel/blob/main/cibuildwheel/resources/cibuildwheel.schema.json +$schema: http://json-schema.org/draft-07/schema +additionalProperties: false +description: cibuildwheel's settings. +type: object +properties: + 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: + default: default + description: Set the tool to use to build, either "pip" (default for now) or "build" + oneOf: + - enum: [pip, build, default] + - type: string + pattern: '^pip; ?args:' + - type: string + pattern: '^build; ?args:' + - type: object + additionalProperties: false + required: [name] + properties: + name: + enum: [pip, build] + args: + type: array + items: + type: string + 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:' + - type: string + pattern: '^podman; ?create_args:' + - type: object + additionalProperties: false + required: [name] + properties: + name: + enum: [docker, podman] + create-args: + type: array + items: + type: string + dependency-versions: + default: pinned + description: Specify how cibuildwheel controls the versions of the tools it uses + type: string + 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-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-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-i686-image: + type: string + description: Specify alternative manylinux / musllinux container images + musllinux-ppc64le-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 + repair-wheel-command: + type: string_array + description: Execute a shell command to repair each built wheel. + 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-requires: + description: Install Python dependencies before running the tests + type: string_array + test-skip: + description: Skip running tests on some builds. + type: string_array +""" + +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 +""" +) + +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 + +overrides = yaml.safe_load( + """ +type: array +description: An overrides array +items: + type: object + required: ["select"] + additionalProperties: false + properties: + select: {} +""" +) + +non_global_options = copy.deepcopy(schema["properties"]) +del non_global_options["build"] +del non_global_options["skip"] +del non_global_options["container-engine"] +del non_global_options["test-skip"] + +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"] +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), +} + +oses["linux"]["properties"]["repair-wheel-command"][ + "default" +] = "auditwheel repair -w {dest_dir} {wheel}" +oses["macos"]["properties"]["repair-wheel-command"][ + "default" +] = "delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel}" + +del oses["linux"]["properties"]["dependency-versions"] + +schema["properties"]["overrides"] = overrides +schema["properties"] |= oses + +for key, value in schema["properties"].items(): + value["title"] = f'CIBW_{key.replace("-", "_").upper()}' +for key, value in schema["properties"]["linux"]["properties"].items(): + value["title"] = f'CIBW_{key.replace("-", "_").upper()}_LINUX' +for key, value in schema["properties"]["macos"]["properties"].items(): + value["title"] = f'CIBW_{key.replace("-", "_").upper()}_MACOS' +for key, value in schema["properties"]["windows"]["properties"].items(): + value["title"] = f'CIBW_{key.replace("-", "_").upper()}_WINDOWS' + +print(json.dumps(schema, indent=2)) diff --git a/cibuildwheel/_compat/tomllib.py b/cibuildwheel/_compat/tomllib.py index 62d601c6..b061ba91 100644 --- a/cibuildwheel/_compat/tomllib.py +++ b/cibuildwheel/_compat/tomllib.py @@ -3,8 +3,8 @@ from __future__ import annotations import sys if sys.version_info >= (3, 11): - from tomllib import load + from tomllib import load, loads else: - from tomli import load + from tomli import load, loads -__all__ = ("load",) +__all__ = ["load", "loads"] diff --git a/cibuildwheel/resources/cibuildwheel.schema.json b/cibuildwheel/resources/cibuildwheel.schema.json new file mode 100644 index 00000000..5930b497 --- /dev/null +++ b/cibuildwheel/resources/cibuildwheel.schema.json @@ -0,0 +1,1465 @@ +{ + "$id": "https://github.com/pypa/cibuildwheel/blob/main/cibuildwheel/resources/cibuildwheel.schema.json", + "$schema": "http://json-schema.org/draft-07/schema", + "additionalProperties": false, + "description": "cibuildwheel's settings.", + "type": "object", + "properties": { + "archs": { + "description": "Change the architectures built on your machine by default.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_ARCHS" + }, + "before-all": { + "description": "Execute a shell command on the build system before any wheels are built.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_BEFORE_ALL" + }, + "before-build": { + "description": "Execute a shell command preparing each wheel's build.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_BEFORE_BUILD" + }, + "before-test": { + "description": "Execute a shell command before testing each wheel.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_BEFORE_TEST" + }, + "build": { + "default": [ + "*" + ], + "description": "Choose the Python versions to build.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_BUILD" + }, + "build-frontend": { + "default": "default", + "description": "Set the tool to use to build, either \"pip\" (default for now) or \"build\"", + "oneOf": [ + { + "enum": [ + "pip", + "build", + "default" + ] + }, + { + "type": "string", + "pattern": "^pip; ?args:" + }, + { + "type": "string", + "pattern": "^build; ?args:" + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "name" + ], + "properties": { + "name": { + "enum": [ + "pip", + "build" + ] + }, + "args": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + ], + "title": "CIBW_BUILD_FRONTEND" + }, + "build-verbosity": { + "type": "integer", + "minimum": -3, + "maximum": 3, + "default": 0, + "description": "Increase/decrease the output of pip wheel.", + "title": "CIBW_BUILD_VERBOSITY" + }, + "config-settings": { + "description": "Specify config-settings for the build backend.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".+": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + } + } + ], + "title": "CIBW_CONFIG_SETTINGS" + }, + "container-engine": { + "oneOf": [ + { + "enum": [ + "docker", + "podman" + ] + }, + { + "type": "string", + "pattern": "^docker; ?create_args:" + }, + { + "type": "string", + "pattern": "^podman; ?create_args:" + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "name" + ], + "properties": { + "name": { + "enum": [ + "docker", + "podman" + ] + }, + "create-args": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + ], + "title": "CIBW_CONTAINER_ENGINE" + }, + "dependency-versions": { + "default": "pinned", + "description": "Specify how cibuildwheel controls the versions of the tools it uses", + "type": "string", + "title": "CIBW_DEPENDENCY_VERSIONS" + }, + "environment": { + "description": "Set environment variables needed during the build.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".+": [ + { + "type": "string" + } + ] + } + } + ], + "title": "CIBW_ENVIRONMENT" + }, + "environment-pass": { + "description": "Set environment variables on the host to pass-through to the container during the build.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_ENVIRONMENT_PASS" + }, + "manylinux-aarch64-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_AARCH64_IMAGE" + }, + "manylinux-i686-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_I686_IMAGE" + }, + "manylinux-ppc64le-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_PPC64LE_IMAGE" + }, + "manylinux-pypy_aarch64-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_PYPY_AARCH64_IMAGE" + }, + "manylinux-pypy_i686-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_PYPY_I686_IMAGE" + }, + "manylinux-pypy_x86_64-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_PYPY_X86_64_IMAGE" + }, + "manylinux-s390x-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_S390X_IMAGE" + }, + "manylinux-x86_64-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_X86_64_IMAGE" + }, + "musllinux-aarch64-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MUSLLINUX_AARCH64_IMAGE" + }, + "musllinux-i686-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MUSLLINUX_I686_IMAGE" + }, + "musllinux-ppc64le-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MUSLLINUX_PPC64LE_IMAGE" + }, + "musllinux-s390x-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MUSLLINUX_S390X_IMAGE" + }, + "musllinux-x86_64-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MUSLLINUX_X86_64_IMAGE" + }, + "repair-wheel-command": { + "description": "Execute a shell command to repair each built wheel.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_REPAIR_WHEEL_COMMAND" + }, + "skip": { + "description": "Choose the Python versions to skip.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_SKIP" + }, + "test-command": { + "description": "Execute a shell command to test each built wheel.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_TEST_COMMAND" + }, + "test-extras": { + "description": "Install your wheel for testing using `extras_require`", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_TEST_EXTRAS" + }, + "test-requires": { + "description": "Install Python dependencies before running the tests", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_TEST_REQUIRES" + }, + "test-skip": { + "description": "Skip running tests on some builds.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_TEST_SKIP" + }, + "overrides": { + "type": "array", + "description": "An overrides array", + "items": { + "type": "object", + "required": [ + "select" + ], + "additionalProperties": false, + "properties": { + "select": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "before-all": { + "description": "Execute a shell command on the build system before any wheels are built.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "before-build": { + "description": "Execute a shell command preparing each wheel's build.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "before-test": { + "description": "Execute a shell command before testing each wheel.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "build-frontend": { + "default": "default", + "description": "Set the tool to use to build, either \"pip\" (default for now) or \"build\"", + "oneOf": [ + { + "enum": [ + "pip", + "build", + "default" + ] + }, + { + "type": "string", + "pattern": "^pip; ?args:" + }, + { + "type": "string", + "pattern": "^build; ?args:" + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "name" + ], + "properties": { + "name": { + "enum": [ + "pip", + "build" + ] + }, + "args": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + ] + }, + "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.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".+": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + } + } + ] + }, + "dependency-versions": { + "default": "pinned", + "description": "Specify how cibuildwheel controls the versions of the tools it uses", + "type": "string" + }, + "environment": { + "description": "Set environment variables needed during the build.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".+": [ + { + "type": "string" + } + ] + } + } + ] + }, + "environment-pass": { + "description": "Set environment variables on the host to pass-through to the container during the build.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "manylinux-aarch64-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-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-i686-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images" + }, + "musllinux-ppc64le-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" + }, + "repair-wheel-command": { + "description": "Execute a shell command to repair each built wheel.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "test-command": { + "description": "Execute a shell command to test each built wheel.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "test-extras": { + "description": "Install your wheel for testing using `extras_require`", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "test-requires": { + "description": "Install Python dependencies before running the tests", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + } + }, + "title": "CIBW_OVERRIDES" + }, + "linux": { + "type": "object", + "additionalProperties": false, + "properties": { + "archs": { + "description": "Change the architectures built on your machine by default.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_ARCHS_LINUX" + }, + "before-all": { + "description": "Execute a shell command on the build system before any wheels are built.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_BEFORE_ALL_LINUX" + }, + "before-build": { + "description": "Execute a shell command preparing each wheel's build.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_BEFORE_BUILD_LINUX" + }, + "before-test": { + "description": "Execute a shell command before testing each wheel.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_BEFORE_TEST_LINUX" + }, + "build-frontend": { + "default": "default", + "description": "Set the tool to use to build, either \"pip\" (default for now) or \"build\"", + "oneOf": [ + { + "enum": [ + "pip", + "build", + "default" + ] + }, + { + "type": "string", + "pattern": "^pip; ?args:" + }, + { + "type": "string", + "pattern": "^build; ?args:" + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "name" + ], + "properties": { + "name": { + "enum": [ + "pip", + "build" + ] + }, + "args": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + ], + "title": "CIBW_BUILD_FRONTEND_LINUX" + }, + "build-verbosity": { + "type": "integer", + "minimum": -3, + "maximum": 3, + "default": 0, + "description": "Increase/decrease the output of pip wheel.", + "title": "CIBW_BUILD_VERBOSITY_LINUX" + }, + "config-settings": { + "description": "Specify config-settings for the build backend.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".+": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + } + } + ], + "title": "CIBW_CONFIG_SETTINGS_LINUX" + }, + "environment": { + "description": "Set environment variables needed during the build.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".+": [ + { + "type": "string" + } + ] + } + } + ], + "title": "CIBW_ENVIRONMENT_LINUX" + }, + "environment-pass": { + "description": "Set environment variables on the host to pass-through to the container during the build.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_ENVIRONMENT_PASS_LINUX" + }, + "manylinux-aarch64-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_AARCH64_IMAGE_LINUX" + }, + "manylinux-i686-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_I686_IMAGE_LINUX" + }, + "manylinux-ppc64le-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_PPC64LE_IMAGE_LINUX" + }, + "manylinux-pypy_aarch64-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_PYPY_AARCH64_IMAGE_LINUX" + }, + "manylinux-pypy_i686-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_PYPY_I686_IMAGE_LINUX" + }, + "manylinux-pypy_x86_64-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_PYPY_X86_64_IMAGE_LINUX" + }, + "manylinux-s390x-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_S390X_IMAGE_LINUX" + }, + "manylinux-x86_64-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_X86_64_IMAGE_LINUX" + }, + "musllinux-aarch64-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MUSLLINUX_AARCH64_IMAGE_LINUX" + }, + "musllinux-i686-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MUSLLINUX_I686_IMAGE_LINUX" + }, + "musllinux-ppc64le-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MUSLLINUX_PPC64LE_IMAGE_LINUX" + }, + "musllinux-s390x-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MUSLLINUX_S390X_IMAGE_LINUX" + }, + "musllinux-x86_64-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MUSLLINUX_X86_64_IMAGE_LINUX" + }, + "repair-wheel-command": { + "description": "Execute a shell command to repair each built wheel.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "default": "auditwheel repair -w {dest_dir} {wheel}", + "title": "CIBW_REPAIR_WHEEL_COMMAND_LINUX" + }, + "test-command": { + "description": "Execute a shell command to test each built wheel.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_TEST_COMMAND_LINUX" + }, + "test-extras": { + "description": "Install your wheel for testing using `extras_require`", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_TEST_EXTRAS_LINUX" + }, + "test-requires": { + "description": "Install Python dependencies before running the tests", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_TEST_REQUIRES_LINUX" + } + }, + "title": "CIBW_LINUX" + }, + "windows": { + "type": "object", + "additionalProperties": false, + "properties": { + "archs": { + "description": "Change the architectures built on your machine by default.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_ARCHS_WINDOWS" + }, + "before-all": { + "description": "Execute a shell command on the build system before any wheels are built.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_BEFORE_ALL_WINDOWS" + }, + "before-build": { + "description": "Execute a shell command preparing each wheel's build.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_BEFORE_BUILD_WINDOWS" + }, + "before-test": { + "description": "Execute a shell command before testing each wheel.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_BEFORE_TEST_WINDOWS" + }, + "build-frontend": { + "default": "default", + "description": "Set the tool to use to build, either \"pip\" (default for now) or \"build\"", + "oneOf": [ + { + "enum": [ + "pip", + "build", + "default" + ] + }, + { + "type": "string", + "pattern": "^pip; ?args:" + }, + { + "type": "string", + "pattern": "^build; ?args:" + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "name" + ], + "properties": { + "name": { + "enum": [ + "pip", + "build" + ] + }, + "args": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + ], + "title": "CIBW_BUILD_FRONTEND_WINDOWS" + }, + "build-verbosity": { + "type": "integer", + "minimum": -3, + "maximum": 3, + "default": 0, + "description": "Increase/decrease the output of pip wheel.", + "title": "CIBW_BUILD_VERBOSITY_WINDOWS" + }, + "config-settings": { + "description": "Specify config-settings for the build backend.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".+": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + } + } + ], + "title": "CIBW_CONFIG_SETTINGS_WINDOWS" + }, + "dependency-versions": { + "default": "pinned", + "description": "Specify how cibuildwheel controls the versions of the tools it uses", + "type": "string", + "title": "CIBW_DEPENDENCY_VERSIONS_WINDOWS" + }, + "environment": { + "description": "Set environment variables needed during the build.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".+": [ + { + "type": "string" + } + ] + } + } + ], + "title": "CIBW_ENVIRONMENT_WINDOWS" + }, + "repair-wheel-command": { + "description": "Execute a shell command to repair each built wheel.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_REPAIR_WHEEL_COMMAND_WINDOWS" + }, + "test-command": { + "description": "Execute a shell command to test each built wheel.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_TEST_COMMAND_WINDOWS" + }, + "test-extras": { + "description": "Install your wheel for testing using `extras_require`", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_TEST_EXTRAS_WINDOWS" + }, + "test-requires": { + "description": "Install Python dependencies before running the tests", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_TEST_REQUIRES_WINDOWS" + } + }, + "title": "CIBW_WINDOWS" + }, + "macos": { + "type": "object", + "additionalProperties": false, + "properties": { + "archs": { + "description": "Change the architectures built on your machine by default.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_ARCHS_MACOS" + }, + "before-all": { + "description": "Execute a shell command on the build system before any wheels are built.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_BEFORE_ALL_MACOS" + }, + "before-build": { + "description": "Execute a shell command preparing each wheel's build.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_BEFORE_BUILD_MACOS" + }, + "before-test": { + "description": "Execute a shell command before testing each wheel.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_BEFORE_TEST_MACOS" + }, + "build-frontend": { + "default": "default", + "description": "Set the tool to use to build, either \"pip\" (default for now) or \"build\"", + "oneOf": [ + { + "enum": [ + "pip", + "build", + "default" + ] + }, + { + "type": "string", + "pattern": "^pip; ?args:" + }, + { + "type": "string", + "pattern": "^build; ?args:" + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "name" + ], + "properties": { + "name": { + "enum": [ + "pip", + "build" + ] + }, + "args": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + ], + "title": "CIBW_BUILD_FRONTEND_MACOS" + }, + "build-verbosity": { + "type": "integer", + "minimum": -3, + "maximum": 3, + "default": 0, + "description": "Increase/decrease the output of pip wheel.", + "title": "CIBW_BUILD_VERBOSITY_MACOS" + }, + "config-settings": { + "description": "Specify config-settings for the build backend.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".+": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + } + } + ], + "title": "CIBW_CONFIG_SETTINGS_MACOS" + }, + "dependency-versions": { + "default": "pinned", + "description": "Specify how cibuildwheel controls the versions of the tools it uses", + "type": "string", + "title": "CIBW_DEPENDENCY_VERSIONS_MACOS" + }, + "environment": { + "description": "Set environment variables needed during the build.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".+": [ + { + "type": "string" + } + ] + } + } + ], + "title": "CIBW_ENVIRONMENT_MACOS" + }, + "repair-wheel-command": { + "description": "Execute a shell command to repair each built wheel.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "default": "delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel}", + "title": "CIBW_REPAIR_WHEEL_COMMAND_MACOS" + }, + "test-command": { + "description": "Execute a shell command to test each built wheel.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_TEST_COMMAND_MACOS" + }, + "test-extras": { + "description": "Install your wheel for testing using `extras_require`", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_TEST_EXTRAS_MACOS" + }, + "test-requires": { + "description": "Install Python dependencies before running the tests", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "title": "CIBW_TEST_REQUIRES_MACOS" + } + }, + "title": "CIBW_MACOS" + } + } +} diff --git a/cibuildwheel/resources/defaults.toml b/cibuildwheel/resources/defaults.toml index 40b42f6e..cf748c62 100644 --- a/cibuildwheel/resources/defaults.toml +++ b/cibuildwheel/resources/defaults.toml @@ -9,7 +9,7 @@ config-settings = {} dependency-versions = "pinned" environment = {} environment-pass = [] -build-verbosity = "" +build-verbosity = 0 before-all = "" before-build = "" diff --git a/cibuildwheel/schema.py b/cibuildwheel/schema.py new file mode 100644 index 00000000..91ca2659 --- /dev/null +++ b/cibuildwheel/schema.py @@ -0,0 +1,15 @@ +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any + +DIR = Path(__file__).parent.resolve() + + +def get_schema(tool_name: str = "cibuildwheel") -> dict[str, Any]: + "Get the stored complete schema for cibuildwheel settings." + assert tool_name == "cibuildwheel", "Only cibuildwheel is supported." + + with DIR.joinpath("resources/cibuildwheel.schema.json").open(encoding="utf-8") as f: + return json.load(f) # type: ignore[no-any-return] diff --git a/docs/options.md b/docs/options.md index 078c907d..d42d8256 100644 --- a/docs/options.md +++ b/docs/options.md @@ -917,9 +917,7 @@ Platform-specific environment variables are also available:
CIBW_REPAIR_WHEEL_COMMAND: > python scripts/repair_wheel.py -w {dest_dir} {wheel} && python scripts/check_repaired_wheel.py -w {dest_dir} {wheel} - ``` - ```yaml # Use abi3audit to catch issues with Limited API wheels CIBW_REPAIR_WHEEL_COMMAND_LINUX: > auditwheel repair -w {dest_dir} {wheel} && @@ -953,9 +951,7 @@ Platform-specific environment variables are also available:
'python scripts/repair_wheel.py -w {dest_dir} {wheel}', 'python scripts/check_repaired_wheel.py -w {dest_dir} {wheel}', ] - ``` - ```toml # Use abi3audit to catch issues with Limited API wheels [tool.cibuildwheel.linux] repair-wheel-command = [ diff --git a/noxfile.py b/noxfile.py index 0e66647c..397d6e72 100644 --- a/noxfile.py +++ b/noxfile.py @@ -113,6 +113,14 @@ def update_proj(session: nox.Session) -> None: ) +@nox.session(reuse_venv=True) +def generate_schema(session: nox.Session) -> None: + session.install("pyyaml") + output = session.run("python", "bin/generate_schema.py", silent=True) + assert isinstance(output, str) + DIR.joinpath("cibuildwheel/resources/cibuildwheel.schema.json").write_text(output) + + @nox.session(python="3.9") def docs(session: nox.Session) -> None: """ diff --git a/setup.cfg b/setup.cfg index fb0136a9..12521e9c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -49,6 +49,8 @@ include = [options.entry_points] console_scripts = cibuildwheel = cibuildwheel.__main__:main +validate_pyproject.tool_schema = + cibuildwheel = cibuildwheel.schema:get_schema [options.package_data] cibuildwheel = resources/* diff --git a/setup.py b/setup.py index 1ce3a00d..90f83fed 100644 --- a/setup.py +++ b/setup.py @@ -17,6 +17,7 @@ extras = { "pytest-xdist", "build", "tomli_w", + "validate-pyproject", ], "bin": [ "click", diff --git a/unit_test/validate_schema_test.py b/unit_test/validate_schema_test.py new file mode 100644 index 00000000..74204934 --- /dev/null +++ b/unit_test/validate_schema_test.py @@ -0,0 +1,103 @@ +from __future__ import annotations + +import re +from pathlib import Path + +import pytest +import validate_pyproject.api + +from cibuildwheel._compat import tomllib + +DIR = Path(__file__).parent.resolve() + + +def test_validate_default_schema(): + filepath = DIR.parent / "cibuildwheel/resources/defaults.toml" + with filepath.open("rb") as f: + example = tomllib.load(f) + + validator = validate_pyproject.api.Validator() + assert validator(example) is not None + + +def test_validate_bad_container_engine(): + example = tomllib.loads( + """ + [tool.cibuildwheel.linux] + container-engine = "docker" + """ + ) + + validator = validate_pyproject.api.Validator() + with pytest.raises(validate_pyproject.error_reporting.ValidationError): + validator(example) + + +def test_overrides_select(): + example = tomllib.loads( + """ + [[tool.cibuildwheel.overrides]] + select = "somestring" + repair-wheel-command = "something" + """ + ) + + validator = validate_pyproject.api.Validator() + assert validator(example) is not None + + +def test_overrides_no_select(): + example = tomllib.loads( + """ + [[tool.cibuildwheel.overrides]] + repair-wheel-command = "something" + """ + ) + + validator = validate_pyproject.api.Validator() + with pytest.raises(validate_pyproject.error_reporting.ValidationError): + validator(example) + + +def test_docs_examples(): + """ + Parse out all the configuration examples, build valid TOML out of them, and + make sure they pass. + """ + + expr = re.compile( + r""" +!!! tab examples "pyproject.toml" +\s* +\s*```toml +(.*?)```""", + re.MULTILINE | re.DOTALL, + ) + + txt = DIR.parent.joinpath("docs/options.md").read_text() + + blocks: list[str] = [] + for match in expr.finditer(txt): + lines = (line.strip() for line in match.group(1).strip().splitlines() if line.strip()) + block: list[str] = [] + header = "" + for line in lines: + if line.startswith(("[tool.cibuildwheel", "[[tool.cibuildwheel")): + header = line + elif line.startswith("#"): + if block: + blocks.append("\n".join([header, *block])) + block = [] + elif " = " in line and any(x.startswith(line.partition(" = ")[0]) for x in block): + blocks.append("\n".join([header, *block])) + block = [line] + else: + block.append(line) + blocks.append("\n".join([header, *block])) + + for example_txt in blocks: + print(example_txt) + print() + example = tomllib.loads(example_txt) + validator = validate_pyproject.api.Validator() + assert validator(example) is not None