Skip to content

Commit

Permalink
refactor: remove global
Browse files Browse the repository at this point in the history
  • Loading branch information
henryiii committed May 27, 2021
1 parent 1536d69 commit 706ba88
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 93 deletions.
12 changes: 6 additions & 6 deletions cibuildwheel/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import cibuildwheel.windows
from cibuildwheel.architecture import Architecture, allowed_architectures_check
from cibuildwheel.environment import EnvironmentParseError, parse_environment
from cibuildwheel.options import ConfigNamespace, ConfigOptions
from cibuildwheel.options import ConfigOptions
from cibuildwheel.projectfiles import get_requires_python_str
from cibuildwheel.typing import PLATFORMS, PlatformName, assert_never
from cibuildwheel.util import (
Expand Down Expand Up @@ -143,12 +143,12 @@ def main() -> None:
output_dir = Path(
args.output_dir
if args.output_dir is not None
else options("output-dir", namespace=ConfigNamespace.MAIN)
else os.environ.get("CIBW_OUTPUT_DIR", "wheelhouse")
)

build_config = options("build", namespace=ConfigNamespace.MAIN) or "*"
skip_config = options("skip", namespace=ConfigNamespace.MAIN)
test_skip = options("test-skip", namespace=ConfigNamespace.MAIN)
build_config = options("build", env_plat=False) or "*"
skip_config = options("skip", env_plat=False)
test_skip = options("test-skip", env_plat=False)

archs_config_str = options("archs") if args.archs is None else args.archs

Expand Down Expand Up @@ -247,7 +247,7 @@ def main() -> None:
]:
pinned_images = all_pinned_docker_images[build_platform]

config_value = options(f"{build_platform}-image", namespace=ConfigNamespace.MANYLINUX)
config_value = options(f"manylinux.{build_platform}-image")

if config_value is None:
# default to manylinux2010 if it's available, otherwise manylinux2014
Expand Down
98 changes: 39 additions & 59 deletions cibuildwheel/options.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import enum
import os
from pathlib import Path
from typing import Any, Dict, Iterator, KeysView, Mapping, Tuple
from typing import Any, Dict, Mapping, Tuple

import toml

Expand All @@ -11,6 +10,11 @@

Setting = str

# These keys are allowed to merge; setting one will not go away if another is
# set in a overriding file. tool.cibuildwheel.manylinux.X will not remove
# tool.cibuildwheel.manylinux.Y from defaults, for example.
ALLOWED_TO_MERGE = {"manylinux"}


class ConfigOptionError(KeyError):
pass
Expand All @@ -27,20 +31,6 @@ def _dig_first(*pairs: Tuple[Mapping[str, Setting], str]) -> Setting:
return dict_like.get(key, _dig_first(*others)) if others else dict_like[key]


def _global_first(keys: KeysView[str]) -> Iterator[str]:
keys_ = set(keys)
if "global" in keys_:
keys_.remove("global")
yield "global"
yield from keys_


class ConfigNamespace(enum.Enum):
PLATFORM = enum.auto() # Available in "global" and plat-specific namespace
MAIN = enum.auto() # Available without a namespace
MANYLINUX = enum.auto() # Only in the manylinux namespace


