mirror of https://github.com/pypa/pip
Deprecate install-location-related options in --install-option
This commit is contained in:
parent
55a943e556
commit
b8f626ace6
|
@ -0,0 +1 @@
|
|||
Deprecate passing install-location-related options via ``--install-option``.
|
|
@ -32,6 +32,8 @@ from pip._internal.locations import distutils_scheme
|
|||
from pip._internal.operations.check import check_install_conflicts
|
||||
from pip._internal.req import RequirementSet, install_given_reqs
|
||||
from pip._internal.req.req_tracker import get_requirement_tracker
|
||||
from pip._internal.utils.deprecation import deprecated
|
||||
from pip._internal.utils.distutils_args import parse_distutils_args
|
||||
from pip._internal.utils.filesystem import check_path_owner, test_writable_dir
|
||||
from pip._internal.utils.misc import (
|
||||
ensure_dir,
|
||||
|
@ -46,7 +48,7 @@ from pip._internal.wheel_builder import WheelBuilder
|
|||
|
||||
if MYPY_CHECK_RUNNING:
|
||||
from optparse import Values
|
||||
from typing import Any, List, Optional
|
||||
from typing import Any, Iterable, List, Optional
|
||||
|
||||
from pip._internal.models.format_control import FormatControl
|
||||
from pip._internal.req.req_install import InstallRequirement
|
||||
|
@ -355,6 +357,11 @@ class InstallCommand(RequirementCommand):
|
|||
requirement_set, args, options, finder, session,
|
||||
wheel_cache
|
||||
)
|
||||
|
||||
warn_deprecated_install_options(
|
||||
requirement_set, options.install_options
|
||||
)
|
||||
|
||||
preparer = self.make_requirement_preparer(
|
||||
temp_build_dir=directory,
|
||||
options=options,
|
||||
|
@ -660,6 +667,61 @@ def decide_user_install(
|
|||
return True
|
||||
|
||||
|
||||
def warn_deprecated_install_options(requirement_set, options):
|
||||
# type: (RequirementSet, Optional[List[str]]) -> None
|
||||
"""If any location-changing --install-option arguments were passed for
|
||||
requirements or on the command-line, then show a deprecation warning.
|
||||
"""
|
||||
def format_options(option_names):
|
||||
# type: (Iterable[str]) -> List[str]
|
||||
return ["--{}".format(name.replace("_", "-")) for name in option_names]
|
||||
|
||||
requirements = (
|
||||
requirement_set.unnamed_requirements +
|
||||
list(requirement_set.requirements.values())
|
||||
)
|
||||
|
||||
offenders = []
|
||||
|
||||
for requirement in requirements:
|
||||
install_options = requirement.options.get("install_options", [])
|
||||
location_options = parse_distutils_args(install_options)
|
||||
if location_options:
|
||||
offenders.append(
|
||||
"{!r} from {}".format(
|
||||
format_options(location_options.keys()), requirement
|
||||
)
|
||||
)
|
||||
|
||||
if options:
|
||||
location_options = parse_distutils_args(options)
|
||||
if location_options:
|
||||
offenders.append(
|
||||
"{!r} from command line".format(
|
||||
format_options(location_options.keys())
|
||||
)
|
||||
)
|
||||
|
||||
if not offenders:
|
||||
return
|
||||
|
||||
deprecated(
|
||||
reason=(
|
||||
"Location-changing options found in --install-option: {}. "
|
||||
"This configuration may cause unexpected behavior and is "
|
||||
"unsupported.".format(
|
||||
"; ".join(offenders)
|
||||
)
|
||||
),
|
||||
replacement=(
|
||||
"using pip-level options like --user, --prefix, --root, and "
|
||||
"--target"
|
||||
),
|
||||
gone_in="20.2",
|
||||
issue=7309,
|
||||
)
|
||||
|
||||
|
||||
def create_env_error_message(error, show_traceback, using_user_site):
|
||||
"""Format an error message for an EnvironmentError
|
||||
|
||||
|
|
|
@ -536,6 +536,7 @@ def test_install_options_local_to_package(script, data):
|
|||
'install',
|
||||
'--no-index', '-f', data.find_links,
|
||||
'-r', reqs_file,
|
||||
expect_stderr=True,
|
||||
)
|
||||
|
||||
simple = test_simple / 'lib' / 'python' / 'simple'
|
||||
|
|
|
@ -2,12 +2,16 @@ import errno
|
|||
|
||||
import pytest
|
||||
from mock import Mock, call, patch
|
||||
from pip._vendor.packaging.requirements import Requirement
|
||||
|
||||
from pip._internal.commands.install import (
|
||||
build_wheels,
|
||||
create_env_error_message,
|
||||
decide_user_install,
|
||||
warn_deprecated_install_options,
|
||||
)
|
||||
from pip._internal.req.req_install import InstallRequirement
|
||||
from pip._internal.req.req_set import RequirementSet
|
||||
|
||||
|
||||
class TestWheelCache:
|
||||
|
@ -102,6 +106,44 @@ class TestDecideUserInstall:
|
|||
assert decide_user_install(use_user_site=None) is result
|
||||
|
||||
|
||||
def test_deprecation_notice_for_pip_install_options(recwarn):
|
||||
install_options = ["--prefix=/hello"]
|
||||
req_set = RequirementSet()
|
||||
warn_deprecated_install_options(req_set, install_options)
|
||||
|
||||
assert len(recwarn) == 1
|
||||
message = recwarn[0].message.args[0]
|
||||
assert "['--prefix'] from command line" in message
|
||||
|
||||
|
||||
def test_deprecation_notice_for_requirement_options(recwarn):
|
||||
install_options = []
|
||||
req_set = RequirementSet()
|
||||
|
||||
bad_named_req_options = {"install_options": ["--home=/wow"]}
|
||||
bad_named_req = InstallRequirement(
|
||||
Requirement("hello"), "requirements.txt", options=bad_named_req_options
|
||||
)
|
||||
req_set.add_named_requirement(bad_named_req)
|
||||
|
||||
bad_unnamed_req_options = {"install_options": ["--install-lib=/lib"]}
|
||||
bad_unnamed_req = InstallRequirement(
|
||||
None, "requirements2.txt", options=bad_unnamed_req_options
|
||||
)
|
||||
req_set.add_unnamed_requirement(bad_unnamed_req)
|
||||
|
||||
warn_deprecated_install_options(req_set, install_options)
|
||||
|
||||
assert len(recwarn) == 1
|
||||
message = recwarn[0].message.args[0]
|
||||
|
||||
assert (
|
||||
"['--install-lib'] from <InstallRequirement> (from requirements2.txt)"
|
||||
in message
|
||||
)
|
||||
assert "['--home'] from hello (from requirements.txt)" in message
|
||||
|
||||
|
||||
@pytest.mark.parametrize('error, show_traceback, using_user_site, expected', [
|
||||
# show_traceback = True, using_user_site = True
|
||||
(EnvironmentError("Illegal byte sequence"), True, True, 'Could not install'
|
||||
|
|
Loading…
Reference in New Issue