Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always use pep 517 when the 'wheel' package is absent #11871

Merged
merged 13 commits into from
Mar 27, 2023
Merged
2 changes: 2 additions & 0 deletions news/8559.removal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
When the ``wheel`` package is not installed, pip now uses the default build backend
instead of ``setup.py install`` for project without ``pyproject.toml``.
10 changes: 7 additions & 3 deletions src/pip/_internal/cli/cmdoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -783,10 +783,14 @@ def _handle_no_use_pep517(
"""
raise_option_error(parser, option=option, msg=msg)

# If user doesn't wish to use pep517, we check if setuptools is installed
# If user doesn't wish to use pep517, we check if setuptools and wheel are installed
# and raise error if it is not.
if not importlib.util.find_spec("setuptools"):
msg = "It is not possible to use --no-use-pep517 without setuptools installed."
packages = ("setuptools", "wheel")
if not all(importlib.util.find_spec(package) for package in packages):
msg = (
f"It is not possible to use --no-use-pep517 "
f"without {' and '.join(packages)} installed."
)
raise_option_error(parser, option=option, msg=msg)

# Otherwise, --no-use-pep517 was passed via the command-line.
Expand Down
9 changes: 7 additions & 2 deletions src/pip/_internal/pyproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,17 @@ def load_pyproject_toml(
# we do so if the project has a pyproject.toml file
# or if we cannot import setuptools.

# We fallback to PEP 517 when without setuptools,
# We fallback to PEP 517 when without setuptools or without the wheel package,
# so setuptools can be installed as a default build backend.
# For more info see:
# https://discuss.python.org/t/pip-without-setuptools-could-the-experience-be-improved/11810/9
# https://github.com/pypa/pip/issues/8559
elif use_pep517 is None:
use_pep517 = has_pyproject or not importlib.util.find_spec("setuptools")
use_pep517 = (
has_pyproject
or not importlib.util.find_spec("setuptools")
or not importlib.util.find_spec("wheel")
)

# At this point, we know whether we're going to use PEP 517.
assert use_pep517 is not None
Expand Down
14 changes: 0 additions & 14 deletions src/pip/_internal/utils/deprecation.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,17 +159,3 @@ def emit_deprecation(self, name: str) -> None:
issue=8368,
emit_after_success=True,
)


LegacyInstallReasonMissingWheelPackage = LegacyInstallReason(
reason=(
"{name} is being installed using the legacy "
"'setup.py install' method, because it does not have a "
"'pyproject.toml' and the 'wheel' package "
"is not installed."
),
replacement="to enable the '--use-pep517' option",
gone_in="23.1",
issue=8559,
emit_before_install=True,
)
12 changes: 0 additions & 12 deletions src/pip/_internal/utils/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -614,18 +614,6 @@ def hash_file(path: str, blocksize: int = 1 << 20) -> Tuple[Any, int]:
return h, length


def is_wheel_installed() -> bool:
"""
Return whether the wheel package is installed.
"""
try:
import wheel # noqa: F401
except ImportError:
return False

return True


def pairwise(iterable: Iterable[Any]) -> Iterator[Tuple[Any, Any]]:
"""
Return paired elements.
Expand Down
11 changes: 1 addition & 10 deletions src/pip/_internal/wheel_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@
from pip._internal.operations.build.wheel_editable import build_wheel_editable
from pip._internal.operations.build.wheel_legacy import build_wheel_legacy
from pip._internal.req.req_install import InstallRequirement
from pip._internal.utils.deprecation import LegacyInstallReasonMissingWheelPackage
from pip._internal.utils.logging import indent_log
from pip._internal.utils.misc import ensure_dir, hash_file, is_wheel_installed
from pip._internal.utils.misc import ensure_dir, hash_file
from pip._internal.utils.setuptools_build import make_setuptools_clean_args
from pip._internal.utils.subprocess import call_subprocess
from pip._internal.utils.temp_dir import TempDirectory
Expand Down Expand Up @@ -73,14 +72,6 @@ def _should_build(
# we only build PEP 660 editable requirements
return req.supports_pyproject_editable()

if req.use_pep517:
return True

if not is_wheel_installed():
# we don't build legacy requirements if wheel is not installed
req.legacy_install_reason = LegacyInstallReasonMissingWheelPackage
return False

return True


Expand Down
9 changes: 3 additions & 6 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ def virtualenv_template(
tmpdir_factory: pytest.TempPathFactory,
pip_src: Path,
setuptools_install: Path,
wheel_install: Path,
coverage_install: Path,
) -> Iterator[VirtualEnvironment]:

Expand All @@ -442,8 +443,9 @@ def virtualenv_template(
tmpdir = tmpdir_factory.mktemp("virtualenv")
venv = VirtualEnvironment(tmpdir.joinpath("venv_orig"), venv_type=venv_type)

# Install setuptools and pip.
# Install setuptools, wheel and pip.
install_pth_link(venv, "setuptools", setuptools_install)
install_pth_link(venv, "wheel", wheel_install)
pip_editable = tmpdir_factory.mktemp("pip") / "pip"
shutil.copytree(pip_src, pip_editable, symlinks=True)
# noxfile.py is Python 3 only
Expand Down Expand Up @@ -501,11 +503,6 @@ def virtualenv(
yield virtualenv_factory(tmpdir.joinpath("workspace", "venv"))


@pytest.fixture
def with_wheel(virtualenv: VirtualEnvironment, wheel_install: Path) -> None:
install_pth_link(virtualenv, "wheel", wheel_install)


class ScriptFactory(Protocol):
def __call__(
self,
Expand Down
2 changes: 1 addition & 1 deletion tests/data/packages/BrokenEmitsUTF8/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class FakeError(Exception):
pass


if sys.argv[1] == "install":
if sys.argv[1] in ("install", "bdist_wheel"):
if hasattr(sys.stdout, "buffer"):
sys.stdout.buffer.write(
"\nThis package prints out UTF-8 stuff like:\n".encode("utf-8")
Expand Down
2 changes: 0 additions & 2 deletions tests/functional/test_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,6 @@ def make_wheel_with_python_requires(
return package_dir / "dist" / file_name


@pytest.mark.usefixtures("with_wheel")
def test_download__python_version_used_for_python_requires(
script: PipTestEnvironment, data: TestData
) -> None:
Expand Down Expand Up @@ -700,7 +699,6 @@ def make_args(python_version: str) -> List[str]:
script.pip(*args) # no exception


@pytest.mark.usefixtures("with_wheel")
def test_download_ignore_requires_python_dont_fail_with_wrong_python(
script: PipTestEnvironment,
) -> None:
Expand Down
3 changes: 0 additions & 3 deletions tests/functional/test_freeze.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ def test_exclude_and_normalization(script: PipTestEnvironment, tmpdir: Path) ->
assert "Normalizable_Name" not in result.stdout


@pytest.mark.usefixtures("with_wheel")
def test_freeze_multiple_exclude_with_all(script: PipTestEnvironment) -> None:
result = script.pip("freeze", "--all")
assert "pip==" in result.stdout
Expand Down Expand Up @@ -962,7 +961,6 @@ def test_freeze_path_multiple(
_check_output(result.stdout, expected)


@pytest.mark.usefixtures("with_wheel")
def test_freeze_direct_url_archive(
script: PipTestEnvironment, shared_data: TestData
) -> None:
Expand Down Expand Up @@ -1005,7 +1003,6 @@ def test_freeze_include_work_dir_pkg(script: PipTestEnvironment) -> None:
assert "simple==1.0" in result.stdout


@pytest.mark.usefixtures("with_wheel")
def test_freeze_pep610_editable(script: PipTestEnvironment) -> None:
"""
Test that a package installed with a direct_url.json with editable=true
Expand Down
3 changes: 2 additions & 1 deletion tests/functional/test_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ def test_inspect_basic(simple_script: PipTestEnvironment) -> None:
result = simple_script.pip("inspect")
report = json.loads(result.stdout)
installed = report["installed"]
assert len(installed) == 4
assert len(installed) == 5
installed_by_name = {i["metadata"]["name"]: i for i in installed}
assert installed_by_name.keys() == {
"pip",
"setuptools",
"wheel",
"coverage",
"simplewheel",
}
Expand Down
Loading