Skip to content

Commit

Permalink
Merge pull request #11874 from sbidoul/drop-setup-py-install-sbi
Browse files Browse the repository at this point in the history
Drop `setup.py install` support
  • Loading branch information
sbidoul authored Mar 31, 2023
2 parents fded808 + 849dcbd commit 295a35b
Show file tree
Hide file tree
Showing 13 changed files with 59 additions and 380 deletions.
9 changes: 0 additions & 9 deletions docs/html/reference/build-system/setup-py.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ The overall process for building a package is:

- Generate the package's metadata.
- Generate a wheel for the package.
- If this fails and we're trying to install the package, attempt a direct
installation.

The wheel can then be used to perform an installation, if necessary.

Expand Down Expand Up @@ -58,13 +56,6 @@ If this wheel generation fails, pip runs `setup.py clean` to clean up any build
artifacts that may have been generated. After that, pip will attempt a direct
installation.

### Direct Installation

When all else fails, pip will invoke `setup.py install` to install a package
using setuptools' mechanisms to perform the installation. This is currently the
last-resort fallback for projects that cannot be built into wheels, and may not
be supported in the future.

### Editable Installation

For installing packages in "editable" mode
Expand Down
2 changes: 2 additions & 0 deletions news/8368.removal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Remove ``setup.py install`` fallback when building a wheel failed for projects without
``pyproject.toml``.
17 changes: 2 additions & 15 deletions src/pip/_internal/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
check_legacy_setup_py_options,
)
from pip._internal.utils.compat import WINDOWS
from pip._internal.utils.deprecation import LegacyInstallReasonFailedBdistWheel
from pip._internal.utils.filesystem import test_writable_dir
from pip._internal.utils.logging import getLogger
from pip._internal.utils.misc import (
Expand Down Expand Up @@ -423,26 +422,14 @@ def run(self, options: Values, args: List[str]) -> int:
global_options=global_options,
)

# If we're using PEP 517, we cannot do a legacy setup.py install
# so we fail here.
pep517_build_failure_names: List[str] = [
r.name for r in build_failures if r.use_pep517 # type: ignore
]
if pep517_build_failure_names:
if build_failures:
raise InstallationError(
"Could not build wheels for {}, which is required to "
"install pyproject.toml-based projects".format(
", ".join(pep517_build_failure_names)
", ".join(r.name for r in build_failures) # type: ignore
)
)

# For now, we just warn about failures building legacy
# requirements, as we'll fall through to a setup.py install for
# those.
for r in build_failures:
if not r.use_pep517:
r.legacy_install_reason = LegacyInstallReasonFailedBdistWheel

to_install = resolver.get_installation_order(requirement_set)

# Check for conflicts in the package set we're installing.
Expand Down
14 changes: 0 additions & 14 deletions src/pip/_internal/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,20 +361,6 @@ def __str__(self) -> str:
)


class LegacyInstallFailure(DiagnosticPipError):
"""Error occurred while executing `setup.py install`"""

reference = "legacy-install-failure"

def __init__(self, package_details: str) -> None:
super().__init__(
message="Encountered error while trying to install package.",
context=package_details,
hint_stmt="See above for output from the failure.",
note_stmt="This is an issue with the package mentioned above, not pip.",
)


class InstallationSubprocessError(DiagnosticPipError, InstallationError):
"""A subprocess call failed."""

Expand Down
117 changes: 0 additions & 117 deletions src/pip/_internal/operations/install/legacy.py

This file was deleted.

81 changes: 16 additions & 65 deletions src/pip/_internal/req/req_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from pip._vendor.pyproject_hooks import BuildBackendHookCaller

