From b779a88fde08aa85dd2e86dea536b70dfcad913c Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Tue, 28 Jan 2020 21:28:22 +0000 Subject: [PATCH 1/9] Add note about 254 {vmImage: 'vs2017-win2016'} on Azure to docs See #254 --- docs/setup.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/setup.md b/docs/setup.md index 01580747..c45c4333 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -11,6 +11,9 @@ Using Azure pipelines, you can build all three platforms on the same service. Cr {% include "../examples/azure-pipelines-minimal.yml" %} ``` +!!! note + To support Python 3.5 on Windows, make sure to specify the use of `{vmImage: 'vs2017-win2016'}` on Windows, to ensure the required toolchain is available. + Commit this file, enable building of your repo on Azure Pipelines, and push. Wheels will be stored for you and available through the Pipelines interface. For more info on this file, check out the [docs](https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema). From 513ef49cd43b4c4d80fcf11afa48cefde8deb784 Mon Sep 17 00:00:00 2001 From: mayeut Date: Tue, 19 Nov 2019 23:36:20 +0100 Subject: [PATCH 2/9] Only build x86_64 / Intel 10.9+ on macOS --- README.md | 14 +++++++------- cibuildwheel/__main__.py | 4 ++-- cibuildwheel/macos.py | 23 ++++++++++++++--------- docs/options.md | 20 ++++++++++---------- test/shared/utils.py | 14 ++++++-------- unit_test/main_options_test.py | 16 ++++++++-------- 6 files changed, 47 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 38d8413c..2989eac2 100644 --- a/README.md +++ b/README.md @@ -15,13 +15,13 @@ Python wheels are great. Building them across **Mac, Linux, Windows**, on **mult What does it do? ---------------- -| | macOS 10.6+ intel | macOS 10.9+ x86_64 | manylinux i686 | manylinux x86_64 | Windows 32bit | Windows 64bit | -|---|---|---|---|---|---|---| -| Python 2.7 | ✅ | | ✅ | ✅ | ✅¹ | ✅¹ | -| Python 3.5 | ✅ | | ✅ | ✅ | ✅ | ✅ | -| Python 3.6 | ✅ | | ✅ | ✅ | ✅ | ✅ | -| Python 3.7 | ✅ | | ✅ | ✅ | ✅ | ✅ | -| Python 3.8 | | ✅ | ✅ | ✅ | ✅ | ✅ | +| | macOS 10.9+ x86_64 | manylinux i686 | manylinux x86_64 | Windows 32bit | Windows 64bit | +|---|---|---|---|---|---| +| Python 2.7 | ✅ | ✅ | ✅ | ✅¹ | ✅¹ | +| Python 3.5 | ✅ | ✅ | ✅ | ✅ | ✅ | +| Python 3.6 | ✅ | ✅ | ✅ | ✅ | ✅ | +| Python 3.7 | ✅ | ✅ | ✅ | ✅ | ✅ | +| Python 3.8 | ✅ | ✅ | ✅ | ✅ | ✅ | > ¹ Not supported on Travis diff --git a/cibuildwheel/__main__.py b/cibuildwheel/__main__.py index 9b3db905..e4a1b016 100644 --- a/cibuildwheel/__main__.py +++ b/cibuildwheel/__main__.py @@ -61,7 +61,7 @@ def main(): args = parser.parse_args() detect_obsolete_options() - + if args.platform != 'auto': platform = args.platform else: @@ -97,7 +97,7 @@ def main(): if platform == 'linux': repair_command_default = 'auditwheel repair -w {dest_dir} {wheel}' elif platform == 'macos': - repair_command_default = 'delocate-listdeps {wheel} && delocate-wheel -w {dest_dir} {wheel}' + repair_command_default = 'delocate-listdeps {wheel} && delocate-wheel --require-archs x86_64 -w {dest_dir} {wheel}' else: repair_command_default = '' repair_command = get_option_from_environment('CIBW_REPAIR_WHEEL_COMMAND', platform=platform, default=repair_command_default) diff --git a/cibuildwheel/macos.py b/cibuildwheel/macos.py index d7a50d0c..c137da8a 100644 --- a/cibuildwheel/macos.py +++ b/cibuildwheel/macos.py @@ -14,11 +14,11 @@ from .util import prepare_command, get_build_verbosity_extra_flags def get_python_configurations(build_selector): PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'identifier', 'url']) python_configurations = [ - PythonConfiguration(version='2.7', identifier='cp27-macosx_intel', url='https://www.python.org/ftp/python/2.7.17/python-2.7.17-macosx10.6.pkg'), - PythonConfiguration(version='3.5', identifier='cp35-macosx_intel', url='https://www.python.org/ftp/python/3.5.4/python-3.5.4-macosx10.6.pkg'), - PythonConfiguration(version='3.6', identifier='cp36-macosx_intel', url='https://www.python.org/ftp/python/3.6.8/python-3.6.8-macosx10.6.pkg'), - PythonConfiguration(version='3.7', identifier='cp37-macosx_intel', url='https://www.python.org/ftp/python/3.7.5/python-3.7.5-macosx10.6.pkg'), - PythonConfiguration(version='3.8', identifier='cp38-macosx_x86_64', url='https://www.python.org/ftp/python/3.8.0/python-3.8.0-macosx10.9.pkg'), + PythonConfiguration(version='2.7', identifier='cp27-macosx_x86_64', url='https://www.python.org/ftp/python/2.7.17/python-2.7.17-macosx10.9.pkg'), + PythonConfiguration(version='3.5', identifier='cp35-macosx_x86_64', url='https://www.python.org/ftp/python/3.5.4/python-3.5.4-macosx10.6.pkg'), + PythonConfiguration(version='3.6', identifier='cp36-macosx_x86_64', url='https://www.python.org/ftp/python/3.6.8/python-3.6.8-macosx10.9.pkg'), + PythonConfiguration(version='3.7', identifier='cp37-macosx_x86_64', url='https://www.python.org/ftp/python/3.7.6/python-3.7.6-macosx10.9.pkg'), + PythonConfiguration(version='3.8', identifier='cp38-macosx_x86_64', url='https://www.python.org/ftp/python/3.8.1/python-3.8.1-macosx10.9.pkg'), ] # skip builds as required @@ -32,6 +32,7 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef repaired_wheel_dir = os.path.join(temp_dir, 'repaired_wheel') python_configurations = get_python_configurations(build_selector) + get_pip_url = 'https://bootstrap.pypa.io/get-pip.py' get_pip_script = '/tmp/get-pip.py' @@ -50,20 +51,19 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef return subprocess.check_call(args, env=env, cwd=cwd, shell=shell) # get latest pip once and for all - - call(['curl', '-L', '--retry', '3', '--retry-delay', '3', '-o', get_pip_script, get_pip_url]) + call(['curl', '--retry', '3', '--retry-delay', '3', '-sSLo', get_pip_script, get_pip_url]) for config in python_configurations: # if this version of python isn't installed, get it from python.org and install python_package_identifier = 'org.python.Python.PythonFramework-%s' % config.version if python_package_identifier not in installed_system_packages: # download the pkg - call(['curl', '-L', '-o', '/tmp/Python.pkg', config.url]) + call(['curl', '--retry', '3', '--retry-delay', '3', '-sSLo', '/tmp/Python.pkg', config.url]) # install call(['sudo', 'installer', '-pkg', '/tmp/Python.pkg', '-target', '/']) # patch open ssl if config.version == '3.5': - call(['curl', '-fsSLo', '/tmp/python-patch.tar.gz', 'https://github.com/mayeut/patch-macos-python-openssl/releases/download/v1.0.2t/patch-macos-python-%s-openssl-v1.0.2t.tar.gz' % config.version]) + call(['curl', '--retry', '3', '--retry-delay', '3', '-fsSLo', '/tmp/python-patch.tar.gz', 'https://github.com/mayeut/patch-macos-python-openssl/releases/download/v1.0.2t/patch-macos-python-%s-openssl-v1.0.2t.tar.gz' % config.version]) call(['sudo', 'tar', '-C', '/Library/Frameworks/Python.framework/Versions/%s/' % config.version, '-xmf', '/tmp/python-patch.tar.gz']) installation_bin_path = '/Library/Frameworks/Python.framework/Versions/{}/bin'.format(config.version) @@ -98,6 +98,11 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef call(['pip', '--version'], env=env) call(['pip', 'install', '--upgrade', 'setuptools', 'wheel', 'delocate'], env=env) + # setup target platform, only required for python 3.5 + if config.version == '3.5': + env['_PYTHON_HOST_PLATFORM'] = 'macosx-10.9-x86_64' # cross-compilation platform override + env['ARCHFLAGS'] = '-arch x86_64' # https://github.com/python/cpython/blob/a5ed2fe0eedefa1649aa93ee74a0bafc8e628a10/Lib/_osx_support.py#L260 + # run the before_build command if before_build: before_build_prepared = prepare_command(before_build, project=abs_project_dir) diff --git a/docs/options.md b/docs/options.md index 52433586..82c1f435 100644 --- a/docs/options.md +++ b/docs/options.md @@ -64,7 +64,7 @@ This option can also be set using the command-line option `--platform`. > Choose the Python versions to build -Space-separated list of builds to build and skip. Each build has an identifier like `cp27-manylinux_x86_64` or `cp35-macosx_intel` - you can list specific ones to build and `cibuildwheel` will only build those, and/or list ones to skip and `cibuildwheel` won't try to build them. +Space-separated list of builds to build and skip. Each build has an identifier like `cp27-manylinux_x86_64` or `cp35-macosx_x86_64` - you can list specific ones to build and `cibuildwheel` will only build those, and/or list ones to skip and `cibuildwheel` won't try to build them. When both options are specified, both conditions are applied and only builds with a tag that matches `CIBW_BUILD` and does not match `CIBW_SKIP` will be built. @@ -72,13 +72,13 @@ When setting the options, you can use shell-style globbing syntax (as per `fnmat
-| | macOS 64bit | macOS 32/64bit | Manylinux 64bit | Manylinux 32bit | Windows 64bit | Windows 32bit | -|------------|---------------------|--------------------|------------------------|----------------------|-----------------|----------------| -| Python 2.7 | | cp27-macosx_intel | cp27-manylinux_x86_64 | cp27-manylinux_i686 | cp27-win_amd64 | cp27-win32 | -| Python 3.5 | | cp35-macosx_intel | cp35-manylinux_x86_64 | cp35-manylinux_i686 | cp35-win_amd64 | cp35-win32 | -| Python 3.6 | | cp36-macosx_intel | cp36-manylinux_x86_64 | cp36-manylinux_i686 | cp36-win_amd64 | cp36-win32 | -| Python 3.7 | | cp37-macosx_intel | cp37-manylinux_x86_64 | cp37-manylinux_i686 | cp37-win_amd64 | cp37-win32 | -| Python 3.8 | cp38-macosx_x86_64 | | cp38-manylinux_x86_64 | cp38-manylinux_i686 | cp38-win_amd64 | cp38-win32 | +| | macOS 64bit | Manylinux 64bit | Manylinux 32bit | Windows 64bit | Windows 32bit | +|------------|--------------------|------------------------|----------------------|-----------------|----------------| +| Python 2.7 | cp27-macosx_x86_64 | cp27-manylinux_x86_64 | cp27-manylinux_i686 | cp27-win_amd64 | cp27-win32 | +| Python 3.5 | cp35-macosx_x86_64 | cp35-manylinux_x86_64 | cp35-manylinux_i686 | cp35-win_amd64 | cp35-win32 | +| Python 3.6 | cp36-macosx_x86_64 | cp36-manylinux_x86_64 | cp36-manylinux_i686 | cp36-win_amd64 | cp36-win32 | +| Python 3.7 | cp37-macosx_x86_64 | cp37-manylinux_x86_64 | cp37-manylinux_i686 | cp37-win_amd64 | cp37-win32 | +| Python 3.8 | cp38-macosx_x86_64 | cp38-manylinux_x86_64 | cp38-manylinux_i686 | cp38-win_amd64 | cp38-win32 | The list of supported and currently selected build identifiers can also be retrieved by passing the `--print-build-identifiers` flag to `cibuildwheel`. The format is `python_tag-platform_tag`, with tags similar to those in [PEP 425](https://www.python.org/dev/peps/pep-0425/#details). @@ -90,7 +90,7 @@ The format is `python_tag-platform_tag`, with tags similar to those in [PEP 425] CIBW_BUILD: cp36-* # Skip building on Python 2.7 on the Mac -CIBW_SKIP: cp27-macosx_intel +CIBW_SKIP: cp27-macosx_x86_64 # Skip building on Python 3.8 on the Mac CIBW_SKIP: cp38-macosx_x86_64 @@ -208,7 +208,7 @@ CIBW_BEFORE_BUILD: yum install -y libffi-dev && pip install . Default: - on Linux: `'auditwheel repair -w {dest_dir} {wheel}'` -- on macOS: `'delocate-listdeps {wheel} && delocate-wheel -w {dest_dir} {wheel}'` +- on macOS: `'delocate-listdeps {wheel} && delocate-wheel --require-archs x86_64 -w {dest_dir} {wheel}'` - on Windows: `''` A shell command to repair a built wheel by copying external library dependencies into the wheel tree and relinking them. diff --git a/test/shared/utils.py b/test/shared/utils.py index 9ed730ff..09923326 100644 --- a/test/shared/utils.py +++ b/test/shared/utils.py @@ -86,22 +86,20 @@ def expected_wheels(package_name, package_version, manylinux_versions=['manylinu platform_tags.append('{manylinux_version}_{architecture}'.format( manylinux_version=manylinux_version, architecture=architecture )) - + def get_platform_tags(python_abi_tag): return platform_tags - + elif platform == 'windows': def get_platform_tags(python_abi_tag): return ['win32', 'win_amd64'] - + elif platform == 'macos': - + def get_platform_tags(python_abi_tag): - if python_abi_tag == 'cp38-cp38': - return ['macosx_' + (macosx_deployment_target or "10.9").replace(".", "_") + '_x86_64'] - else: - return ['macosx_' + (macosx_deployment_target or "10.6").replace(".", "_") + '_intel'] + return ['macosx_' + (macosx_deployment_target or "10.9").replace(".", "_") + '_x86_64'] + else: raise Exception('unsupported platform') diff --git a/unit_test/main_options_test.py b/unit_test/main_options_test.py index 90935fe8..ece86fce 100644 --- a/unit_test/main_options_test.py +++ b/unit_test/main_options_test.py @@ -50,7 +50,7 @@ def test_build_selector(platform, intercepted_build_args, monkeypatch): monkeypatch.setenv('CIBW_SKIP', SKIP) main() - + intercepted_build_selector = intercepted_build_args.kwargs['build_selector'] assert isinstance(intercepted_build_selector, BuildSelector) assert intercepted_build_selector('build-this') @@ -60,12 +60,12 @@ def test_build_selector(platform, intercepted_build_args, monkeypatch): @pytest.mark.parametrize('architecture, image, full_image', [ - ('x86_64', None, 'quay.io/pypa/manylinux2010_x86_64'), + ('x86_64', None, 'quay.io/pypa/manylinux2010_x86_64'), ('x86_64', 'manylinux1', 'quay.io/pypa/manylinux1_x86_64'), ('x86_64', 'manylinux2010', 'quay.io/pypa/manylinux2010_x86_64'), ('x86_64', 'manylinux2014', 'quay.io/pypa/manylinux2014_x86_64'), ('x86_64', 'custom_image', 'custom_image'), - ('i686', None, 'quay.io/pypa/manylinux2010_i686'), + ('i686', None, 'quay.io/pypa/manylinux2010_i686'), ('i686', 'manylinux1', 'quay.io/pypa/manylinux1_i686'), ('i686', 'manylinux2010', 'quay.io/pypa/manylinux2010_i686'), ('i686', 'manylinux2014', 'quay.io/pypa/manylinux2014_i686'), @@ -87,7 +87,7 @@ def get_default_repair_command(platform): if platform == 'linux': return 'auditwheel repair -w {dest_dir} {wheel}' elif platform == 'macos': - return 'delocate-listdeps {wheel} && delocate-wheel -w {dest_dir} {wheel}' + return 'delocate-listdeps {wheel} && delocate-wheel --require-archs x86_64 -w {dest_dir} {wheel}' elif platform == 'windows': return '' else: @@ -139,9 +139,9 @@ def test_test_requires(test_requires, platform_specific, platform, intercepted_b monkeypatch.setenv('CIBW_TEST_REQUIRES', 'overwritten') else: monkeypatch.setenv('CIBW_TEST_REQUIRES', test_requires) - + main() - + assert intercepted_build_args.kwargs['test_requires'] == (test_requires or '').split() @@ -154,9 +154,9 @@ def test_test_extras(test_extras, platform_specific, platform, intercepted_build monkeypatch.setenv('CIBW_TEST_EXTRAS', 'overwritten') else: monkeypatch.setenv('CIBW_TEST_EXTRAS', test_extras) - + main() - + assert intercepted_build_args.kwargs['test_extras'] == ('[' + test_extras + ']' if test_extras else '') From 88029d2a28a36be58904cb2cec3ccca0500da3c1 Mon Sep 17 00:00:00 2001 From: Yannick Jadoul Date: Thu, 30 Jan 2020 17:20:14 +0100 Subject: [PATCH 3/9] Clean up temporary workaround in test/06_docker_images/cibuildwheel_test.py --- test/06_docker_images/cibuildwheel_test.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/06_docker_images/cibuildwheel_test.py b/test/06_docker_images/cibuildwheel_test.py index 4fb6941d..1bfc50a7 100644 --- a/test/06_docker_images/cibuildwheel_test.py +++ b/test/06_docker_images/cibuildwheel_test.py @@ -9,12 +9,9 @@ def test(): actual_wheels = utils.cibuildwheel_run(project_dir, add_env={ 'CIBW_MANYLINUX_X86_64_IMAGE': 'dockcross/manylinux2010-x64', - 'CIBW_MANYLINUX_I686_IMAGE': 'dockcross/manylinux1-x86', - 'CIBW_BEFORE_BUILD': '/opt/python/cp36-cp36m/bin/pip install -U auditwheel', # Currently necessary on dockcross images to get auditwheel 2.1 supporting AUDITWHEEL_PLAT - 'CIBW_ENVIRONMENT': 'AUDITWHEEL_PLAT=`if [ $(uname -i) == "x86_64" ]; then echo "manylinux2010_x86_64"; else echo "manylinux1_i686"; fi`', + 'CIBW_MANYLINUX_I686_IMAGE': 'dockcross/manylinux2010-x86', }) # also check that we got the right wheels built - expected_wheels = [w for w in utils.expected_wheels('spam', '0.1.0') - if '-manylinux2010_i686' not in w] + expected_wheels = utils.expected_wheels('spam', '0.1.0') assert set(actual_wheels) == set(expected_wheels) From 1a7d1d8cb1d9ef4a0119518144a1e4490edf4501 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Fri, 31 Jan 2020 17:05:32 +0000 Subject: [PATCH 4/9] Add MACOSX_DEPLOYMENT_TARGET flag and don't overwrite user-set env vars --- cibuildwheel/macos.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cibuildwheel/macos.py b/cibuildwheel/macos.py index c137da8a..e677d813 100644 --- a/cibuildwheel/macos.py +++ b/cibuildwheel/macos.py @@ -100,8 +100,14 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef # setup target platform, only required for python 3.5 if config.version == '3.5': - env['_PYTHON_HOST_PLATFORM'] = 'macosx-10.9-x86_64' # cross-compilation platform override - env['ARCHFLAGS'] = '-arch x86_64' # https://github.com/python/cpython/blob/a5ed2fe0eedefa1649aa93ee74a0bafc8e628a10/Lib/_osx_support.py#L260 + if '_PYTHON_HOST_PLATFORM' not in env: + # cross-compilation platform override + env['_PYTHON_HOST_PLATFORM'] = 'macosx-10.9-x86_64' + if 'ARCHFLAGS' not in env: + # https://github.com/python/cpython/blob/a5ed2fe0eedefa1649aa93ee74a0bafc8e628a10/Lib/_osx_support.py#L260 + env['ARCHFLAGS'] = '-arch x86_64' + if 'MACOSX_DEPLOYMENT_TARGET' not in env: + env['MACOSX_DEPLOYMENT_TARGET'] = '10.9' # run the before_build command if before_build: From a143ff2bfdf85063a173b77443b3560cf69eb8f3 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Fri, 31 Jan 2020 17:06:58 +0000 Subject: [PATCH 5/9] Use the internal download() function rather than curl --- cibuildwheel/macos.py | 9 +++++---- cibuildwheel/util.py | 31 +++++++++++++++++++++++++++++++ cibuildwheel/windows.py | 30 +----------------------------- 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/cibuildwheel/macos.py b/cibuildwheel/macos.py index e677d813..7480990f 100644 --- a/cibuildwheel/macos.py +++ b/cibuildwheel/macos.py @@ -8,7 +8,7 @@ try: except ImportError: from pipes import quote as shlex_quote -from .util import prepare_command, get_build_verbosity_extra_flags +from .util import prepare_command, get_build_verbosity_extra_flags, download def get_python_configurations(build_selector): @@ -51,19 +51,20 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef return subprocess.check_call(args, env=env, cwd=cwd, shell=shell) # get latest pip once and for all - call(['curl', '--retry', '3', '--retry-delay', '3', '-sSLo', get_pip_script, get_pip_url]) + download(get_pip_url, get_pip_script) for config in python_configurations: # if this version of python isn't installed, get it from python.org and install python_package_identifier = 'org.python.Python.PythonFramework-%s' % config.version if python_package_identifier not in installed_system_packages: # download the pkg - call(['curl', '--retry', '3', '--retry-delay', '3', '-sSLo', '/tmp/Python.pkg', config.url]) + download(config.url, '/tmp/Python.pkg') # install call(['sudo', 'installer', '-pkg', '/tmp/Python.pkg', '-target', '/']) # patch open ssl if config.version == '3.5': - call(['curl', '--retry', '3', '--retry-delay', '3', '-fsSLo', '/tmp/python-patch.tar.gz', 'https://github.com/mayeut/patch-macos-python-openssl/releases/download/v1.0.2t/patch-macos-python-%s-openssl-v1.0.2t.tar.gz' % config.version]) + open_ssl_patch_url = 'https://github.com/mayeut/patch-macos-python-openssl/releases/download/v1.0.2t/patch-macos-python-%s-openssl-v1.0.2t.tar.gz' % config.version + download(open_ssl_patch_url, '/tmp/python-patch.tar.gz') call(['sudo', 'tar', '-C', '/Library/Frameworks/Python.framework/Versions/%s/' % config.version, '-xmf', '/tmp/python-patch.tar.gz']) installation_bin_path = '/Library/Frameworks/Python.framework/Versions/{}/bin'.format(config.version) diff --git a/cibuildwheel/util.py b/cibuildwheel/util.py index ccbe57c0..0aedbcac 100644 --- a/cibuildwheel/util.py +++ b/cibuildwheel/util.py @@ -1,5 +1,12 @@ from fnmatch import fnmatch import warnings +import os +from time import sleep + +try: + from urllib.request import urlopen +except ImportError: + from urllib2 import urlopen def prepare_command(command, **kwargs): @@ -50,3 +57,27 @@ class Unbuffered(object): def __getattr__(self, attr): return getattr(self.stream, attr) + + +def download(url, dest): + print('+ Download ' + url + ' to ' + dest) + dest_dir = os.path.dirname(dest) + if not os.path.exists(dest_dir): + os.makedirs(dest_dir) + + repeat_num = 3 + for i in range(repeat_num): + try: + response = urlopen(url) + except: + if i == repeat_num - 1: + raise + sleep(3) + continue + break + + try: + with open(dest, 'wb') as file: + file.write(response.read()) + finally: + response.close() diff --git a/cibuildwheel/windows.py b/cibuildwheel/windows.py index c0923934..c50c9810 100644 --- a/cibuildwheel/windows.py +++ b/cibuildwheel/windows.py @@ -1,6 +1,5 @@ from __future__ import print_function import os, tempfile, subprocess, shutil, sys -from time import sleep from collections import namedtuple from glob import glob @@ -9,12 +8,7 @@ try: except ImportError: from pipes import quote as shlex_quote -try: - from urllib.request import urlopen -except ImportError: - from urllib2 import urlopen - -from .util import prepare_command, get_build_verbosity_extra_flags +from .util import prepare_command, get_build_verbosity_extra_flags, download IS_RUNNING_ON_AZURE = os.path.exists('C:\\hostedtoolcache') @@ -64,28 +58,6 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef args = ['cmd', '/E:ON', '/V:ON', '/C'] + args return subprocess.check_call(' '.join(args), env=env, cwd=cwd) - def download(url, dest): - print('+ Download ' + url + ' to ' + dest) - dest_dir = os.path.dirname(dest) - if not os.path.exists(dest_dir): - os.makedirs(dest_dir) - repeat_num = 3 - for i in range(repeat_num): - try: - response = urlopen(url) - except: - if i == repeat_num - 1: - raise - sleep(3) - continue - break - - try: - with open(dest, 'wb') as file: - file.write(response.read()) - finally: - response.close() - if IS_RUNNING_ON_AZURE or IS_RUNNING_ON_TRAVIS: shell = simple_shell else: From a97b6a13f1e4f9975e33d96eaafb3d84382dc912 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Fri, 31 Jan 2020 17:11:56 +0000 Subject: [PATCH 6/9] Fix test protection reference --- unit_test/main_util_fixtures.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unit_test/main_util_fixtures.py b/unit_test/main_util_fixtures.py index 8bc80d87..3c993b35 100644 --- a/unit_test/main_util_fixtures.py +++ b/unit_test/main_util_fixtures.py @@ -4,7 +4,7 @@ import sys import os import subprocess -from cibuildwheel import linux, macos, windows +from cibuildwheel import linux, macos, windows, util class ArgsInterceptor(object): @@ -26,7 +26,7 @@ def mock_protection(monkeypatch): raise RuntimeError("This should never be called") monkeypatch.setattr(subprocess, 'Popen', fail_on_call) - monkeypatch.setattr(windows, 'urlopen', fail_on_call) + monkeypatch.setattr(util, 'download', fail_on_call) monkeypatch.setattr(windows, 'build', fail_on_call) monkeypatch.setattr(linux, 'build', fail_on_call) monkeypatch.setattr(macos, 'build', fail_on_call) From c3f628d03d91d2d082aec2cbe7fdba6390e2b353 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Sat, 1 Feb 2020 21:44:07 +0000 Subject: [PATCH 7/9] Add migration for build identifier change, and test for migration --- cibuildwheel/__main__.py | 21 ++++++++++++--------- unit_test/main_options_test.py | 23 +++++++++++++++++++++++ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/cibuildwheel/__main__.py b/cibuildwheel/__main__.py index e4a1b016..bdc34aaf 100644 --- a/cibuildwheel/__main__.py +++ b/cibuildwheel/__main__.py @@ -198,15 +198,18 @@ def detect_obsolete_options(): print("Option '{}' is not empty. Please unset '{}'".format(alternative, deprecated)) exit(2) - # Check for 'manylinux1' in the 'CIBW_BUILD' and 'CIBW_SKIP' options - for deprecated in ['CIBW_BUILD', 'CIBW_SKIP']: - if deprecated in os.environ and 'manylinux1' in os.environ[deprecated]: - print("Build identifiers with 'manylinux1' have been deprecated. Replacing all occurences of 'manylinux1' by 'manylinux' in the option '{}'".format(deprecated)) - os.environ[deprecated] = os.environ[deprecated].replace('manylinux1', 'manylinux') - if deprecated in os.environ and ("macosx_10_6" in os.environ[deprecated] or "macosx_10_9" in os.environ[deprecated]): - print("Build identifiers with 'macosx_10_6' or 'macosx_10_9' have been deprecated. Replacing all occurences with 'macosx' in the option '{}'".format(deprecated)) - os.environ[deprecated] = os.environ[deprecated].replace('macosx_10_6', 'macosx').replace('macosx_10_9', 'macosx') - + # Check for deprecated identifiers in 'CIBW_BUILD' and 'CIBW_SKIP' options + for option in ['CIBW_BUILD', 'CIBW_SKIP']: + for deprecated, alternative in [('manylinux1', 'manylinux'), + ('macosx_10_6_intel', 'macosx_x86_64'), + ('macosx_10_9_x86_64', 'macosx_x86_64')]: + if option in os.environ and deprecated in os.environ[option]: + print("Build identifiers with '{deprecated}' have been deprecated. Replacing all occurences of '{deprecated}' with '{alternative}' in the option '{option}'".format( + deprecated=deprecated, + alternative=alternative, + option=option, + )) + os.environ[option] = os.environ[option].replace(deprecated, alternative) def print_preamble(platform, build_options): print(textwrap.dedent(''' diff --git a/unit_test/main_options_test.py b/unit_test/main_options_test.py index ece86fce..44d92da8 100644 --- a/unit_test/main_options_test.py +++ b/unit_test/main_options_test.py @@ -204,3 +204,26 @@ def test_build_verbosity(build_verbosity, platform_specific, platform, intercept expected_verbosity = max(-3, min(3, int(build_verbosity or 0))) assert intercepted_build_args.kwargs['build_verbosity'] == expected_verbosity + + +@pytest.mark.parametrize('option_name', ['CIBW_BUILD', 'CIBW_SKIP']) +@pytest.mark.parametrize('option_value, build_selector_patterns', [ + ('*-manylinux1_*', ['*-manylinux_*']), + ('*-macosx_10_6_intel', ['*-macosx_x86_64']), + ('*-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): + monkeypatch.setenv(option_name, option_value) + + main() + + intercepted_build_selector = intercepted_build_args.kwargs['build_selector'] + assert isinstance(intercepted_build_selector, BuildSelector) + + if option_name == 'CIBW_BUILD': + assert intercepted_build_selector.build_patterns == build_selector_patterns + else: + assert intercepted_build_selector.skip_patterns == build_selector_patterns + + From 4bc851ddf256458664a098fb344a8411edd16240 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Sun, 2 Feb 2020 15:16:23 +0000 Subject: [PATCH 8/9] Add an editorconfig to standardise styles across projects See https://editorconfig.org/ --- .editorconfig | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..a73ff5cf --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +# http://editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +# Use 4 spaces the Python files +[*.py] +indent_size = 4 From 17a224c525d00af70888399d416975ad7ff28226 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Sun, 2 Feb 2020 15:16:36 +0000 Subject: [PATCH 9/9] Ignore a python2 virtualenv too --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index e78281bc..627af7b1 100644 --- a/.gitignore +++ b/.gitignore @@ -86,9 +86,11 @@ celerybeat-schedule .venv venv/ venv3/ +venv2/ ENV/ env/ env3/ +env2/ # Spyder project settings .spyderproject