class ConfigOptions:
"""
Gets options from the environment, optionally scoped by the platform.
Expand Down Expand Up @@ -72,7 +62,7 @@ def _update(
new_dict: Dict[str, Any],
*,
update: bool,
path: str = "",
_platform: bool = False,
) -> None:
"""
Updates a dict with a new dict - optionally checking to see if the key
Expand All @@ -81,39 +71,34 @@ def _update(
will be forced to have no new keys.
"""

for key in _global_first(new_dict.keys()):
# Check to see if key is already present (in global too if a platform)
if update:
options = set(self.config[path] if path else self.config)
if path in PLATFORMS:
options |= set(self.config["global"])
# _platform will be True if this is being called on tool.cibuildwheel.<platform>
# for the new_dict (old_dict does not have platforms in it)
if _platform:
normal_keys = set(new_dict)
else:
normal_keys = set(new_dict) - PLATFORMS

if key not in options:
raise ConfigOptionError(
f"Key not supported, problem in config file: {path} {key}"
)
for key in normal_keys:
# Check to see if key is already present
if update:
# TODO: Also check nested items
if key not in self.config:
msg = f"Key not supported, problem in config file: {key}"
raise ConfigOptionError(msg)

# This is recursive; update dicts (subsections) if needed. Only handles one level.
if isinstance(new_dict[key], dict):
if path:
raise ConfigOptionError(
f"Nested keys not supported, {key} should not be in {path}"
)

if key in ALLOWED_TO_MERGE and isinstance(new_dict[key], dict):
if key not in old_dict:
old_dict[key] = {}

if update and key == "global":
# "new global" overrides "old platform"
# this requires processing the "global" key first
for sub_key in new_dict[key]:
for platform in PLATFORMS:
old_dict[platform].pop(sub_key, None)

self._update(old_dict[key], new_dict[key], update=update, path=key)
old_dict[key].update(new_dict[key])
else:
old_dict[key] = new_dict[key]

# Allow new_dict[<platform>][key] to override old_dict[key]
if not _platform and self.platform in new_dict:
self._update(old_dict, new_dict[self.platform], update=update, _platform=True)

def _load_file(self, filename: Path, *, update: bool) -> None:
"""
Load a toml file, global and current platform. Raise an error if any
Expand All @@ -135,40 +120,35 @@ def _load_file(self, filename: Path, *, update: bool) -> None:

self._update(self.config, tool_cibuildwheel, update=update)

def __call__(
self, name: str, *, namespace: ConfigNamespace = ConfigNamespace.PLATFORM
) -> Setting:
def __call__(self, name: str, *, env_plat: bool = True) -> Setting:
"""
Get and return envvar for name or the override or the default.
"""
config = self.config

# Get config settings for the requested namespace and current platform
if namespace == ConfigNamespace.MAIN:
config = self.config
elif namespace == ConfigNamespace.MANYLINUX:
config = self.config["manylinux"]
elif namespace == ConfigNamespace.PLATFORM:
config = {**self.config["global"], **self.config[self.platform]}
# Allow singly nested names, like manylinux.X
if "." in name:
parent, key = name.split(".")
config = self.config[parent]
else:
key = name

if name not in config:
if key not in config:
raise ConfigOptionError(f"{name} must be in cibuildwheel/resources/defaults.toml file")

# Environment variable form
if namespace == ConfigNamespace.MANYLINUX:
envvar = f"CIBW_MANYLINUX_{name.upper().replace('-', '_')}"
else:
envvar = f"CIBW_{name.upper().replace('-', '_')}"
envvar = f"CIBW_{name.upper().replace('-', '_').replace('.', '_')}"

# Let environment variable override setting in config
if namespace == ConfigNamespace.PLATFORM:
if env_plat:
plat_envvar = f"{envvar}_{self.platform.upper()}"
return _dig_first(
(os.environ, plat_envvar),
(os.environ, envvar),
(config, name),
(config, key),
)
else:
return _dig_first(
(os.environ, envvar),
(config, name),
(config, key),
)
25 changes: 11 additions & 14 deletions cibuildwheel/resources/defaults.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,7 @@
build = "*"
skip = ""
test-skip = ""
output-dir = "wheelhouse"


[tool.cibuildwheel.manylinux]
x86_64-image = "manylinux2010"
i686-image = "manylinux2010"
pypy_x86_64-image = "manylinux2010"
pypy_i686-image = "manylinux2010"
pypy_aarch64-image = "manylinux2010"
aarch64-image = "manylinux2014"
ppc64le-image = "manylinux2014"
s390x-image = "manylinux2014"


[tool.cibuildwheel.global]
archs = "auto"
dependency-versions = "pinned"
environment = ""
Expand All @@ -32,6 +18,17 @@ test-requires = ""
test-extras = ""


[tool.cibuildwheel.manylinux]
x86_64-image = "manylinux2010"
i686-image = "manylinux2010"
pypy_x86_64-image = "manylinux2010"
pypy_i686-image = "manylinux2010"
pypy_aarch64-image = "manylinux2010"
aarch64-image = "manylinux2014"
ppc64le-image = "manylinux2014"
s390x-image = "manylinux2014"


[tool.cibuildwheel.linux]
repair-wheel-command = "auditwheel repair -w {dest_dir} {wheel}"

Expand Down
31 changes: 17 additions & 14 deletions unit_test/options_toml_test.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import pytest

from cibuildwheel.options import ConfigNamespace, ConfigOptions
from cibuildwheel.options import ConfigOptions

PYPROJECT_1 = """
[tool.cibuildwheel]
build = "cp39*"
[tool.cibuildwheel.manylinux]
x86_64-image = "manylinux1"
[tool.cibuildwheel.global]
test-command = "pyproject"
test-requires = "something"
[tool.cibuildwheel.manylinux]
x86_64-image = "manylinux1"
[tool.cibuildwheel.macos]
test-requires = "else"
Expand All @@ -32,8 +31,7 @@ def test_simple_settings(tmp_path, platform):

options = ConfigOptions(tmp_path, platform=platform)

assert options("build", namespace=ConfigNamespace.MAIN) == "cp39*"
assert options("output-dir", namespace=ConfigNamespace.MAIN) == "wheelhouse"
assert options("build", env_plat=False) == "cp39*"

assert options("test-command") == "pyproject"
assert options("archs") == "auto"
Expand All @@ -42,8 +40,8 @@ def test_simple_settings(tmp_path, platform):
== {"windows": "something", "macos": "else", "linux": "other"}[platform]
)

assert options("x86_64-image", namespace=ConfigNamespace.MANYLINUX) == "manylinux1"
assert options("i686-image", namespace=ConfigNamespace.MANYLINUX) == "manylinux2010"
assert options("manylinux.x86_64-image") == "manylinux1"
assert options("manylinux.i686-image") == "manylinux2010"


def test_envvar_override(tmp_path, platform, monkeypatch):
Expand All @@ -60,9 +58,14 @@ def test_envvar_override(tmp_path, platform, monkeypatch):

assert options("archs") == "auto"

assert options("build", namespace=ConfigNamespace.MAIN) == "cp38*"
assert options("x86_64-image", namespace=ConfigNamespace.MANYLINUX) == "manylinux2014"
assert options("i686-image", namespace=ConfigNamespace.MANYLINUX) == "manylinux2010"
assert (
options(
"build",
)
== "cp38*"
)
assert options("manylinux.x86_64-image") == "manylinux2014"
assert options("manylinux.i686-image") == "manylinux2010"

assert (
options("test-requires") == {"windows": "docs", "macos": "docs", "linux": "scod"}[platform]
Expand All @@ -73,7 +76,7 @@ def test_envvar_override(tmp_path, platform, monkeypatch):
def test_project_global_override_default_platform(tmp_path, platform):
tmp_path.joinpath("pyproject.toml").write_text(
"""
[tool.cibuildwheel.global]
[tool.cibuildwheel]
repair-wheel-command = "repair-project-global"
"""
)
Expand Down Expand Up @@ -112,7 +115,7 @@ def test_global_platform_order(tmp_path, platform):
repair-wheel-command = "repair-project-windows"
[tool.cibuildwheel.macos]
repair-wheel-command = "repair-project-macos"
[tool.cibuildwheel.global]
[tool.cibuildwheel]
repair-wheel-command = "repair-project-global"
"""
)
Expand Down

0 comments on commit 706ba88

Please sign in to comment.