diff --git a/src/pip/_internal/cli/base_command.py b/src/pip/_internal/cli/base_command.py index cc92cab289c..aaab6ca4c43 100644 --- a/src/pip/_internal/cli/base_command.py +++ b/src/pip/_internal/cli/base_command.py @@ -10,7 +10,6 @@ import traceback from pip._internal.cli import cmdoptions -from pip._internal.cli.cmdoptions import make_search_scope from pip._internal.cli.parser import ( ConfigOptionParser, UpdatingDefaultsHelpFormatter, @@ -30,16 +29,6 @@ PreviousBuildDirError, UninstallationError, ) -from pip._internal.index import PackageFinder -from pip._internal.legacy_resolve import Resolver -from pip._internal.models.selection_prefs import SelectionPreferences -from pip._internal.models.target_python import TargetPython -from pip._internal.operations.prepare import RequirementPreparer -from pip._internal.req.constructors import ( - install_req_from_editable, - install_req_from_line, -) -from pip._internal.req.req_file import parse_requirements from pip._internal.utils.deprecation import deprecated from pip._internal.utils.logging import BrokenStdoutLoggingError, setup_logging from pip._internal.utils.misc import get_prog, normalize_path @@ -50,10 +39,6 @@ if MYPY_CHECK_RUNNING: from typing import Optional, List, Tuple, Any from optparse import Values - from pip._internal.cache import WheelCache - from pip._internal.req.req_set import RequirementSet - from pip._internal.req.req_tracker import RequirementTracker - from pip._internal.utils.temp_dir import TempDirectory __all__ = ['Command'] @@ -257,161 +242,3 @@ def main(self, args): logging.shutdown() return SUCCESS - - -class RequirementCommand(Command): - - @staticmethod - def make_requirement_preparer( - temp_directory, # type: TempDirectory - options, # type: Values - req_tracker, # type: RequirementTracker - download_dir=None, # type: str - wheel_download_dir=None, # type: str - ): - # type: (...) -> RequirementPreparer - """ - Create a RequirementPreparer instance for the given parameters. - """ - return RequirementPreparer( - build_dir=temp_directory.path, - src_dir=options.src_dir, - download_dir=download_dir, - wheel_download_dir=wheel_download_dir, - progress_bar=options.progress_bar, - build_isolation=options.build_isolation, - req_tracker=req_tracker, - ) - - @staticmethod - def make_resolver( - preparer, # type: RequirementPreparer - session, # type: PipSession - finder, # type: PackageFinder - options, # type: Values - wheel_cache=None, # type: Optional[WheelCache] - use_user_site=False, # type: bool - ignore_installed=True, # type: bool - ignore_requires_python=False, # type: bool - 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, ...]] - ): - # type: (...) -> Resolver - """ - Create a Resolver instance for the given parameters. - """ - return Resolver( - preparer=preparer, - session=session, - finder=finder, - wheel_cache=wheel_cache, - 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, - isolated=options.isolated_mode, - upgrade_strategy=upgrade_strategy, - use_pep517=use_pep517, - py_version_info=py_version_info - ) - - @staticmethod - def populate_requirement_set(requirement_set, # type: RequirementSet - args, # type: List[str] - options, # type: Values - finder, # type: PackageFinder - session, # type: PipSession - name, # type: str - wheel_cache # type: Optional[WheelCache] - ): - # type: (...) -> None - """ - Marshal cmd line args into a requirement set. - """ - # NOTE: As a side-effect, options.require_hashes and - # requirement_set.require_hashes may be updated - - for filename in options.constraints: - for req_to_add in parse_requirements( - filename, - constraint=True, finder=finder, options=options, - session=session, wheel_cache=wheel_cache): - req_to_add.is_direct = True - requirement_set.add_requirement(req_to_add) - - for req in args: - req_to_add = install_req_from_line( - req, None, isolated=options.isolated_mode, - use_pep517=options.use_pep517, - wheel_cache=wheel_cache - ) - req_to_add.is_direct = True - requirement_set.add_requirement(req_to_add) - - for req in options.editables: - req_to_add = install_req_from_editable( - req, - isolated=options.isolated_mode, - use_pep517=options.use_pep517, - wheel_cache=wheel_cache - ) - req_to_add.is_direct = True - requirement_set.add_requirement(req_to_add) - - for filename in options.requirements: - for req_to_add in parse_requirements( - filename, - finder=finder, options=options, session=session, - wheel_cache=wheel_cache, - use_pep517=options.use_pep517): - req_to_add.is_direct = True - requirement_set.add_requirement(req_to_add) - # If --require-hashes was a line in a requirements file, tell - # RequirementSet about it: - requirement_set.require_hashes = options.require_hashes - - if not (args or options.editables or options.requirements): - opts = {'name': name} - if options.find_links: - raise CommandError( - 'You must give at least one requirement to %(name)s ' - '(maybe you meant "pip %(name)s %(links)s"?)' % - dict(opts, links=' '.join(options.find_links))) - else: - raise CommandError( - 'You must give at least one requirement to %(name)s ' - '(see "pip help %(name)s")' % opts) - - def _build_package_finder( - self, - options, # type: Values - session, # type: PipSession - target_python=None, # type: Optional[TargetPython] - ignore_requires_python=None, # type: Optional[bool] - ): - # type: (...) -> PackageFinder - """ - Create a package finder appropriate to this requirement command. - - :param ignore_requires_python: Whether to ignore incompatible - "Requires-Python" values in links. Defaults to False. - """ - search_scope = make_search_scope(options) - selection_prefs = SelectionPreferences( - allow_yanked=True, - format_control=options.format_control, - allow_all_prereleases=options.pre, - prefer_binary=options.prefer_binary, - ignore_requires_python=ignore_requires_python, - ) - - return PackageFinder.create( - search_scope=search_scope, - selection_prefs=selection_prefs, - trusted_hosts=options.trusted_hosts, - session=session, - target_python=target_python, - ) diff --git a/src/pip/_internal/cli/req_command.py b/src/pip/_internal/cli/req_command.py new file mode 100644 index 00000000000..63776f523b1 --- /dev/null +++ b/src/pip/_internal/cli/req_command.py @@ -0,0 +1,188 @@ +"""Contains the RequirementCommand base class. + +This is in a separate module so that Command classes not inheriting from +RequirementCommand don't need to import e.g. the PackageFinder machinery +and all its vendored dependencies. +""" + +from pip._internal.cli.base_command import Command +from pip._internal.cli.cmdoptions import make_search_scope +from pip._internal.exceptions import CommandError +from pip._internal.index import PackageFinder +from pip._internal.legacy_resolve import Resolver +from pip._internal.models.selection_prefs import SelectionPreferences +from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req.constructors import ( + install_req_from_editable, + install_req_from_line, +) +from pip._internal.req.req_file import parse_requirements +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import List, Optional, Tuple + from pip._internal.cache import WheelCache + from pip._internal.download import PipSession + from pip._internal.models.target_python import TargetPython + from pip._internal.req.req_set import RequirementSet + from pip._internal.req.req_tracker import RequirementTracker + from pip._internal.utils.temp_dir import TempDirectory + + +class RequirementCommand(Command): + + @staticmethod + def make_requirement_preparer( + temp_directory, # type: TempDirectory + options, # type: Values + req_tracker, # type: RequirementTracker + download_dir=None, # type: str + wheel_download_dir=None, # type: str + ): + # type: (...) -> RequirementPreparer + """ + Create a RequirementPreparer instance for the given parameters. + """ + return RequirementPreparer( + build_dir=temp_directory.path, + src_dir=options.src_dir, + download_dir=download_dir, + wheel_download_dir=wheel_download_dir, + progress_bar=options.progress_bar, + build_isolation=options.build_isolation, + req_tracker=req_tracker, + ) + + @staticmethod + def make_resolver( + preparer, # type: RequirementPreparer + session, # type: PipSession + finder, # type: PackageFinder + options, # type: Values + wheel_cache=None, # type: Optional[WheelCache] + use_user_site=False, # type: bool + ignore_installed=True, # type: bool + ignore_requires_python=False, # type: bool + 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, ...]] + ): + # type: (...) -> Resolver + """ + Create a Resolver instance for the given parameters. + """ + return Resolver( + preparer=preparer, + session=session, + finder=finder, + wheel_cache=wheel_cache, + 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, + isolated=options.isolated_mode, + upgrade_strategy=upgrade_strategy, + use_pep517=use_pep517, + py_version_info=py_version_info + ) + + @staticmethod + def populate_requirement_set(requirement_set, # type: RequirementSet + args, # type: List[str] + options, # type: Values + finder, # type: PackageFinder + session, # type: PipSession + name, # type: str + wheel_cache # type: Optional[WheelCache] + ): + # type: (...) -> None + """ + Marshal cmd line args into a requirement set. + """ + # NOTE: As a side-effect, options.require_hashes and + # requirement_set.require_hashes may be updated + + for filename in options.constraints: + for req_to_add in parse_requirements( + filename, + constraint=True, finder=finder, options=options, + session=session, wheel_cache=wheel_cache): + req_to_add.is_direct = True + requirement_set.add_requirement(req_to_add) + + for req in args: + req_to_add = install_req_from_line( + req, None, isolated=options.isolated_mode, + use_pep517=options.use_pep517, + wheel_cache=wheel_cache + ) + req_to_add.is_direct = True + requirement_set.add_requirement(req_to_add) + + for req in options.editables: + req_to_add = install_req_from_editable( + req, + isolated=options.isolated_mode, + use_pep517=options.use_pep517, + wheel_cache=wheel_cache + ) + req_to_add.is_direct = True + requirement_set.add_requirement(req_to_add) + + for filename in options.requirements: + for req_to_add in parse_requirements( + filename, + finder=finder, options=options, session=session, + wheel_cache=wheel_cache, + use_pep517=options.use_pep517): + req_to_add.is_direct = True + requirement_set.add_requirement(req_to_add) + # If --require-hashes was a line in a requirements file, tell + # RequirementSet about it: + requirement_set.require_hashes = options.require_hashes + + if not (args or options.editables or options.requirements): + opts = {'name': name} + if options.find_links: + raise CommandError( + 'You must give at least one requirement to %(name)s ' + '(maybe you meant "pip %(name)s %(links)s"?)' % + dict(opts, links=' '.join(options.find_links))) + else: + raise CommandError( + 'You must give at least one requirement to %(name)s ' + '(see "pip help %(name)s")' % opts) + + def _build_package_finder( + self, + options, # type: Values + session, # type: PipSession + target_python=None, # type: Optional[TargetPython] + ignore_requires_python=None, # type: Optional[bool] + ): + # type: (...) -> PackageFinder + """ + Create a package finder appropriate to this requirement command. + + :param ignore_requires_python: Whether to ignore incompatible + "Requires-Python" values in links. Defaults to False. + """ + search_scope = make_search_scope(options) + selection_prefs = SelectionPreferences( + allow_yanked=True, + format_control=options.format_control, + allow_all_prereleases=options.pre, + prefer_binary=options.prefer_binary, + ignore_requires_python=ignore_requires_python, + ) + + return PackageFinder.create( + search_scope=search_scope, + selection_prefs=selection_prefs, + trusted_hosts=options.trusted_hosts, + session=session, + target_python=target_python, + ) diff --git a/src/pip/_internal/commands/download.py b/src/pip/_internal/commands/download.py index 22e0b380830..92665eae32b 100644 --- a/src/pip/_internal/commands/download.py +++ b/src/pip/_internal/commands/download.py @@ -4,8 +4,8 @@ import os from pip._internal.cli import cmdoptions -from pip._internal.cli.base_command import RequirementCommand from pip._internal.cli.cmdoptions import make_target_python +from pip._internal.cli.req_command import RequirementCommand from pip._internal.req import RequirementSet from pip._internal.req.req_tracker import RequirementTracker from pip._internal.utils.filesystem import check_path_owner diff --git a/src/pip/_internal/commands/install.py b/src/pip/_internal/commands/install.py index a4c5f5952e5..fc81b66f4d2 100644 --- a/src/pip/_internal/commands/install.py +++ b/src/pip/_internal/commands/install.py @@ -11,8 +11,8 @@ from pip._internal.cache import WheelCache from pip._internal.cli import cmdoptions -from pip._internal.cli.base_command import RequirementCommand from pip._internal.cli.cmdoptions import make_target_python +from pip._internal.cli.req_command import RequirementCommand from pip._internal.cli.status_codes import ERROR from pip._internal.exceptions import ( CommandError, diff --git a/src/pip/_internal/commands/wheel.py b/src/pip/_internal/commands/wheel.py index 88396330360..d4a0aa858d2 100644 --- a/src/pip/_internal/commands/wheel.py +++ b/src/pip/_internal/commands/wheel.py @@ -6,7 +6,7 @@ from pip._internal.cache import WheelCache from pip._internal.cli import cmdoptions -from pip._internal.cli.base_command import RequirementCommand +from pip._internal.cli.req_command import RequirementCommand from pip._internal.exceptions import CommandError, PreviousBuildDirError from pip._internal.req import RequirementSet from pip._internal.req.req_tracker import RequirementTracker