From 4e9316036c43b15c1264ca0bedbb1a7bb37591ba Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Tue, 7 Jan 2020 00:17:03 +0100 Subject: [PATCH 01/21] add before test variable --- cibuildwheel/__main__.py | 2 + cibuildwheel/linux.py | 9 +- cibuildwheel/macos.py | 6 +- cibuildwheel/windows.py | 6 +- test/10_before_test/cibuildwheel_test.py | 22 +++ test/10_before_test/setup.py | 19 ++ test/10_before_test/spam.c | 48 +++++ test/10_before_test/test/spam_test.py | 24 +++ unit_test/main_options_test.py | 221 +++++++++++++++++++++++ 9 files changed, 354 insertions(+), 3 deletions(-) create mode 100644 test/10_before_test/cibuildwheel_test.py create mode 100644 test/10_before_test/setup.py create mode 100644 test/10_before_test/spam.c create mode 100644 test/10_before_test/test/spam_test.py create mode 100644 unit_test/main_options_test.py diff --git a/cibuildwheel/__main__.py b/cibuildwheel/__main__.py index aa7f6587..e20028d8 100644 --- a/cibuildwheel/__main__.py +++ b/cibuildwheel/__main__.py @@ -113,6 +113,7 @@ def main(): repair_command_default = '' repair_command = get_option_from_environment('CIBW_REPAIR_WHEEL_COMMAND', platform=platform, default=repair_command_default) environment_config = get_option_from_environment('CIBW_ENVIRONMENT', platform=platform, default='') + before_test = get_option_from_environment('CIBW_BEFORE_TEST', platform=platform, default='') if test_extras: test_extras = '[{0}]'.format(test_extras) @@ -154,6 +155,7 @@ def main(): build_selector=build_selector, repair_command=repair_command, environment=environment, + before_test=before_test ) if platform == 'linux': diff --git a/cibuildwheel/linux.py b/cibuildwheel/linux.py index 20dae7e6..753da624 100644 --- a/cibuildwheel/linux.py +++ b/cibuildwheel/linux.py @@ -68,7 +68,7 @@ def get_python_configurations(build_selector): return [c for c in python_configurations if matches_platform(c.identifier) and build_selector(c.identifier)] -def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, repair_command, environment, manylinux_images): +def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, repair_command, environment, before_test, manylinux_images): try: subprocess.check_call(['docker', '--version']) except Exception: @@ -154,6 +154,10 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef echo "Running tests using `which python`" + if [ ! -z {before_test} ]; then + sh -c {before_test} + fi + # Install the wheel we just built # Note: If auditwheel produced two wheels, it's because the earlier produced wheel # conforms to multiple manylinux standards. These multiple versions of the wheel are @@ -202,6 +206,9 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef environment_exports='\n'.join(environment.as_shell_commands()), uid=os.getuid(), gid=os.getgid(), + before_test=shlex_quote( + prepare_command(before_test, project='/project') if before_test else '' + ), ) container_name = 'cibuildwheel-{}'.format(uuid.uuid4()) diff --git a/cibuildwheel/macos.py b/cibuildwheel/macos.py index 3b3edcba..50b6392a 100644 --- a/cibuildwheel/macos.py +++ b/cibuildwheel/macos.py @@ -105,7 +105,7 @@ def install_pypy(version, url): return installation_bin_path -def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, repair_command, environment): +def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, repair_command, environment, before_test): abs_project_dir = os.path.abspath(project_dir) temp_dir = tempfile.mkdtemp(prefix='cibuildwheel') built_wheel_dir = os.path.join(temp_dir, 'built_wheel') @@ -214,6 +214,10 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef # check that we are using the Python from the virtual environment call(['which', 'python'], env=virtualenv_env) + if before_test: + before_test_prepared = prepare_command(before_test, project=abs_project_dir) + call(before_test_prepared, env=virtualenv_env, shell=True) + # install the wheel call(['pip', 'install', repaired_wheel + test_extras], env=virtualenv_env) diff --git a/cibuildwheel/windows.py b/cibuildwheel/windows.py index 24e19c38..15a53209 100644 --- a/cibuildwheel/windows.py +++ b/cibuildwheel/windows.py @@ -87,7 +87,7 @@ def install_pypy(version, arch, url): return installation_path -def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, repair_command, environment): +def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, repair_command, environment, before_test): abs_project_dir = os.path.abspath(project_dir) temp_dir = tempfile.mkdtemp(prefix='cibuildwheel') built_wheel_dir = os.path.join(temp_dir, 'built_wheel') @@ -193,6 +193,10 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef # check that we are using the Python from the virtual environment shell(['which', 'python'], env=virtualenv_env) + if before_test: + before_test_prepared = prepare_command(before_test, project=abs_project_dir) + shell([before_test_prepared], env=virtualenv_env) + # install the wheel shell(['pip', 'install', repaired_wheel + test_extras], env=virtualenv_env) diff --git a/test/10_before_test/cibuildwheel_test.py b/test/10_before_test/cibuildwheel_test.py new file mode 100644 index 00000000..f6a56af4 --- /dev/null +++ b/test/10_before_test/cibuildwheel_test.py @@ -0,0 +1,22 @@ +import os +import utils + +def test(): + project_dir = os.path.dirname(__file__) + + # build the wheels + actual_wheels = utils.cibuildwheel_run(project_dir, add_env={ + # write python version information to a temporary file, this is + # checked in setup.py + 'CIBW_BEFORE_TEST': '''python -c "import sys; open('/tmp/pythonversion.txt', 'w').write(sys.version)" && python -c "import sys; open('/tmp/pythonexecutable.txt', 'w').write(sys.executable)"''', + 'CIBW_BEFORE_TEST_WINDOWS': '''python -c "import sys; open('c:\\pythonversion.txt', 'w').write(sys.version)" && python -c "import sys; open('c:\\pythonexecutable.txt', 'w').write(sys.executable)"''', + 'CIBW_TEST_REQUIRES': 'nose', + # the 'false ||' bit is to ensure this command runs in a shell on + # mac/linux. + 'CIBW_TEST_COMMAND': 'false || nosetests {project}/test', + 'CIBW_TEST_COMMAND_WINDOWS': 'nosetests {project}/test', + }) + + # also check that we got the right wheels + expected_wheels = utils.expected_wheels('spam', '0.1.0') + assert set(actual_wheels) == set(expected_wheels) diff --git a/test/10_before_test/setup.py b/test/10_before_test/setup.py new file mode 100644 index 00000000..8abc7921 --- /dev/null +++ b/test/10_before_test/setup.py @@ -0,0 +1,19 @@ +from setuptools import setup, Extension +import sys, os + +# assert that the Python version as written to pythonversion.txt in the CIBW_BEFORE_BUILD step +# is the same one as is currently running. +version_file = 'c:\\pythonversion.txt' if sys.platform == 'win32' else '/tmp/pythonversion.txt' +if os.path.exists(version_file): + os.remove(version_file) + +# check that the executable also was written +executable_file = 'c:\\pythonexecutable.txt' if sys.platform == 'win32' else '/tmp/pythonexecutable.txt' +if os.path.exists(executable_file): + os.remove(executable_file) + +setup( + name="spam", + ext_modules=[Extension('spam', sources=['spam.c'])], + version="0.1.0", +) diff --git a/test/10_before_test/spam.c b/test/10_before_test/spam.c new file mode 100644 index 00000000..d1ab0f22 --- /dev/null +++ b/test/10_before_test/spam.c @@ -0,0 +1,48 @@ +#include + +static PyObject * +spam_system(PyObject *self, PyObject *args) +{ + const char *command; + int sts; + + if (!PyArg_ParseTuple(args, "s", &command)) + return NULL; + sts = system(command); + return PyLong_FromLong(sts); +} + +/* Module initialization */ + +#if PY_MAJOR_VERSION >= 3 + #define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void) + #define MOD_DEF(m, name, doc, methods, module_state_size) \ + static struct PyModuleDef moduledef = { \ + PyModuleDef_HEAD_INIT, name, doc, module_state_size, methods, }; \ + m = PyModule_Create(&moduledef); + #define MOD_RETURN(m) return m; +#else + #define MOD_INIT(name) PyMODINIT_FUNC init##name(void) + #define MOD_DEF(m, name, doc, methods, module_state_size) \ + m = Py_InitModule3(name, methods, doc); + #define MOD_RETURN(m) return; +#endif + +static PyMethodDef module_methods[] = { + {"system", (PyCFunction)spam_system, METH_VARARGS, + "Execute a shell command."}, + {NULL} /* Sentinel */ +}; + +MOD_INIT(spam) +{ + PyObject* m; + + MOD_DEF(m, + "spam", + "Example module", + module_methods, + -1) + + MOD_RETURN(m) +} diff --git a/test/10_before_test/test/spam_test.py b/test/10_before_test/test/spam_test.py new file mode 100644 index 00000000..7560b438 --- /dev/null +++ b/test/10_before_test/test/spam_test.py @@ -0,0 +1,24 @@ +import sys, os +from unittest import TestCase + + +class TestBeforeTest(TestCase): + def test_version(self): + # assert that the Python version as written to pythonversion.txt in the CIBW_BEFORE_BUILD step + # is the same one as is currently running. + version_file = 'c:\\pythonversion.txt' if sys.platform == 'win32' else '/tmp/pythonversion.txt' + with open(version_file) as f: + stored_version = f.read() + print('stored_version', stored_version) + print('sys.version', sys.version) + assert stored_version == sys.version + + def test_executable(self): + # check that the executable also was written + executable_file = 'c:\\pythonexecutable.txt' if sys.platform == 'win32' else '/tmp/pythonexecutable.txt' + with open(executable_file) as f: + stored_executable = f.read() + print('stored_executable', stored_executable) + print('sys.executable', sys.executable) + # windows/mac are case insensitive + assert os.path.realpath(stored_executable).lower() == os.path.realpath(sys.executable).lower() diff --git a/unit_test/main_options_test.py b/unit_test/main_options_test.py new file mode 100644 index 00000000..99387bf5 --- /dev/null +++ b/unit_test/main_options_test.py @@ -0,0 +1,221 @@ +import pytest + +import sys + +from cibuildwheel.__main__ import main +from cibuildwheel.environment import ParsedEnvironment +from cibuildwheel.util import BuildSelector + +from main_util_fixtures import mock_protection, fake_project_dir, platform, intercepted_build_args + + + +# CIBW_PLATFORM is tested in main_platform_test.py + + +def test_output_dir(platform, intercepted_build_args, monkeypatch): + OUTPUT_DIR = 'some_output_dir' + + monkeypatch.setenv('CIBW_OUTPUT_DIR', OUTPUT_DIR) + + main() + + assert intercepted_build_args.kwargs['output_dir'] == OUTPUT_DIR + + +def test_output_dir_default(platform, intercepted_build_args, monkeypatch): + main() + + assert intercepted_build_args.kwargs['output_dir'] == 'wheelhouse' + + +@pytest.mark.parametrize('also_set_environment', [False, True]) +def test_output_dir_argument(also_set_environment, platform, intercepted_build_args, monkeypatch): + OUTPUT_DIR = 'some_output_dir' + + monkeypatch.setattr(sys, 'argv', sys.argv + ['--output-dir', OUTPUT_DIR]) + if also_set_environment: + monkeypatch.setenv('CIBW_OUTPUT_DIR', 'not_this_output_dir') + + main() + + assert intercepted_build_args.kwargs['output_dir'] == OUTPUT_DIR + + +def test_build_selector(platform, intercepted_build_args, monkeypatch): + BUILD = 'some build* *-selector' + SKIP = 'some skip* *-selector' + + monkeypatch.setenv('CIBW_BUILD', BUILD) + 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') + assert not intercepted_build_selector('skip-that') + # This unit test is just testing the options of 'main' + # Unit tests for BuildSelector are in build_selector_test.py + + +@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'), + ('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', 'manylinux1', 'quay.io/pypa/manylinux1_i686'), + ('i686', 'manylinux2010', 'quay.io/pypa/manylinux2010_i686'), + ('i686', 'manylinux2014', 'quay.io/pypa/manylinux2014_i686'), + ('i686', 'custom_image', 'custom_image'), +]) +def test_manylinux_images(architecture, image, full_image, platform, intercepted_build_args, monkeypatch): + if image is not None: + monkeypatch.setenv('CIBW_MANYLINUX_' + architecture.upper() + '_IMAGE', image) + + main() + + if platform == 'linux': + assert intercepted_build_args.kwargs['manylinux_images'][architecture] == full_image + else: + assert 'manylinux_images' not in intercepted_build_args.kwargs + + +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}' + elif platform == 'windows': + return '' + else: + raise ValueError('Unknown platform', platform) + +@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): + if repair_command is not None: + if platform_specific: + monkeypatch.setenv('CIBW_REPAIR_WHEEL_COMMAND_' + platform.upper(), repair_command) + monkeypatch.setenv('CIBW_REPAIR_WHEEL_COMMAND', 'overwritten') + else: + monkeypatch.setenv('CIBW_REPAIR_WHEEL_COMMAND', repair_command) + + main() + + expected_repair = repair_command or get_default_repair_command(platform) + assert intercepted_build_args.kwargs['repair_command'] == expected_repair + + +@pytest.mark.parametrize('environment', [ + {}, + {'something': 'value'}, + {'something': 'value', 'something_else': 'other_value'} +]) +@pytest.mark.parametrize('platform_specific', [False, True]) +def test_environment(environment, platform_specific, platform, intercepted_build_args, monkeypatch): + env_string = ' '.join(['{}={}'.format(k, v) for k, v in environment.items()]) + if platform_specific: + monkeypatch.setenv('CIBW_ENVIRONMENT_' + platform.upper(), env_string) + monkeypatch.setenv('CIBW_ENVIRONMENT', 'overwritten') + else: + monkeypatch.setenv('CIBW_ENVIRONMENT', env_string) + + main() + + intercepted_environment = intercepted_build_args.kwargs['environment'] + assert isinstance(intercepted_environment, ParsedEnvironment) + assert intercepted_environment.as_dictionary(prev_environment={}) == environment + + +@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): + if test_requires is not None: + if platform_specific: + monkeypatch.setenv('CIBW_TEST_REQUIRES_' + platform.upper(), test_requires) + 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() + + +@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): + if test_extras is not None: + if platform_specific: + monkeypatch.setenv('CIBW_TEST_EXTRAS_' + platform.upper(), test_extras) + 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 '') + + +@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): + if test_command is not None: + if platform_specific: + monkeypatch.setenv('CIBW_TEST_COMMAND_' + platform.upper(), test_command) + monkeypatch.setenv('CIBW_TEST_COMMAND', 'overwritten') + else: + monkeypatch.setenv('CIBW_TEST_COMMAND', test_command) + + main() + + assert intercepted_build_args.kwargs['test_command'] == test_command + + +@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): + if before_build is not None: + if platform_specific: + monkeypatch.setenv('CIBW_BEFORE_BUILD_' + platform.upper(), before_build) + monkeypatch.setenv('CIBW_BEFORE_BUILD', 'overwritten') + else: + monkeypatch.setenv('CIBW_BEFORE_BUILD', before_build) + + main() + + assert intercepted_build_args.kwargs['before_build'] == before_build + + +@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): + if build_verbosity is not None: + if platform_specific: + monkeypatch.setenv('CIBW_BUILD_VERBOSITY_' + platform.upper(), str(build_verbosity)) + monkeypatch.setenv('CIBW_BUILD_VERBOSITY', 'overwritten') + else: + monkeypatch.setenv('CIBW_BUILD_VERBOSITY', str(build_verbosity)) + + main() + + expected_verbosity = max(-3, min(3, int(build_verbosity or 0))) + assert intercepted_build_args.kwargs['build_verbosity'] == expected_verbosity + + +@pytest.mark.parametrize('before_test', ["", 'before --test']) +@pytest.mark.parametrize('platform_specific', [False, True]) +def test_before_test(before_test, platform_specific, platform, intercepted_build_args, monkeypatch): + if before_test is not None: + if platform_specific: + monkeypatch.setenv('CIBW_BEFORE_TEST_' + platform.upper(), before_test) + monkeypatch.setenv('CIBW_BEFORE_TEST', 'overwritten') + else: + monkeypatch.setenv('CIBW_BEFORE_TEST', before_test) + + main() + + assert intercepted_build_args.kwargs['before_test'] == before_test \ No newline at end of file From d9e6bbfa4f018b0c2d61dd80c1c2259396cdfac9 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Tue, 7 Jan 2020 09:03:14 +0100 Subject: [PATCH 02/21] add documentation --- README.md | 3 ++- docs/options.md | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d918c808..9c7ecb59 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,8 @@ Options | **Testing** | [`CIBW_TEST_COMMAND`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-command) | Execute a shell command to test each built wheel | | | [`CIBW_TEST_REQUIRES`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-requires) | Install Python dependencies before running the tests | | | [`CIBW_TEST_EXTRAS`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-extras) | Install your wheel for testing using extras_require | -| **Other** | [`CIBW_BUILD_VERBOSITY`](https://cibuildwheel.readthedocs.io/en/stable/options/#build-verbosity) | Increase/decrease the output of pip wheel | +| | [`CIBW_BEFORE_TEST`](https://cibuildwheel.readthedocs.io/en/stable/options/#before-test) | Execute shell command to prepare test environment | +| **Other** | [`CIBW_BUILD_VERBOSITY`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-extras) | Increase/decrease the output of pip wheel | Working examples ---------------- diff --git a/docs/options.md b/docs/options.md index 4b4069ac..95c7a728 100644 --- a/docs/options.md +++ b/docs/options.md @@ -340,6 +340,32 @@ Platform-specific variants also available:
CIBW_TEST_EXTRAS: test,qt ``` +### `CIBW_BEFORE_TEST` {: #before-test} +> Execute a shell command preparing test environment + +A shell command to run after setup test environment. This option allows you to run a command in **each** Python environment before the `pip wheel` command. This is useful if you need to install non pip package, change values of environment variables +or perform multi step pip installation (like install `scikit-build` or `cython` before install test package) + +If dependencies are required to build your wheel (for example if you include a header from a Python module), set this to `pip install .`, and the dependencies will be installed automatically by pip. However, this means your package will be built twice - if your package takes a long time to build, you might wish to manually list the dependencies here instead. + +The active Python binary can be accessed using `python`, and pip with `pip`; `cibuildwheel` makes sure the right version of Python and pip will be executed. `{project}` can be used as a placeholder for the absolute path to the project's root and will be replaced by `cibuildwheel`. + +On Linux and macOS, the command is run in a shell, so you can write things like `cmd1 && cmd2`. + +Platform-specific variants also available:
+ `CIBW_BEFORE_TEST_MACOS` | `CIBW_BEFORE_TEST_WINDOWS` | `CIBW_BEFORE_TEST_LINUX` + +#### Examples +```yaml +# install packages needed to build test dependencies +CIBW_BEFORE_TEST: pip install cmake scikit-build + +# install test dependencies with overwritten environment variables. +CIBW_BEFORE_TEST: CC=gcc CXX=g++ pip install -r requirements.txt + +# chain commands using && +CIBW_BEFORE_TEST: yum install -y libffi-dev && pip install . +``` ## Other From 6461074ec96a5918a0693d8bb79d6f932f6865e6 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Fri, 10 Jan 2020 23:08:27 +0100 Subject: [PATCH 03/21] Apply spell suggestions from joerick code review Co-Authored-By: Joe Rickerby --- docs/options.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/options.md b/docs/options.md index 95c7a728..dff21fe4 100644 --- a/docs/options.md +++ b/docs/options.md @@ -341,12 +341,11 @@ CIBW_TEST_EXTRAS: test,qt ``` ### `CIBW_BEFORE_TEST` {: #before-test} -> Execute a shell command preparing test environment +> Execute a shell command before testing each wheel -A shell command to run after setup test environment. This option allows you to run a command in **each** Python environment before the `pip wheel` command. This is useful if you need to install non pip package, change values of environment variables +A shell command to run in **each** test virtual environment, before your wheel is installed and tested. This is useful if you need to install non pip package, change values of environment variables or perform multi step pip installation (like install `scikit-build` or `cython` before install test package) -If dependencies are required to build your wheel (for example if you include a header from a Python module), set this to `pip install .`, and the dependencies will be installed automatically by pip. However, this means your package will be built twice - if your package takes a long time to build, you might wish to manually list the dependencies here instead. The active Python binary can be accessed using `python`, and pip with `pip`; `cibuildwheel` makes sure the right version of Python and pip will be executed. `{project}` can be used as a placeholder for the absolute path to the project's root and will be replaced by `cibuildwheel`. From 01a7c2d6df9158471a5ef3c35940b23fe654f864 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Thu, 16 Jan 2020 17:30:14 +0100 Subject: [PATCH 04/21] reorder before_test --- README.md | 2 +- cibuildwheel/linux.py | 2 +- cibuildwheel/macos.py | 2 +- cibuildwheel/windows.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9c7ecb59..08159b81 100644 --- a/README.md +++ b/README.md @@ -104,9 +104,9 @@ Options | | [`CIBW_REPAIR_WHEEL_COMMAND`](https://cibuildwheel.readthedocs.io/en/stable/options/#repair-wheel-command) | Execute a shell command to repair each (non-pure Python) built wheel | | | [`CIBW_MANYLINUX_X86_64_IMAGE`](https://cibuildwheel.readthedocs.io/en/stable/options/#manylinux-image) [`CIBW_MANYLINUX_I686_IMAGE`](https://cibuildwheel.readthedocs.io/en/stable/options/#manylinux-image) [`CIBW_MANYLINUX_PYPY_X86_64_IMAGE`](https://cibuildwheel.readthedocs.io/en/stable/options/#manylinux-image) | Specify alternative manylinux docker images | | **Testing** | [`CIBW_TEST_COMMAND`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-command) | Execute a shell command to test each built wheel | +| | [`CIBW_BEFORE_TEST`](https://cibuildwheel.readthedocs.io/en/stable/options/#before-test) | Execute shell command to prepare test environment | | | [`CIBW_TEST_REQUIRES`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-requires) | Install Python dependencies before running the tests | | | [`CIBW_TEST_EXTRAS`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-extras) | Install your wheel for testing using extras_require | -| | [`CIBW_BEFORE_TEST`](https://cibuildwheel.readthedocs.io/en/stable/options/#before-test) | Execute shell command to prepare test environment | | **Other** | [`CIBW_BUILD_VERBOSITY`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-extras) | Increase/decrease the output of pip wheel | Working examples diff --git a/cibuildwheel/linux.py b/cibuildwheel/linux.py index 753da624..39494ef9 100644 --- a/cibuildwheel/linux.py +++ b/cibuildwheel/linux.py @@ -68,7 +68,7 @@ def get_python_configurations(build_selector): return [c for c in python_configurations if matches_platform(c.identifier) and build_selector(c.identifier)] -def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, repair_command, environment, before_test, manylinux_images): +def build(project_dir, output_dir, test_command, before_test, test_requires, test_extras, before_build, build_verbosity, build_selector, repair_command, environment, manylinux_images): try: subprocess.check_call(['docker', '--version']) except Exception: diff --git a/cibuildwheel/macos.py b/cibuildwheel/macos.py index 50b6392a..7b2ba8a9 100644 --- a/cibuildwheel/macos.py +++ b/cibuildwheel/macos.py @@ -105,7 +105,7 @@ def install_pypy(version, url): return installation_bin_path -def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, repair_command, environment, before_test): +def build(project_dir, output_dir, test_command, before_test, test_requires, test_extras, before_build, build_verbosity, build_selector, repair_command, environment): abs_project_dir = os.path.abspath(project_dir) temp_dir = tempfile.mkdtemp(prefix='cibuildwheel') built_wheel_dir = os.path.join(temp_dir, 'built_wheel') diff --git a/cibuildwheel/windows.py b/cibuildwheel/windows.py index 15a53209..7a4edbe1 100644 --- a/cibuildwheel/windows.py +++ b/cibuildwheel/windows.py @@ -87,7 +87,7 @@ def install_pypy(version, arch, url): return installation_path -def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, repair_command, environment, before_test): +def build(project_dir, output_dir, test_command, before_test, test_requires, test_extras, before_build, build_verbosity, build_selector, repair_command, environment): abs_project_dir = os.path.abspath(project_dir) temp_dir = tempfile.mkdtemp(prefix='cibuildwheel') built_wheel_dir = os.path.join(temp_dir, 'built_wheel') From d613a8c1a63525a5e58ec2c3b190995359d067f7 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Mon, 20 Jan 2020 00:03:28 +0100 Subject: [PATCH 05/21] remove clean files from setup.py, fixes in doc --- docs/options.md | 12 ++++++------ test/10_before_test/setup.py | 10 ---------- test/10_before_test/test/spam_test.py | 3 ++- unit_test/main_options_test.py | 2 +- 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/docs/options.md b/docs/options.md index dff21fe4..b1d64042 100644 --- a/docs/options.md +++ b/docs/options.md @@ -343,8 +343,8 @@ CIBW_TEST_EXTRAS: test,qt ### `CIBW_BEFORE_TEST` {: #before-test} > Execute a shell command before testing each wheel -A shell command to run in **each** test virtual environment, before your wheel is installed and tested. This is useful if you need to install non pip package, change values of environment variables -or perform multi step pip installation (like install `scikit-build` or `cython` before install test package) +A shell command to run in **each** test virtual environment, before your wheel is installed and tested. This is useful if you need to install a non pip package, change values of environment variables +or perform multi step pip installation (e.g. installing `scikit-build` or `cython` before install test package) The active Python binary can be accessed using `python`, and pip with `pip`; `cibuildwheel` makes sure the right version of Python and pip will be executed. `{project}` can be used as a placeholder for the absolute path to the project's root and will be replaced by `cibuildwheel`. @@ -356,14 +356,14 @@ Platform-specific variants also available:
#### Examples ```yaml -# install packages needed to build test dependencies -CIBW_BEFORE_TEST: pip install cmake scikit-build - # install test dependencies with overwritten environment variables. CIBW_BEFORE_TEST: CC=gcc CXX=g++ pip install -r requirements.txt # chain commands using && -CIBW_BEFORE_TEST: yum install -y libffi-dev && pip install . +CIBW_BEFORE_TEST : rm -rf ./data/cache && mkdir -p ./data/cache + +# install python packages that are required to install test dependencies +CIBW_BEFORE_TEST: pip install cmake scikit-build ``` ## Other diff --git a/test/10_before_test/setup.py b/test/10_before_test/setup.py index 8abc7921..7bdeac0b 100644 --- a/test/10_before_test/setup.py +++ b/test/10_before_test/setup.py @@ -1,16 +1,6 @@ from setuptools import setup, Extension import sys, os -# assert that the Python version as written to pythonversion.txt in the CIBW_BEFORE_BUILD step -# is the same one as is currently running. -version_file = 'c:\\pythonversion.txt' if sys.platform == 'win32' else '/tmp/pythonversion.txt' -if os.path.exists(version_file): - os.remove(version_file) - -# check that the executable also was written -executable_file = 'c:\\pythonexecutable.txt' if sys.platform == 'win32' else '/tmp/pythonexecutable.txt' -if os.path.exists(executable_file): - os.remove(executable_file) setup( name="spam", diff --git a/test/10_before_test/test/spam_test.py b/test/10_before_test/test/spam_test.py index 7560b438..f5d9d605 100644 --- a/test/10_before_test/test/spam_test.py +++ b/test/10_before_test/test/spam_test.py @@ -4,8 +4,9 @@ from unittest import TestCase class TestBeforeTest(TestCase): def test_version(self): - # assert that the Python version as written to pythonversion.txt in the CIBW_BEFORE_BUILD step + # assert that the Python version as written to pythonversion.txt in the CIBW_BEFORE_TEST step # is the same one as is currently running. + # because of use symlinks in MacOS run this test is also need version_file = 'c:\\pythonversion.txt' if sys.platform == 'win32' else '/tmp/pythonversion.txt' with open(version_file) as f: stored_version = f.read() diff --git a/unit_test/main_options_test.py b/unit_test/main_options_test.py index 99387bf5..73545d61 100644 --- a/unit_test/main_options_test.py +++ b/unit_test/main_options_test.py @@ -218,4 +218,4 @@ def test_before_test(before_test, platform_specific, platform, intercepted_build main() - assert intercepted_build_args.kwargs['before_test'] == before_test \ No newline at end of file + assert intercepted_build_args.kwargs['before_test'] == before_test From baba7706e0b824a5ecab84274f51b09f24eb2ce3 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Mon, 20 Jan 2020 00:25:30 +0100 Subject: [PATCH 06/21] add example with non pip python package --- docs/options.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/options.md b/docs/options.md index b1d64042..0aabadc0 100644 --- a/docs/options.md +++ b/docs/options.md @@ -362,6 +362,9 @@ CIBW_BEFORE_TEST: CC=gcc CXX=g++ pip install -r requirements.txt # chain commands using && CIBW_BEFORE_TEST : rm -rf ./data/cache && mkdir -p ./data/cache +# install non pip python package +CIBW_BEFORE_TEST: cd some_dir; ./configure; make; make install + # install python packages that are required to install test dependencies CIBW_BEFORE_TEST: pip install cmake scikit-build ``` From 6265d87d0923a7405a55a24434892358587f16f9 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Sat, 7 Mar 2020 12:17:49 +0000 Subject: [PATCH 07/21] Try removing the explicit cmd call --- cibuildwheel/windows.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cibuildwheel/windows.py b/cibuildwheel/windows.py index 59f67460..e3d864f8 100644 --- a/cibuildwheel/windows.py +++ b/cibuildwheel/windows.py @@ -20,8 +20,7 @@ IS_RUNNING_ON_TRAVIS = os.environ.get('TRAVIS_OS_NAME') == 'windows' def shell(args, env=None, cwd=None): print('+ ' + ' '.join(args)) - args = ['cmd', '/E:ON', '/V:ON', '/C'] + args - return subprocess.check_call(' '.join(args), env=env, cwd=cwd) + return subprocess.check_call(' '.join(args), env=env, cwd=cwd, shell=True) def get_nuget_args(version, arch): From c33fa2ada06286e0855b73ddfe4f3fb0a9666bd9 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Sat, 7 Mar 2020 12:21:31 +0000 Subject: [PATCH 08/21] Add test for boolean ops on windows --- test/02_test/cibuildwheel_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/02_test/cibuildwheel_test.py b/test/02_test/cibuildwheel_test.py index ca084d65..d0126465 100644 --- a/test/02_test/cibuildwheel_test.py +++ b/test/02_test/cibuildwheel_test.py @@ -32,7 +32,7 @@ def test_extras_require(): # the 'false ||' bit is to ensure this command runs in a shell on # mac/linux. 'CIBW_TEST_COMMAND': 'false || nosetests {project}/test', - 'CIBW_TEST_COMMAND_WINDOWS': 'nosetests {project}/test', + 'CIBW_TEST_COMMAND_WINDOWS': 'COLOR 00 || nosetests {project}/test', }) # also check that we got the right wheels From 8de326a67aa54c2bcb0ff0e5ed46436202bd470e Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Sat, 7 Mar 2020 12:22:44 +0000 Subject: [PATCH 09/21] Another test --- test/02_test/cibuildwheel_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/02_test/cibuildwheel_test.py b/test/02_test/cibuildwheel_test.py index d0126465..21878d2c 100644 --- a/test/02_test/cibuildwheel_test.py +++ b/test/02_test/cibuildwheel_test.py @@ -15,7 +15,7 @@ def test(): # the 'false ||' bit is to ensure this command runs in a shell on # mac/linux. 'CIBW_TEST_COMMAND': 'false || nosetests {project}/test', - 'CIBW_TEST_COMMAND_WINDOWS': 'nosetests {project}/test', + 'CIBW_TEST_COMMAND_WINDOWS': 'COLOR 00 || nosetests {project}/test', }) # also check that we got the right wheels From 79cf7e47aed8721a0b6d9f327b81bac0649fe1c9 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Fri, 28 Feb 2020 19:05:02 +0100 Subject: [PATCH 10/21] fix test after rebase, fix typos in readme --- README.md | 2 +- cibuildwheel/linux.py | 2 +- .../cibuildwheel_test.py | 1 + .../setup.py | 1 - .../{10_before_test => 11_before_test}/spam.c | 0 .../test/spam_test.py | 9 +- unit_test/main_options_test.py | 221 ------------------ 7 files changed, 9 insertions(+), 227 deletions(-) rename test/{10_before_test => 11_before_test}/cibuildwheel_test.py (99%) rename test/{10_before_test => 11_before_test}/setup.py (90%) rename test/{10_before_test => 11_before_test}/spam.c (100%) rename test/{10_before_test => 11_before_test}/test/spam_test.py (82%) delete mode 100644 unit_test/main_options_test.py diff --git a/README.md b/README.md index 08159b81..aa843107 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ Options | | [`CIBW_BEFORE_TEST`](https://cibuildwheel.readthedocs.io/en/stable/options/#before-test) | Execute shell command to prepare test environment | | | [`CIBW_TEST_REQUIRES`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-requires) | Install Python dependencies before running the tests | | | [`CIBW_TEST_EXTRAS`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-extras) | Install your wheel for testing using extras_require | -| **Other** | [`CIBW_BUILD_VERBOSITY`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-extras) | Increase/decrease the output of pip wheel | +| **Other** | [`CIBW_BUILD_VERBOSITY`](https://cibuildwheel.readthedocs.io/en/stable/options/#build-verbosity) | Increase/decrease the output of pip wheel | Working examples ---------------- diff --git a/cibuildwheel/linux.py b/cibuildwheel/linux.py index 39494ef9..3113f309 100644 --- a/cibuildwheel/linux.py +++ b/cibuildwheel/linux.py @@ -206,7 +206,7 @@ def build(project_dir, output_dir, test_command, before_test, test_requires, tes environment_exports='\n'.join(environment.as_shell_commands()), uid=os.getuid(), gid=os.getgid(), - before_test=shlex_quote( + before_test=shlex.quote( prepare_command(before_test, project='/project') if before_test else '' ), ) diff --git a/test/10_before_test/cibuildwheel_test.py b/test/11_before_test/cibuildwheel_test.py similarity index 99% rename from test/10_before_test/cibuildwheel_test.py rename to test/11_before_test/cibuildwheel_test.py index f6a56af4..7db1b127 100644 --- a/test/10_before_test/cibuildwheel_test.py +++ b/test/11_before_test/cibuildwheel_test.py @@ -1,6 +1,7 @@ import os import utils + def test(): project_dir = os.path.dirname(__file__) diff --git a/test/10_before_test/setup.py b/test/11_before_test/setup.py similarity index 90% rename from test/10_before_test/setup.py rename to test/11_before_test/setup.py index 7bdeac0b..e3ea2938 100644 --- a/test/10_before_test/setup.py +++ b/test/11_before_test/setup.py @@ -1,5 +1,4 @@ from setuptools import setup, Extension -import sys, os setup( diff --git a/test/10_before_test/spam.c b/test/11_before_test/spam.c similarity index 100% rename from test/10_before_test/spam.c rename to test/11_before_test/spam.c diff --git a/test/10_before_test/test/spam_test.py b/test/11_before_test/test/spam_test.py similarity index 82% rename from test/10_before_test/test/spam_test.py rename to test/11_before_test/test/spam_test.py index f5d9d605..e25cc0c7 100644 --- a/test/10_before_test/test/spam_test.py +++ b/test/11_before_test/test/spam_test.py @@ -1,4 +1,5 @@ -import sys, os +import sys +import os from unittest import TestCase @@ -21,5 +22,7 @@ class TestBeforeTest(TestCase): stored_executable = f.read() print('stored_executable', stored_executable) print('sys.executable', sys.executable) - # windows/mac are case insensitive - assert os.path.realpath(stored_executable).lower() == os.path.realpath(sys.executable).lower() + # Works around path-comparison bugs caused by short-paths on Windows e.g. + # vssadm~1 instead of vssadministrator + + assert os.stat(stored_executable) == os.stat(sys.executable) diff --git a/unit_test/main_options_test.py b/unit_test/main_options_test.py deleted file mode 100644 index 73545d61..00000000 --- a/unit_test/main_options_test.py +++ /dev/null @@ -1,221 +0,0 @@ -import pytest - -import sys - -from cibuildwheel.__main__ import main -from cibuildwheel.environment import ParsedEnvironment -from cibuildwheel.util import BuildSelector - -from main_util_fixtures import mock_protection, fake_project_dir, platform, intercepted_build_args - - - -# CIBW_PLATFORM is tested in main_platform_test.py - - -def test_output_dir(platform, intercepted_build_args, monkeypatch): - OUTPUT_DIR = 'some_output_dir' - - monkeypatch.setenv('CIBW_OUTPUT_DIR', OUTPUT_DIR) - - main() - - assert intercepted_build_args.kwargs['output_dir'] == OUTPUT_DIR - - -def test_output_dir_default(platform, intercepted_build_args, monkeypatch): - main() - - assert intercepted_build_args.kwargs['output_dir'] == 'wheelhouse' - - -@pytest.mark.parametrize('also_set_environment', [False, True]) -def test_output_dir_argument(also_set_environment, platform, intercepted_build_args, monkeypatch): - OUTPUT_DIR = 'some_output_dir' - - monkeypatch.setattr(sys, 'argv', sys.argv + ['--output-dir', OUTPUT_DIR]) - if also_set_environment: - monkeypatch.setenv('CIBW_OUTPUT_DIR', 'not_this_output_dir') - - main() - - assert intercepted_build_args.kwargs['output_dir'] == OUTPUT_DIR - - -def test_build_selector(platform, intercepted_build_args, monkeypatch): - BUILD = 'some build* *-selector' - SKIP = 'some skip* *-selector' - - monkeypatch.setenv('CIBW_BUILD', BUILD) - 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') - assert not intercepted_build_selector('skip-that') - # This unit test is just testing the options of 'main' - # Unit tests for BuildSelector are in build_selector_test.py - - -@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'), - ('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', 'manylinux1', 'quay.io/pypa/manylinux1_i686'), - ('i686', 'manylinux2010', 'quay.io/pypa/manylinux2010_i686'), - ('i686', 'manylinux2014', 'quay.io/pypa/manylinux2014_i686'), - ('i686', 'custom_image', 'custom_image'), -]) -def test_manylinux_images(architecture, image, full_image, platform, intercepted_build_args, monkeypatch): - if image is not None: - monkeypatch.setenv('CIBW_MANYLINUX_' + architecture.upper() + '_IMAGE', image) - - main() - - if platform == 'linux': - assert intercepted_build_args.kwargs['manylinux_images'][architecture] == full_image - else: - assert 'manylinux_images' not in intercepted_build_args.kwargs - - -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}' - elif platform == 'windows': - return '' - else: - raise ValueError('Unknown platform', platform) - -@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): - if repair_command is not None: - if platform_specific: - monkeypatch.setenv('CIBW_REPAIR_WHEEL_COMMAND_' + platform.upper(), repair_command) - monkeypatch.setenv('CIBW_REPAIR_WHEEL_COMMAND', 'overwritten') - else: - monkeypatch.setenv('CIBW_REPAIR_WHEEL_COMMAND', repair_command) - - main() - - expected_repair = repair_command or get_default_repair_command(platform) - assert intercepted_build_args.kwargs['repair_command'] == expected_repair - - -@pytest.mark.parametrize('environment', [ - {}, - {'something': 'value'}, - {'something': 'value', 'something_else': 'other_value'} -]) -@pytest.mark.parametrize('platform_specific', [False, True]) -def test_environment(environment, platform_specific, platform, intercepted_build_args, monkeypatch): - env_string = ' '.join(['{}={}'.format(k, v) for k, v in environment.items()]) - if platform_specific: - monkeypatch.setenv('CIBW_ENVIRONMENT_' + platform.upper(), env_string) - monkeypatch.setenv('CIBW_ENVIRONMENT', 'overwritten') - else: - monkeypatch.setenv('CIBW_ENVIRONMENT', env_string) - - main() - - intercepted_environment = intercepted_build_args.kwargs['environment'] - assert isinstance(intercepted_environment, ParsedEnvironment) - assert intercepted_environment.as_dictionary(prev_environment={}) == environment - - -@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): - if test_requires is not None: - if platform_specific: - monkeypatch.setenv('CIBW_TEST_REQUIRES_' + platform.upper(), test_requires) - 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() - - -@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): - if test_extras is not None: - if platform_specific: - monkeypatch.setenv('CIBW_TEST_EXTRAS_' + platform.upper(), test_extras) - 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 '') - - -@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): - if test_command is not None: - if platform_specific: - monkeypatch.setenv('CIBW_TEST_COMMAND_' + platform.upper(), test_command) - monkeypatch.setenv('CIBW_TEST_COMMAND', 'overwritten') - else: - monkeypatch.setenv('CIBW_TEST_COMMAND', test_command) - - main() - - assert intercepted_build_args.kwargs['test_command'] == test_command - - -@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): - if before_build is not None: - if platform_specific: - monkeypatch.setenv('CIBW_BEFORE_BUILD_' + platform.upper(), before_build) - monkeypatch.setenv('CIBW_BEFORE_BUILD', 'overwritten') - else: - monkeypatch.setenv('CIBW_BEFORE_BUILD', before_build) - - main() - - assert intercepted_build_args.kwargs['before_build'] == before_build - - -@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): - if build_verbosity is not None: - if platform_specific: - monkeypatch.setenv('CIBW_BUILD_VERBOSITY_' + platform.upper(), str(build_verbosity)) - monkeypatch.setenv('CIBW_BUILD_VERBOSITY', 'overwritten') - else: - monkeypatch.setenv('CIBW_BUILD_VERBOSITY', str(build_verbosity)) - - main() - - expected_verbosity = max(-3, min(3, int(build_verbosity or 0))) - assert intercepted_build_args.kwargs['build_verbosity'] == expected_verbosity - - -@pytest.mark.parametrize('before_test', ["", 'before --test']) -@pytest.mark.parametrize('platform_specific', [False, True]) -def test_before_test(before_test, platform_specific, platform, intercepted_build_args, monkeypatch): - if before_test is not None: - if platform_specific: - monkeypatch.setenv('CIBW_BEFORE_TEST_' + platform.upper(), before_test) - monkeypatch.setenv('CIBW_BEFORE_TEST', 'overwritten') - else: - monkeypatch.setenv('CIBW_BEFORE_TEST', before_test) - - main() - - assert intercepted_build_args.kwargs['before_test'] == before_test From 7dfc173bca1830ef0e45544427901af1d686e884 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Sat, 7 Mar 2020 18:05:30 +0000 Subject: [PATCH 11/21] Update docs --- docs/options.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/options.md b/docs/options.md index 4b4069ac..1ae87f04 100644 --- a/docs/options.md +++ b/docs/options.md @@ -158,7 +158,7 @@ You must set this variable to pass variables to Linux builds (since they execute You can use `$PATH` syntax to insert other variables, or the `$(pwd)` syntax to insert the output of other shell commands. -To specify more than one environment variable, separate the assignments by spaces. +To specify more than one environment variable, separate the assignments by spaces. Platform-specific variants also available:
`CIBW_ENVIRONMENT_MACOS` | `CIBW_ENVIRONMENT_WINDOWS` | `CIBW_ENVIRONMENT_LINUX` @@ -194,7 +194,7 @@ If dependencies are required to build your wheel (for example if you include a h The active Python binary can be accessed using `python`, and pip with `pip`; `cibuildwheel` makes sure the right version of Python and pip will be executed. `{project}` can be used as a placeholder for the absolute path to the project's root and will be replaced by `cibuildwheel`. -On Linux and macOS, the command is run in a shell, so you can write things like `cmd1 && cmd2`. +The command is run in a shell, so you can write things like `cmd1 && cmd2`. Platform-specific variants also available:
`CIBW_BEFORE_BUILD_MACOS` | `CIBW_BEFORE_BUILD_WINDOWS` | `CIBW_BEFORE_BUILD_LINUX` @@ -209,6 +209,9 @@ CIBW_BEFORE_BUILD: pip install pybind11 # chain commands using && CIBW_BEFORE_BUILD: yum install -y libffi-dev && pip install . + +# run a script that's inside your repo +CIBW_BEFORE_BUILD: bash scripts/prepare_for_build.sh ``` @@ -229,7 +232,7 @@ The following placeholders must be used inside the command and will be replaced - `{wheel}` for the absolute path to the built wheel - `{dest_dir}` for the absolute path of the directory where to create the repaired wheel. -On Linux and macOS, the command is run in a shell, so you can write things like `cmd1 && cmd2`. +The command is run in a shell, so you can run multiple commands like `cmd1 && cmd2`. Platform-specific variants also available:
`CIBW_REPAIR_WHEEL_COMMAND_MACOS` | `CIBW_REPAIR_WHEEL_COMMAND_WINDOWS` | `CIBW_REPAIR_WHEEL_COMMAND_LINUX` @@ -285,7 +288,7 @@ CIBW_MANYLINUX_I686_IMAGE: dockcross/manylinux-x86 Shell command to run tests after the build. The wheel will be installed automatically and available for import from the tests. `{project}` can be used as a placeholder for the absolute path to the project's root and will be replaced by `cibuildwheel`. -On Linux and macOS, the command is run in a shell, so you can write things like `cmd1 && cmd2`. +The command is run in a shell, so you can write things like `cmd1 && cmd2`. Platform-specific variants also available:
`CIBW_TEST_COMMAND_MACOS` | `CIBW_TEST_COMMAND_WINDOWS` | `CIBW_TEST_COMMAND_LINUX` From ff99cb37f8f31381aa2ff1bd05b8dd2a5c8d17c0 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Sat, 7 Mar 2020 19:08:04 +0000 Subject: [PATCH 12/21] Update changelog --- README.md | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7f5f0a8c..f5302ee1 100644 --- a/README.md +++ b/README.md @@ -18,14 +18,15 @@ What does it do? | | macOS x86_64 | Windows 64bit | Windows 32bit | manylinux x86_64 | manylinux i686 | manylinux aarch64 | manylinux ppc64le | manylinux s390x | |---|---|---|---|---|---|---|---|---| | CPython 2.7 | ✅ | ✅¹ | ✅¹ | ✅ | ✅ | | | | -| CPython 3.5 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| CPython 3.6 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| CPython 3.7 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| CPython 3.8 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| CPython 3.5 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² | +| CPython 3.6 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² | +| CPython 3.7 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² | +| CPython 3.8 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² | | PyPy 2.7 v7.3.0 | ✅ | | ✅ | ✅ | | | | | | PyPy 3.6 v7.3.0 | ✅ | | ✅ | ✅ | | | | | -¹ Not supported on Travis +¹ Not supported on Travis
+² Beta support until Travis CI fixes a bug - Builds manylinux, macOS and Windows wheels for CPython and PyPy using Azure Pipelines, Travis CI, AppVeyor, and CircleCI - Bundles shared library dependencies on Linux and macOS through [auditwheel](https://github.com/pypa/auditwheel) and [delocate](https://github.com/matthew-brett/delocate) @@ -138,6 +139,29 @@ This is similar to static linking, so it might have some licence implications. C Changelog ========= +### Next version + +_7 March 2020_ + +- ✨ Add support for building PyPy wheels, across Manylinux, macOS, and + Windows. (#185) +- ✨ Added the ability to build ARM64 (aarch64), ppc64le, and s390x wheels, + using manylinux2014 and Travis CI. (#273) +- ✨ You can now build macOS wheels on Appveyor. (#230) +- 🛠 Changed default macOS minimum target to 10.9, from 10.6. This allows the + use of more modern C++ libraries, among other things. (#156) +- 🛠 Stop building universal binaries on macOS. We now only build x86_64 + wheels on macOS. (#220) +- ✨ Allow chaining of commands using `&&` and `||` on Windows inside + CIBW_BEFORE_BUILD and CIBW_TEST_COMMAND. (#293) +- 🛠 Improved error reporting for failed Cython builds due to stale .so files + (#263) +- 🛠 Update CPython from 3.7.5 to 3.7.6 and from 3.8.0 to 3.8.2 on Mac/Windows +- 🛠 Improved error messages when a bad config breaks cibuildwheel's PATH + variable. (#264) +- ⚠️ Removed support for *running* cibuildwheel on Python 2.7. cibuildwheel + will continue to build Python 2.7 wheels for a little while. + ### 1.1.0 _7 December 2019_ From 18b4d42f83f95644946199bb42d2fb1578c525d7 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Sun, 8 Mar 2020 12:34:56 +0000 Subject: [PATCH 13/21] Add bump_version.py script --- bin/bump_version.py | 113 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100755 bin/bump_version.py diff --git a/bin/bump_version.py b/bin/bump_version.py new file mode 100755 index 00000000..8ad630ac --- /dev/null +++ b/bin/bump_version.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 + +import click +from pathlib import Path +import os +import cibuildwheel +from packaging.version import Version, InvalidVersion +import subprocess +import glob + +config = [ + # file path, version find/replace format + ('cibuildwheel/__init__.py', "__version__ = '{}'"), + ('setup.py', "version='{}'"), + ('README.md', "cibuildwheel=={}"), + ('examples/*', "cibuildwheel=={}"), +] + + +@click.command() +def bump_version(): + git_changes_result = subprocess.run(['git diff-index --quiet HEAD --'], shell=True) + repo_has_uncommitted_changes = git_changes_result.returncode != 0 + + if repo_has_uncommitted_changes: + print('error: Uncommitted changes detected.') + exit(1) + + current_version = cibuildwheel.__version__ + print( 'Current version:', current_version) # noqa + new_version = input(' New version: ').strip() + + try: + Version(new_version) + except InvalidVersion: + print("error: This version doesn't conform to PEP440") + print(' https://www.python.org/dev/peps/pep-0440/') + exit(1) + + actions = [] + + for path_pattern, version_pattern in config: + paths = [Path(p) for p in glob.glob(path_pattern)] + + if not paths: + print(f'error: Pattern {path_pattern} didn’t match any files') + exit(1) + + find_pattern = version_pattern.format(current_version) + replace_pattern = version_pattern.format(new_version) + found_at_least_one_file_needing_update = False + + for path in paths: + contents = path.read_text(encoding='utf8') + if find_pattern in contents: + found_at_least_one_file_needing_update = True + actions.append( + (path, find_pattern, replace_pattern) + ) + + if not found_at_least_one_file_needing_update: + print('error: Didn’t find any occurences of “{}” in “{}”'.format(find_pattern, path_pattern)) + exit(1) + + print() + print("Here's the plan:") + print() + + for action in actions: + print('{} {red}{}{off} → {green}{}{off}'.format( + *action, + red="\u001b[31m", green="\u001b[32m", off="\u001b[0m" + )) + + print('Then commit, and tag as v{}'.format(new_version)) + + answer = input('Proceed? [y/N] ').strip() + + if answer != 'y': + print('Aborted') + exit(1) + + for path, find, replace in actions: + contents = path.read_text(encoding='utf8') + contents = contents.replace(find, replace) + path.write_text(contents, encoding='utf8') + + print('Files updated. If you want to update the changelog as part of this') + print('commit, do that now.') + + while input('Type "done" to continue: ').strip().lower() != 'done': + pass + + subprocess.run([ + 'git', 'commit', + '-a', + '-m', f'Bump version: v{new_version}' + ], check=True) + + subprocess.run([ + 'git', 'tag', + '-a', + '-m', f'v{new_version}', + f'v{new_version}' + ], check=True) + + print('Done.') + + +if __name__ == '__main__': + os.chdir(os.path.dirname(__file__)) + os.chdir('..') + bump_version() From 4628c1334e3350630710bff2a148ab1e18ff2464 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Sun, 8 Mar 2020 12:50:23 +0000 Subject: [PATCH 14/21] Bump version: v1.2.0 --- README.md | 8 ++++---- cibuildwheel/__init__.py | 2 +- examples/appveyor-minimal.yml | 2 +- examples/azure-pipelines-minimal.yml | 6 +++--- examples/circleci-minimal.yml | 4 ++-- examples/travis-ci-deploy-only.yml | 2 +- examples/travis-ci-minimal.yml | 2 +- examples/travis-ci-test-and-deploy.yml | 6 +++--- setup.py | 2 +- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index f5302ee1..021fcdc3 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ env: # Note: TWINE_PASSWORD is set to a PyPI API token in Travis settings install: - - python3 -m pip install cibuildwheel==1.1.0 + - python3 -m pip install cibuildwheel==1.2.0 script: # build the wheels, put them into './wheelhouse' @@ -139,9 +139,9 @@ This is similar to static linking, so it might have some licence implications. C Changelog ========= -### Next version +### 1.2.0 -_7 March 2020_ +_8 March 2020_ - ✨ Add support for building PyPy wheels, across Manylinux, macOS, and Windows. (#185) @@ -160,7 +160,7 @@ _7 March 2020_ - 🛠 Improved error messages when a bad config breaks cibuildwheel's PATH variable. (#264) - ⚠️ Removed support for *running* cibuildwheel on Python 2.7. cibuildwheel - will continue to build Python 2.7 wheels for a little while. + will continue to build Python 2.7 wheels for a little while. (#265) ### 1.1.0 diff --git a/cibuildwheel/__init__.py b/cibuildwheel/__init__.py index 1a72d32e..58d478ab 100644 --- a/cibuildwheel/__init__.py +++ b/cibuildwheel/__init__.py @@ -1 +1 @@ -__version__ = '1.1.0' +__version__ = '1.2.0' diff --git a/examples/appveyor-minimal.yml b/examples/appveyor-minimal.yml index a6d8654b..3b5625e1 100644 --- a/examples/appveyor-minimal.yml +++ b/examples/appveyor-minimal.yml @@ -12,7 +12,7 @@ stack: python 3.7 init: - cmd: set PATH=C:\Python37;C:\Python37\Scripts;%PATH% -install: python -m pip install cibuildwheel==1.1.0 +install: python -m pip install cibuildwheel==1.2.0 build_script: python -m cibuildwheel --output-dir wheelhouse diff --git a/examples/azure-pipelines-minimal.yml b/examples/azure-pipelines-minimal.yml index d5504b2d..d457e1b5 100644 --- a/examples/azure-pipelines-minimal.yml +++ b/examples/azure-pipelines-minimal.yml @@ -5,7 +5,7 @@ jobs: - task: UsePythonVersion@0 - bash: | python3 -m pip install --upgrade pip - pip3 install cibuildwheel==1.1.0 + pip3 install cibuildwheel==1.2.0 cibuildwheel --output-dir wheelhouse . - task: PublishBuildArtifacts@1 inputs: {pathtoPublish: 'wheelhouse'} @@ -16,7 +16,7 @@ jobs: - task: UsePythonVersion@0 - bash: | python3 -m pip install --upgrade pip - pip3 install cibuildwheel==1.1.0 + pip3 install cibuildwheel==1.2.0 cibuildwheel --output-dir wheelhouse . - task: PublishBuildArtifacts@1 inputs: {pathtoPublish: 'wheelhouse'} @@ -29,7 +29,7 @@ jobs: displayName: Install Visual C++ for Python 2.7 - bash: | python -m pip install --upgrade pip - pip install cibuildwheel==1.1.0 + pip install cibuildwheel==1.2.0 cibuildwheel --output-dir wheelhouse . - task: PublishBuildArtifacts@1 inputs: {pathtoPublish: 'wheelhouse'} diff --git a/examples/circleci-minimal.yml b/examples/circleci-minimal.yml index fd6c00e8..f76b011c 100644 --- a/examples/circleci-minimal.yml +++ b/examples/circleci-minimal.yml @@ -11,7 +11,7 @@ jobs: - run: name: Build the Linux wheels. command: | - pip3 install --user cibuildwheel==1.1.0 + pip3 install --user cibuildwheel==1.2.0 cibuildwheel --output-dir wheelhouse - store_artifacts: path: wheelhouse/ @@ -25,7 +25,7 @@ jobs: - run: name: Build the OS X wheels. command: | - pip3 install --user cibuildwheel==1.1.0 + pip3 install --user cibuildwheel==1.2.0 cibuildwheel --output-dir wheelhouse - store_artifacts: path: wheelhouse/ diff --git a/examples/travis-ci-deploy-only.yml b/examples/travis-ci-deploy-only.yml index 1e08893f..f205bc76 100644 --- a/examples/travis-ci-deploy-only.yml +++ b/examples/travis-ci-deploy-only.yml @@ -25,7 +25,7 @@ env: # Note: TWINE_PASSWORD is set to a PyPI API token in Travis settings install: - - python3 -m pip install cibuildwheel==1.1.0 + - python3 -m pip install cibuildwheel==1.2.0 script: # build the wheels, put them into './wheelhouse' diff --git a/examples/travis-ci-minimal.yml b/examples/travis-ci-minimal.yml index d3bb5a75..2060444e 100644 --- a/examples/travis-ci-minimal.yml +++ b/examples/travis-ci-minimal.yml @@ -26,7 +26,7 @@ jobs: - ln -s /c/Python38/python.exe /c/Python38/python3.exe install: - - python3 -m pip install cibuildwheel==1.1.0 + - python3 -m pip install cibuildwheel==1.2.0 script: # build the wheels, put them into './wheelhouse' diff --git a/examples/travis-ci-test-and-deploy.yml b/examples/travis-ci-test-and-deploy.yml index 2012a06f..5a92634a 100644 --- a/examples/travis-ci-test-and-deploy.yml +++ b/examples/travis-ci-test-and-deploy.yml @@ -56,7 +56,7 @@ jobs: - stage: deploy name: Build and deploy Linux wheels services: docker - install: python3 -m pip install cibuildwheel==1.1.0 + install: python3 -m pip install cibuildwheel==1.2.0 script: python3 -m cibuildwheel --output-dir wheelhouse after_success: | python3 -m pip install twine @@ -66,7 +66,7 @@ jobs: name: Build and deploy macOS wheels os: osx language: shell - install: python3 -m pip install cibuildwheel==1.1.0 + install: python3 -m pip install cibuildwheel==1.2.0 script: python3 -m cibuildwheel --output-dir wheelhouse after_success: | python3 -m pip install twine @@ -76,7 +76,7 @@ jobs: name: Build and deploy Windows wheels os: windows language: shell - install: python3 -m pip install cibuildwheel==1.1.0 + install: python3 -m pip install cibuildwheel==1.2.0 script: python3 -m cibuildwheel --output-dir wheelhouse after_success: | python3 -m pip install twine diff --git a/setup.py b/setup.py index 010d5621..e139d8fb 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ with io.open(os.path.join(this_directory, 'README.md'), encoding='utf-8') as f: setup( name='cibuildwheel', - version='1.1.0', + version='1.2.0', install_requires=['bashlex!=0.13'], description="Build Python wheels on CI with minimal configuration.", long_description=long_description, From 42489436a2aa77bd1f470d7d361cc4c7555906a6 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Sun, 8 Mar 2020 12:52:22 +0000 Subject: [PATCH 15/21] Remove obsolete bumpversion config --- setup.cfg | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/setup.cfg b/setup.cfg index 4346b720..2aeb8aaf 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,21 +1,3 @@ -[bumpversion] -current_version = 1.1.0 -commit = True -tag = True -message = Bump version - -[bumpversion:file:setup.py] - -[bumpversion:file:cibuildwheel/__init__.py] - -[bumpversion:file:README.md] -search = cibuildwheel=={current_version} -replace = cibuildwheel=={new_version} - -[bumpversion:file:docs/setup.md] -search = cibuildwheel=={current_version} -replace = cibuildwheel=={new_version} - [bdist_wheel] universal = 1 From 9ae2ae4ac6ee426831096ac6069fcbd1a13bbcc9 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Sun, 8 Mar 2020 13:10:06 +0000 Subject: [PATCH 16/21] Produce a python-3-only wheel --- setup.cfg | 3 --- 1 file changed, 3 deletions(-) diff --git a/setup.cfg b/setup.cfg index 2aeb8aaf..b2c53158 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,3 @@ -[bdist_wheel] -universal = 1 - [flake8] ignore = E501,W503 application-import-names = cibuildwheel From 7e566e46eee4b37c54bfa7881b50c3676091cad5 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Sun, 8 Mar 2020 14:25:36 +0100 Subject: [PATCH 17/21] uses sys.prefix instead of sys.executable in before_test --- test/11_before_test/cibuildwheel_test.py | 4 ++-- test/11_before_test/test/spam_test.py | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/11_before_test/cibuildwheel_test.py b/test/11_before_test/cibuildwheel_test.py index 7db1b127..5aa1c4ca 100644 --- a/test/11_before_test/cibuildwheel_test.py +++ b/test/11_before_test/cibuildwheel_test.py @@ -9,8 +9,8 @@ def test(): actual_wheels = utils.cibuildwheel_run(project_dir, add_env={ # write python version information to a temporary file, this is # checked in setup.py - 'CIBW_BEFORE_TEST': '''python -c "import sys; open('/tmp/pythonversion.txt', 'w').write(sys.version)" && python -c "import sys; open('/tmp/pythonexecutable.txt', 'w').write(sys.executable)"''', - 'CIBW_BEFORE_TEST_WINDOWS': '''python -c "import sys; open('c:\\pythonversion.txt', 'w').write(sys.version)" && python -c "import sys; open('c:\\pythonexecutable.txt', 'w').write(sys.executable)"''', + 'CIBW_BEFORE_TEST': '''python -c "import sys; open('/tmp/pythonversion.txt', 'w').write(sys.version)" && python -c "import sys; open('/tmp/pythonprefix.txt', 'w').write(sys.prefix)"''', + 'CIBW_BEFORE_TEST_WINDOWS': '''python -c "import sys; open('c:\\pythonversion.txt', 'w').write(sys.version)" && python -c "import sys; open('c:\\pythonprefix.txt', 'w').write(sys.prefix)"''', 'CIBW_TEST_REQUIRES': 'nose', # the 'false ||' bit is to ensure this command runs in a shell on # mac/linux. diff --git a/test/11_before_test/test/spam_test.py b/test/11_before_test/test/spam_test.py index e25cc0c7..21bad8c2 100644 --- a/test/11_before_test/test/spam_test.py +++ b/test/11_before_test/test/spam_test.py @@ -15,14 +15,14 @@ class TestBeforeTest(TestCase): print('sys.version', sys.version) assert stored_version == sys.version - def test_executable(self): - # check that the executable also was written - executable_file = 'c:\\pythonexecutable.txt' if sys.platform == 'win32' else '/tmp/pythonexecutable.txt' - with open(executable_file) as f: - stored_executable = f.read() - print('stored_executable', stored_executable) - print('sys.executable', sys.executable) + def test_prefix(self): + # check that the prefix also was written + prefix_file = 'c:\\pythonprefix.txt' if sys.platform == 'win32' else '/tmp/pythonprefix.txt' + with open(prefix_file) as f: + stored_prefix = f.read() + print('stored_prefix', stored_prefix) + print('sys.prefix', sys.prefix) # Works around path-comparison bugs caused by short-paths on Windows e.g. # vssadm~1 instead of vssadministrator - assert os.stat(stored_executable) == os.stat(sys.executable) + assert os.stat(stored_prefix) == os.stat(sys.prefix) From 23870b6780d760ea2e9ff2fbadfcf3e8f1c21161 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Sun, 8 Mar 2020 18:06:14 +0000 Subject: [PATCH 18/21] Update options.md Docs edit- now Windows does run in a shell too --- docs/options.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/options.md b/docs/options.md index 81ed03c3..7006f9d8 100644 --- a/docs/options.md +++ b/docs/options.md @@ -349,10 +349,9 @@ CIBW_TEST_EXTRAS: test,qt A shell command to run in **each** test virtual environment, before your wheel is installed and tested. This is useful if you need to install a non pip package, change values of environment variables or perform multi step pip installation (e.g. installing `scikit-build` or `cython` before install test package) - The active Python binary can be accessed using `python`, and pip with `pip`; `cibuildwheel` makes sure the right version of Python and pip will be executed. `{project}` can be used as a placeholder for the absolute path to the project's root and will be replaced by `cibuildwheel`. -On Linux and macOS, the command is run in a shell, so you can write things like `cmd1 && cmd2`. +The command is run in a shell, so you can write things like `cmd1 && cmd2`. Platform-specific variants also available:
`CIBW_BEFORE_TEST_MACOS` | `CIBW_BEFORE_TEST_WINDOWS` | `CIBW_BEFORE_TEST_LINUX` From 77fb97caf33f60dc624ccdeae5dba6c45cc6c3c2 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Sun, 8 Mar 2020 18:08:48 +0000 Subject: [PATCH 19/21] Fix typo --- docs/options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/options.md b/docs/options.md index 7006f9d8..d2feaa0f 100644 --- a/docs/options.md +++ b/docs/options.md @@ -362,7 +362,7 @@ Platform-specific variants also available:
CIBW_BEFORE_TEST: CC=gcc CXX=g++ pip install -r requirements.txt # chain commands using && -CIBW_BEFORE_TEST : rm -rf ./data/cache && mkdir -p ./data/cache +CIBW_BEFORE_TEST: rm -rf ./data/cache && mkdir -p ./data/cache # install non pip python package CIBW_BEFORE_TEST: cd some_dir; ./configure; make; make install From bb12d3dc31dfa580e8e6c0e8692cd943d221e3d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan-David=20Schr=C3=B6der?= Date: Mon, 9 Mar 2020 19:10:18 +0100 Subject: [PATCH 20/21] Referencing gmic-py as Working example (for the macosx Github Actions builds) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 748ae19e..6a069aa3 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,7 @@ Here are some repos that use cibuildwheel. - [apriltags2-ethz](https://github.com/safijari/apriltags2_ethz) - [TgCrypto](https://github.com/pyrogram/tgcrypto) - [Twisted](https://github.com/twisted/twisted) +- [gmic-py](https://github.com/dtschump/gmic-py) > Add your repo here! Send a PR. From ce85c8730dc6dbd02d45474884cf86da0059005c Mon Sep 17 00:00:00 2001 From: Yannick Jadoul Date: Mon, 9 Mar 2020 20:53:48 +0100 Subject: [PATCH 21/21] Use yaml anchors and references to not repeat full job in allow_failures --- .travis.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 02b90836..4ad0022c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,8 @@ jobs: env: - PYTHON=C:\\Python35\\python - - name: Linux | s390x | Python 3.5 + - &linux_s390x_35 + name: Linux | s390x | Python 3.5 language: python python: 3.5 services: docker @@ -43,12 +44,7 @@ jobs: allow_failures: # must repeat the s390x job above exactly to match - - name: Linux | s390x | Python 3.5 - language: python - python: 3.5 - services: docker - arch: s390x - env: PYTHON=python + - *linux_s390x_35 install: $PYTHON -m pip install -r requirements-dev.txt