refactor: Override options redesign

* Add test for defaults, fix platform detection

* Improve correctness of reader.identifier with block

* Fix options test to be multiplatform

* 'Refactored by Sourcery'

docs: write a section on overrides

tests: test docker launches

feat: add identifiers to launches

test: add test for correct build step generation

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
This commit is contained in:
Joe Rickerby
2021-10-16 21:39:55 -04:00
committed by Henry Schreiner
parent cd07697fe5
commit 08a694485d
20 changed files with 1205 additions and 799 deletions
+39 -43
View File
@@ -2,8 +2,7 @@ import argparse
import os
import sys
import textwrap
from pathlib import Path
from typing import List, Set, Union
from typing import List, Optional, Set, Union
import cibuildwheel
import cibuildwheel.linux
@@ -11,17 +10,12 @@ import cibuildwheel.macos
import cibuildwheel.util
import cibuildwheel.windows
from cibuildwheel.architecture import Architecture, allowed_architectures_check
from cibuildwheel.options import compute_options
from cibuildwheel.options import CommandLineArguments, Options, compute_options
from cibuildwheel.typing import PLATFORMS, PlatformName, assert_never
from cibuildwheel.util import (
AllBuildOptions,
BuildSelector,
Unbuffered,
detect_ci_provider,
)
from cibuildwheel.util import BuildSelector, Unbuffered, detect_ci_provider
def main() -> None:
def main(sys_args: Optional[List[str]] = None) -> None:
platform: PlatformName
parser = argparse.ArgumentParser(
@@ -104,7 +98,7 @@ def main() -> None:
help="Enable pre-release Python versions if available.",
)
args = parser.parse_args()
args = parser.parse_args(args=sys_args, namespace=CommandLineArguments())
if args.platform != "auto":
platform = args.platform
@@ -141,19 +135,21 @@ def main() -> None:
print(f"cibuildwheel: Unsupported platform: {platform}", file=sys.stderr)
sys.exit(2)
package_dir = Path(args.package_dir)
output_dir = Path(
args.output_dir
if args.output_dir is not None
else os.environ.get("CIBW_OUTPUT_DIR", "wheelhouse")
)
options = compute_options(platform=platform, command_line_arguments=args)
all_build_options, build_options_by_selector = compute_options(
platform, package_dir, output_dir, args.config_file, args.archs, args.prerelease_pythons
)
package_dir = options.globals.package_dir
package_files = {"setup.py", "setup.cfg", "pyproject.toml"}
if not any(package_dir.joinpath(name).exists() for name in package_files):
names = ", ".join(sorted(package_files, reverse=True))
msg = f"cibuildwheel: Could not find any of {{{names}}} at root of package"
print(msg, file=sys.stderr)
sys.exit(2)
identifiers = get_build_identifiers(
platform, all_build_options.build_selector, all_build_options.architectures
platform=platform,
build_selector=options.globals.build_selector,
architectures=options.globals.architectures,
)
if args.print_build_identifiers:
@@ -161,8 +157,6 @@ def main() -> None:
print(identifier)
sys.exit(0)
build_options = AllBuildOptions(all_build_options, build_options_by_selector, identifiers)
# Add CIBUILDWHEEL environment variable
# This needs to be passed on to the docker container in linux.py
os.environ["CIBUILDWHEEL"] = "1"
@@ -170,22 +164,25 @@ def main() -> None:
# Python is buffering by default when running on the CI platforms, giving problems interleaving subprocess call output with unflushed calls to 'print'
sys.stdout = Unbuffered(sys.stdout) # type: ignore[no-untyped-call,assignment]
print_preamble(platform, build_options)
print_preamble(platform=platform, options=options, identifiers=identifiers)
try:
allowed_architectures_check(platform, build_options.architectures)
options.check_for_invalid_configuration(identifiers)
allowed_architectures_check(platform, options.globals.architectures)
except ValueError as err:
print("cibuildwheel:", *err.args, file=sys.stderr)
sys.exit(4)
if not identifiers:
print(
f"cibuildwheel: No build identifiers selected: {build_options.build_selector}",
f"cibuildwheel: No build identifiers selected: {options.globals.build_selector}",
file=sys.stderr,
)
if not args.allow_empty:
sys.exit(3)
output_dir = options.globals.output_dir
if not output_dir.exists():
output_dir.mkdir(parents=True)
@@ -193,16 +190,16 @@ def main() -> None:
"\n{n} wheels produced in {m:.0f} minutes:", output_dir
):
if platform == "linux":
cibuildwheel.linux.build(build_options)
cibuildwheel.linux.build(options)
elif platform == "windows":
cibuildwheel.windows.build(build_options)
cibuildwheel.windows.build(options)
elif platform == "macos":
cibuildwheel.macos.build(build_options)
cibuildwheel.macos.build(options)
else:
assert_never(platform)
def print_preamble(platform: str, build_options: AllBuildOptions) -> None:
def print_preamble(platform: str, options: Options, identifiers: List[str]) -> None:
print(
textwrap.dedent(
"""
@@ -218,9 +215,9 @@ def print_preamble(platform: str, build_options: AllBuildOptions) -> None:
print("Build options:")
print(f" platform: {platform!r}")
print(textwrap.indent(str(build_options), " "))
print(textwrap.indent(options.summary(identifiers), " "))
warnings = detect_warnings(platform, build_options)
warnings = detect_warnings(platform=platform, options=options, identifiers=identifiers)
if warnings:
print("\nWarnings:")
for warning in warnings:
@@ -256,21 +253,20 @@ def get_build_identifiers(
return [config.identifier for config in python_configurations]
def detect_warnings(platform: str, all_options: AllBuildOptions) -> List[str]:
def detect_warnings(platform: str, options: Options, identifiers: List[str]) -> List[str]:
warnings = []
# warn about deprecated {python} and {pip}
for build_options in all_options.values():
for option_name in ["test_command", "before_build"]:
option_value = getattr(build_options, option_name)
for option_name in ["test_command", "before_build"]:
option_values = [getattr(options.build_options(i), option_name) for i in identifiers]
if option_value and ("{python}" in option_value or "{pip}" in option_value):
# Reminder: in an f-string, double braces means literal single brace
msg = (
f"{option_name}: '{{python}}' and '{{pip}}' are no longer needed, "
"and will be removed in a future release. Simply use 'python' or 'pip' instead."
)
warnings.append(msg)
if any(o and ("{python}" in o or "{pip}" in o) for o in option_values):
# Reminder: in an f-string, double braces means literal single brace
msg = (
f"{option_name}: '{{python}}' and '{{pip}}' are no longer needed, "
"and will be removed in a future release. Simply use 'python' or 'pip' instead."
)
warnings.append(msg)
return warnings