Merge pull request #9019 from pradyunsg/flip-the-switch-on-new-resolver

This commit is contained in:
Pradyun Gedam 2020-10-31 00:36:32 +05:30 committed by GitHub
commit cdc5422ed5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 210 additions and 195 deletions

View File

@ -10,7 +10,6 @@ addons:
stages:
- primary
- secondary
- experimental
jobs:
include:
@ -32,25 +31,6 @@ jobs:
- env: GROUP=2
python: pypy2.7-7.1.1
# Test experimental stuff that are not part of the standard pip usage.
# Helpful for developers working on them to see how they're doing.
- stage: experimental
env:
- GROUP=1
- NEW_RESOLVER=1
- env:
- GROUP=2
- NEW_RESOLVER=1
- env:
- GROUP=3
- NEW_RESOLVER=1
fast_finish: true
allow_failures:
- env:
- GROUP=3
- NEW_RESOLVER=1
before_install: tools/travis/setup.sh
install: travis_retry tools/travis/install.sh
script: tools/travis/run.sh

1
news/9019.feature.rst Normal file
View File

@ -0,0 +1 @@
Switch to the new dependency resolver by default.

View File

@ -61,7 +61,6 @@ markers =
mercurial: VCS: Mercurial
git: VCS: git
yaml: yaml based tests
fails_on_new_resolver: Does not yet work on the new resolver
[coverage:run]
branch = True

View File

