Skip to content

Commit ee7bcae

Browse files
authored
Merge pull request #11331 from sbidoul/8559-take-2-sbi
Deprecate setup.py install fallback when wheel package is absent
2 parents 496bf56 + ae802e3 commit ee7bcae

File tree

7 files changed

+105
-20
lines changed

7 files changed

+105
-20
lines changed

news/8559.removal.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Deprecate installation with 'setup.py install' when the 'wheel' package is absent for
2+
source distributions without 'pyproject.toml'.

src/pip/_internal/commands/install.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from pip._internal.req import install_given_reqs
3030
from pip._internal.req.req_install import InstallRequirement
3131
from pip._internal.utils.compat import WINDOWS
32+
from pip._internal.utils.deprecation import LegacyInstallReasonFailedBdistWheel
3233
from pip._internal.utils.distutils_args import parse_distutils_args
3334
from pip._internal.utils.filesystem import test_writable_dir
3435
from pip._internal.utils.logging import getLogger
@@ -440,7 +441,7 @@ def run(self, options: Values, args: List[str]) -> int:
440441
# those.
441442
for r in build_failures:
442443
if not r.use_pep517:
443-
r.legacy_install_reason = 8368
444+
r.legacy_install_reason = LegacyInstallReasonFailedBdistWheel
444445

445446
to_install = resolver.get_installation_order(requirement_set)
446447

