feat: adding overrides
This commit is contained in:
+70
-12
@@ -1,9 +1,10 @@
|
||||
import copy
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
from configparser import ConfigParser
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Mapping, Optional, Set, Tuple, Union
|
||||
from typing import Any, Dict, List, Mapping, Optional, Set, Tuple, TypeVar, Union
|
||||
|
||||
import tomli
|
||||
from packaging.specifiers import SpecifierSet
|
||||
@@ -58,6 +59,9 @@ def _dig_first(*pairs: Tuple[Mapping[str, Setting], str], ignore_empty: bool = F
|
||||
raise KeyError(key)
|
||||
|
||||
|
||||
T = TypeVar("T", bound="ConfigOptions")
|
||||
|
||||
|
||||
class ConfigOptions:
|
||||
"""
|
||||
Gets options from the environment, config or defaults, optionally scoped
|
||||
@@ -117,12 +121,27 @@ class ConfigOptions:
|
||||
self.config_options = config_options
|
||||
self.config_platform_options = config_platform_options
|
||||
|
||||
self.overrides: Dict[str, Dict[str, Any]] = {}
|
||||
self.current_override: str = "*"
|
||||
|
||||
overrides = self.config_options.get("overrides")
|
||||
if overrides is not None:
|
||||
if not isinstance(overrides, list):
|
||||
raise ConfigOptionError('"tool.cibuildwheel.overrides" must be a list')
|
||||
for override in overrides:
|
||||
selector = override.pop("select")
|
||||
if isinstance(selector, list):
|
||||
selector = " ".join(selector)
|
||||
if selector in {"", "*"}:
|
||||
raise ConfigOptionError("select all must not be used in an override")
|
||||
self.overrides[selector.strip()] = override
|
||||
|
||||
def _is_valid_global_option(self, name: str) -> bool:
|
||||
"""
|
||||
Returns True if an option with this name is allowed in the
|
||||
[tool.cibuildwheel] section of a config file.
|
||||
"""
|
||||
allowed_option_names = self.default_options.keys() | PLATFORMS
|
||||
allowed_option_names = self.default_options.keys() | PLATFORMS | {"overrides"}
|
||||
|
||||
return name in allowed_option_names
|
||||
|
||||
@@ -151,6 +170,14 @@ class ConfigOptions:
|
||||
|
||||
return global_options, platform_options
|
||||
|
||||
def override(self: T, selector: str) -> T:
|
||||
"""
|
||||
Start an override scope.
|
||||
"""
|
||||
other = copy.copy(self)
|
||||
other.current_override = selector
|
||||
return other
|
||||
|
||||
def __call__(
|
||||
self,
|
||||
name: str,
|
||||
@@ -179,9 +206,11 @@ class ConfigOptions:
|
||||
|
||||
# get the option from the environment, then the config file, then finally the default.
|
||||
# platform-specific options are preferred, if they're allowed.
|
||||
empty: Dict[str, Any] = {}
|
||||
result = _dig_first(
|
||||
(os.environ if env_plat else {}, plat_envvar), # type: ignore[arg-type]
|
||||
(os.environ, envvar),
|
||||
(self.overrides.get(self.current_override, empty), name),
|
||||
(self.config_platform_options, name),
|
||||
(self.config_options, name),
|
||||
(self.default_platform_options, name),
|
||||
@@ -210,7 +239,7 @@ def compute_options(
|
||||
config_file: Optional[str],
|
||||
args_archs: Optional[str],
|
||||
prerelease_pythons: bool,
|
||||
) -> BuildOptions:
|
||||
) -> Tuple[BuildOptions, Dict[str, BuildOptions]]:
|
||||
"""
|
||||
Compute the options from the environment and configuration file.
|
||||
"""
|
||||
@@ -263,11 +292,25 @@ def compute_options(
|
||||
)
|
||||
test_selector = TestSelector(skip_config=test_skip)
|
||||
|
||||
return _compute_single_options(
|
||||
return _compute_all_options(
|
||||
options, args_archs, build_selector, test_selector, platform, package_dir, output_dir
|
||||
)
|
||||
|
||||
|
||||
def _get_pinned_docker_images() -> Mapping[str, Mapping[str, str]]:
|
||||
"""
|
||||
This looks like a dict of dicts, e.g.
|
||||
{ 'x86_64': {'manylinux1': '...', 'manylinux2010': '...', 'manylinux2014': '...'},
|
||||
'i686': {'manylinux1': '...', 'manylinux2010': '...', 'manylinux2014': '...'},
|
||||
'pypy_x86_64': {'manylinux2010': '...' }
|
||||
... }
|
||||
"""
|
||||
pinned_docker_images_file = resources_dir / "pinned_docker_images.cfg"
|
||||
all_pinned_docker_images = ConfigParser()
|
||||
all_pinned_docker_images.read(pinned_docker_images_file)
|
||||
return all_pinned_docker_images
|
||||
|
||||
|
||||
def _compute_single_options(
|
||||
options: ConfigOptions,
|
||||
args_archs: Optional[str],
|
||||
@@ -337,14 +380,7 @@ def _compute_single_options(
|
||||
manylinux_images: Dict[str, str] = {}
|
||||
musllinux_images: Dict[str, str] = {}
|
||||
if platform == "linux":
|
||||
pinned_docker_images_file = resources_dir / "pinned_docker_images.cfg"
|
||||
all_pinned_docker_images = ConfigParser()
|
||||
all_pinned_docker_images.read(pinned_docker_images_file)
|
||||
# all_pinned_docker_images looks like a dict of dicts, e.g.
|
||||
# { 'x86_64': {'manylinux1': '...', 'manylinux2010': '...', 'manylinux2014': '...'},
|
||||
# 'i686': {'manylinux1': '...', 'manylinux2010': '...', 'manylinux2014': '...'},
|
||||
# 'pypy_x86_64': {'manylinux2010': '...' }
|
||||
# ... }
|
||||
all_pinned_docker_images = _get_pinned_docker_images()
|
||||
|
||||
for build_platform in MANYLINUX_ARCHS:
|
||||
pinned_images = all_pinned_docker_images[build_platform]
|
||||
@@ -359,6 +395,7 @@ def _compute_single_options(
|
||||
else:
|
||||
image = config_value
|
||||
|
||||
assert image is not None
|
||||
manylinux_images[build_platform] = image
|
||||
|
||||
for build_platform in MUSLLINUX_ARCHS:
|
||||
@@ -397,6 +434,27 @@ def _compute_single_options(
|
||||
)
|
||||
|
||||
|
||||
def _compute_all_options(
|
||||
options: ConfigOptions,
|
||||
args_archs: Optional[str],
|
||||
build_selector: BuildSelector,
|
||||
test_selector: TestSelector,
|
||||
platform: PlatformName,
|
||||
package_dir: Path,
|
||||
output_dir: Path,
|
||||
) -> Tuple[BuildOptions, Dict[str, BuildOptions]]:
|
||||
args = (args_archs, build_selector, test_selector, platform, package_dir, output_dir)
|
||||
|
||||
general_build_options = _compute_single_options(options, *args)
|
||||
|
||||
selectors = options.overrides.keys()
|
||||
build_options_by_selector = {
|
||||
s: _compute_single_options(options.override(s), *args) for s in selectors
|
||||
}
|
||||
|
||||
return general_build_options, build_options_by_selector
|
||||
|
||||
|
||||
def deprecated_selectors(name: str, selector: str, *, error: bool = False) -> None:
|
||||
if "p2" in selector or "p35" in selector:
|
||||
msg = f"cibuildwheel 2.x no longer supports Python < 3.6. Please use the 1.x series or update {name}"
|
||||
|
||||
Reference in New Issue
Block a user