"""'pip wheel' tests""" import os import re import sys from pathlib import Path import pytest from pip._internal.cli.status_codes import ERROR from tests.lib import ( PipTestEnvironment, TestData, pyversion, ) def add_files_to_dist_directory(folder: Path) -> None: (folder / "dist").mkdir(parents=True) (folder / "dist" / "a_name-0.0.1.tar.gz").write_text("hello") # Not adding a wheel file since that confuses setuptools' backend. # (folder / 'dist' / 'a_name-0.0.1-py2.py3-none-any.whl').write_text( # "hello" # ) def test_wheel_exit_status_code_when_no_requirements( script: PipTestEnvironment, ) -> None: """ Test wheel exit status code when no requirements specified """ result = script.pip("wheel", expect_error=True) assert "You must give at least one requirement to wheel" in result.stderr assert result.returncode == ERROR def test_wheel_exit_status_code_when_blank_requirements_file( script: PipTestEnvironment, ) -> None: """ Test wheel exit status code when blank requirements file specified """ script.scratch_path.joinpath("blank.txt").write_text("\n") script.pip("wheel", "-r", "blank.txt") def test_pip_wheel_success(script: PipTestEnvironment, data: TestData) -> None: """ Test 'pip wheel' success. """ result = script.pip( "wheel", "--no-index", "-f", data.find_links, "simple==3.0", ) wheel_file_name = f"simple-3.0-py{pyversion[0]}-none-any.whl" wheel_file_path = script.scratch / wheel_file_name assert re.search( r"Created wheel for simple: " rf"filename={re.escape(wheel_file_name)} size=\d+ sha256=[A-Fa-f0-9]{{64}}", result.stdout, ) assert re.search(r"^\s+Stored in directory: ", result.stdout, re.M) result.did_create(wheel_file_path) assert "Successfully built simple" in result.stdout, result.stdout def test_pip_wheel_build_cache(script: PipTestEnvironment, data: TestData) -> None: """ Test 'pip wheel' builds and caches. """ result = script.pip( "wheel", "--no-index", "-f", data.find_links, "simple==3.0", ) wheel_file_name = f"simple-3.0-py{pyversion[0]}-none-any.whl" wheel_file_path = script.scratch / wheel_file_name result.did_create(wheel_file_path) assert "Successfully built simple" in result.stdout, result.stdout # remove target file (script.scratch_path / wheel_file_name).unlink() # pip wheel again and test that no build occurs since # we get the wheel from cache result = script.pip( "wheel", "--no-index", "-f", data.find_links, "simple==3.0", ) result.did_create(wheel_file_path) assert "Successfully built simple" not in result.stdout, result.stdout def test_basic_pip_wheel_downloads_wheels( script: PipTestEnvironment, data: TestData ) -> None: """ Test 'pip wheel' downloads wheels """ result = script.pip( "wheel", "--no-index", "-f", data.find_links, "simple.dist", ) wheel_file_name = "simple.dist-0.1-py2.py3-none-any.whl" wheel_file_path = script.scratch / wheel_file_name result.did_create(wheel_file_path) assert "Saved" in result.stdout, result.stdout def test_pip_wheel_build_relative_cachedir( script: PipTestEnvironment, data: TestData ) -> None: """ Test 'pip wheel' builds and caches with a non-absolute cache directory. """ result = script.pip( "wheel", "--no-index", "-f", data.find_links, "--cache-dir", "./cache", "simple==3.0", ) assert result.returncode == 0 def test_pip_wheel_builds_when_no_binary_set( script: PipTestEnvironment, data: TestData ) -> None: data.packages.joinpath("simple-3.0-py2.py3-none-any.whl").touch() # Check that the wheel package is ignored res = script.pip( "wheel", "--no-index", "--no-binary", ":all:", "-f", data.find_links, "simple==3.0", ) assert "Building wheel for simple" in str(res), str(res) @pytest.mark.skipif("sys.platform == 'win32'") def test_pip_wheel_readonly_cache( script: PipTestEnvironment, data: TestData, tmpdir: Path ) -> None: cache_dir = tmpdir / "cache" cache_dir.mkdir() os.chmod(cache_dir, 0o400) # read-only cache # Check that the wheel package is ignored res = script.pip( "wheel", "--no-index", "-f", data.find_links, "--cache-dir", cache_dir, "simple==3.0", allow_stderr_warning=True, ) assert res.returncode == 0 assert "The cache has been disabled." in str(res), str(res) def test_pip_wheel_builds_editable_deps( script: PipTestEnvironment, data: TestData ) -> None: """ Test 'pip wheel' finds and builds dependencies of editables """ editable_path = os.path.join(data.src, "requires_simple") result = script.pip( "wheel", "--no-index", "-f", data.find_links, "-e", editable_path ) wheel_file_name = f"simple-1.0-py{pyversion[0]}-none-any.whl" wheel_file_path = script.scratch / wheel_file_name result.did_create(wheel_file_path) def test_pip_wheel_builds_editable(script: PipTestEnvironment, data: TestData) -> None: """ Test 'pip wheel' builds an editable package """ editable_path = os.path.join(data.src, "simplewheel-1.0") result = script.pip( "wheel", "--no-index", "-f", data.find_links, "-e", editable_path ) wheel_file_name = f"simplewheel-1.0-py{pyversion[0]}-none-any.whl" wheel_file_path = script.scratch / wheel_file_name result.did_create(wheel_file_path) @pytest.mark.network def test_pip_wheel_git_editable_keeps_clone( script: PipTestEnvironment, tmpdir: Path ) -> None: """ Test that `pip wheel -e giturl` preserves a git clone in src. """ script.pip( "wheel", "--no-deps", "-e", "git+https://github.com/pypa/pip-test-package#egg=pip-test-package", "--src", tmpdir / "src", "--wheel-dir", tmpdir, ) assert (tmpdir / "src" / "pip-test-package").exists() assert (tmpdir / "src" / "pip-test-package" / ".git").exists() def test_pip_wheel_builds_editable_does_not_create_zip( script: PipTestEnvironment, data: TestData, tmpdir: Path ) -> None: """ Test 'pip wheel' of editables does not create zip files (regression test for issue #9122) """ wheel_dir = tmpdir / "wheel_dir" wheel_dir.mkdir() editable_path = os.path.join(data.src, "simplewheel-1.0") script.pip("wheel", "--no-deps", "-e", editable_path, "-w", wheel_dir) wheels = os.listdir(wheel_dir) assert len(wheels) == 1 assert wheels[0].endswith(".whl") def test_pip_wheel_fail(script: PipTestEnvironment, data: TestData) -> None: """ Test 'pip wheel' failure. """ result = script.pip( "wheel", "--no-index", "-f", data.find_links, "wheelbroken==0.1", expect_error=True, ) wheel_file_name = f"wheelbroken-0.1-py{pyversion[0]}-none-any.whl" wheel_file_path = script.scratch / wheel_file_name result.did_not_create(wheel_file_path) assert "FakeError" in result.stderr, result.stderr assert "Failed to build wheelbroken" in result.stdout, result.stdout assert result.returncode != 0 def test_pip_wheel_source_deps(script: PipTestEnvironment, data: TestData) -> None: """ Test 'pip wheel' finds and builds source archive dependencies of wheels """ # 'requires_source' is a wheel that depends on the 'source' project result = script.pip( "wheel", "--no-index", "-f", data.find_links, "requires_source", ) wheel_file_name = f"source-1.0-py{pyversion[0]}-none-any.whl" wheel_file_path = script.scratch / wheel_file_name result.did_create(wheel_file_path) assert "Successfully built source" in result.stdout, result.stdout def test_wheel_package_with_latin1_setup( script: PipTestEnvironment, data: TestData ) -> None: """Create a wheel from a package with latin-1 encoded setup.py.""" pkg_to_wheel = data.packages.joinpath("SetupPyLatin1") result = script.pip("wheel", pkg_to_wheel) assert "Successfully built SetupPyUTF8" in result.stdout def test_pip_wheel_with_pep518_build_reqs( script: PipTestEnvironment, data: TestData, common_wheels: Path ) -> None: result = script.pip( "wheel", "--no-index", "-f", data.find_links, "-f", common_wheels, "pep518==3.0", ) wheel_file_name = f"pep518-3.0-py{pyversion[0]}-none-any.whl" wheel_file_path = script.scratch / wheel_file_name result.did_create(wheel_file_path) assert "Successfully built pep518" in result.stdout, result.stdout assert "Installing build dependencies" in result.stdout, result.stdout def test_pip_wheel_with_pep518_build_reqs_no_isolation( script: PipTestEnvironment, data: TestData ) -> None: script.pip_install_local("simplewheel==2.0") result = script.pip( "wheel", "--no-index", "-f", data.find_links, "--no-build-isolation", "pep518==3.0", ) wheel_file_name = f"pep518-3.0-py{pyversion[0]}-none-any.whl" wheel_file_path = script.scratch / wheel_file_name result.did_create(wheel_file_path) assert "Successfully built pep518" in result.stdout, result.stdout assert "Installing build dependencies" not in result.stdout, result.stdout def test_pip_wheel_with_user_set_in_config( script: PipTestEnvironment, data: TestData, common_wheels: Path ) -> None: config_file = script.scratch_path / "pip.conf" script.environ["PIP_CONFIG_FILE"] = str(config_file) config_file.write_text("[install]\nuser = true") result = script.pip( "wheel", data.src / "withpyproject", "--no-index", "-f", common_wheels ) assert "Successfully built withpyproject" in result.stdout, result.stdout @pytest.mark.skipif( sys.platform.startswith("win"), reason="The empty extension module does not work on Win", ) def test_pip_wheel_ext_module_with_tmpdir_inside( script: PipTestEnvironment, data: TestData, common_wheels: Path ) -> None: tmpdir = data.src / "extension/tmp" tmpdir.mkdir() script.environ["TMPDIR"] = str(tmpdir) # To avoid a test dependency on a C compiler, we set the env vars to "noop" # The .c source is empty anyway script.environ["CC"] = script.environ["LDSHARED"] = "true" result = script.pip( "wheel", data.src / "extension", "--no-index", "-f", common_wheels ) assert "Successfully built extension" in result.stdout, result.stdout @pytest.mark.network def test_pep517_wheels_are_not_confused_with_other_files( script: PipTestEnvironment, data: TestData ) -> None: """Check correct wheels are copied. (#6196)""" pkg_to_wheel = data.src / "withpyproject" add_files_to_dist_directory(pkg_to_wheel) result = script.pip("wheel", pkg_to_wheel, "-w", script.scratch_path) assert "Installing build dependencies" in result.stdout, result.stdout wheel_file_name = f"withpyproject-0.0.1-py{pyversion[0]}-none-any.whl" wheel_file_path = script.scratch / wheel_file_name result.did_create(wheel_file_path) def test_legacy_wheels_are_not_confused_with_other_files( script: PipTestEnvironment, data: TestData ) -> None: """Check correct wheels are copied. (#6196)""" pkg_to_wheel = data.src / "simplewheel-1.0" add_files_to_dist_directory(pkg_to_wheel) result = script.pip("wheel", pkg_to_wheel, "-w", script.scratch_path) assert "Installing build dependencies" not in result.stdout, result.stdout wheel_file_name = f"simplewheel-1.0-py{pyversion[0]}-none-any.whl" wheel_file_path = script.scratch / wheel_file_name result.did_create(wheel_file_path)