src/pip/_internal/req/req_install.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
from pip._internal.operations.install.wheel import install_wheel
4343
from pip._internal.pyproject import load_pyproject_toml, make_pyproject_path
4444
from pip._internal.req.req_uninstall import UninstallPathSet
45-
from pip._internal.utils.deprecation import deprecated
45+
from pip._internal.utils.deprecation import LegacyInstallReason, deprecated
4646
from pip._internal.utils.direct_url_helpers import (
4747
direct_url_for_editable,
4848
direct_url_from_link,
@@ -96,7 +96,7 @@ def __init__(
9696
self.constraint = constraint
9797
self.editable = editable
9898
self.permit_editable_wheels = permit_editable_wheels
99-
self.legacy_install_reason: Optional[int] = None
99+
self.legacy_install_reason: Optional[LegacyInstallReason] = None
100100

101101
# source_dir is the local directory where the linked requirement is
102102
# located, or unpacked. In case unpacking is needed, creating and
@@ -811,6 +811,11 @@ def install(
811811
install_options = list(install_options) + self.install_options
812812

813813
try:
814+
if (
815+
self.legacy_install_reason is not None
816+
and self.legacy_install_reason.emit_before_install
817+
):
818+
self.legacy_install_reason.emit_deprecation(self.name)
814819
success = install_legacy(
815820
install_options=install_options,
816821
global_options=global_options,
@@ -836,18 +841,12 @@ def install(
836841

837842
self.install_succeeded = success
838843

839-
if success and self.legacy_install_reason == 8368:
840-
deprecated(
841-
reason=(
842-
"{} was installed using the legacy 'setup.py install' "
843-
"method, because a wheel could not be built for it.".format(
844-
self.name
845-
)
846-
),
847-
replacement="to fix the wheel build issue reported above",
848-
gone_in=None,
849-
issue=8368,
850-
)
844+
if (
845+
success
846+
and self.legacy_install_reason is not None
847+
and self.legacy_install_reason.emit_after_success
848+
):
849+
self.legacy_install_reason.emit_deprecation(self.name)
851850

852851

853852
def check_invalid_constraint_type(req: InstallRequirement) -> str:

src/pip/_internal/utils/deprecation.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,58 @@ def deprecated(
118118
raise PipDeprecationWarning(message)
119119

120120
warnings.warn(message, category=PipDeprecationWarning, stacklevel=2)
121+
122+
123+
class LegacyInstallReason:
124+
def __init__(
125+
self,
126+
reason: str,
127+
replacement: Optional[str],
128+
gone_in: Optional[str],
129+
feature_flag: Optional[str] = None,
130+
issue: Optional[int] = None,
131+
emit_after_success: bool = False,
132+
emit_before_install: bool = False,
133+
):
134+
self._reason = reason
135+
self._replacement = replacement
136+
self._gone_in = gone_in
137+
self._feature_flag = feature_flag
138+
self._issue = issue
139+
self.emit_after_success = emit_after_success
140+
self.emit_before_install = emit_before_install
141+
142+
def emit_deprecation(self, name: str) -> None:
143+
deprecated(
144+
reason=self._reason.format(name=name),
145+
replacement=self._replacement,
146+
gone_in=self._gone_in,
147+
feature_flag=self._feature_flag,
148+
issue=self._issue,
149+
)
150+
151+
152+
LegacyInstallReasonFailedBdistWheel = LegacyInstallReason(
153+
reason=(
154+
"{name} was installed using the legacy 'setup.py install' "
155+
"method, because a wheel could not be built for it."
156+
),
157+
replacement="to fix the wheel build issue reported above",
158+
gone_in=None,
159+
issue=8368,
160+
emit_after_success=True,
161+
)
162+
163+
164+
LegacyInstallReasonMissingWheelPackage = LegacyInstallReason(
165+
reason=(
166+
"{name} is being installed using the legacy "
167+
"'setup.py install' method, because it does not have a "
168+
"'pyproject.toml' and the 'wheel' package "
169+
"is not installed."
170+
),
171+
replacement="to enable the '--use-pep517' option",
172+
gone_in=None,
173+
issue=8559,
174+
emit_before_install=True,
175+
)

src/pip/_internal/wheel_builder.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from pip._internal.operations.build.wheel_editable import build_wheel_editable
2020
from pip._internal.operations.build.wheel_legacy import build_wheel_legacy
2121
from pip._internal.req.req_install import InstallRequirement
22+
from pip._internal.utils.deprecation import LegacyInstallReasonMissingWheelPackage
2223
from pip._internal.utils.logging import indent_log
2324
from pip._internal.utils.misc import ensure_dir, hash_file, is_wheel_installed
2425
from pip._internal.utils.setuptools_build import make_setuptools_clean_args
@@ -86,11 +87,7 @@ def _should_build(
8687

8788
if not is_wheel_installed():
8889
# we don't build legacy requirements if wheel is not installed
89-
logger.info(
90-
"Using legacy 'setup.py install' for %s, "
91-
"since package 'wheel' is not installed.",
92-
req.name,
93-
)
90+
req.legacy_install_reason = LegacyInstallReasonMissingWheelPackage
9491
return False
9592

9693
return True

tests/functional/test_install.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
from pip._internal.cli.status_codes import ERROR, SUCCESS
1414
from pip._internal.models.index import PyPI, TestPyPI
15+
from pip._internal.utils.deprecation import DEPRECATION_MSG_PREFIX
1516
from pip._internal.utils.misc import rmtree
1617
from tests.conftest import CertFactory
1718
from tests.lib import (
@@ -2303,3 +2304,32 @@ def test_install_dry_run(script: PipTestEnvironment, data: TestData) -> None:
23032304
)
23042305
assert "Would install simple-3.0" in result.stdout
23052306
assert "Successfully installed" not in result.stdout
2307+
2308+
2309+
def test_install_8559_missing_wheel_package(
2310+
script: PipTestEnvironment, shared_data: TestData
2311+
) -> None:
2312+
result = script.pip(
2313+
"install",
2314+
"--find-links",
2315+
shared_data.find_links,
2316+
"simple",
2317+
allow_stderr_warning=True,
2318+
)
2319+
assert DEPRECATION_MSG_PREFIX in result.stderr
2320+
assert "'wheel' package is not installed" in result.stderr
2321+
assert "using the legacy 'setup.py install' method" in result.stderr
2322+
2323+
2324+
@pytest.mark.usefixtures("with_wheel")
2325+
def test_install_8559_wheel_package_present(
2326+
script: PipTestEnvironment, shared_data: TestData
2327+
) -> None:
2328+
result = script.pip(
2329+
"install",
2330+
"--find-links",
2331+
shared_data.find_links,
2332+
"simple",
2333+
allow_stderr_warning=False,
2334+
)
2335+
assert DEPRECATION_MSG_PREFIX not in result.stderr

tests/functional/test_install_index.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def test_find_links_relative_path(script: PipTestEnvironment, data: TestData) ->
2323
result.did_create(initools_folder)
2424

2525

26+
@pytest.mark.usefixtures("with_wheel")
2627
def test_find_links_no_doctype(script: PipTestEnvironment, data: TestData) -> None:
2728
shutil.copy(data.packages / "simple-1.0.tar.gz", script.scratch_path)
2829
html = script.scratch_path.joinpath("index.html")

0 commit comments

Comments
 (0)