mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
Add --unstable-feature=resolver
This introduces a new general option --unstable-feature that can be used to opt into "preview" features in pip not enabled by default. Currently the only available feature is "resolver". A stub resolver interface (which would fail on invocation) is provided to respond to the flag. The --unstable-feature option is hidden from --help since the resolver does not yet work. This suppression should be removed when we release the resolver for general/public testing.
This commit is contained in:
parent
e15ef595dd
commit
fc810d7353
|
@ -915,6 +915,19 @@ no_python_version_warning = partial(
|
||||||
) # type: Callable[..., Option]
|
) # type: Callable[..., Option]
|
||||||
|
|
||||||
|
|
||||||
|
unstable_feature = partial(
|
||||||
|
Option,
|
||||||
|
'--unstable-feature',
|
||||||
|
dest='unstable_features',
|
||||||
|
metavar='feature',
|
||||||
|
action='append',
|
||||||
|
default=[],
|
||||||
|
choices=['resolver'],
|
||||||
|
help=SUPPRESS_HELP, # TODO: Enable this when the resolver actually works.
|
||||||
|
# help='Enable unstable feature(s) that may be backward incompatible.',
|
||||||
|
) # type: Callable[..., Option]
|
||||||
|
|
||||||
|
|
||||||
##########
|
##########
|
||||||
# groups #
|
# groups #
|
||||||
##########
|
##########
|
||||||
|
@ -943,6 +956,7 @@ general_group = {
|
||||||
disable_pip_version_check,
|
disable_pip_version_check,
|
||||||
no_color,
|
no_color,
|
||||||
no_python_version_warning,
|
no_python_version_warning,
|
||||||
|
unstable_feature,
|
||||||
]
|
]
|
||||||
} # type: Dict[str, Any]
|
} # type: Dict[str, Any]
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ from pip._internal.req.constructors import (
|
||||||
)
|
)
|
||||||
from pip._internal.req.req_file import parse_requirements
|
from pip._internal.req.req_file import parse_requirements
|
||||||
from pip._internal.req.req_set import RequirementSet
|
from pip._internal.req.req_set import RequirementSet
|
||||||
from pip._internal.resolution.legacy.resolver import Resolver
|
|
||||||
from pip._internal.self_outdated_check import (
|
from pip._internal.self_outdated_check import (
|
||||||
make_link_collector,
|
make_link_collector,
|
||||||
pip_self_version_check,
|
pip_self_version_check,
|
||||||
|
@ -42,6 +41,7 @@ if MYPY_CHECK_RUNNING:
|
||||||
from pip._internal.models.target_python import TargetPython
|
from pip._internal.models.target_python import TargetPython
|
||||||
from pip._internal.req.req_install import InstallRequirement
|
from pip._internal.req.req_install import InstallRequirement
|
||||||
from pip._internal.req.req_tracker import RequirementTracker
|
from pip._internal.req.req_tracker import RequirementTracker
|
||||||
|
from pip._internal.resolution.base import BaseResolver
|
||||||
from pip._internal.utils.temp_dir import (
|
from pip._internal.utils.temp_dir import (
|
||||||
TempDirectory,
|
TempDirectory,
|
||||||
TempDirectoryTypeRegistry,
|
TempDirectoryTypeRegistry,
|
||||||
|
@ -248,7 +248,7 @@ class RequirementCommand(IndexGroupCommand):
|
||||||
use_pep517=None, # type: Optional[bool]
|
use_pep517=None, # type: Optional[bool]
|
||||||
py_version_info=None # type: Optional[Tuple[int, ...]]
|
py_version_info=None # type: Optional[Tuple[int, ...]]
|
||||||
):
|
):
|
||||||
# type: (...) -> Resolver
|
# type: (...) -> BaseResolver
|
||||||
"""
|
"""
|
||||||
Create a Resolver instance for the given parameters.
|
Create a Resolver instance for the given parameters.
|
||||||
"""
|
"""
|
||||||
|
@ -258,7 +258,25 @@ class RequirementCommand(IndexGroupCommand):
|
||||||
wheel_cache=wheel_cache,
|
wheel_cache=wheel_cache,
|
||||||
use_pep517=use_pep517,
|
use_pep517=use_pep517,
|
||||||
)
|
)
|
||||||
return Resolver(
|
# 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 'resolver' in options.unstable_features:
|
||||||
|
import pip._internal.resolution.resolvelib.resolver
|
||||||
|
return pip._internal.resolution.resolvelib.resolver.Resolver(
|
||||||
|
preparer=preparer,
|
||||||
|
finder=finder,
|
||||||
|
make_install_req=make_install_req,
|
||||||
|
use_user_site=use_user_site,
|
||||||
|
ignore_dependencies=options.ignore_dependencies,
|
||||||
|
ignore_installed=ignore_installed,
|
||||||
|
ignore_requires_python=ignore_requires_python,
|
||||||
|
force_reinstall=force_reinstall,
|
||||||
|
upgrade_strategy=upgrade_strategy,
|
||||||
|
py_version_info=py_version_info,
|
||||||
|
)
|
||||||
|
import pip._internal.resolution.legacy.resolver
|
||||||
|
return pip._internal.resolution.legacy.resolver.Resolver(
|
||||||
preparer=preparer,
|
preparer=preparer,
|
||||||
finder=finder,
|
finder=finder,
|
||||||
make_install_req=make_install_req,
|
make_install_req=make_install_req,
|
||||||
|
|
20
src/pip/_internal/resolution/base.py
Normal file
20
src/pip/_internal/resolution/base.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||||
|
|
||||||
|
if MYPY_CHECK_RUNNING:
|
||||||
|
from typing import Callable, List
|
||||||
|
from pip._internal.req.req_install import InstallRequirement
|
||||||
|
from pip._internal.req.req_set import RequirementSet
|
||||||
|
|
||||||
|
InstallRequirementProvider = Callable[
|
||||||
|
[str, InstallRequirement], InstallRequirement
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class BaseResolver(object):
|
||||||
|
def resolve(self, root_reqs, check_supported_wheels):
|
||||||
|
# type: (List[InstallRequirement], bool) -> RequirementSet
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def get_installation_order(self, req_set):
|
||||||
|
# type: (RequirementSet) -> List[InstallRequirement]
|
||||||
|
raise NotImplementedError()
|
|
@ -29,6 +29,7 @@ from pip._internal.exceptions import (
|
||||||
UnsupportedPythonVersion,
|
UnsupportedPythonVersion,
|
||||||
)
|
)
|
||||||
from pip._internal.req.req_set import RequirementSet
|
from pip._internal.req.req_set import RequirementSet
|
||||||
|
from pip._internal.resolution.base import BaseResolver
|
||||||
from pip._internal.utils.logging import indent_log
|
from pip._internal.utils.logging import indent_log
|
||||||
from pip._internal.utils.misc import dist_in_usersite, normalize_version_info
|
from pip._internal.utils.misc import dist_in_usersite, normalize_version_info
|
||||||
from pip._internal.utils.packaging import (
|
from pip._internal.utils.packaging import (
|
||||||
|
@ -38,17 +39,15 @@ from pip._internal.utils.packaging import (
|
||||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||||
|
|
||||||
if MYPY_CHECK_RUNNING:
|
if MYPY_CHECK_RUNNING:
|
||||||
from typing import Callable, DefaultDict, List, Optional, Set, Tuple
|
from typing import DefaultDict, List, Optional, Set, Tuple
|
||||||
from pip._vendor import pkg_resources
|
from pip._vendor import pkg_resources
|
||||||
|
|
||||||
from pip._internal.distributions import AbstractDistribution
|
from pip._internal.distributions import AbstractDistribution
|
||||||
from pip._internal.index.package_finder import PackageFinder
|
from pip._internal.index.package_finder import PackageFinder
|
||||||
from pip._internal.operations.prepare import RequirementPreparer
|
from pip._internal.operations.prepare import RequirementPreparer
|
||||||
from pip._internal.req.req_install import InstallRequirement
|
from pip._internal.req.req_install import InstallRequirement
|
||||||
|
from pip._internal.resolution.base import InstallRequirementProvider
|
||||||
|
|
||||||
InstallRequirementProvider = Callable[
|
|
||||||
[str, InstallRequirement], InstallRequirement
|
|
||||||
]
|
|
||||||
DiscoveredDependencies = DefaultDict[str, List[InstallRequirement]]
|
DiscoveredDependencies = DefaultDict[str, List[InstallRequirement]]
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -102,7 +101,7 @@ def _check_dist_requires_python(
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
class Resolver(object):
|
class Resolver(BaseResolver):
|
||||||
"""Resolves which packages need to be installed/uninstalled to perform \
|
"""Resolves which packages need to be installed/uninstalled to perform \
|
||||||
the requested operation without breaking the requirements of any package.
|
the requested operation without breaking the requirements of any package.
|
||||||
"""
|
"""
|
||||||
|
|
0
src/pip/_internal/resolution/resolvelib/__init__.py
Normal file
0
src/pip/_internal/resolution/resolvelib/__init__.py
Normal file
36
src/pip/_internal/resolution/resolvelib/resolver.py
Normal file
36
src/pip/_internal/resolution/resolvelib/resolver.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
from pip._internal.resolution.base import BaseResolver
|
||||||
|
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||||
|
|
||||||
|
if MYPY_CHECK_RUNNING:
|
||||||
|
from typing import List, Optional, Tuple
|
||||||
|
|
||||||
|
from pip._internal.index.package_finder import PackageFinder
|
||||||
|
from pip._internal.operations.prepare import RequirementPreparer
|
||||||
|
from pip._internal.req.req_install import InstallRequirement
|
||||||
|
from pip._internal.req.req_set import RequirementSet
|
||||||
|
from pip._internal.resolution.base import InstallRequirementProvider
|
||||||
|
|
||||||
|
|
||||||
|
class Resolver(BaseResolver):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
preparer, # type: RequirementPreparer
|
||||||
|
finder, # type: PackageFinder
|
||||||
|
make_install_req, # type: InstallRequirementProvider
|
||||||
|
use_user_site, # type: bool
|
||||||
|
ignore_dependencies, # type: bool
|
||||||
|
ignore_installed, # type: bool
|
||||||
|
ignore_requires_python, # type: bool
|
||||||
|
force_reinstall, # type: bool
|
||||||
|
upgrade_strategy, # type: str
|
||||||
|
py_version_info=None, # type: Optional[Tuple[int, ...]]
|
||||||
|
):
|
||||||
|
super(Resolver, self).__init__()
|
||||||
|
|
||||||
|
def resolve(self, root_reqs, check_supported_wheels):
|
||||||
|
# type: (List[InstallRequirement], bool) -> RequirementSet
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def get_installation_order(self, req_set):
|
||||||
|
# type: (RequirementSet) -> List[InstallRequirement]
|
||||||
|
raise NotImplementedError()
|
Loading…
Reference in a new issue