From d198c90f7a282667a27a73a4bcd4b28402e27566 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Fri, 24 Nov 2023 11:49:26 +0000 Subject: [PATCH 1/5] Allow the user to set PIP_CONSTRAINT and it affect build-system.requires --- cibuildwheel/macos.py | 4 +++- cibuildwheel/windows.py | 4 +++- docs/options.md | 2 +- test/test_environment.py | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/cibuildwheel/macos.py b/cibuildwheel/macos.py index 77ae492a..07d1bf95 100644 --- a/cibuildwheel/macos.py +++ b/cibuildwheel/macos.py @@ -409,7 +409,9 @@ def build(options: Options, tmp_path: Path) -> None: config.version ) ) - build_env["PIP_CONSTRAINT"] = constraint_path.as_uri() + build_env["PIP_CONSTRAINT"] = ( + constraint_path.as_uri() + " " + build_env.get("PIP_CONSTRAINT", "") + ) build_env["VIRTUALENV_PIP"] = get_pip_version(env) call( "python", diff --git a/cibuildwheel/windows.py b/cibuildwheel/windows.py index 881821bd..9fe9f489 100644 --- a/cibuildwheel/windows.py +++ b/cibuildwheel/windows.py @@ -455,7 +455,9 @@ def build(options: Options, tmp_path: Path) -> None: tmp_file.write_bytes(constraints_path.read_bytes()) constraints_path = tmp_file - build_env["PIP_CONSTRAINT"] = str(constraints_path) + build_env["PIP_CONSTRAINT"] = ( + str(constraints_path) + " " + build_env.get("PIP_CONSTRAINT", "") + ) build_env["VIRTUALENV_PIP"] = get_pip_version(env) call( "python", diff --git a/docs/options.md b/docs/options.md index e9e343a3..eff5ccd3 100644 --- a/docs/options.md +++ b/docs/options.md @@ -674,7 +674,7 @@ Platform-specific environment variables are also available:
cibuildwheel always defines the environment variable `CIBUILDWHEEL=1`. This can be useful for [building wheels with optional extensions](faq.md#building-packages-with-optional-c-extensions). !!! note - To do its work, cibuildwheel internally sets the options `PIP_CONSTRAINT`, `VIRTUALENV_PIP`, `DIST_EXTRA_CONFIG`, `SETUPTOOLS_EXT_SUFFIX`, `PIP_DISABLE_PIP_VERSION_CHECK`, `PIP_ROOT_USER_ACTION`. Your assignments to these options might be overridden. + To do its work, cibuildwheel internally sets the options `VIRTUALENV_PIP`, `DIST_EXTRA_CONFIG`, `SETUPTOOLS_EXT_SUFFIX`, `PIP_DISABLE_PIP_VERSION_CHECK`, `PIP_ROOT_USER_ACTION`. Your assignments to these options might be overridden. ### `CIBW_ENVIRONMENT_PASS_LINUX` {: #environment-pass} > Set environment variables on the host to pass-through to the container. diff --git a/test/test_environment.py b/test/test_environment.py index 35de8785..1ab76d1b 100644 --- a/test/test_environment.py +++ b/test/test_environment.py @@ -93,3 +93,40 @@ def test_overridden_path(tmp_path, capfd): assert len(os.listdir(output_dir)) == 0 captured = capfd.readouterr() assert "python available on PATH doesn't match our installed instance" in captured.err + + +@pytest.mark.parametrize("build_frontend", ["pip", "build"]) +def test_overridden_pip_constraint(tmp_path, build_frontend): + project_dir = tmp_path / "project" + + project = test_projects.new_c_project( + setup_py_add=textwrap.dedent( + """ + import pytz + assert pytz.__version__ == "2022.4" + """ + ) + ) + project.files["pyproject.toml"] = textwrap.dedent( + """ + [build-system] + requires = ["setuptools", "pytz"] + build-backend = "setuptools.build_meta" + """ + ) + project.generate(project_dir) + + constraints_file = tmp_path / "constraints.txt" + constraints_file.write_text("pytz==2022.4") + + actual_wheels = utils.cibuildwheel_run( + project_dir, + add_env={ + "CIBW_BUILD": "cp312-*", + "CIBW_BUILD_FRONTEND": build_frontend, + "CIBW_ENVIRONMENT": f"PIP_CONSTRAINT={constraints_file}", + }, + ) + + expected_wheels = [w for w in utils.expected_wheels("spam", "0.1.0") if "cp312" in w] + assert set(actual_wheels) == set(expected_wheels) From c2b03ead3e751772d4efd43c88dcd8f6f58459a8 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Fri, 24 Nov 2023 15:12:49 +0000 Subject: [PATCH 2/5] Fix test issue around container paths --- test/test_environment.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/test/test_environment.py b/test/test_environment.py index 1ab76d1b..f7a31b16 100644 --- a/test/test_environment.py +++ b/test/test_environment.py @@ -97,6 +97,11 @@ def test_overridden_path(tmp_path, capfd): @pytest.mark.parametrize("build_frontend", ["pip", "build"]) def test_overridden_pip_constraint(tmp_path, build_frontend): + """ + Verify that users can use PIP_CONSTRAINT to specify a specific version of + a build-system.requires dependency, by asserting the version of pytz in the + setup.py. + """ project_dir = tmp_path / "project" project = test_projects.new_c_project( @@ -116,7 +121,13 @@ def test_overridden_pip_constraint(tmp_path, build_frontend): ) project.generate(project_dir) - constraints_file = tmp_path / "constraints.txt" + if utils.platform == "linux": + # put the constraints file in the project directory, so it's available + # in the docker container + constraints_file = project_dir / "constraints.txt" + else: + constraints_file = tmp_path / "constraints.txt" + constraints_file.write_text("pytz==2022.4") actual_wheels = utils.cibuildwheel_run( @@ -125,6 +136,7 @@ def test_overridden_pip_constraint(tmp_path, build_frontend): "CIBW_BUILD": "cp312-*", "CIBW_BUILD_FRONTEND": build_frontend, "CIBW_ENVIRONMENT": f"PIP_CONSTRAINT={constraints_file}", + "CIBW_ENVIRONMENT_LINUX": "PIP_CONSTRAINT=./constraints.txt", }, ) From 2a1edad716639bb25e974596dc8844237b99fd77 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Fri, 24 Nov 2023 17:57:08 +0000 Subject: [PATCH 3/5] Backslashes in Windows paths mess with CIBW_ENVIRONMENT string parsing --- test/test_environment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_environment.py b/test/test_environment.py index f7a31b16..faaba7f3 100644 --- a/test/test_environment.py +++ b/test/test_environment.py @@ -135,7 +135,7 @@ def test_overridden_pip_constraint(tmp_path, build_frontend): add_env={ "CIBW_BUILD": "cp312-*", "CIBW_BUILD_FRONTEND": build_frontend, - "CIBW_ENVIRONMENT": f"PIP_CONSTRAINT={constraints_file}", + "PIP_CONSTRAINT": str(constraints_file), "CIBW_ENVIRONMENT_LINUX": "PIP_CONSTRAINT=./constraints.txt", }, ) From ddc2c6e845fa787074fdbf24ba7d0557805680e3 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Fri, 26 Jan 2024 18:52:47 +0000 Subject: [PATCH 4/5] Make the note on environment variables clear --- docs/options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/options.md b/docs/options.md index eff5ccd3..1b11cf3b 100644 --- a/docs/options.md +++ b/docs/options.md @@ -674,7 +674,7 @@ Platform-specific environment variables are also available:
cibuildwheel always defines the environment variable `CIBUILDWHEEL=1`. This can be useful for [building wheels with optional extensions](faq.md#building-packages-with-optional-c-extensions). !!! note - To do its work, cibuildwheel internally sets the options `VIRTUALENV_PIP`, `DIST_EXTRA_CONFIG`, `SETUPTOOLS_EXT_SUFFIX`, `PIP_DISABLE_PIP_VERSION_CHECK`, `PIP_ROOT_USER_ACTION`. Your assignments to these options might be overridden. + To do its work, cibuildwheel sets the variables `VIRTUALENV_PIP`, `DIST_EXTRA_CONFIG`, `SETUPTOOLS_EXT_SUFFIX`, `PIP_DISABLE_PIP_VERSION_CHECK`, `PIP_ROOT_USER_ACTION`, and it extends the variables `PATH` and `PIP_CONSTRAINT`. Your assignments to these options might be replaced or extended. ### `CIBW_ENVIRONMENT_PASS_LINUX` {: #environment-pass} > Set environment variables on the host to pass-through to the container. From 6940c77cd3450d4435ccd7b1610dd6419b81bc81 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Sat, 2 Mar 2024 18:16:20 +0000 Subject: [PATCH 5/5] style improvements from code review --- cibuildwheel/macos.py | 6 ++++-- cibuildwheel/windows.py | 7 +++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/cibuildwheel/macos.py b/cibuildwheel/macos.py index 79eb7bf5..e2970412 100644 --- a/cibuildwheel/macos.py +++ b/cibuildwheel/macos.py @@ -409,8 +409,10 @@ def build(options: Options, tmp_path: Path) -> None: config.version ) ) - build_env["PIP_CONSTRAINT"] = ( - constraint_path.as_uri() + " " + build_env.get("PIP_CONSTRAINT", "") + user_constraints = build_env.get("PIP_CONSTRAINT") + our_constraints = constraint_path.as_uri() + build_env["PIP_CONSTRAINT"] = " ".join( + c for c in [user_constraints, our_constraints] if c ) build_env["VIRTUALENV_PIP"] = get_pip_version(env) call( diff --git a/cibuildwheel/windows.py b/cibuildwheel/windows.py index 30553fc8..4d89b9c9 100644 --- a/cibuildwheel/windows.py +++ b/cibuildwheel/windows.py @@ -455,9 +455,12 @@ def build(options: Options, tmp_path: Path) -> None: tmp_file.write_bytes(constraints_path.read_bytes()) constraints_path = tmp_file - build_env["PIP_CONSTRAINT"] = ( - str(constraints_path) + " " + build_env.get("PIP_CONSTRAINT", "") + our_constraints = str(constraints_path) + user_constraints = build_env.get("PIP_CONSTRAINT") + build_env["PIP_CONSTRAINT"] = " ".join( + c for c in [our_constraints, user_constraints] if c ) + build_env["VIRTUALENV_PIP"] = get_pip_version(env) call( "python",