@ -905,7 +905,7 @@ use_deprecated_feature = partial(
metavar='feature',
action='append',
default=[],
choices=[],
choices=['legacy-resolver'],
help=(
'Enable deprecated functionality, that will be removed in the future.'
),

View File

@ -9,6 +9,8 @@ import logging
import os
from functools import partial
from pip._vendor.six import PY2
from pip._internal.cli import cmdoptions
from pip._internal.cli.base_command import Command
from pip._internal.cli.command_context import CommandContextMixIn
@ -195,7 +197,33 @@ class RequirementCommand(IndexGroupCommand):
self.cmd_opts.add_option(cmdoptions.no_clean())
@staticmethod
def determine_resolver_variant(options):
# type: (Values) -> str
"""Determines which resolver should be used, based on the given options."""
# We didn't want to change things for Python 2, since it's nearly done with
# and we're using performance improvements that only work on Python 3.
if PY2:
if '2020-resolver' in options.features_enabled:
return "2020-resolver"
else:
return "legacy"
# Warn about the options that are gonna be removed.
if '2020-resolver' in options.features_enabled:
logger.warning(
"--use-feature=2020-resolver no longer has any effect, "
"since it is now the default dependency resolver in pip. "
"This will become an error in pip 21.0."
)
if "legacy-resolver" in options.deprecated_features_enabled:
return "legacy"
return "2020-resolver"
@classmethod
def make_requirement_preparer(
cls,
temp_build_dir, # type: TempDirectory
options, # type: Values
req_tracker, # type: RequirementTracker
@ -211,7 +239,8 @@ class RequirementCommand(IndexGroupCommand):
temp_build_dir_path = temp_build_dir.path
assert temp_build_dir_path is not None
if '2020-resolver' in options.features_enabled:
resolver_variant = cls.determine_resolver_variant(options)
if resolver_variant == "2020-resolver":
lazy_wheel = 'fast-deps' in options.features_enabled
if lazy_wheel:
logger.warning(
@ -223,6 +252,10 @@ class RequirementCommand(IndexGroupCommand):
)
else:
lazy_wheel = False
if 'fast-deps' in options.features_enabled:
logger.warning(
'fast-deps has no effect when used with the legacy resolver.'
)
return RequirementPreparer(
build_dir=temp_build_dir_path,
@ -238,8 +271,9 @@ class RequirementCommand(IndexGroupCommand):
lazy_wheel=lazy_wheel,
)
@staticmethod
@classmethod
def make_resolver(
cls,
preparer, # type: RequirementPreparer
finder, # type: PackageFinder
options, # type: Values
@ -250,7 +284,7 @@ class RequirementCommand(IndexGroupCommand):
force_reinstall=False, # type: bool
upgrade_strategy="to-satisfy-only", # type: str
use_pep517=None, # type: Optional[bool]
py_version_info=None # type: Optional[Tuple[int, ...]]
py_version_info=None, # type: Optional[Tuple[int, ...]]
):
# type: (...) -> BaseResolver
"""
@ -261,10 +295,11 @@ class RequirementCommand(IndexGroupCommand):
isolated=options.isolated_mode,
use_pep517=use_pep517,
)
resolver_variant = cls.determine_resolver_variant(options)
# The long import name and duplicated invocation is needed to convince
# Mypy into correctly typechecking. Otherwise it would complain the
# "Resolver" class being redefined.
if '2020-resolver' in options.features_enabled:
if resolver_variant == "2020-resolver":
import pip._internal.resolution.resolvelib.resolver
return pip._internal.resolution.resolvelib.resolver.Resolver(

View File

@ -427,7 +427,7 @@ class InstallCommand(RequirementCommand):
if conflicts is not None:
self._warn_about_conflicts(
conflicts,
new_resolver='2020-resolver' in options.features_enabled,
resolver_variant=self.determine_resolver_variant(options),
)
installed_desc = ' '.join(items)
@ -520,14 +520,14 @@ class InstallCommand(RequirementCommand):
)
return None
def _warn_about_conflicts(self, conflict_details, new_resolver):
# type: (ConflictDetails, bool) -> None
def _warn_about_conflicts(self, conflict_details, resolver_variant):
# type: (ConflictDetails, str) -> None
package_set, (missing, conflicting) = conflict_details
if not missing and not conflicting:
return
parts = [] # type: List[str]
if not new_resolver:
if resolver_variant == "legacy":
parts.append(
"After October 2020 you may experience errors when installing "
"or updating packages. This is because pip will change the "

View File

@ -39,16 +39,11 @@ def pytest_addoption(parser):
help="keep temporary test directories",
)
parser.addoption(
"--new-resolver",
action="store_true",
default=False,
help="use new resolver in tests",
)
parser.addoption(
"--new-resolver-runtests",
action="store_true",
default=False,
help="run the skipped tests for the new resolver",
"--resolver",
action="store",
default="2020-resolver",
choices=["2020-resolver", "legacy"],
help="use given resolver in tests",
)
parser.addoption(
"--use-venv",
@ -68,12 +63,6 @@ def pytest_collection_modifyitems(config, items):
if item.get_closest_marker('network') is not None:
item.add_marker(pytest.mark.flaky(reruns=3, reruns_delay=2))
if (item.get_closest_marker('fails_on_new_resolver') and
config.getoption("--new-resolver") and
not config.getoption("--new-resolver-runtests")):
item.add_marker(pytest.mark.skip(
'This test does not work with the new resolver'))
if six.PY3:
if (item.get_closest_marker('incompatible_with_test_venv') and
config.getoption("--use-venv")):
@ -103,17 +92,32 @@ def pytest_collection_modifyitems(config, items):
@pytest.fixture(scope="session", autouse=True)
def use_new_resolver(request):
"""Set environment variable to make pip default to the new resolver.
def resolver_variant(request):
"""Set environment variable to make pip default to the correct resolver.
"""
new_resolver = request.config.getoption("--new-resolver")
resolver = request.config.getoption("--resolver")
# Handle the environment variables for this test.
features = set(os.environ.get("PIP_USE_FEATURE", "").split())
if new_resolver:
features.add("2020-resolver")
deprecated_features = set(os.environ.get("PIP_USE_DEPRECATED", "").split())
if six.PY3:
if resolver == "legacy":
deprecated_features.add("legacy-resolver")
else:
deprecated_features.discard("legacy-resolver")
else:
features.discard("2020-resolver")
with patch.dict(os.environ, {"PIP_USE_FEATURE": " ".join(features)}):
yield new_resolver
if resolver == "2020-resolver":
features.add("2020-resolver")
else:
features.discard("2020-resolver")
env = {
"PIP_USE_FEATURE": " ".join(features),
"PIP_USE_DEPRECATED": " ".join(deprecated_features),
}
with patch.dict(os.environ, env):
yield resolver
@pytest.fixture(scope='session')

View File

@ -407,7 +407,7 @@ def test_vcs_url_urlquote_normalization(script, tmpdir):
)
@pytest.mark.parametrize("resolver", ["", "--use-feature=2020-resolver"])
@pytest.mark.parametrize("resolver", ["", "--use-deprecated=legacy-resolver"])
def test_basic_install_from_local_directory(
script, data, resolver, with_wheel
):
@ -538,7 +538,7 @@ def assert_re_match(pattern, text):
@pytest.mark.network
@pytest.mark.fails_on_new_resolver
@pytest.mark.skip("Fails on new resolver")
def test_hashed_install_failure_later_flag(script, tmpdir):
with requirements_file(
"blessings==1.0\n"
@ -941,7 +941,7 @@ def test_install_nonlocal_compatible_wheel(script, data):
def test_install_nonlocal_compatible_wheel_path(
script,
data,
use_new_resolver
resolver_variant,
):
target_dir = script.scratch_path / 'target'
@ -952,9 +952,9 @@ def test_install_nonlocal_compatible_wheel_path(
'--no-index',
'--only-binary=:all:',
Path(data.packages) / 'simplewheel-2.0-py3-fakeabi-fakeplat.whl',
expect_error=use_new_resolver
expect_error=(resolver_variant == "2020-resolver"),
)
if use_new_resolver:
if resolver_variant == "2020-resolver":
assert result.returncode == ERROR
else:
assert result.returncode == SUCCESS
@ -1456,7 +1456,7 @@ def test_install_no_binary_disables_cached_wheels(script, data, with_wheel):
assert "Running setup.py install for upper" in str(res), str(res)
def test_install_editable_with_wrong_egg_name(script, use_new_resolver):
def test_install_editable_with_wrong_egg_name(script, resolver_variant):
script.scratch_path.joinpath("pkga").mkdir()
pkga_path = script.scratch_path / 'pkga'
pkga_path.joinpath("setup.py").write_text(textwrap.dedent("""
@ -1467,12 +1467,12 @@ def test_install_editable_with_wrong_egg_name(script, use_new_resolver):
result = script.pip(
'install', '--editable',
'file://{pkga_path}#egg=pkgb'.format(**locals()),
expect_error=use_new_resolver,
expect_error=(resolver_variant == "2020-resolver"),
)
assert ("Generating metadata for package pkgb produced metadata "
"for project name pkga. Fix your #egg=pkgb "
"fragments.") in result.stderr
if use_new_resolver:
if resolver_variant == "2020-resolver":
assert "has different name in metadata" in result.stderr, str(result)
else:
assert "Successfully installed pkga" in str(result), str(result)
@ -1505,7 +1505,7 @@ def test_double_install(script):
assert msg not in result.stderr
def test_double_install_fail(script, use_new_resolver):
def test_double_install_fail(script, resolver_variant):
"""
Test double install failing with two different version requirements
"""
@ -1514,9 +1514,9 @@ def test_double_install_fail(script, use_new_resolver):
'pip==7.*',
'pip==7.1.2',
# The new resolver is perfectly capable of handling this
expect_error=(not use_new_resolver)
expect_error=(resolver_variant == "legacy"),
)
if not use_new_resolver:
if resolver_variant == "legacy":
msg = ("Double requirement given: pip==7.1.2 (already in pip==7.*, "
"name='pip')")
assert msg in result.stderr
@ -1770,11 +1770,11 @@ def test_user_config_accepted(script):
)
@pytest.mark.parametrize("use_module", [True, False])
def test_install_pip_does_not_modify_pip_when_satisfied(
script, install_args, expected_message, use_module, use_new_resolver):
script, install_args, expected_message, use_module, resolver_variant):
"""
Test it doesn't upgrade the pip if it already satisfies the requirement.
"""
variation = "satisfied" if use_new_resolver else "up-to-date"
variation = "satisfied" if resolver_variant else "up-to-date"
expected_message = expected_message.format(variation)
result = script.pip_install_local(
'pip', *install_args, use_module=use_module
@ -1837,6 +1837,7 @@ def test_install_yanked_file_and_print_warning(script, data):
assert 'Successfully installed simple-3.0\n' in result.stdout, str(result)
@skip_if_python2
@pytest.mark.parametrize("install_args", [
(),
("--trusted-host", "localhost"),

View File

@ -5,6 +5,7 @@ import textwrap
import pytest
from tests.lib import skip_if_python2
from tests.lib.server import (
authorization_response,
file_response,
@ -129,6 +130,7 @@ def test_command_line_appends_correctly(script, data):
), 'stdout: {}'.format(result.stdout)
@skip_if_python2
def test_config_file_override_stack(
script, virtualenv, mock_server, shared_data
):
@ -247,6 +249,7 @@ def test_prompt_for_authentication(script, data, cert_factory):
result.stdout, str(result)
@skip_if_python2
def test_do_not_prompt_for_authentication(script, data, cert_factory):
"""Test behaviour if --no-input option is given while installing
from a index url requiring authentication

View File

@ -211,6 +211,7 @@ def test_multiple_constraints_files(script, data):
assert 'installed Upper-1.0' in result.stdout
@pytest.mark.xfail(reason="Unclear what this guarantee is for.")
def test_respect_order_in_requirements_file(script, data):
script.scratch_path.joinpath("frameworks-req.txt").write_text(textwrap.dedent("""\
parent
@ -376,7 +377,7 @@ def test_constraints_local_install_causes_error(script, data):
def test_constraints_constrain_to_local_editable(
script,
data,
use_new_resolver
resolver_variant,
):
to_install = data.src.joinpath("singlemodule")
script.scratch_path.joinpath("constraints.txt").write_text(
@ -386,15 +387,15 @@ def test_constraints_constrain_to_local_editable(
'install', '--no-index', '-f', data.find_links, '-c',
script.scratch_path / 'constraints.txt', 'singlemodule',
allow_stderr_warning=True,
expect_error=use_new_resolver
expect_error=(resolver_variant == "2020-resolver"),
)
if use_new_resolver:
if resolver_variant == "2020-resolver":
assert 'Links are not allowed as constraints' in result.stderr
else:
assert 'Running setup.py develop for singlemodule' in result.stdout
def test_constraints_constrain_to_local(script, data, use_new_resolver):
def test_constraints_constrain_to_local(script, data, resolver_variant):
to_install = data.src.joinpath("singlemodule")
script.scratch_path.joinpath("constraints.txt").write_text(
"{url}#egg=singlemodule".format(url=path_to_url(to_install))
@ -403,15 +404,15 @@ def test_constraints_constrain_to_local(script, data, use_new_resolver):
'install', '--no-index', '-f', data.find_links, '-c',
script.scratch_path / 'constraints.txt', 'singlemodule',
allow_stderr_warning=True,
expect_error=use_new_resolver
expect_error=(resolver_variant == "2020-resolver"),
)
if use_new_resolver:
if resolver_variant == "2020-resolver":
assert 'Links are not allowed as constraints' in result.stderr
else:
assert 'Running setup.py install for singlemodule' in result.stdout
def test_constrained_to_url_install_same_url(script, data, use_new_resolver):
def test_constrained_to_url_install_same_url(script, data, resolver_variant):
to_install = data.src.joinpath("singlemodule")
constraints = path_to_url(to_install) + "#egg=singlemodule"
script.scratch_path.joinpath("constraints.txt").write_text(constraints)
@ -419,9 +420,9 @@ def test_constrained_to_url_install_same_url(script, data, use_new_resolver):
'install', '--no-index', '-f', data.find_links, '-c',
script.scratch_path / 'constraints.txt', to_install,
allow_stderr_warning=True,
expect_error=use_new_resolver
expect_error=(resolver_variant == "2020-resolver"),
)
if use_new_resolver:
if resolver_variant == "2020-resolver":
assert 'Links are not allowed as constraints' in result.stderr
else:
assert ('Running setup.py install for singlemodule'
@ -462,7 +463,7 @@ def test_double_install_spurious_hash_mismatch(
assert 'Successfully installed simple-1.0' in str(result)
def test_install_with_extras_from_constraints(script, data, use_new_resolver):
def test_install_with_extras_from_constraints(script, data, resolver_variant):
to_install = data.packages.joinpath("LocalExtras")
script.scratch_path.joinpath("constraints.txt").write_text(
"{url}#egg=LocalExtras[bar]".format(url=path_to_url(to_install))
@ -470,9 +471,9 @@ def test_install_with_extras_from_constraints(script, data, use_new_resolver):
result = script.pip_install_local(
'-c', script.scratch_path / 'constraints.txt', 'LocalExtras',
allow_stderr_warning=True,
expect_error=use_new_resolver
expect_error=(resolver_variant == "2020-resolver"),
)
if use_new_resolver:
if resolver_variant == "2020-resolver":
assert 'Links are not allowed as constraints' in result.stderr
else:
result.did_create(script.site_packages / 'simple')
@ -494,7 +495,7 @@ def test_install_with_extras_from_install(script):
result.did_create(script.site_packages / 'singlemodule.py')
def test_install_with_extras_joined(script, data, use_new_resolver):
def test_install_with_extras_joined(script, data, resolver_variant):
to_install = data.packages.joinpath("LocalExtras")
script.scratch_path.joinpath("constraints.txt").write_text(
"{url}#egg=LocalExtras[bar]".format(url=path_to_url(to_install))
@ -502,16 +503,16 @@ def test_install_with_extras_joined(script, data, use_new_resolver):
result = script.pip_install_local(
'-c', script.scratch_path / 'constraints.txt', 'LocalExtras[baz]',
allow_stderr_warning=True,
expect_error=use_new_resolver
expect_error=(resolver_variant == "2020-resolver"),
)
if use_new_resolver:
if resolver_variant == "2020-resolver":
assert 'Links are not allowed as constraints' in result.stderr
else:
result.did_create(script.site_packages / 'simple')
result.did_create(script.site_packages / 'singlemodule.py')
def test_install_with_extras_editable_joined(script, data, use_new_resolver):
def test_install_with_extras_editable_joined(script, data, resolver_variant):
to_install = data.packages.joinpath("LocalExtras")
script.scratch_path.joinpath("constraints.txt").write_text(
"-e {url}#egg=LocalExtras[bar]".format(url=path_to_url(to_install))
@ -519,9 +520,9 @@ def test_install_with_extras_editable_joined(script, data, use_new_resolver):
result = script.pip_install_local(
'-c', script.scratch_path / 'constraints.txt', 'LocalExtras[baz]',
allow_stderr_warning=True,
expect_error=use_new_resolver
expect_error=(resolver_variant == "2020-resolver"),
)
if use_new_resolver:
if resolver_variant == "2020-resolver":
assert 'Links are not allowed as constraints' in result.stderr
else:
result.did_create(script.site_packages / 'simple')
@ -550,7 +551,7 @@ def test_install_distribution_duplicate_extras(script, data):
def test_install_distribution_union_with_constraints(
script,
data,
use_new_resolver
resolver_variant,
):
to_install = data.packages.joinpath("LocalExtras")
script.scratch_path.joinpath("constraints.txt").write_text(
@ -558,9 +559,9 @@ def test_install_distribution_union_with_constraints(
result = script.pip_install_local(
'-c', script.scratch_path / 'constraints.txt', to_install + '[baz]',
allow_stderr_warning=True,
expect_error=use_new_resolver
expect_error=(resolver_variant == "2020-resolver"),
)
if use_new_resolver:
if resolver_variant == "2020-resolver":
msg = 'Unnamed requirements are not allowed as constraints'
assert msg in result.stderr
else:
@ -571,20 +572,17 @@ def test_install_distribution_union_with_constraints(
def test_install_distribution_union_with_versions(
script,
data,
use_new_resolver,
resolver_variant,
):
to_install_001 = data.packages.joinpath("LocalExtras")
to_install_002 = data.packages.joinpath("LocalExtras-0.0.2")
result = script.pip_install_local(
to_install_001 + "[bar]",
to_install_002 + "[baz]",
expect_error=use_new_resolver,
expect_error=(resolver_variant == "2020-resolver"),
)
if use_new_resolver:
assert (
"Cannot install localextras[bar] 0.0.1 and localextras[baz] 0.0.2 "
"because these package versions have conflicting dependencies."
) in result.stderr
if resolver_variant == "2020-resolver":
assert "Cannot install localextras[bar]" in result.stderr
assert (
"localextras[bar] 0.0.1 depends on localextras 0.0.1"
) in result.stdout

View File

@ -40,7 +40,7 @@ def test_invalid_upgrade_strategy_causes_error(script):
def test_only_if_needed_does_not_upgrade_deps_when_satisfied(
script,
use_new_resolver,
resolver_variant,
with_wheel
):
"""
@ -62,7 +62,7 @@ def test_only_if_needed_does_not_upgrade_deps_when_satisfied(
), "should not have uninstalled simple==2.0"
msg = "Requirement already satisfied"
if not use_new_resolver:
if resolver_variant == "legacy":
msg = msg + ", skipping upgrade: simple"
assert (
msg in result.stdout
@ -184,7 +184,7 @@ def test_upgrade_if_requested(script, with_wheel):
)
def test_upgrade_with_newest_already_installed(script, data, use_new_resolver):
def test_upgrade_with_newest_already_installed(script, data, resolver_variant):
"""
If the newest version of a package is already installed, the package should
not be reinstalled and the user should be informed.
@ -194,7 +194,7 @@ def test_upgrade_with_newest_already_installed(script, data, use_new_resolver):
'install', '--upgrade', '-f', data.find_links, '--no-index', 'simple'
)
assert not result.files_created, 'simple upgraded when it should not have'
if use_new_resolver:
if resolver_variant == "2020-resolver":
msg = "Requirement already satisfied"
else:
msg = "already up-to-date"

View File

@ -53,7 +53,7 @@ def test_new_resolver_can_install(script):
"0.1.0",
)
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"simple"
@ -68,7 +68,7 @@ def test_new_resolver_can_install_with_version(script):
"0.1.0",
)
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"simple==0.1.0"
@ -88,7 +88,7 @@ def test_new_resolver_picks_latest_version(script):
"0.2.0",
)
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"simple"
@ -108,7 +108,7 @@ def test_new_resolver_picks_installed_version(script):
"0.2.0",
)
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"simple==0.1.0"
@ -116,7 +116,7 @@ def test_new_resolver_picks_installed_version(script):
assert_installed(script, simple="0.1.0")
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"simple"
@ -137,7 +137,7 @@ def test_new_resolver_picks_installed_version_if_no_match_found(script):
"0.2.0",
)
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"simple==0.1.0"
@ -145,7 +145,7 @@ def test_new_resolver_picks_installed_version_if_no_match_found(script):
assert_installed(script, simple="0.1.0")
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"simple"
)
@ -166,7 +166,7 @@ def test_new_resolver_installs_dependencies(script):
"0.1.0",
)
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base"
@ -187,7 +187,7 @@ def test_new_resolver_ignore_dependencies(script):
"0.1.0",
)
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index", "--no-deps",
"--find-links", script.scratch_path,
"base"
@ -219,7 +219,7 @@ def test_new_resolver_installs_extras(tmpdir, script, root_dep):
"0.1.0",
)
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"-r", req_file,
@ -243,7 +243,7 @@ def test_new_resolver_installs_extras_deprecated(tmpdir, script):
"0.1.0",
)
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"-r", req_file,
@ -266,7 +266,7 @@ def test_new_resolver_installs_extras_warn_missing(script):
"0.1.0",
)
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base[add,missing]",
@ -280,7 +280,7 @@ def test_new_resolver_installs_extras_warn_missing(script):
def test_new_resolver_installed_message(script):
create_basic_wheel_for_package(script, "A", "1.0")
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"A",
@ -292,7 +292,7 @@ def test_new_resolver_installed_message(script):
def test_new_resolver_no_dist_message(script):
create_basic_wheel_for_package(script, "A", "1.0")
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"B",
@ -323,7 +323,7 @@ def test_new_resolver_installs_editable(script):
version="0.1.0",
)
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base",
@ -371,7 +371,6 @@ def test_new_resolver_requires_python(
args = [
"install",
"--use-feature=2020-resolver",
"--no-cache-dir",
"--no-index",
"--find-links", script.scratch_path,
@ -393,7 +392,7 @@ def test_new_resolver_requires_python_error(script):
requires_python="<2",
)
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base",
@ -421,7 +420,7 @@ def test_new_resolver_installed(script):
)
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base",
@ -429,7 +428,7 @@ def test_new_resolver_installed(script):
assert "Requirement already satisfied" not in result.stdout, str(result)
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base~=0.1.0",
@ -451,7 +450,7 @@ def test_new_resolver_ignore_installed(script):
satisfied_output = "Requirement already satisfied"
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base",
@ -459,7 +458,7 @@ def test_new_resolver_ignore_installed(script):
assert satisfied_output not in result.stdout, str(result)
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index", "--ignore-installed",
"--find-links", script.scratch_path,
"base",
@ -492,7 +491,7 @@ def test_new_resolver_only_builds_sdists_when_needed(script):
)
# We only ever need to check dep 0.2.0 as it's the latest version
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base"
@ -501,7 +500,7 @@ def test_new_resolver_only_builds_sdists_when_needed(script):
# We merge criteria here, as we have two "dep" requirements
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base", "dep"
@ -514,7 +513,7 @@ def test_new_resolver_install_different_version(script):
create_basic_wheel_for_package(script, "base", "0.2.0")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base==0.1.0",
@ -522,7 +521,7 @@ def test_new_resolver_install_different_version(script):
# This should trigger an uninstallation of base.
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base==0.2.0",
@ -541,7 +540,7 @@ def test_new_resolver_force_reinstall(script):
create_basic_wheel_for_package(script, "base", "0.1.0")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base==0.1.0",
@ -550,7 +549,7 @@ def test_new_resolver_force_reinstall(script):
# This should trigger an uninstallation of base due to --force-reinstall,
# even though the installed version matches.
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"--force-reinstall",
@ -589,7 +588,7 @@ def test_new_resolver_handles_prerelease(
for version in available_versions:
create_basic_wheel_for_package(script, "pkg", version)
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
*pip_args
@ -611,7 +610,7 @@ def test_new_reolver_skips_marker(script, pkg_deps, root_deps):
create_basic_wheel_for_package(script, "dep", "1.0")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
*root_deps
@ -636,7 +635,7 @@ def test_new_resolver_constraints(script, constraints):
constraints_file = script.scratch_path / "constraints.txt"
constraints_file.write_text("\n".join(constraints))
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"-c", constraints_file,
@ -652,7 +651,7 @@ def test_new_resolver_constraint_no_specifier(script):
constraints_file = script.scratch_path / "constraints.txt"
constraints_file.write_text("pkg")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"-c", constraints_file,
@ -683,7 +682,7 @@ def test_new_resolver_constraint_reject_invalid(script, constraint, error):
constraints_file = script.scratch_path / "constraints.txt"
constraints_file.write_text(constraint)
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"-c", constraints_file,
@ -702,7 +701,7 @@ def test_new_resolver_constraint_on_dependency(script):
constraints_file = script.scratch_path / "constraints.txt"
constraints_file.write_text("dep==2.0")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"-c", constraints_file,
@ -719,7 +718,7 @@ def test_new_resolver_constraint_on_path(script):
constraints_txt = script.scratch_path / "constraints.txt"
constraints_txt.write_text("foo==1.0")
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"-c", constraints_txt,
str(script.scratch_path),
@ -745,7 +744,7 @@ def test_new_resolver_constraint_only_marker_match(script):
constraints_txt.write_text(constrants_content)
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"-c", constraints_txt,
"--find-links", script.scratch_path,
@ -758,7 +757,7 @@ def test_new_resolver_upgrade_needs_option(script):
# Install pkg 1.0.0
create_basic_wheel_for_package(script, "pkg", "1.0.0")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"pkg",
@ -769,7 +768,7 @@ def test_new_resolver_upgrade_needs_option(script):
# This should not upgrade because we don't specify --upgrade
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"pkg",
@ -780,7 +779,7 @@ def test_new_resolver_upgrade_needs_option(script):
# This should upgrade
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"--upgrade",
@ -800,7 +799,7 @@ def test_new_resolver_upgrade_strategy(script):
create_basic_wheel_for_package(script, "base", "1.0.0", depends=["dep"])
create_basic_wheel_for_package(script, "dep", "1.0.0")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base",
@ -814,7 +813,7 @@ def test_new_resolver_upgrade_strategy(script):
create_basic_wheel_for_package(script, "dep", "2.0.0")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"--upgrade",
@ -828,7 +827,7 @@ def test_new_resolver_upgrade_strategy(script):
create_basic_wheel_for_package(script, "base", "3.0.0", depends=["dep"])
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"--upgrade", "--upgrade-strategy=eager",
@ -907,7 +906,7 @@ class TestExtraMerge(object):
)
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
requirement + "[dev]",
@ -946,7 +945,7 @@ def test_new_resolver_build_directory_error_zazo_19(script):
create_basic_sdist_for_package(script, "pkg_b", "1.0.0")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"pkg-a", "pkg-b",
@ -959,7 +958,7 @@ def test_new_resolver_upgrade_same_version(script):
create_basic_wheel_for_package(script, "pkg", "1")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"pkg",
@ -967,7 +966,7 @@ def test_new_resolver_upgrade_same_version(script):
assert_installed(script, pkg="2")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"--upgrade",
@ -983,7 +982,7 @@ def test_new_resolver_local_and_req(script):
version="0.1.0",
)
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
source_dir, "pkg!=0.1.0",
expect_error=True,
@ -1006,7 +1005,6 @@ def test_new_resolver_no_deps_checks_requires_python(script):
result = script.pip(
"install",
"--use-feature=2020-resolver",
"--no-cache-dir",
"--no-index",
"--no-deps",
@ -1029,7 +1027,6 @@ def test_new_resolver_prefers_installed_in_upgrade_if_latest(script):
# Install the version that's not on the index.
script.pip(
"install",
"--use-feature=2020-resolver",
"--no-cache-dir",
"--no-index",
local_pkg,
@ -1038,7 +1035,6 @@ def test_new_resolver_prefers_installed_in_upgrade_if_latest(script):
# Now --upgrade should still pick the local version because it's "better".
script.pip(
"install",
"--use-feature=2020-resolver",
"--no-cache-dir",
"--no-index",
"--find-links", script.scratch_path,
@ -1079,7 +1075,6 @@ def test_new_resolver_presents_messages_when_backtracking_a_lot(script, N):
# Install A
result = script.pip(
"install",
"--use-feature=2020-resolver",
"--no-cache-dir",
"--no-index",
"--find-links", script.scratch_path,

View File

@ -15,7 +15,7 @@ def test_new_resolver_conflict_requirements_file(tmpdir, script):
req_file.write_text("pkga\npkgb")
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"-r", req_file,

View File

@ -72,7 +72,6 @@ def test_new_resolver_hash_intersect(script, requirements_template, message):
result = script.pip(
"install",
"--use-feature=2020-resolver",
"--no-cache-dir",
"--no-deps",
"--no-index",
@ -105,7 +104,6 @@ def test_new_resolver_hash_intersect_from_constraint(script):
result = script.pip(
"install",
"--use-feature=2020-resolver",
"--no-cache-dir",
"--no-deps",
"--no-index",
@ -162,7 +160,6 @@ def test_new_resolver_hash_intersect_empty(
result = script.pip(
"install",
"--use-feature=2020-resolver",
"--no-cache-dir",
"--no-deps",
"--no-index",
@ -193,7 +190,6 @@ def test_new_resolver_hash_intersect_empty_from_constraint(script):
result = script.pip(
"install",
"--use-feature=2020-resolver",
"--no-cache-dir",
"--no-deps",
"--no-index",

View File

@ -37,7 +37,7 @@ def test_new_resolver_target_checks_compatibility_failure(
):
fake_wheel_tag = "fakepy1-fakeabi-fakeplat"
args = [
"install", "--use-feature=2020-resolver",
"install",
"--only-binary=:all:",
"--no-cache-dir", "--no-index",
"--target", str(script.scratch_path.joinpath("target")),

View File

@ -10,7 +10,7 @@ from tests.lib import create_basic_wheel_for_package
def test_new_resolver_install_user(script):
create_basic_wheel_for_package(script, "base", "0.1.0")
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"--user",
@ -28,13 +28,13 @@ def test_new_resolver_install_user_satisfied_by_global_site(script):
create_basic_wheel_for_package(script, "base", "1.0.0")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base==1.0.0",
)
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"--user",
@ -54,7 +54,7 @@ def test_new_resolver_install_user_conflict_in_user_site(script):
create_basic_wheel_for_package(script, "base", "2.0.0")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"--user",
@ -62,7 +62,7 @@ def test_new_resolver_install_user_conflict_in_user_site(script):
)
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"--user",
@ -82,13 +82,13 @@ def test_new_resolver_install_user_in_virtualenv_with_conflict_fails(script):
create_basic_wheel_for_package(script, "base", "2.0.0")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base==2.0.0",
)
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"--user",
@ -128,13 +128,13 @@ def test_new_resolver_install_user_reinstall_global_site(script):
create_basic_wheel_for_package(script, "base", "1.0.0")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base==1.0.0",
)
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"--user",
@ -159,14 +159,14 @@ def test_new_resolver_install_user_conflict_in_global_site(script):
create_basic_wheel_for_package(script, "base", "2.0.0")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base==1.0.0",
)
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"--user",
@ -191,13 +191,13 @@ def test_new_resolver_install_user_conflict_in_global_and_user_sites(script):
create_basic_wheel_for_package(script, "base", "2.0.0")
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"base==2.0.0",
)
script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"--user",
@ -206,7 +206,7 @@ def test_new_resolver_install_user_conflict_in_global_and_user_sites(script):
)
result = script.pip(
"install", "--use-feature=2020-resolver",
"install",
"--no-cache-dir", "--no-index",
"--find-links", script.scratch_path,
"--user",

View File

@ -193,7 +193,7 @@ def test_pip_wheel_fail(script, data):
def test_no_clean_option_blocks_cleaning_after_wheel(
script,
data,
use_new_resolver,
resolver_variant,
):
"""
Test --no-clean option blocks cleaning after wheel build
@ -209,7 +209,7 @@ def test_no_clean_option_blocks_cleaning_after_wheel(
allow_stderr_warning=True,
)
if not use_new_resolver:
if resolver_variant == "legacy":
build = build / 'simple'
message = "build/simple should still exist {}".format(result)
assert exists(build), message

View File

@ -27,7 +27,7 @@ def generate_yaml_tests(directory):
base = data.get("base", {})
cases = data["cases"]
for resolver in 'old', 'new':
for resolver in 'legacy', '2020-resolver':
for i, case_template in enumerate(cases):
case = base.copy()
case.update(case_template)
@ -39,7 +39,7 @@ def generate_yaml_tests(directory):
case[":resolver:"] = resolver
skip = case.pop("skip", False)
assert skip in [False, True, 'old', 'new']
assert skip in [False, True, 'legacy', '2020-resolver']
if skip is True or skip == resolver:
case = pytest.param(case, marks=pytest.mark.xfail)
@ -84,11 +84,11 @@ def convert_to_dict(string):
return retval
def handle_request(script, action, requirement, options, new_resolver=False):
def handle_request(script, action, requirement, options, resolver_variant):
if action == 'install':
args = ['install']
if new_resolver:
args.append("--use-feature=2020-resolver")
if resolver_variant == "legacy":
args.append("--use-deprecated=legacy-resolver")
args.extend(["--no-index", "--find-links",
path_to_url(script.scratch_path)])
elif action == 'uninstall':
@ -183,7 +183,7 @@ def test_yaml_based(script, case):
effect = handle_request(script, action,
request[action],
request.get('options', '').split(),
case[':resolver:'] == 'new')
resolver_variant=case[':resolver:'])
result = effect['result']
if 0: # for analyzing output easier

View File

@ -97,7 +97,10 @@ def _mock_wsgi_adapter(mock):
"""
def adapter(environ, start_response):
# type: (Environ, StartResponse) -> Body
responder = mock(environ, start_response)
try:
responder = mock(environ, start_response)
except StopIteration:
raise RuntimeError('Ran out of mocked responses.')
return responder(environ, start_response)
return adapter

View File

@ -37,4 +37,4 @@ cases:
- A 1.0.0
- B 1.0.0
- C 1.0.0
skip: old
skip: legacy

View File

@ -12,7 +12,7 @@ cases:
- error:
code: 0
stderr: ['incompatible']
skip: old
skip: legacy
# -- a good error message would be:
# A 1.0.0 has incompatible requirements B==1.0.0, B==2.0.0
@ -22,7 +22,7 @@ cases:
response:
- state:
- B 1.0.0
skip: old
skip: legacy
# -- old error:
# Double requirement given: B (already in B==1.0.0, name='B')
@ -36,7 +36,7 @@ cases:
stderr: >-
Cannot install B==1.0.0 and B==2.0.0 because these
package versions have conflicting dependencies.
skip: old
skip: legacy
# -- currently the (new resolver) error message is:
# Could not find a version that satisfies the requirement B==1.0.0
# Could not find a version that satisfies the requirement B==2.0.0
@ -55,7 +55,7 @@ cases:
error:
code: 1
stderr: 'no\s+matching\s+distribution'
skip: old
skip: legacy
# -- currently (new resolver) error message is:
# Could not find a version that satisfies the requirement B==1.5.0
# No matching distribution found for b
@ -71,7 +71,7 @@ cases:
error:
code: 1
stderr: 'no\s+matching\s+distribution'
skip: old
skip: legacy
# -- currently the error message is:
# Could not find a version that satisfies the requirement A==2.0
# No matching distribution found for a

View File

@ -25,4 +25,4 @@ cases:
stderr: >-
Cannot install six<1.12 and virtualenv 20.0.2 because these
package versions have conflicting dependencies.
skip: old
skip: legacy

View File

@ -11,7 +11,7 @@ cases:
- install: A
response:
- state: null
skip: old
skip: legacy
# -- currently the error message is:
# Could not find a version that satisfies the requirement C==2.0.0 (from a)
# Could not find a version that satisfies the requirement C==1.0.0 (from b)

View File

@ -16,4 +16,4 @@ cases:
versions have conflicting dependencies.
# TODO: Tweak this error message to make sense.
# https://github.com/pypa/pip/issues/8495
skip: old
skip: legacy

View File

@ -15,4 +15,4 @@ cases:
- error:
code: 0
stderr: ['c==1\.0\.0', 'incompatible']
skip: old
skip: legacy

View File

@ -39,7 +39,7 @@ cases:
- D 1.0.0
- E 1.0.0
- F 1.0.0
skip: old
skip: legacy
-
request:
- install: D[extra_1]

View File

@ -17,4 +17,4 @@ cases:
# the old resolver tries to install A 1.0.0 (which fails), but the new
# resolver realises that A 1.0.0 cannot be installed and falls back to
# installing the older version A 0.8.0 instead.
skip: old
skip: legacy

View File

@ -251,7 +251,7 @@ cases:
- idna 2.7
- pycparser 2.18
- six 1.11.0
skip: old
skip: legacy
-
request:
- install: cachecontrol
@ -292,4 +292,4 @@ cases:
html5lib 0.999999999 because these package versions have
conflicting dependencies.
skip: old
skip: legacy

View File

@ -27,7 +27,7 @@ cases:
- fussy 3.8.0
- myapp 0.2.4
- requests 1.3.0
skip: old
skip: legacy
-
request:
- install: fussy

View File

@ -34,4 +34,4 @@ cases:
# - B 2.0.0
# - C 1.0.0
# but because B 2.0.0 depends on C >=2.0.0 this is wrong
skip: old
skip: legacy

View File

@ -21,4 +21,4 @@ cases:
- poetry 1.0.5
- sphinx 3.0.1
- zappa 0.51.0
skip: old
skip: legacy