feat: add --only (#1098)
* fix(style): use sub recommended replacement method See https://docs.python.org/3/library/re.html#re.escape Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> * feat: add --build * refactor: switch to using --only Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> * docs: cover --only Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> * docs: undo change to --plat for auditwheel Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> * (unrelated) speed up running the unit tests based on a profile run, this speeds up the unit tests by 3x * Remove `intercepted_build_args` reliance on `platform` fixture * Add test that checks if 'only' overrides env var options * Ensure that the --only command line option overrides env vars * Fix UnboundLocalError * Test cleanups * style: typing.cast instead of plain cast * feat: add only: to the GHA Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> Co-authored-by: Joe Rickerby <joerick@mac.com>
This commit is contained in:
co-authored by
Joe Rickerby
parent
3a46bde3fb
commit
eb39da0b10
@@ -6,6 +6,7 @@ import shutil
|
||||
import sys
|
||||
import tarfile
|
||||
import textwrap
|
||||
import typing
|
||||
from pathlib import Path
|
||||
from tempfile import mkdtemp
|
||||
|
||||
@@ -40,7 +41,7 @@ def main() -> None:
|
||||
parser.add_argument(
|
||||
"--platform",
|
||||
choices=["auto", "linux", "macos", "windows"],
|
||||
default=os.environ.get("CIBW_PLATFORM", "auto"),
|
||||
default=None,
|
||||
help="""
|
||||
Platform to build for. Use this option to override the
|
||||
auto-detected platform or to run cibuildwheel on your development
|
||||
@@ -64,6 +65,16 @@ def main() -> None:
|
||||
""",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--only",
|
||||
default=None,
|
||||
help="""
|
||||
Force a single wheel build when given an identifier. Overrides
|
||||
CIBW_BUILD/CIBW_SKIP. --platform and --arch cannot be specified
|
||||
if this is given.
|
||||
""",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--output-dir",
|
||||
type=Path,
|
||||
@@ -154,10 +165,40 @@ def main() -> None:
|
||||
|
||||
|
||||
def build_in_directory(args: CommandLineArguments) -> None:
|
||||
platform_option_value = args.platform or os.environ.get("CIBW_PLATFORM", "auto")
|
||||
platform: PlatformName
|
||||
|
||||
if args.platform != "auto":
|
||||
platform = args.platform
|
||||
if args.only:
|
||||
if "linux_" in args.only:
|
||||
platform = "linux"
|
||||
elif "macosx_" in args.only:
|
||||
platform = "macos"
|
||||
elif "win_" in args.only:
|
||||
platform = "windows"
|
||||
else:
|
||||
print(
|
||||
f"Invalid --only='{args.only}', must be a build selector with a known platform",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(2)
|
||||
if args.platform is not None:
|
||||
print(
|
||||
"--platform cannot be specified with --only, it is computed from --only",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(2)
|
||||
if args.archs is not None:
|
||||
print(
|
||||
"--arch cannot be specified with --only, it is computed from --only",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(2)
|
||||
elif platform_option_value != "auto":
|
||||
if platform_option_value not in PLATFORMS:
|
||||
print(f"cibuildwheel: Unsupported platform: {platform_option_value}", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
platform = typing.cast(PlatformName, platform_option_value)
|
||||
else:
|
||||
ci_provider = detect_ci_provider()
|
||||
if ci_provider is None:
|
||||
@@ -187,10 +228,6 @@ def build_in_directory(args: CommandLineArguments) -> None:
|
||||
)
|
||||
sys.exit(2)
|
||||
|
||||
if platform not in PLATFORMS:
|
||||
print(f"cibuildwheel: Unsupported platform: {platform}", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
options = compute_options(platform=platform, command_line_arguments=args)
|
||||
|
||||
package_dir = options.globals.package_dir
|
||||
|
||||
+15
-5
@@ -42,9 +42,10 @@ from .util import (
|
||||
|
||||
@dataclass
|
||||
class CommandLineArguments:
|
||||
platform: Literal["auto", "linux", "macos", "windows"]
|
||||
platform: Literal["auto", "linux", "macos", "windows"] | None
|
||||
archs: str | None
|
||||
output_dir: Path
|
||||
only: str | None
|
||||
config_file: str
|
||||
package_dir: Path
|
||||
print_build_identifiers: bool
|
||||
@@ -403,6 +404,15 @@ class Options:
|
||||
)
|
||||
requires_python = None if requires_python_str is None else SpecifierSet(requires_python_str)
|
||||
|
||||
archs_config_str = args.archs or self.reader.get("archs", sep=" ")
|
||||
architectures = Architecture.parse_config(archs_config_str, platform=self.platform)
|
||||
|
||||
# Process `--only`
|
||||
if args.only:
|
||||
build_config = args.only
|
||||
skip_config = ""
|
||||
architectures = Architecture.all_archs(self.platform)
|
||||
|
||||
build_selector = BuildSelector(
|
||||
build_config=build_config,
|
||||
skip_config=skip_config,
|
||||
@@ -411,9 +421,6 @@ class Options:
|
||||
)
|
||||
test_selector = TestSelector(skip_config=test_skip)
|
||||
|
||||
archs_config_str = args.archs or self.reader.get("archs", sep=" ")
|
||||
architectures = Architecture.parse_config(archs_config_str, platform=self.platform)
|
||||
|
||||
container_engine_str = self.reader.get("container-engine")
|
||||
|
||||
if container_engine_str not in ["docker", "podman"]:
|
||||
@@ -588,6 +595,9 @@ class Options:
|
||||
]
|
||||
|
||||
build_option_defaults = self.build_options(identifier=None)
|
||||
build_options_for_identifier = {
|
||||
identifier: self.build_options(identifier) for identifier in identifiers
|
||||
}
|
||||
|
||||
for option_name, default_value in sorted(asdict(build_option_defaults).items()):
|
||||
if option_name == "globals":
|
||||
@@ -597,7 +607,7 @@ class Options:
|
||||
|
||||
# if any identifiers have an overridden value, print that too
|
||||
for identifier in identifiers:
|
||||
option_value = getattr(self.build_options(identifier=identifier), option_name)
|
||||
option_value = getattr(build_options_for_identifier[identifier], option_name)
|
||||
if option_value != default_value:
|
||||
lines.append(f" {identifier}: {option_value!r}")
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ def shell(*commands: str, env: dict[str, str] | None = None, cwd: PathOrStr | No
|
||||
subprocess.run(command, env=env, cwd=cwd, shell=True, check=True)
|
||||
|
||||
|
||||
def format_safe(template: str, **kwargs: Any) -> str:
|
||||
def format_safe(template: str, **kwargs: str | os.PathLike[str]) -> str:
|
||||
"""
|
||||
Works similarly to `template.format(**kwargs)`, except that unmatched
|
||||
fields in `template` are passed through untouched.
|
||||
@@ -173,11 +173,9 @@ def format_safe(template: str, **kwargs: Any) -> str:
|
||||
re.VERBOSE,
|
||||
)
|
||||
|
||||
# we use a function for repl to prevent re.sub interpreting backslashes
|
||||
# in repl as escape sequences.
|
||||
result = re.sub(
|
||||
pattern=find_pattern,
|
||||
repl=lambda _: str(value), # pylint: disable=cell-var-from-loop
|
||||
repl=str(value).replace("\\", r"\\"),
|
||||
string=result,
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user