From 27a0053386bc73ba340b5bcb9f44fcea42ce6875 Mon Sep 17 00:00:00 2001 From: Henry Fredrick Schreiner Date: Mon, 18 Jan 2021 00:09:11 -0500 Subject: [PATCH 1/8] fix: error if selector is empty --- cibuildwheel/__main__.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/cibuildwheel/__main__.py b/cibuildwheel/__main__.py index f5a7ace9..8bac5e5d 100644 --- a/cibuildwheel/__main__.py +++ b/cibuildwheel/__main__.py @@ -5,7 +5,7 @@ import textwrap import traceback from configparser import ConfigParser from pathlib import Path -from typing import Any, Dict, List, Optional, Set, overload +from typing import Dict, List, Optional, Set, Union, overload import cibuildwheel import cibuildwheel.linux @@ -194,8 +194,14 @@ def main() -> None: archs_config_str = get_option_from_environment('CIBW_ARCHS', platform=platform, default='auto') archs = Architecture.parse_config(archs_config_str, platform=platform) + identifiers = get_build_identifiers(platform, build_selector, archs) + if not identifiers: + print("ERROR: No build identifiers selected!") + sys.exit(3) + if args.print_build_identifiers: - print_build_identifiers(platform, build_selector, archs) + for identifier in identifiers: + print(identifier) sys.exit(0) manylinux_images: Optional[Dict[str, str]] = None @@ -311,20 +317,22 @@ def print_preamble(platform: str, build_options: BuildOptions) -> None: print('\nHere we go!\n') -def print_build_identifiers( - platform: str, build_selector: BuildSelector, architectures: Set[Architecture] -) -> None: - - python_configurations: List[Any] = [] +def get_build_identifiers( + platform: PlatformName, build_selector: BuildSelector, architectures: Set[Architecture] +) -> List[str]: + python_configurations: Union[List[cibuildwheel.linux.PythonConfiguration], + List[cibuildwheel.windows.PythonConfiguration], + List[cibuildwheel.macos.PythonConfiguration]] if platform == 'linux': python_configurations = cibuildwheel.linux.get_python_configurations(build_selector, architectures) elif platform == 'windows': python_configurations = cibuildwheel.windows.get_python_configurations(build_selector, architectures) elif platform == 'macos': python_configurations = cibuildwheel.macos.get_python_configurations(build_selector) + else: + assert_never(platform) - for config in python_configurations: - print(config.identifier) + return [config.identifier for config in python_configurations] def detect_warnings(platform: str, build_options: BuildOptions) -> List[str]: From 61b94434b287b4c432240787657a6aa8f780ebca Mon Sep 17 00:00:00 2001 From: Henry Fredrick Schreiner Date: Mon, 18 Jan 2021 01:03:15 -0500 Subject: [PATCH 2/8] fix: error if build selectors are empty --- cibuildwheel/__main__.py | 7 ++++--- pyproject.toml | 6 ++++++ unit_test/main_tests/conftest.py | 9 +++++++++ unit_test/main_tests/main_options_test.py | 23 ++++++++++++++++++++++ unit_test/main_tests/main_platform_test.py | 5 +++++ 5 files changed, 47 insertions(+), 3 deletions(-) diff --git a/cibuildwheel/__main__.py b/cibuildwheel/__main__.py index 8bac5e5d..068897dc 100644 --- a/cibuildwheel/__main__.py +++ b/cibuildwheel/__main__.py @@ -195,9 +195,6 @@ def main() -> None: archs = Architecture.parse_config(archs_config_str, platform=platform) identifiers = get_build_identifiers(platform, build_selector, archs) - if not identifiers: - print("ERROR: No build identifiers selected!") - sys.exit(3) if args.print_build_identifiers: for identifier in identifiers: @@ -269,6 +266,10 @@ def main() -> None: else: assert_never(platform) + if not identifiers: + print("ERROR: No build identifiers selected!") + sys.exit(3) + def detect_obsolete_options() -> None: # Check the old 'MANYLINUX1_*_IMAGE' options diff --git a/pyproject.toml b/pyproject.toml index 285367ae..c05fec7d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,3 +5,9 @@ requires = [ ] build-backend = "setuptools.build_meta" + + +[tool.pytest.ini_options] +markers = [ + "allow_empty(platform): Allow main tests on this platform(s) to be empty", +] diff --git a/unit_test/main_tests/conftest.py b/unit_test/main_tests/conftest.py index 1122a88c..c9ae6e8a 100644 --- a/unit_test/main_tests/conftest.py +++ b/unit_test/main_tests/conftest.py @@ -59,6 +59,15 @@ def fake_package_dir(monkeypatch): def platform(request, monkeypatch): platform_value = request.param monkeypatch.setenv('CIBW_PLATFORM', platform_value) + + marker = request.node.get_closest_marker('allow_empty') + if marker is not None and (len(marker.args) == 0 or platform_value in marker.args): + def pass_exit(val: int): + if val not in {3}: + sys.exit(val) + + monkeypatch.setattr(sys, 'exit', pass_exit) + return platform_value diff --git a/unit_test/main_tests/main_options_test.py b/unit_test/main_tests/main_options_test.py index f28b1ed4..fef74203 100644 --- a/unit_test/main_tests/main_options_test.py +++ b/unit_test/main_tests/main_options_test.py @@ -11,6 +11,7 @@ from cibuildwheel.util import BuildSelector # CIBW_PLATFORM is tested in main_platform_test.py +@pytest.mark.allow_empty('windows') def test_output_dir(platform, intercepted_build_args, monkeypatch): OUTPUT_DIR = Path('some_output_dir') @@ -21,12 +22,14 @@ def test_output_dir(platform, intercepted_build_args, monkeypatch): assert intercepted_build_args.args[0].output_dir == OUTPUT_DIR +@pytest.mark.allow_empty('windows') def test_output_dir_default(platform, intercepted_build_args, monkeypatch): main() assert intercepted_build_args.args[0].output_dir == Path('wheelhouse') +@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('also_set_environment', [False, True]) def test_output_dir_argument(also_set_environment, platform, intercepted_build_args, monkeypatch): OUTPUT_DIR = Path('some_output_dir') @@ -40,6 +43,7 @@ def test_output_dir_argument(also_set_environment, platform, intercepted_build_a assert intercepted_build_args.args[0].output_dir == OUTPUT_DIR +@pytest.mark.allow_empty def test_build_selector(platform, intercepted_build_args, monkeypatch): BUILD = 'some build* *-selector' SKIP = 'some skip* *-selector' @@ -57,6 +61,16 @@ def test_build_selector(platform, intercepted_build_args, monkeypatch): # Unit tests for BuildSelector are in build_selector_test.py +def test_empty_selector(platform, intercepted_build_args, monkeypatch): + monkeypatch.setenv('CIBW_SKIP', '*') + + with pytest.raises(SystemExit) as e: + main() + + assert e.value.code == 3 + + +@pytest.mark.allow_empty @pytest.mark.parametrize('architecture, image, full_image', [ ('x86_64', None, 'quay.io/pypa/manylinux2010_x86_64:*'), ('x86_64', 'manylinux1', 'quay.io/pypa/manylinux1_x86_64:*'), @@ -100,6 +114,7 @@ def get_default_repair_command(platform): raise ValueError('Unknown platform', platform) +@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('repair_command', [None, 'repair', 'repair -w {dest_dir} {wheel}']) @pytest.mark.parametrize('platform_specific', [False, True]) def test_repair_command(repair_command, platform_specific, platform, intercepted_build_args, monkeypatch): @@ -116,6 +131,7 @@ def test_repair_command(repair_command, platform_specific, platform, intercepted assert intercepted_build_args.args[0].repair_command == expected_repair +@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('environment', [ {}, {'something': 'value'}, @@ -137,6 +153,7 @@ def test_environment(environment, platform_specific, platform, intercepted_build assert intercepted_environment.as_dictionary(prev_environment={}) == environment +@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('test_requires', [None, 'requirement other_requirement']) @pytest.mark.parametrize('platform_specific', [False, True]) def test_test_requires(test_requires, platform_specific, platform, intercepted_build_args, monkeypatch): @@ -152,6 +169,7 @@ def test_test_requires(test_requires, platform_specific, platform, intercepted_b assert intercepted_build_args.args[0].test_requires == (test_requires or '').split() +@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('test_extras', [None, 'extras']) @pytest.mark.parametrize('platform_specific', [False, True]) def test_test_extras(test_extras, platform_specific, platform, intercepted_build_args, monkeypatch): @@ -167,6 +185,7 @@ def test_test_extras(test_extras, platform_specific, platform, intercepted_build assert intercepted_build_args.args[0].test_extras == ('[' + test_extras + ']' if test_extras else '') +@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('test_command', [None, 'test --command']) @pytest.mark.parametrize('platform_specific', [False, True]) def test_test_command(test_command, platform_specific, platform, intercepted_build_args, monkeypatch): @@ -182,6 +201,7 @@ def test_test_command(test_command, platform_specific, platform, intercepted_bui assert intercepted_build_args.args[0].test_command == test_command +@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('before_build', [None, 'before --build']) @pytest.mark.parametrize('platform_specific', [False, True]) def test_before_build(before_build, platform_specific, platform, intercepted_build_args, monkeypatch): @@ -197,6 +217,7 @@ def test_before_build(before_build, platform_specific, platform, intercepted_bui assert intercepted_build_args.args[0].before_build == before_build +@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('build_verbosity', [None, 0, 2, -2, 4, -4]) @pytest.mark.parametrize('platform_specific', [False, True]) def test_build_verbosity(build_verbosity, platform_specific, platform, intercepted_build_args, monkeypatch): @@ -213,6 +234,7 @@ def test_build_verbosity(build_verbosity, platform_specific, platform, intercept assert intercepted_build_args.args[0].build_verbosity == expected_verbosity +@pytest.mark.allow_empty @pytest.mark.parametrize('option_name', ['CIBW_BUILD', 'CIBW_SKIP']) @pytest.mark.parametrize('option_value, build_selector_patterns', [ ('*-manylinux1_*', ['*-manylinux_*']), @@ -234,6 +256,7 @@ def test_build_selector_migrations(intercepted_build_args, monkeypatch, option_n assert intercepted_build_selector.skip_patterns == build_selector_patterns +@pytest.mark.allow_empty @pytest.mark.parametrize('before_all', ["", None, 'test text']) @pytest.mark.parametrize('platform_specific', [False, True]) def test_before_all(before_all, platform_specific, platform, intercepted_build_args, monkeypatch): diff --git a/unit_test/main_tests/main_platform_test.py b/unit_test/main_tests/main_platform_test.py index 9b7c06fe..6445f331 100644 --- a/unit_test/main_tests/main_platform_test.py +++ b/unit_test/main_tests/main_platform_test.py @@ -52,6 +52,7 @@ def test_unknown_platform(monkeypatch, capsys): assert 'cibuildwheel: Unsupported platform: nonexistent' in err +@pytest.mark.allow_empty('windows') def test_platform_argument(platform, intercepted_build_args, monkeypatch): monkeypatch.setenv('CIBW_PLATFORM', 'nonexistent') monkeypatch.setattr(sys, 'argv', sys.argv + ['--platform', platform]) @@ -61,12 +62,14 @@ def test_platform_argument(platform, intercepted_build_args, monkeypatch): assert intercepted_build_args.args[0].package_dir == MOCK_PACKAGE_DIR +@pytest.mark.allow_empty('windows') def test_platform_environment(platform, intercepted_build_args, monkeypatch): main() assert intercepted_build_args.args[0].package_dir == MOCK_PACKAGE_DIR +@pytest.mark.allow_empty('windows') def test_archs_default(platform, intercepted_build_args, monkeypatch): monkeypatch.setattr(platform_module, 'machine', lambda: 'x86_64') @@ -79,6 +82,7 @@ def test_archs_default(platform, intercepted_build_args, monkeypatch): assert build_options.architectures == {Architecture.x86_64} +@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('use_env_var', [False, True]) def test_archs_argument(platform, intercepted_build_args, monkeypatch, use_env_var): monkeypatch.setattr(platform_module, 'machine', lambda: 'x86_64') @@ -112,6 +116,7 @@ def test_archs_platform_specific(platform, intercepted_build_args, monkeypatch): assert build_options.architectures == {Architecture.x86_64} +@pytest.mark.allow_empty('windows') def test_archs_platform_native(platform, intercepted_build_args, monkeypatch): monkeypatch.setattr(platform_module, 'machine', lambda: 'x86_64') monkeypatch.setenv('CIBW_ARCHS', 'native') From c90c7666b929f96e4c02916ebd54a311f21f1c98 Mon Sep 17 00:00:00 2001 From: Henry Fredrick Schreiner Date: Mon, 18 Jan 2021 09:54:32 -0500 Subject: [PATCH 3/8] tests: fix arch for platform tests --- unit_test/main_tests/conftest.py | 6 ++++++ unit_test/main_tests/main_options_test.py | 12 ------------ unit_test/main_tests/main_platform_test.py | 2 -- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/unit_test/main_tests/conftest.py b/unit_test/main_tests/conftest.py index c9ae6e8a..c70ff98e 100644 --- a/unit_test/main_tests/conftest.py +++ b/unit_test/main_tests/conftest.py @@ -1,3 +1,4 @@ +import platform as platform_module import subprocess import sys from pathlib import Path @@ -60,6 +61,11 @@ def platform(request, monkeypatch): platform_value = request.param monkeypatch.setenv('CIBW_PLATFORM', platform_value) + if platform_value == 'windows': + monkeypatch.setattr(platform_module, 'machine', lambda: 'AMD64') + else: + monkeypatch.setattr(platform_module, 'machine', lambda: 'x86_64') + marker = request.node.get_closest_marker('allow_empty') if marker is not None and (len(marker.args) == 0 or platform_value in marker.args): def pass_exit(val: int): diff --git a/unit_test/main_tests/main_options_test.py b/unit_test/main_tests/main_options_test.py index fef74203..345cfe2a 100644 --- a/unit_test/main_tests/main_options_test.py +++ b/unit_test/main_tests/main_options_test.py @@ -11,7 +11,6 @@ from cibuildwheel.util import BuildSelector # CIBW_PLATFORM is tested in main_platform_test.py -@pytest.mark.allow_empty('windows') def test_output_dir(platform, intercepted_build_args, monkeypatch): OUTPUT_DIR = Path('some_output_dir') @@ -22,14 +21,12 @@ def test_output_dir(platform, intercepted_build_args, monkeypatch): assert intercepted_build_args.args[0].output_dir == OUTPUT_DIR -@pytest.mark.allow_empty('windows') def test_output_dir_default(platform, intercepted_build_args, monkeypatch): main() assert intercepted_build_args.args[0].output_dir == Path('wheelhouse') -@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('also_set_environment', [False, True]) def test_output_dir_argument(also_set_environment, platform, intercepted_build_args, monkeypatch): OUTPUT_DIR = Path('some_output_dir') @@ -70,7 +67,6 @@ def test_empty_selector(platform, intercepted_build_args, monkeypatch): assert e.value.code == 3 -@pytest.mark.allow_empty @pytest.mark.parametrize('architecture, image, full_image', [ ('x86_64', None, 'quay.io/pypa/manylinux2010_x86_64:*'), ('x86_64', 'manylinux1', 'quay.io/pypa/manylinux1_x86_64:*'), @@ -114,7 +110,6 @@ def get_default_repair_command(platform): raise ValueError('Unknown platform', platform) -@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('repair_command', [None, 'repair', 'repair -w {dest_dir} {wheel}']) @pytest.mark.parametrize('platform_specific', [False, True]) def test_repair_command(repair_command, platform_specific, platform, intercepted_build_args, monkeypatch): @@ -131,7 +126,6 @@ def test_repair_command(repair_command, platform_specific, platform, intercepted assert intercepted_build_args.args[0].repair_command == expected_repair -@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('environment', [ {}, {'something': 'value'}, @@ -153,7 +147,6 @@ def test_environment(environment, platform_specific, platform, intercepted_build assert intercepted_environment.as_dictionary(prev_environment={}) == environment -@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('test_requires', [None, 'requirement other_requirement']) @pytest.mark.parametrize('platform_specific', [False, True]) def test_test_requires(test_requires, platform_specific, platform, intercepted_build_args, monkeypatch): @@ -169,7 +162,6 @@ def test_test_requires(test_requires, platform_specific, platform, intercepted_b assert intercepted_build_args.args[0].test_requires == (test_requires or '').split() -@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('test_extras', [None, 'extras']) @pytest.mark.parametrize('platform_specific', [False, True]) def test_test_extras(test_extras, platform_specific, platform, intercepted_build_args, monkeypatch): @@ -185,7 +177,6 @@ def test_test_extras(test_extras, platform_specific, platform, intercepted_build assert intercepted_build_args.args[0].test_extras == ('[' + test_extras + ']' if test_extras else '') -@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('test_command', [None, 'test --command']) @pytest.mark.parametrize('platform_specific', [False, True]) def test_test_command(test_command, platform_specific, platform, intercepted_build_args, monkeypatch): @@ -201,7 +192,6 @@ def test_test_command(test_command, platform_specific, platform, intercepted_bui assert intercepted_build_args.args[0].test_command == test_command -@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('before_build', [None, 'before --build']) @pytest.mark.parametrize('platform_specific', [False, True]) def test_before_build(before_build, platform_specific, platform, intercepted_build_args, monkeypatch): @@ -217,7 +207,6 @@ def test_before_build(before_build, platform_specific, platform, intercepted_bui assert intercepted_build_args.args[0].before_build == before_build -@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('build_verbosity', [None, 0, 2, -2, 4, -4]) @pytest.mark.parametrize('platform_specific', [False, True]) def test_build_verbosity(build_verbosity, platform_specific, platform, intercepted_build_args, monkeypatch): @@ -256,7 +245,6 @@ def test_build_selector_migrations(intercepted_build_args, monkeypatch, option_n assert intercepted_build_selector.skip_patterns == build_selector_patterns -@pytest.mark.allow_empty @pytest.mark.parametrize('before_all', ["", None, 'test text']) @pytest.mark.parametrize('platform_specific', [False, True]) def test_before_all(before_all, platform_specific, platform, intercepted_build_args, monkeypatch): diff --git a/unit_test/main_tests/main_platform_test.py b/unit_test/main_tests/main_platform_test.py index 6445f331..0f277afe 100644 --- a/unit_test/main_tests/main_platform_test.py +++ b/unit_test/main_tests/main_platform_test.py @@ -52,7 +52,6 @@ def test_unknown_platform(monkeypatch, capsys): assert 'cibuildwheel: Unsupported platform: nonexistent' in err -@pytest.mark.allow_empty('windows') def test_platform_argument(platform, intercepted_build_args, monkeypatch): monkeypatch.setenv('CIBW_PLATFORM', 'nonexistent') monkeypatch.setattr(sys, 'argv', sys.argv + ['--platform', platform]) @@ -62,7 +61,6 @@ def test_platform_argument(platform, intercepted_build_args, monkeypatch): assert intercepted_build_args.args[0].package_dir == MOCK_PACKAGE_DIR -@pytest.mark.allow_empty('windows') def test_platform_environment(platform, intercepted_build_args, monkeypatch): main() From eb9850dbde2613449bb43938020d23e3ee934339 Mon Sep 17 00:00:00 2001 From: Henry Fredrick Schreiner Date: Mon, 18 Jan 2021 16:44:47 -0500 Subject: [PATCH 4/8] feat: support Windows workaround on Travis CI --- cibuildwheel/windows.py | 3 ++- docs/setup.md | 2 +- test/test_cpp_standards.py | 2 +- test/test_dependency_versions.py | 6 ++++++ test/utils.py | 5 +++-- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/cibuildwheel/windows.py b/cibuildwheel/windows.py index bd929358..5e8c1683 100644 --- a/cibuildwheel/windows.py +++ b/cibuildwheel/windows.py @@ -70,7 +70,8 @@ def get_python_configurations( '64': Architecture.AMD64, } - if IS_RUNNING_ON_TRAVIS: + custom_compiler = os.environ.get('DISTUTILS_USE_SDK') and os.environ.get('MSSdk') + if IS_RUNNING_ON_TRAVIS and not custom_compiler: # cannot install VCForPython27.msi which is needed for compiling C software # try with (and similar): msiexec /i VCForPython27.msi ALLUSERS=1 ACCEPT=YES /passive python_configurations = [c for c in python_configurations if not c.version.startswith('2.7')] diff --git a/docs/setup.md b/docs/setup.md index 282edde9..c86ebf13 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -44,7 +44,7 @@ To build Linux, Mac, and Windows wheels on Travis CI, create a `.travis.yml` fil {% include "../examples/travis-ci-minimal.yml" %} ``` -Note that building Windows Python 2.7 wheels on Travis is unsupported. +Note that building Windows Python 2.7 wheels on Travis is unsupported unless using a newer compiler [via a workaround](cpp-standards.md). Commit this file, enable building of your repo on Travis CI, and push. diff --git a/test/test_cpp_standards.py b/test/test_cpp_standards.py index 0ecf196d..8ab5becd 100644 --- a/test/test_cpp_standards.py +++ b/test/test_cpp_standards.py @@ -202,7 +202,7 @@ def test_cpp17_py27_modern_msvc_workaround(tmp_path): add_env_x64['CIBW_BUILD'] = 'cp27-win_amd64' actual_wheels += utils.cibuildwheel_run(project_dir, add_env=add_env_x64) - expected_wheels = [w for w in utils.expected_wheels('spam', '0.1.0') + expected_wheels = [w for w in utils.expected_wheels('spam', '0.1.0', filter_27=False) if 'cp27-cp27m-win' in w or 'pp27-pypy_73-win32' in w] diff --git a/test/test_dependency_versions.py b/test/test_dependency_versions.py index 07d22e24..1b415bb4 100644 --- a/test/test_dependency_versions.py +++ b/test/test_dependency_versions.py @@ -52,6 +52,9 @@ def test_pinned_versions(tmp_path, python_version): if utils.platform == 'linux': pytest.skip('linux doesn\'t pin individual tool versions, it pins manylinux images instead') + if utils.IS_WINDOWS_RUNNING_ON_TRAVIS and python_version == '2.7': + pytest.skip('Windows + Travis CI requires a workaround') + project_dir = tmp_path / 'project' project_with_expected_version_checks.generate(project_dir) @@ -114,6 +117,9 @@ def test_dependency_constraints_file(tmp_path, python_version): if utils.platform == 'linux': pytest.skip('linux doesn\'t pin individual tool versions, it pins manylinux images instead') + if utils.IS_WINDOWS_RUNNING_ON_TRAVIS and python_version == '2.7': + pytest.skip('Windows + Travis CI requires a workaround') + project_dir = tmp_path / 'project' project_with_expected_version_checks.generate(project_dir) diff --git a/test/utils.py b/test/utils.py index bae3853b..4fcdba47 100644 --- a/test/utils.py +++ b/test/utils.py @@ -76,7 +76,8 @@ def cibuildwheel_run(project_path, package_dir='.', env=None, add_env=None, outp def expected_wheels(package_name, package_version, manylinux_versions=None, - macosx_deployment_target='10.9', machine_arch=None): + macosx_deployment_target='10.9', machine_arch=None, *, + filter_27=IS_WINDOWS_RUNNING_ON_TRAVIS): ''' Returns a list of expected wheels from a run of cibuildwheel. ''' @@ -134,7 +135,7 @@ def expected_wheels(package_name, package_version, manylinux_versions=None, for platform_tag in platform_tags: wheels.append(f'{package_name}-{package_version}-{python_abi_tag}-{platform_tag}.whl') - if IS_WINDOWS_RUNNING_ON_TRAVIS: + if filter_27: # Python 2.7 isn't supported on Travis. wheels = [w for w in wheels if '-cp27-' not in w and '-pp2' not in w] From 5762aa5e3bb77661c22817ab616e40d7de316441 Mon Sep 17 00:00:00 2001 From: Henry Fredrick Schreiner Date: Tue, 19 Jan 2021 20:52:06 -0500 Subject: [PATCH 5/8] feat: allow-empty and simpler testing --- cibuildwheel/__main__.py | 8 ++++++-- pyproject.toml | 6 ------ unit_test/main_tests/conftest.py | 17 ++++++++--------- unit_test/main_tests/main_options_test.py | 6 ++---- unit_test/main_tests/main_platform_test.py | 14 ++++++++------ 5 files changed, 24 insertions(+), 27 deletions(-) diff --git a/cibuildwheel/__main__.py b/cibuildwheel/__main__.py index 068897dc..bcdfef8c 100644 --- a/cibuildwheel/__main__.py +++ b/cibuildwheel/__main__.py @@ -95,6 +95,9 @@ def main() -> None: parser.add_argument('--print-build-identifiers', action='store_true', help='Print the build identifiers matched by the current invocation and exit.') + parser.add_argument('--allow-empty', + action='store_true', + help='Do not report an error code if the build does not match any wheels.') args = parser.parse_args() @@ -267,8 +270,9 @@ def main() -> None: assert_never(platform) if not identifiers: - print("ERROR: No build identifiers selected!") - sys.exit(3) + print(f'cibuildwheel: No build identifiers selected: {build_selector}', file=sys.stderr) + if not args.allow_empty: + sys.exit(3) def detect_obsolete_options() -> None: diff --git a/pyproject.toml b/pyproject.toml index c05fec7d..285367ae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,9 +5,3 @@ requires = [ ] build-backend = "setuptools.build_meta" - - -[tool.pytest.ini_options] -markers = [ - "allow_empty(platform): Allow main tests on this platform(s) to be empty", -] diff --git a/unit_test/main_tests/conftest.py b/unit_test/main_tests/conftest.py index c70ff98e..3ce025a0 100644 --- a/unit_test/main_tests/conftest.py +++ b/unit_test/main_tests/conftest.py @@ -52,8 +52,15 @@ def fake_package_dir(monkeypatch): else: return real_path_exists(path) + args = ['cibuildwheel', str(MOCK_PACKAGE_DIR)] monkeypatch.setattr(Path, 'exists', mock_path_exists) - monkeypatch.setattr(sys, 'argv', ['cibuildwheel', str(MOCK_PACKAGE_DIR)]) + monkeypatch.setattr(sys, 'argv', args) + return args + + +@pytest.fixture +def allow_empty(request, monkeypatch, fake_package_dir): + monkeypatch.setattr(sys, 'argv', fake_package_dir + ['--allow-empty']) @pytest.fixture(params=['linux', 'macos', 'windows']) @@ -66,14 +73,6 @@ def platform(request, monkeypatch): else: monkeypatch.setattr(platform_module, 'machine', lambda: 'x86_64') - marker = request.node.get_closest_marker('allow_empty') - if marker is not None and (len(marker.args) == 0 or platform_value in marker.args): - def pass_exit(val: int): - if val not in {3}: - sys.exit(val) - - monkeypatch.setattr(sys, 'exit', pass_exit) - return platform_value diff --git a/unit_test/main_tests/main_options_test.py b/unit_test/main_tests/main_options_test.py index 345cfe2a..f6c80ff7 100644 --- a/unit_test/main_tests/main_options_test.py +++ b/unit_test/main_tests/main_options_test.py @@ -40,8 +40,7 @@ def test_output_dir_argument(also_set_environment, platform, intercepted_build_a assert intercepted_build_args.args[0].output_dir == OUTPUT_DIR -@pytest.mark.allow_empty -def test_build_selector(platform, intercepted_build_args, monkeypatch): +def test_build_selector(platform, intercepted_build_args, monkeypatch, allow_empty): BUILD = 'some build* *-selector' SKIP = 'some skip* *-selector' @@ -223,7 +222,6 @@ def test_build_verbosity(build_verbosity, platform_specific, platform, intercept assert intercepted_build_args.args[0].build_verbosity == expected_verbosity -@pytest.mark.allow_empty @pytest.mark.parametrize('option_name', ['CIBW_BUILD', 'CIBW_SKIP']) @pytest.mark.parametrize('option_value, build_selector_patterns', [ ('*-manylinux1_*', ['*-manylinux_*']), @@ -231,7 +229,7 @@ def test_build_verbosity(build_verbosity, platform_specific, platform, intercept ('*-macosx_10_9_x86_64', ['*-macosx_x86_64']), ('cp37-macosx_10_9_x86_64', ['cp37-macosx_x86_64']), ]) -def test_build_selector_migrations(intercepted_build_args, monkeypatch, option_name, option_value, build_selector_patterns): +def test_build_selector_migrations(intercepted_build_args, monkeypatch, option_name, option_value, build_selector_patterns, allow_empty): monkeypatch.setenv(option_name, option_value) main() diff --git a/unit_test/main_tests/main_platform_test.py b/unit_test/main_tests/main_platform_test.py index 0f277afe..844cf811 100644 --- a/unit_test/main_tests/main_platform_test.py +++ b/unit_test/main_tests/main_platform_test.py @@ -67,22 +67,25 @@ def test_platform_environment(platform, intercepted_build_args, monkeypatch): assert intercepted_build_args.args[0].package_dir == MOCK_PACKAGE_DIR -@pytest.mark.allow_empty('windows') def test_archs_default(platform, intercepted_build_args, monkeypatch): - monkeypatch.setattr(platform_module, 'machine', lambda: 'x86_64') + monkeypatch.setattr(platform_module, 'machine', lambda: 'AMD64' if platform == 'windows' else 'x86_64') main() build_options = intercepted_build_args.args[0] if platform == 'linux': assert build_options.architectures == {Architecture.x86_64, Architecture.i686} + elif platform == 'windows': + assert build_options.architectures == {Architecture.AMD64, Architecture.x86} else: assert build_options.architectures == {Architecture.x86_64} -@pytest.mark.allow_empty('windows') @pytest.mark.parametrize('use_env_var', [False, True]) def test_archs_argument(platform, intercepted_build_args, monkeypatch, use_env_var): + if platform == 'windows': + pytest.skip('Will have empty build selectors on Windows') + monkeypatch.setattr(platform_module, 'machine', lambda: 'x86_64') if use_env_var: monkeypatch.setenv('CIBW_ARCHS', 'ppc64le') @@ -114,9 +117,8 @@ def test_archs_platform_specific(platform, intercepted_build_args, monkeypatch): assert build_options.architectures == {Architecture.x86_64} -@pytest.mark.allow_empty('windows') def test_archs_platform_native(platform, intercepted_build_args, monkeypatch): - monkeypatch.setattr(platform_module, 'machine', lambda: 'x86_64') + monkeypatch.setattr(platform_module, 'machine', lambda: 'AMD64' if platform == 'windows' else 'x86_64') monkeypatch.setenv('CIBW_ARCHS', 'native') main() @@ -125,7 +127,7 @@ def test_archs_platform_native(platform, intercepted_build_args, monkeypatch): if platform == 'linux': assert build_options.architectures == {Architecture.x86_64} elif platform == 'windows': - assert build_options.architectures == {Architecture.x86_64} + assert build_options.architectures == {Architecture.AMD64} elif platform == 'macos': assert build_options.architectures == {Architecture.x86_64} From cc0e7ec0a1020a9adb41fa2c33663731f078b075 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Fri, 22 Jan 2021 08:54:19 -0500 Subject: [PATCH 6/8] fix: review from @joerick --- cibuildwheel/__main__.py | 10 +++++----- test/test_cpp_standards.py | 2 +- test/utils.py | 7 ++++--- unit_test/main_tests/main_platform_test.py | 6 ------ 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/cibuildwheel/__main__.py b/cibuildwheel/__main__.py index bcdfef8c..538d56f1 100644 --- a/cibuildwheel/__main__.py +++ b/cibuildwheel/__main__.py @@ -257,6 +257,11 @@ def main() -> None: print_preamble(platform, build_options) + if not identifiers: + print(f'cibuildwheel: No build identifiers selected: {build_selector}', file=sys.stderr) + if not args.allow_empty: + sys.exit(3) + if not output_dir.exists(): output_dir.mkdir(parents=True) @@ -269,11 +274,6 @@ def main() -> None: else: assert_never(platform) - if not identifiers: - print(f'cibuildwheel: No build identifiers selected: {build_selector}', file=sys.stderr) - if not args.allow_empty: - sys.exit(3) - def detect_obsolete_options() -> None: # Check the old 'MANYLINUX1_*_IMAGE' options diff --git a/test/test_cpp_standards.py b/test/test_cpp_standards.py index 8ab5becd..762414bf 100644 --- a/test/test_cpp_standards.py +++ b/test/test_cpp_standards.py @@ -202,7 +202,7 @@ def test_cpp17_py27_modern_msvc_workaround(tmp_path): add_env_x64['CIBW_BUILD'] = 'cp27-win_amd64' actual_wheels += utils.cibuildwheel_run(project_dir, add_env=add_env_x64) - expected_wheels = [w for w in utils.expected_wheels('spam', '0.1.0', filter_27=False) + expected_wheels = [w for w in utils.expected_wheels('spam', '0.1.0', exclude_27=False) if 'cp27-cp27m-win' in w or 'pp27-pypy_73-win32' in w] diff --git a/test/utils.py b/test/utils.py index 4fcdba47..8b11a0e6 100644 --- a/test/utils.py +++ b/test/utils.py @@ -77,7 +77,7 @@ def cibuildwheel_run(project_path, package_dir='.', env=None, add_env=None, outp def expected_wheels(package_name, package_version, manylinux_versions=None, macosx_deployment_target='10.9', machine_arch=None, *, - filter_27=IS_WINDOWS_RUNNING_ON_TRAVIS): + exclude_27=IS_WINDOWS_RUNNING_ON_TRAVIS): ''' Returns a list of expected wheels from a run of cibuildwheel. ''' @@ -135,8 +135,9 @@ def expected_wheels(package_name, package_version, manylinux_versions=None, for platform_tag in platform_tags: wheels.append(f'{package_name}-{package_version}-{python_abi_tag}-{platform_tag}.whl') - if filter_27: - # Python 2.7 isn't supported on Travis. + # Travis on Windows does not support using the default Python 2.7 compiler, + # so we support skipping here. + if exclude_27: wheels = [w for w in wheels if '-cp27-' not in w and '-pp2' not in w] return wheels diff --git a/unit_test/main_tests/main_platform_test.py b/unit_test/main_tests/main_platform_test.py index 844cf811..aa004c5c 100644 --- a/unit_test/main_tests/main_platform_test.py +++ b/unit_test/main_tests/main_platform_test.py @@ -1,4 +1,3 @@ -import platform as platform_module import sys import pytest @@ -68,7 +67,6 @@ def test_platform_environment(platform, intercepted_build_args, monkeypatch): def test_archs_default(platform, intercepted_build_args, monkeypatch): - monkeypatch.setattr(platform_module, 'machine', lambda: 'AMD64' if platform == 'windows' else 'x86_64') main() build_options = intercepted_build_args.args[0] @@ -86,7 +84,6 @@ def test_archs_argument(platform, intercepted_build_args, monkeypatch, use_env_v if platform == 'windows': pytest.skip('Will have empty build selectors on Windows') - monkeypatch.setattr(platform_module, 'machine', lambda: 'x86_64') if use_env_var: monkeypatch.setenv('CIBW_ARCHS', 'ppc64le') else: @@ -100,7 +97,6 @@ def test_archs_argument(platform, intercepted_build_args, monkeypatch, use_env_v def test_archs_platform_specific(platform, intercepted_build_args, monkeypatch): - monkeypatch.setattr(platform_module, 'machine', lambda: 'x86_64') monkeypatch.setenv('CIBW_ARCHS', 'unused') monkeypatch.setenv('CIBW_ARCHS_LINUX', 'ppc64le') monkeypatch.setenv('CIBW_ARCHS_WINDOWS', 'x86') @@ -118,7 +114,6 @@ def test_archs_platform_specific(platform, intercepted_build_args, monkeypatch): def test_archs_platform_native(platform, intercepted_build_args, monkeypatch): - monkeypatch.setattr(platform_module, 'machine', lambda: 'AMD64' if platform == 'windows' else 'x86_64') monkeypatch.setenv('CIBW_ARCHS', 'native') main() @@ -133,7 +128,6 @@ def test_archs_platform_native(platform, intercepted_build_args, monkeypatch): def test_archs_platform_all(platform, intercepted_build_args, monkeypatch): - monkeypatch.setattr(platform_module, 'machine', lambda: 'x86_64') monkeypatch.setenv('CIBW_ARCHS', 'all') main() From f5b84797e52181bb0387afaab725a2293a51f7d6 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Fri, 22 Jan 2021 09:23:52 -0500 Subject: [PATCH 7/8] fix: move and simplify arch check --- cibuildwheel/__main__.py | 7 +++++++ cibuildwheel/linux.py | 3 --- cibuildwheel/macos.py | 3 --- cibuildwheel/windows.py | 3 --- unit_test/main_tests/main_platform_test.py | 13 ++++++++----- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/cibuildwheel/__main__.py b/cibuildwheel/__main__.py index 538d56f1..010d9eea 100644 --- a/cibuildwheel/__main__.py +++ b/cibuildwheel/__main__.py @@ -20,6 +20,7 @@ from cibuildwheel.util import ( DependencyConstraints, TestSelector, Unbuffered, + allowed_architectures_check, detect_ci_provider, resources_dir, ) @@ -257,6 +258,12 @@ def main() -> None: print_preamble(platform, build_options) + try: + allowed_architectures_check(platform, build_options) + 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_selector}', file=sys.stderr) if not args.allow_empty: diff --git a/cibuildwheel/linux.py b/cibuildwheel/linux.py index 1a104d7c..ce725b55 100644 --- a/cibuildwheel/linux.py +++ b/cibuildwheel/linux.py @@ -12,7 +12,6 @@ from .util import ( BuildOptions, BuildSelector, NonPlatformWheelError, - allowed_architectures_check, get_build_verbosity_extra_flags, prepare_command, read_python_configs, @@ -49,8 +48,6 @@ def get_python_configurations( def build(options: BuildOptions) -> None: - allowed_architectures_check('linux', options) - try: subprocess.check_output(['docker', '--version']) except Exception: diff --git a/cibuildwheel/macos.py b/cibuildwheel/macos.py index 66b41b3f..cf691995 100644 --- a/cibuildwheel/macos.py +++ b/cibuildwheel/macos.py @@ -14,7 +14,6 @@ from .util import ( BuildOptions, BuildSelector, NonPlatformWheelError, - allowed_architectures_check, download, get_build_verbosity_extra_flags, get_pip_script, @@ -188,8 +187,6 @@ def setup_python(python_configuration: PythonConfiguration, def build(options: BuildOptions) -> None: - allowed_architectures_check("macos", options) - temp_dir = Path(tempfile.mkdtemp(prefix='cibuildwheel')) built_wheel_dir = temp_dir / 'built_wheel' repaired_wheel_dir = temp_dir / 'repaired_wheel' diff --git a/cibuildwheel/windows.py b/cibuildwheel/windows.py index 5e8c1683..e2a6d254 100644 --- a/cibuildwheel/windows.py +++ b/cibuildwheel/windows.py @@ -17,7 +17,6 @@ from .util import ( BuildOptions, BuildSelector, NonPlatformWheelError, - allowed_architectures_check, download, get_build_verbosity_extra_flags, get_pip_script, @@ -207,8 +206,6 @@ def pep_518_cp35_workaround(package_dir: Path, env: Dict[str, str]) -> None: def build(options: BuildOptions) -> None: - allowed_architectures_check('windows', options) - temp_dir = Path(tempfile.mkdtemp(prefix='cibuildwheel')) built_wheel_dir = temp_dir / 'built_wheel' repaired_wheel_dir = temp_dir / 'repaired_wheel' diff --git a/unit_test/main_tests/main_platform_test.py b/unit_test/main_tests/main_platform_test.py index aa004c5c..e0897dc8 100644 --- a/unit_test/main_tests/main_platform_test.py +++ b/unit_test/main_tests/main_platform_test.py @@ -81,8 +81,6 @@ def test_archs_default(platform, intercepted_build_args, monkeypatch): @pytest.mark.parametrize('use_env_var', [False, True]) def test_archs_argument(platform, intercepted_build_args, monkeypatch, use_env_var): - if platform == 'windows': - pytest.skip('Will have empty build selectors on Windows') if use_env_var: monkeypatch.setenv('CIBW_ARCHS', 'ppc64le') @@ -90,10 +88,15 @@ def test_archs_argument(platform, intercepted_build_args, monkeypatch, use_env_v monkeypatch.setenv('CIBW_ARCHS', 'unused') monkeypatch.setattr(sys, 'argv', sys.argv + ['--archs', 'ppc64le']) - main() - build_options = intercepted_build_args.args[0] + if platform in {'macos', 'windows'}: + with pytest.raises(SystemExit) as err: + main() + assert err.value.args == (4,) - assert build_options.architectures == {Architecture.ppc64le} + else: + main() + build_options = intercepted_build_args.args[0] + assert build_options.architectures == {Architecture.ppc64le} def test_archs_platform_specific(platform, intercepted_build_args, monkeypatch): From ff8f8810988b5bde2b9d5ceaddbf4ded22069b5a Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Fri, 22 Jan 2021 09:33:22 -0500 Subject: [PATCH 8/8] refactor: pull arch out into separate file --- cibuildwheel/__main__.py | 5 +- cibuildwheel/architecture.py | 86 ++++++++++++++++++++++ cibuildwheel/linux.py | 2 +- cibuildwheel/util.py | 86 +--------------------- cibuildwheel/windows.py | 2 +- unit_test/main_tests/main_platform_test.py | 4 +- 6 files changed, 94 insertions(+), 91 deletions(-) create mode 100644 cibuildwheel/architecture.py diff --git a/cibuildwheel/__main__.py b/cibuildwheel/__main__.py index 010d9eea..8f65f28b 100644 --- a/cibuildwheel/__main__.py +++ b/cibuildwheel/__main__.py @@ -11,16 +11,15 @@ import cibuildwheel import cibuildwheel.linux import cibuildwheel.macos import cibuildwheel.windows +from cibuildwheel.architecture import Architecture, allowed_architectures_check from cibuildwheel.environment import EnvironmentParseError, parse_environment from cibuildwheel.typing import PLATFORMS, PlatformName, assert_never from cibuildwheel.util import ( - Architecture, BuildOptions, BuildSelector, DependencyConstraints, TestSelector, Unbuffered, - allowed_architectures_check, detect_ci_provider, resources_dir, ) @@ -259,7 +258,7 @@ def main() -> None: print_preamble(platform, build_options) try: - allowed_architectures_check(platform, build_options) + allowed_architectures_check(platform, build_options.architectures) except ValueError as err: print("cibuildwheel:", *err.args, file=sys.stderr) sys.exit(4) diff --git a/cibuildwheel/architecture.py b/cibuildwheel/architecture.py new file mode 100644 index 00000000..f7bf4354 --- /dev/null +++ b/cibuildwheel/architecture.py @@ -0,0 +1,86 @@ +import functools +import platform as platform_module +import re +from enum import Enum +from typing import Set + +from .typing import PlatformName, assert_never + +PRETTY_NAMES = {'linux': 'Linux', 'macos': 'macOS', 'windows': 'Windows'} + + +@functools.total_ordering +class Architecture(Enum): + value: str + + # mac/linux archs + x86_64 = 'x86_64' + i686 = 'i686' + aarch64 = 'aarch64' + ppc64le = 'ppc64le' + s390x = 's390x' + + # windows archs + x86 = 'x86' + AMD64 = 'AMD64' + + # Allow this to be sorted + def __lt__(self, other: "Architecture") -> bool: + return self.value < other.value + + @staticmethod + def parse_config(config: str, platform: PlatformName) -> 'Set[Architecture]': + result = set() + for arch_str in re.split(r'[\s,]+', config): + if arch_str == 'auto': + result |= Architecture.auto_archs(platform=platform) + elif arch_str == 'native': + result.add(Architecture(platform_module.machine())) + elif arch_str == 'all': + result |= Architecture.all_archs(platform=platform) + else: + result.add(Architecture(arch_str)) + return result + + @staticmethod + def auto_archs(platform: PlatformName) -> 'Set[Architecture]': + native_architecture = Architecture(platform_module.machine()) + result = {native_architecture} + if platform == 'linux' and native_architecture == Architecture.x86_64: + # x86_64 machines can run i686 docker containers + result.add(Architecture.i686) + if platform == 'windows' and native_architecture == Architecture.AMD64: + result.add(Architecture.x86) + return result + + @staticmethod + def all_archs(platform: PlatformName) -> 'Set[Architecture]': + if platform == 'linux': + return {Architecture.x86_64, Architecture.i686, Architecture.aarch64, Architecture.ppc64le, Architecture.s390x} + elif platform == 'macos': + return {Architecture.x86_64} + elif platform == 'windows': + return {Architecture.x86, Architecture.AMD64} + else: + assert_never(platform) + + +def allowed_architectures_check( + platform: PlatformName, + architectures: Set[Architecture], +) -> None: + + allowed_architectures = Architecture.all_archs(platform) + + msg = f'{PRETTY_NAMES[platform]} only supports {sorted(allowed_architectures)} at the moment.' + + if platform != 'linux': + msg += ' If you want to set emulation architectures on Linux, use CIBW_ARCHS_LINUX instead.' + + if not architectures <= allowed_architectures: + msg = f'Invalid archs option {architectures}. ' + msg + raise ValueError(msg) + + if not architectures: + msg = 'Empty archs option set. ' + msg + raise ValueError(msg) diff --git a/cibuildwheel/linux.py b/cibuildwheel/linux.py index ce725b55..13354f43 100644 --- a/cibuildwheel/linux.py +++ b/cibuildwheel/linux.py @@ -4,11 +4,11 @@ import textwrap from pathlib import Path, PurePath from typing import List, NamedTuple, Set +from .architecture import Architecture from .docker_container import DockerContainer from .logger import log from .typing import PathOrStr from .util import ( - Architecture, BuildOptions, BuildSelector, NonPlatformWheelError, diff --git a/cibuildwheel/util.py b/cibuildwheel/util.py index 33435c16..1baf71a9 100644 --- a/cibuildwheel/util.py +++ b/cibuildwheel/util.py @@ -1,9 +1,6 @@ import fnmatch -import functools import itertools import os -import platform as platform_module -import re import ssl import sys import textwrap @@ -17,8 +14,9 @@ import bracex import certifi import toml +from .architecture import Architecture from .environment import ParsedEnvironment -from .typing import PathOrStr, PlatformName, assert_never +from .typing import PathOrStr, PlatformName if sys.version_info < (3, 9): from importlib_resources import files @@ -163,62 +161,6 @@ class DependencyConstraints: return f'{self.__class__.__name__}{self.base_file_path!r})' -@functools.total_ordering -class Architecture(Enum): - value: str - - # mac/linux archs - x86_64 = 'x86_64' - i686 = 'i686' - aarch64 = 'aarch64' - ppc64le = 'ppc64le' - s390x = 's390x' - - # windows archs - x86 = 'x86' - AMD64 = 'AMD64' - - # Allow this to be sorted - def __lt__(self, other: "Architecture") -> bool: - return self.value < other.value - - @staticmethod - def parse_config(config: str, platform: PlatformName) -> 'Set[Architecture]': - result = set() - for arch_str in re.split(r'[\s,]+', config): - if arch_str == 'auto': - result |= Architecture.auto_archs(platform=platform) - elif arch_str == 'native': - result.add(Architecture(platform_module.machine())) - elif arch_str == 'all': - result |= Architecture.all_archs(platform=platform) - else: - result.add(Architecture(arch_str)) - return result - - @staticmethod - def auto_archs(platform: PlatformName) -> 'Set[Architecture]': - native_architecture = Architecture(platform_module.machine()) - result = {native_architecture} - if platform == 'linux' and native_architecture == Architecture.x86_64: - # x86_64 machines can run i686 docker containers - result.add(Architecture.i686) - if platform == 'windows' and native_architecture == Architecture.AMD64: - result.add(Architecture.x86) - return result - - @staticmethod - def all_archs(platform: PlatformName) -> 'Set[Architecture]': - if platform == 'linux': - return {Architecture.x86_64, Architecture.i686, Architecture.aarch64, Architecture.ppc64le, Architecture.s390x} - elif platform == 'macos': - return {Architecture.x86_64} - elif platform == 'windows': - return {Architecture.x86, Architecture.AMD64} - else: - assert_never(platform) - - class BuildOptions(NamedTuple): package_dir: Path output_dir: Path @@ -286,27 +228,3 @@ def detect_ci_provider() -> Optional[CIProvider]: return CIProvider.other else: return None - - -PRETTY_NAMES = {'linux': 'Linux', 'macos': 'macOS', 'windows': 'Windows'} - - -def allowed_architectures_check( - platform: PlatformName, - options: BuildOptions, -) -> None: - - allowed_architectures = Architecture.all_archs(platform) - - msg = f'{PRETTY_NAMES[platform]} only supports {sorted(allowed_architectures)} at the moment.' - - if platform != 'linux': - msg += ' If you want to set emulation architectures on Linux, use CIBW_ARCHS_LINUX instead.' - - if not options.architectures <= allowed_architectures: - msg = f'Invalid archs option {options.architectures}. ' + msg - raise ValueError(msg) - - if not options.architectures: - msg = 'Empty archs option set. ' + msg - raise ValueError(msg) diff --git a/cibuildwheel/windows.py b/cibuildwheel/windows.py index e2a6d254..4d3487ca 100644 --- a/cibuildwheel/windows.py +++ b/cibuildwheel/windows.py @@ -9,11 +9,11 @@ from zipfile import ZipFile import toml +from .architecture import Architecture from .environment import ParsedEnvironment from .logger import log from .typing import PathOrStr from .util import ( - Architecture, BuildOptions, BuildSelector, NonPlatformWheelError, diff --git a/unit_test/main_tests/main_platform_test.py b/unit_test/main_tests/main_platform_test.py index e0897dc8..a06ffe68 100644 --- a/unit_test/main_tests/main_platform_test.py +++ b/unit_test/main_tests/main_platform_test.py @@ -89,9 +89,9 @@ def test_archs_argument(platform, intercepted_build_args, monkeypatch, use_env_v monkeypatch.setattr(sys, 'argv', sys.argv + ['--archs', 'ppc64le']) if platform in {'macos', 'windows'}: - with pytest.raises(SystemExit) as err: + with pytest.raises(SystemExit) as exit: main() - assert err.value.args == (4,) + assert exit.value.args == (4,) else: main()