from pip._internal.build_env import BuildEnvironment, NoOpBuildEnvironment
from pip._internal.exceptions import InstallationError, LegacyInstallFailure
from pip._internal.exceptions import InstallationError
from pip._internal.locations import get_scheme
from pip._internal.metadata import (
BaseDistribution,
Expand All @@ -39,11 +39,10 @@
from pip._internal.operations.install.editable_legacy import (
install_editable as install_editable_legacy,
)
from pip._internal.operations.install.legacy import install as install_legacy
from pip._internal.operations.install.wheel import install_wheel
from pip._internal.pyproject import load_pyproject_toml, make_pyproject_path
from pip._internal.req.req_uninstall import UninstallPathSet
from pip._internal.utils.deprecation import LegacyInstallReason, deprecated
from pip._internal.utils.deprecation import deprecated
from pip._internal.utils.hashes import Hashes
from pip._internal.utils.misc import (
ConfiguredBuildBackendHookCaller,
Expand Down Expand Up @@ -93,7 +92,6 @@ def __init__(
self.constraint = constraint
self.editable = editable
self.permit_editable_wheels = permit_editable_wheels
self.legacy_install_reason: Optional[LegacyInstallReason] = None

# source_dir is the local directory where the linked requirement is
# located, or unpacked. In case unpacking is needed, creating and
Expand Down Expand Up @@ -757,10 +755,9 @@ def install(
prefix=prefix,
)

global_options = global_options if global_options is not None else []
if self.editable and not self.is_wheel:
install_editable_legacy(
global_options=global_options,
global_options=global_options if global_options is not None else [],
prefix=prefix,
home=home,
use_user_site=use_user_site,
Expand All @@ -773,66 +770,20 @@ def install(
self.install_succeeded = True
return

if self.is_wheel:
assert self.local_file_path
install_wheel(
self.name,
self.local_file_path,
scheme=scheme,
req_description=str(self.req),
pycompile=pycompile,
warn_script_location=warn_script_location,
direct_url=self.download_info if self.original_link else None,
requested=self.user_supplied,
)
self.install_succeeded = True
return

# TODO: Why don't we do this for editable installs?

# Extend the list of global options passed on to
# the setup.py call with the ones from the requirements file.
# Options specified in requirements file override those
# specified on the command line, since the last option given
# to setup.py is the one that is used.
global_options = list(global_options) + self.global_options

try:
if (
self.legacy_install_reason is not None
and self.legacy_install_reason.emit_before_install
):
self.legacy_install_reason.emit_deprecation(self.name)
success = install_legacy(
global_options=global_options,
root=root,
home=home,
prefix=prefix,
use_user_site=use_user_site,
pycompile=pycompile,
scheme=scheme,
setup_py_path=self.setup_py_path,
isolated=self.isolated,
req_name=self.name,
build_env=self.build_env,
unpacked_source_directory=self.unpacked_source_directory,
req_description=str(self.req),
)
except LegacyInstallFailure as exc:
self.install_succeeded = False
raise exc
except Exception:
self.install_succeeded = True
raise
assert self.is_wheel
assert self.local_file_path

self.install_succeeded = success

if (
success
and self.legacy_install_reason is not None
and self.legacy_install_reason.emit_after_success
):
self.legacy_install_reason.emit_deprecation(self.name)
install_wheel(
self.name,
self.local_file_path,
scheme=scheme,
req_description=str(self.req),
pycompile=pycompile,
warn_script_location=warn_script_location,
direct_url=self.download_info if self.original_link else None,
requested=self.user_supplied,
)
self.install_succeeded = True


def check_invalid_constraint_type(req: InstallRequirement) -> str:
Expand Down
41 changes: 0 additions & 41 deletions src/pip/_internal/utils/deprecation.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,44 +118,3 @@ def deprecated(
raise PipDeprecationWarning(message)

warnings.warn(message, category=PipDeprecationWarning, stacklevel=2)


class LegacyInstallReason:
def __init__(
self,
reason: str,
replacement: Optional[str] = None,
gone_in: Optional[str] = None,
feature_flag: Optional[str] = None,
issue: Optional[int] = None,
emit_after_success: bool = False,
emit_before_install: bool = False,
):
self._reason = reason
self._replacement = replacement
self._gone_in = gone_in
self._feature_flag = feature_flag
self._issue = issue
self.emit_after_success = emit_after_success
self.emit_before_install = emit_before_install

def emit_deprecation(self, name: str) -> None:
deprecated(
reason=self._reason.format(name=name),
replacement=self._replacement,
gone_in=self._gone_in,
feature_flag=self._feature_flag,
issue=self._issue,
)


LegacyInstallReasonFailedBdistWheel = LegacyInstallReason(
reason=(
"{name} was installed using the legacy 'setup.py install' "
"method, because a wheel could not be built for it."
),
replacement="to fix the wheel build issue reported above",
gone_in="23.1",
issue=8368,
emit_after_success=True,
)
Loading

0 comments on commit 295a35b

Please sign in to comment.