feat: adding overrides
This commit is contained in:
+129
-2
@@ -1,4 +1,5 @@
|
||||
import contextlib
|
||||
import dataclasses
|
||||
import fnmatch
|
||||
import itertools
|
||||
import os
|
||||
@@ -9,10 +10,23 @@ import sys
|
||||
import textwrap
|
||||
import time
|
||||
import urllib.request
|
||||
from collections import defaultdict
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from time import sleep
|
||||
from typing import Dict, Iterator, List, NamedTuple, Optional, Set
|
||||
from typing import (
|
||||
Counter,
|
||||
Dict,
|
||||
Iterable,
|
||||
Iterator,
|
||||
List,
|
||||
Mapping,
|
||||
NamedTuple,
|
||||
Optional,
|
||||
Set,
|
||||
Tuple,
|
||||
TypeVar,
|
||||
)
|
||||
|
||||
import bracex
|
||||
import certifi
|
||||
@@ -22,7 +36,7 @@ from packaging.version import Version
|
||||
|
||||
from .architecture import Architecture
|
||||
from .environment import ParsedEnvironment
|
||||
from .typing import Literal, PathOrStr, PlatformName
|
||||
from .typing import Literal, PathOrStr, PlatformName, Protocol
|
||||
|
||||
resources_dir = Path(__file__).parent / "resources"
|
||||
|
||||
@@ -250,6 +264,119 @@ class BuildOptions(NamedTuple):
|
||||
return "\n".join(res)
|
||||
|
||||
|
||||
class SimpleConfig(Protocol):
|
||||
@property
|
||||
def identifier(self) -> str:
|
||||
...
|
||||
|
||||
|
||||
SC = TypeVar("SC", bound=SimpleConfig)
|
||||
T = TypeVar("T", bound="AllBuildOptions")
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class AllBuildOptions:
|
||||
general_build_options: BuildOptions
|
||||
build_options_by_selector: Dict[str, BuildOptions]
|
||||
identifiers: List[str]
|
||||
|
||||
def __getitem__(self, identifier: str) -> BuildOptions:
|
||||
for sel in self.build_options_by_selector:
|
||||
bs = BuildSelector(build_config=sel, skip_config="")
|
||||
if bs(identifier):
|
||||
return self.build_options_by_selector[sel]
|
||||
|
||||
return self.general_build_options
|
||||
|
||||
def values(self) -> Iterable[BuildOptions]:
|
||||
return itertools.chain(
|
||||
[self.general_build_options], self.build_options_by_selector.values()
|
||||
)
|
||||
|
||||
# These values are not overridable in some cases
|
||||
@property
|
||||
def package_dir(self) -> Path:
|
||||
return self.general_build_options.package_dir
|
||||
|
||||
@property
|
||||
def build_selector(self) -> BuildSelector:
|
||||
return self.general_build_options.build_selector
|
||||
|
||||
@property
|
||||
def output_dir(self) -> Path:
|
||||
return self.general_build_options.output_dir
|
||||
|
||||
@property
|
||||
def architectures(self) -> Set[Architecture]:
|
||||
return self.general_build_options.architectures
|
||||
|
||||
@property
|
||||
def environment(self) -> ParsedEnvironment:
|
||||
return self.general_build_options.environment
|
||||
|
||||
@property
|
||||
def before_all(self) -> str:
|
||||
return self.general_build_options.before_all
|
||||
|
||||
def produce_image_batches(
|
||||
self,
|
||||
configurations: List[SC],
|
||||
platform_tag: str,
|
||||
platform_arch: str,
|
||||
) -> Iterator[Tuple[List[SC], str]]:
|
||||
|
||||
docker_images: Mapping[str, List[SC]] = defaultdict(list)
|
||||
|
||||
for config in configurations:
|
||||
build_options = self[config.identifier]
|
||||
images = (
|
||||
build_options.manylinux_images
|
||||
if platform_tag.startswith("manylinux")
|
||||
else build_options.musllinux_images
|
||||
)
|
||||
assert images is not None
|
||||
docker_images[images[platform_arch]].append(config)
|
||||
|
||||
for image, configs in docker_images.items():
|
||||
# TODO: check for colisions for identifiers in configs
|
||||
# Some settings (before-all) are not overridable in the same image
|
||||
yield configs, image
|
||||
|
||||
def check_build_selectors(self) -> None:
|
||||
hits = Counter[str]()
|
||||
for sel in self.build_options_by_selector:
|
||||
bs = BuildSelector(build_config=sel, skip_config="")
|
||||
hits += Counter(i for i in self.identifiers if bs(i))
|
||||
|
||||
non_unique_identifers = {idnt for idnt, count in hits.items() if count > 1}
|
||||
if non_unique_identifers:
|
||||
msg = "cibuildwheel: error, the windows/macOS selectors must match uniquely"
|
||||
print(msg, file=sys.stderr)
|
||||
for sel in self.build_options_by_selector:
|
||||
bs = BuildSelector(build_config=sel, skip_config="")
|
||||
for i in non_unique_identifers:
|
||||
if bs(i):
|
||||
print(f" {sel}: {i} (nonunique match)")
|
||||
sys.exit(1)
|
||||
|
||||
def __str__(self) -> str:
|
||||
results = []
|
||||
for option in sorted(self.general_build_options._asdict().keys()):
|
||||
variations = {
|
||||
key: value._asdict()[option]
|
||||
for key, value in self.build_options_by_selector.items()
|
||||
}
|
||||
variations["*"] = self.general_build_options._asdict()[option]
|
||||
if len({repr(v) for v in variations.values()}) == 1:
|
||||
results.append(f"{option}: {variations['*']!r}")
|
||||
else:
|
||||
results.append(f"{option}:")
|
||||
for key, value in sorted(variations.items()):
|
||||
results.append(f" {key}: {value!r}")
|
||||
|
||||
return "\n".join(results)
|
||||
|
||||
|
||||
class NonPlatformWheelError(Exception):
|
||||
def __init__(self) -> None:
|
||||
message = textwrap.dedent(
|
||||
|
||||
Reference in New Issue
Block a user