diff --git a/news/11358.removal.rst b/news/11358.removal.rst new file mode 100644 index 000000000..9767949b4 --- /dev/null +++ b/news/11358.removal.rst @@ -0,0 +1,2 @@ +Deprecate ``--install-options`` which forces pip to use the deprecated ``install`` +command of ``setuptools``. diff --git a/src/pip/_internal/cli/cmdoptions.py b/src/pip/_internal/cli/cmdoptions.py index f09503321..9ff7a3d07 100644 --- a/src/pip/_internal/cli/cmdoptions.py +++ b/src/pip/_internal/cli/cmdoptions.py @@ -59,31 +59,6 @@ def make_option_group(group: Dict[str, Any], parser: ConfigOptionParser) -> Opti return option_group -def check_install_build_global( - options: Values, check_options: Optional[Values] = None -) -> None: - """Disable wheels if per-setup.py call options are set. - - :param options: The OptionParser options to update. - :param check_options: The options to check, if not supplied defaults to - options. - """ - if check_options is None: - check_options = options - - def getname(n: str) -> Optional[Any]: - return getattr(check_options, n, None) - - names = ["build_options", "global_options", "install_options"] - if any(map(getname, names)): - control = options.format_control - control.disallow_binaries() - logger.warning( - "Disabling all use of wheels due to the use of --build-option " - "/ --global-option / --install-option.", - ) - - def check_dist_restriction(options: Values, check_target: bool = False) -> None: """Function for determining if custom platform options are allowed. diff --git a/src/pip/_internal/commands/download.py b/src/pip/_internal/commands/download.py index 26a5080c7..4132e0898 100644 --- a/src/pip/_internal/commands/download.py +++ b/src/pip/_internal/commands/download.py @@ -8,6 +8,10 @@ from pip._internal.cli.cmdoptions import make_target_python from pip._internal.cli.req_command import RequirementCommand, with_cleanup from pip._internal.cli.status_codes import SUCCESS from pip._internal.operations.build.build_tracker import get_build_tracker +from pip._internal.req.req_install import ( + LegacySetupPyOptionsCheckMode, + check_legacy_setup_py_options, +) from pip._internal.utils.misc import ensure_dir, normalize_path, write_output from pip._internal.utils.temp_dir import TempDirectory @@ -105,6 +109,9 @@ class DownloadCommand(RequirementCommand): ) reqs = self.get_requirements(args, options, finder, session) + check_legacy_setup_py_options( + options, reqs, LegacySetupPyOptionsCheckMode.DOWNLOAD + ) preparer = self.make_requirement_preparer( temp_build_dir=directory, diff --git a/src/pip/_internal/commands/install.py b/src/pip/_internal/commands/install.py index b37303caa..1a36132b0 100644 --- a/src/pip/_internal/commands/install.py +++ b/src/pip/_internal/commands/install.py @@ -27,7 +27,11 @@ from pip._internal.models.installation_report import InstallationReport from pip._internal.operations.build.build_tracker import get_build_tracker from pip._internal.operations.check import ConflictDetails, check_install_conflicts from pip._internal.req import install_given_reqs -from pip._internal.req.req_install import InstallRequirement +from pip._internal.req.req_install import ( + InstallRequirement, + LegacySetupPyOptionsCheckMode, + check_legacy_setup_py_options, +) from pip._internal.utils.compat import WINDOWS from pip._internal.utils.deprecation import ( LegacyInstallReasonFailedBdistWheel, @@ -280,7 +284,6 @@ class InstallCommand(RequirementCommand): if options.use_user_site and options.target_dir is not None: raise CommandError("Can not combine '--user' and '--target'") - cmdoptions.check_install_build_global(options) upgrade_strategy = "to-satisfy-only" if options.upgrade: upgrade_strategy = options.upgrade_strategy @@ -339,6 +342,9 @@ class InstallCommand(RequirementCommand): try: reqs = self.get_requirements(args, options, finder, session) + check_legacy_setup_py_options( + options, reqs, LegacySetupPyOptionsCheckMode.INSTALL + ) if "no-binary-enable-wheel-cache" in options.features_enabled: # TODO: remove format_control from WheelCache when the deprecation cycle diff --git a/src/pip/_internal/commands/wheel.py b/src/pip/_internal/commands/wheel.py index 5ddb3bd6c..1afbd562c 100644 --- a/src/pip/_internal/commands/wheel.py +++ b/src/pip/_internal/commands/wheel.py @@ -10,7 +10,11 @@ from pip._internal.cli.req_command import RequirementCommand, with_cleanup from pip._internal.cli.status_codes import SUCCESS from pip._internal.exceptions import CommandError from pip._internal.operations.build.build_tracker import get_build_tracker -from pip._internal.req.req_install import InstallRequirement +from pip._internal.req.req_install import ( + InstallRequirement, + LegacySetupPyOptionsCheckMode, + check_legacy_setup_py_options, +) from pip._internal.utils.deprecation import deprecated from pip._internal.utils.misc import ensure_dir, normalize_path from pip._internal.utils.temp_dir import TempDirectory @@ -101,8 +105,6 @@ class WheelCommand(RequirementCommand): @with_cleanup def run(self, options: Values, args: List[str]) -> int: - cmdoptions.check_install_build_global(options) - session = self.get_default_session(options) finder = self._build_package_finder(options, session) @@ -120,6 +122,9 @@ class WheelCommand(RequirementCommand): ) reqs = self.get_requirements(args, options, finder, session) + check_legacy_setup_py_options( + options, reqs, LegacySetupPyOptionsCheckMode.WHEEL + ) if "no-binary-enable-wheel-cache" in options.features_enabled: # TODO: remove format_control from WheelCache when the deprecation cycle diff --git a/src/pip/_internal/req/req_file.py b/src/pip/_internal/req/req_file.py index 06ea6f277..e4b4a9962 100644 --- a/src/pip/_internal/req/req_file.py +++ b/src/pip/_internal/req/req_file.py @@ -186,10 +186,6 @@ def handle_requirement_line( constraint=line.constraint, ) else: - if options: - # Disable wheels if the user has specified build options - cmdoptions.check_install_build_global(options, line.opts) - # get the options that apply to requirements req_options = {} for dest in SUPPORTED_OPTIONS_REQ_DEST: diff --git a/src/pip/_internal/req/req_install.py b/src/pip/_internal/req/req_install.py index 88d481dfe..ae7cd4f56 100644 --- a/src/pip/_internal/req/req_install.py +++ b/src/pip/_internal/req/req_install.py @@ -8,6 +8,8 @@ import shutil import sys import uuid import zipfile +from enum import Enum +from optparse import Values from typing import Any, Collection, Dict, Iterable, List, Optional, Sequence, Union from pip._vendor.packaging.markers import Marker @@ -876,3 +878,51 @@ def check_invalid_constraint_type(req: InstallRequirement) -> str: ) return problem + + +def _has_option(options: Values, reqs: List[InstallRequirement], option: str) -> bool: + if getattr(options, option, None): + return True + for req in reqs: + if getattr(req, option, None): + return True + return False + + +class LegacySetupPyOptionsCheckMode(Enum): + INSTALL = 1 + WHEEL = 2 + DOWNLOAD = 3 + + +def check_legacy_setup_py_options( + options: Values, + reqs: List[InstallRequirement], + mode: LegacySetupPyOptionsCheckMode, +) -> None: + has_install_options = _has_option(options, reqs, "install_options") + has_build_options = _has_option(options, reqs, "build_options") + has_global_options = _has_option(options, reqs, "global_options") + legacy_setup_py_options_present = ( + has_install_options or has_build_options or has_global_options + ) + if not legacy_setup_py_options_present: + return + + options.format_control.disallow_binaries() + logger.warning( + "Implying --no-binary=:all: due to the presence of " + "--build-option / --global-option / --install-option. " + "Consider using --config-settings for more flexibility.", + ) + if mode == LegacySetupPyOptionsCheckMode.INSTALL and has_install_options: + deprecated( + reason=( + "--install-option is deprecated because " + "it forces pip to use the 'setup.py install' " + "command which is itself deprecated." + ), + issue=11358, + replacement="to use --config-settings", + gone_in="23.1", + )