diff --git a/docs/pip_sphinxext.py b/docs/pip_sphinxext.py index b250be47f97..c34c457e394 100644 --- a/docs/pip_sphinxext.py +++ b/docs/pip_sphinxext.py @@ -9,14 +9,14 @@ from docutils.statemachine import ViewList from pip._internal.cli import cmdoptions -from pip._internal.commands import commands_dict as commands +from pip._internal.commands import create_command class PipCommandUsage(rst.Directive): required_arguments = 1 def run(self): - cmd = commands[self.arguments[0]] + cmd = create_command(self.arguments[0]) usage = dedent( cmd.usage.replace('%prog', 'pip {}'.format(cmd.name)) ).strip() @@ -31,7 +31,8 @@ def run(self): node = nodes.paragraph() node.document = self.state.document desc = ViewList() - description = dedent(commands[self.arguments[0]].__doc__) + cmd = create_command(self.arguments[0]) + description = dedent(cmd.__doc__) for line in description.split('\n'): desc.append(line, "") self.state.nested_parse(desc, 0, node) @@ -95,7 +96,7 @@ class PipCommandOptions(PipOptions): required_arguments = 1 def process_options(self): - cmd = commands[self.arguments[0]]() + cmd = create_command(self.arguments[0]) self._format_options( cmd.parser.option_groups[0].option_list, cmd_name=cmd.name, diff --git a/src/pip/_internal/__init__.py b/src/pip/_internal/__init__.py index fbadc28ac21..bb8f0ff8705 100755 --- a/src/pip/_internal/__init__.py +++ b/src/pip/_internal/__init__.py @@ -39,7 +39,7 @@ from pip._internal.cli.autocompletion import autocomplete from pip._internal.cli.main_parser import parse_command -from pip._internal.commands import commands_dict +from pip._internal.commands import create_command from pip._internal.exceptions import PipError from pip._internal.utils import deprecation from pip._vendor.urllib3.exceptions import InsecureRequestWarning @@ -73,5 +73,6 @@ def main(args=None): except locale.Error as e: # setlocale can apparently crash if locale are uninitialized logger.debug("Ignoring error %s when setting locale", e) - command = commands_dict[cmd_name](isolated=("--isolated" in cmd_args)) + command = create_command(cmd_name, isolated=("--isolated" in cmd_args)) + return command.main(cmd_args) diff --git a/src/pip/_internal/cli/autocompletion.py b/src/pip/_internal/cli/autocompletion.py index 0a04199e6dc..287e62c78a5 100644 --- a/src/pip/_internal/cli/autocompletion.py +++ b/src/pip/_internal/cli/autocompletion.py @@ -6,7 +6,7 @@ import sys from pip._internal.cli.main_parser import create_main_parser -from pip._internal.commands import commands_dict, get_summaries +from pip._internal.commands import commands_dict, create_command from pip._internal.utils.misc import get_installed_distributions @@ -23,7 +23,7 @@ def autocomplete(): except IndexError: current = '' - subcommands = [cmd for cmd, summary in get_summaries()] + subcommands = list(commands_dict) options = [] # subcommand try: @@ -54,7 +54,7 @@ def autocomplete(): print(dist) sys.exit(1) - subcommand = commands_dict[subcommand_name]() + subcommand = create_command(subcommand_name) for opt in subcommand.parser.option_list_all: if opt.help != optparse.SUPPRESS_HELP: diff --git a/src/pip/_internal/cli/base_command.py b/src/pip/_internal/cli/base_command.py index 177524804fb..fd771b1412c 100644 --- a/src/pip/_internal/cli/base_command.py +++ b/src/pip/_internal/cli/base_command.py @@ -61,18 +61,20 @@ class Command(object): usage = None # type: Optional[str] ignore_require_venv = False # type: bool - def __init__(self, isolated=False): - # type: (bool) -> None + def __init__(self, name, summary, isolated=False): + # type: (str, str, bool) -> None parser_kw = { 'usage': self.usage, 'prog': '%s %s' % (get_prog(), self.name), 'formatter': UpdatingDefaultsHelpFormatter(), 'add_help_option': False, - 'name': self.name, + 'name': name, 'description': self.__doc__, 'isolated': isolated, } + self.name = name + self.summary = summary self.parser = ConfigOptionParser(**parser_kw) # Commands should add options to this option group diff --git a/src/pip/_internal/cli/main_parser.py b/src/pip/_internal/cli/main_parser.py index 1c371ca3b56..a89821d4489 100644 --- a/src/pip/_internal/cli/main_parser.py +++ b/src/pip/_internal/cli/main_parser.py @@ -9,11 +9,7 @@ ConfigOptionParser, UpdatingDefaultsHelpFormatter, ) -from pip._internal.commands import ( - commands_dict, - get_similar_commands, - get_summaries, -) +from pip._internal.commands import commands_dict, get_similar_commands from pip._internal.exceptions import CommandError from pip._internal.utils.misc import get_pip_version, get_prog from pip._internal.utils.typing import MYPY_CHECK_RUNNING @@ -51,8 +47,10 @@ def create_main_parser(): parser.main = True # type: ignore # create command listing for description - command_summaries = get_summaries() - description = [''] + ['%-27s %s' % (i, j) for i, j in command_summaries] + description = [''] + [ + '%-27s %s' % (name, command_info.summary) + for name, command_info in commands_dict.items() + ] parser.description = '\n'.join(description) return parser diff --git a/src/pip/_internal/commands/__init__.py b/src/pip/_internal/commands/__init__.py index 9e0ab86b9ca..a5d454192d6 100644 --- a/src/pip/_internal/commands/__init__.py +++ b/src/pip/_internal/commands/__init__.py @@ -3,57 +3,97 @@ """ from __future__ import absolute_import -from pip._internal.commands.completion import CompletionCommand -from pip._internal.commands.configuration import ConfigurationCommand -from pip._internal.commands.debug import DebugCommand -from pip._internal.commands.download import DownloadCommand -from pip._internal.commands.freeze import FreezeCommand -from pip._internal.commands.hash import HashCommand -from pip._internal.commands.help import HelpCommand -from pip._internal.commands.list import ListCommand -from pip._internal.commands.check import CheckCommand -from pip._internal.commands.search import SearchCommand -from pip._internal.commands.show import ShowCommand -from pip._internal.commands.install import InstallCommand -from pip._internal.commands.uninstall import UninstallCommand -from pip._internal.commands.wheel import WheelCommand +import importlib +from collections import namedtuple, OrderedDict from pip._internal.utils.typing import MYPY_CHECK_RUNNING if MYPY_CHECK_RUNNING: - from typing import List, Type + from typing import Any from pip._internal.cli.base_command import Command -commands_order = [ - InstallCommand, - DownloadCommand, - UninstallCommand, - FreezeCommand, - ListCommand, - ShowCommand, - CheckCommand, - ConfigurationCommand, - SearchCommand, - WheelCommand, - HashCommand, - CompletionCommand, - DebugCommand, - HelpCommand, -] # type: List[Type[Command]] -commands_dict = {c.name: c for c in commands_order} - - -def get_summaries(ordered=True): - """Yields sorted (command name, command summary) tuples.""" - - if ordered: - cmditems = _sort_commands(commands_dict, commands_order) - else: - cmditems = commands_dict.items() - - for name, command_class in cmditems: - yield (name, command_class.summary) +CommandInfo = namedtuple('CommandInfo', 'module_path, class_name, summary') + +# The ordering matters for help display. +# Also, even though the module path starts with the same +# "pip._internal.commands" prefix in each case, we include the full path +# because it makes testing easier (specifically when modifying commands_dict +# in test setup / teardown by adding info for a FakeCommand class defined +# in a test-related module). +# Finally, we need to pass an iterable of pairs here rather than a dict +# so that the ordering won't be lost when using Python 2.7. +commands_dict = OrderedDict([ + ('install', CommandInfo( + 'pip._internal.commands.install', 'InstallCommand', + 'Install packages.', + )), + ('download', CommandInfo( + 'pip._internal.commands.download', 'DownloadCommand', + 'Download packages.', + )), + ('uninstall', CommandInfo( + 'pip._internal.commands.uninstall', 'UninstallCommand', + 'Uninstall packages.', + )), + ('freeze', CommandInfo( + 'pip._internal.commands.freeze', 'FreezeCommand', + 'Output installed packages in requirements format.', + )), + ('list', CommandInfo( + 'pip._internal.commands.list', 'ListCommand', + 'List installed packages.', + )), + ('show', CommandInfo( + 'pip._internal.commands.show', 'ShowCommand', + 'Show information about installed packages.', + )), + ('check', CommandInfo( + 'pip._internal.commands.check', 'CheckCommand', + 'Verify installed packages have compatible dependencies.', + )), + ('config', CommandInfo( + 'pip._internal.commands.configuration', 'ConfigurationCommand', + 'Manage local and global configuration.', + )), + ('search', CommandInfo( + 'pip._internal.commands.search', 'SearchCommand', + 'Search PyPI for packages.', + )), + ('wheel', CommandInfo( + 'pip._internal.commands.wheel', 'WheelCommand', + 'Build wheels from your requirements.', + )), + ('hash', CommandInfo( + 'pip._internal.commands.hash', 'HashCommand', + 'Compute hashes of package archives.', + )), + ('completion', CommandInfo( + 'pip._internal.commands.completion', 'CompletionCommand', + 'A helper command used for command completion.', + )), + ('debug', CommandInfo( + 'pip._internal.commands.debug', 'DebugCommand', + 'Show information useful for debugging.', + )), + ('help', CommandInfo( + 'pip._internal.commands.help', 'HelpCommand', + 'Show help for commands.', + )), +]) # type: OrderedDict[str, CommandInfo] + + +def create_command(name, **kwargs): + # type: (str, **Any) -> Command + """ + Create an instance of the Command class with the given name. + """ + module_path, class_name, summary = commands_dict[name] + module = importlib.import_module(module_path) + command_class = getattr(module, class_name) + command = command_class(name=name, summary=summary, **kwargs) + + return command def get_similar_commands(name): @@ -68,14 +108,3 @@ def get_similar_commands(name): return close_commands[0] else: return False - - -def _sort_commands(cmddict, order): - def keyfn(key): - try: - return order.index(key[1]) - except ValueError: - # unordered items should come last - return 0xff - - return sorted(cmddict.items(), key=keyfn) diff --git a/src/pip/_internal/commands/check.py b/src/pip/_internal/commands/check.py index 865285b5065..88dff795a1d 100644 --- a/src/pip/_internal/commands/check.py +++ b/src/pip/_internal/commands/check.py @@ -11,10 +11,9 @@ class CheckCommand(Command): """Verify installed packages have compatible dependencies.""" - name = 'check' + usage = """ %prog [options]""" - summary = 'Verify installed packages have compatible dependencies.' def run(self, options, args): package_set, parsing_probs = create_package_set_from_installed() diff --git a/src/pip/_internal/commands/completion.py b/src/pip/_internal/commands/completion.py index 2fcdd393ed6..6c37162813c 100644 --- a/src/pip/_internal/commands/completion.py +++ b/src/pip/_internal/commands/completion.py @@ -47,8 +47,7 @@ class CompletionCommand(Command): """A helper command to be used for command completion.""" - name = 'completion' - summary = 'A helper command used for command completion.' + ignore_require_venv = True def __init__(self, *args, **kw): diff --git a/src/pip/_internal/commands/configuration.py b/src/pip/_internal/commands/configuration.py index 91f916e85ac..31b93d96b17 100644 --- a/src/pip/_internal/commands/configuration.py +++ b/src/pip/_internal/commands/configuration.py @@ -34,7 +34,6 @@ class ConfigurationCommand(Command): default. """ - name = 'config' usage = """ %prog [] list %prog [] [--editor ] edit @@ -44,8 +43,6 @@ class ConfigurationCommand(Command): %prog [] unset name """ - summary = "Manage local and global configuration." - def __init__(self, *args, **kwargs): super(ConfigurationCommand, self).__init__(*args, **kwargs) diff --git a/src/pip/_internal/commands/debug.py b/src/pip/_internal/commands/debug.py index eb4f8c4e6fc..df31c83bf51 100644 --- a/src/pip/_internal/commands/debug.py +++ b/src/pip/_internal/commands/debug.py @@ -77,10 +77,8 @@ class DebugCommand(Command): Display debug information. """ - name = 'debug' usage = """ %prog """ - summary = 'Show information useful for debugging.' ignore_require_venv = True def __init__(self, *args, **kw): diff --git a/src/pip/_internal/commands/download.py b/src/pip/_internal/commands/download.py index 5642b561758..2bb27f876ad 100644 --- a/src/pip/_internal/commands/download.py +++ b/src/pip/_internal/commands/download.py @@ -29,7 +29,6 @@ class DownloadCommand(RequirementCommand): pip also supports downloading from "requirements files", which provide an easy way to specify a whole environment to be downloaded. """ - name = 'download' usage = """ %prog [options] [package-index-options] ... @@ -38,8 +37,6 @@ class DownloadCommand(RequirementCommand): %prog [options] ... %prog [options] ...""" - summary = 'Download packages.' - def __init__(self, *args, **kw): super(DownloadCommand, self).__init__(*args, **kw) diff --git a/src/pip/_internal/commands/freeze.py b/src/pip/_internal/commands/freeze.py index 9fc5b04693c..112a380439d 100644 --- a/src/pip/_internal/commands/freeze.py +++ b/src/pip/_internal/commands/freeze.py @@ -18,10 +18,9 @@ class FreezeCommand(Command): packages are listed in a case-insensitive sorted order. """ - name = 'freeze' + usage = """ %prog [options]""" - summary = 'Output installed packages in requirements format.' log_streams = ("ext://sys.stderr", "ext://sys.stderr") def __init__(self, *args, **kw): diff --git a/src/pip/_internal/commands/hash.py b/src/pip/_internal/commands/hash.py index 423440e9c29..87b09f071e1 100644 --- a/src/pip/_internal/commands/hash.py +++ b/src/pip/_internal/commands/hash.py @@ -18,11 +18,9 @@ class HashCommand(Command): These can be used with --hash in a requirements file to do repeatable installs. - """ - name = 'hash' + usage = '%prog [options] ...' - summary = 'Compute hashes of package archives.' ignore_require_venv = True def __init__(self, *args, **kw): diff --git a/src/pip/_internal/commands/help.py b/src/pip/_internal/commands/help.py index 49a81cbb074..270e82b28c6 100644 --- a/src/pip/_internal/commands/help.py +++ b/src/pip/_internal/commands/help.py @@ -7,14 +7,15 @@ class HelpCommand(Command): """Show help for commands""" - name = 'help' + usage = """ %prog """ - summary = 'Show help for commands.' ignore_require_venv = True def run(self, options, args): - from pip._internal.commands import commands_dict, get_similar_commands + from pip._internal.commands import ( + commands_dict, create_command, get_similar_commands, + ) try: # 'pip help' with no args is handled by pip.__init__.parseopt() @@ -31,7 +32,7 @@ def run(self, options, args): raise CommandError(' - '.join(msg)) - command = commands_dict[cmd_name]() + command = create_command(cmd_name) command.parser.print_help() return SUCCESS diff --git a/src/pip/_internal/commands/install.py b/src/pip/_internal/commands/install.py index 927e7817be2..b18bbd45172 100644 --- a/src/pip/_internal/commands/install.py +++ b/src/pip/_internal/commands/install.py @@ -87,7 +87,6 @@ class InstallCommand(RequirementCommand): pip also supports installing from "requirements files," which provide an easy way to specify a whole environment to be installed. """ - name = 'install' usage = """ %prog [options] [package-index-options] ... @@ -96,8 +95,6 @@ class InstallCommand(RequirementCommand): %prog [options] [-e] ... %prog [options] ...""" - summary = 'Install packages.' - def __init__(self, *args, **kw): super(InstallCommand, self).__init__(*args, **kw) diff --git a/src/pip/_internal/commands/list.py b/src/pip/_internal/commands/list.py index ea7f5eb9c44..2fd39097c12 100644 --- a/src/pip/_internal/commands/list.py +++ b/src/pip/_internal/commands/list.py @@ -27,10 +27,9 @@ class ListCommand(Command): Packages are listed in a case-insensitive sorted order. """ - name = 'list' + usage = """ %prog [options]""" - summary = 'List installed packages.' def __init__(self, *args, **kw): super(ListCommand, self).__init__(*args, **kw) diff --git a/src/pip/_internal/commands/search.py b/src/pip/_internal/commands/search.py index 58027112402..c96f0b90423 100644 --- a/src/pip/_internal/commands/search.py +++ b/src/pip/_internal/commands/search.py @@ -24,10 +24,9 @@ class SearchCommand(Command): """Search for PyPI packages whose name or summary contains .""" - name = 'search' + usage = """ %prog [options] """ - summary = 'Search PyPI for packages.' ignore_require_venv = True def __init__(self, *args, **kw): diff --git a/src/pip/_internal/commands/show.py b/src/pip/_internal/commands/show.py index a18a9020c41..bacd002ae51 100644 --- a/src/pip/_internal/commands/show.py +++ b/src/pip/_internal/commands/show.py @@ -19,10 +19,9 @@ class ShowCommand(Command): The output is in RFC-compliant mail header format. """ - name = 'show' + usage = """ %prog [options] ...""" - summary = 'Show information about installed packages.' ignore_require_venv = True def __init__(self, *args, **kw): diff --git a/src/pip/_internal/commands/uninstall.py b/src/pip/_internal/commands/uninstall.py index 0cd6f54bd86..ede23083857 100644 --- a/src/pip/_internal/commands/uninstall.py +++ b/src/pip/_internal/commands/uninstall.py @@ -19,11 +19,10 @@ class UninstallCommand(Command): leave behind no metadata to determine what files were installed. - Script wrappers installed by ``python setup.py develop``. """ - name = 'uninstall' + usage = """ %prog [options] ... %prog [options] -r ...""" - summary = 'Uninstall packages.' def __init__(self, *args, **kw): super(UninstallCommand, self).__init__(*args, **kw) diff --git a/src/pip/_internal/commands/wheel.py b/src/pip/_internal/commands/wheel.py index 97f3b148af5..a246db65579 100644 --- a/src/pip/_internal/commands/wheel.py +++ b/src/pip/_internal/commands/wheel.py @@ -33,7 +33,6 @@ class WheelCommand(RequirementCommand): """ - name = 'wheel' usage = """ %prog [options] ... %prog [options] -r ... @@ -41,8 +40,6 @@ class WheelCommand(RequirementCommand): %prog [options] [-e] ... %prog [options] ...""" - summary = 'Build wheels from your requirements.' - def __init__(self, *args, **kw): super(WheelCommand, self).__init__(*args, **kw) diff --git a/tests/functional/test_help.py b/tests/functional/test_help.py index 9e3dbcde8c9..1d1e439cf63 100644 --- a/tests/functional/test_help.py +++ b/tests/functional/test_help.py @@ -2,8 +2,7 @@ from mock import Mock from pip._internal.cli.base_command import ERROR, SUCCESS -from pip._internal.commands import commands_dict as commands -from pip._internal.commands.help import HelpCommand +from pip._internal.commands import commands_dict, create_command from pip._internal.exceptions import CommandError @@ -13,7 +12,7 @@ def test_run_method_should_return_success_when_finds_command_name(): """ options_mock = Mock() args = ('freeze',) - help_cmd = HelpCommand() + help_cmd = create_command('help') status = help_cmd.run(options_mock, args) assert status == SUCCESS @@ -24,7 +23,7 @@ def test_run_method_should_return_success_when_command_name_not_specified(): """ options_mock = Mock() args = () - help_cmd = HelpCommand() + help_cmd = create_command('help') status = help_cmd.run(options_mock, args) assert status == SUCCESS @@ -35,7 +34,7 @@ def test_run_method_should_raise_command_error_when_command_does_not_exist(): """ options_mock = Mock() args = ('mycommand',) - help_cmd = HelpCommand() + help_cmd = create_command('help') with pytest.raises(CommandError): help_cmd.run(options_mock, args) @@ -80,7 +79,7 @@ def test_help_commands_equally_functional(in_memory_pip): assert sum(ret) == 0, 'exit codes of: ' + msg assert all(len(o) > 0 for o in out) - for name, cls in commands.items(): + for name in commands_dict: assert ( in_memory_pip.pip('help', name).stdout == in_memory_pip.pip(name, '--help').stdout != "" diff --git a/tests/functional/test_search.py b/tests/functional/test_search.py index ea438a8bb09..70421de3091 100644 --- a/tests/functional/test_search.py +++ b/tests/functional/test_search.py @@ -4,8 +4,8 @@ import pytest from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS +from pip._internal.commands import create_command from pip._internal.commands.search import ( - SearchCommand, highest_version, print_results, transform_hits, @@ -111,7 +111,7 @@ def test_run_method_should_return_success_when_find_packages(): """ Test SearchCommand.run for found package """ - command = SearchCommand() + command = create_command('search') cmdline = "--index=https://pypi.org/pypi pip" options, args = command.parse_args(cmdline.split()) status = command.run(options, args) @@ -123,7 +123,7 @@ def test_run_method_should_return_no_matches_found_when_does_not_find_pkgs(): """ Test SearchCommand.run for no matches """ - command = SearchCommand() + command = create_command('search') cmdline = "--index=https://pypi.org/pypi nonexistentpackage" options, args = command.parse_args(cmdline.split()) status = command.run(options, args) diff --git a/tests/lib/options_helpers.py b/tests/lib/options_helpers.py index a93c40e3aea..120070abb99 100644 --- a/tests/lib/options_helpers.py +++ b/tests/lib/options_helpers.py @@ -5,13 +5,11 @@ from pip._internal.cli import cmdoptions from pip._internal.cli.base_command import Command -from pip._internal.commands import commands_dict +from pip._internal.commands import CommandInfo, commands_dict from tests.lib.configuration_helpers import reset_os_environ class FakeCommand(Command): - name = 'fake' - summary = name def main(self, args): index_opts = cmdoptions.make_option_group( @@ -26,8 +24,10 @@ class AddFakeCommandMixin(object): def setup(self): self.environ_before = os.environ.copy() - commands_dict[FakeCommand.name] = FakeCommand + commands_dict['fake'] = CommandInfo( + 'tests.lib.options_helpers', 'FakeCommand', 'fake summary', + ) def teardown(self): reset_os_environ(self.environ_before) - commands_dict.pop(FakeCommand.name) + commands_dict.pop('fake') diff --git a/tests/unit/test_base_command.py b/tests/unit/test_base_command.py index 293573ab9a4..fc6cf2b7a78 100644 --- a/tests/unit/test_base_command.py +++ b/tests/unit/test_base_command.py @@ -7,8 +7,8 @@ class FakeCommand(Command): - name = 'fake' - summary = name + + _name = 'fake' def __init__(self, run_func=None, error=False): if error: @@ -16,7 +16,7 @@ def run_func(): raise SystemExit(1) self.run_func = run_func - super(FakeCommand, self).__init__() + super(FakeCommand, self).__init__(self._name, self._name) def main(self, args): args.append("--disable-pip-version-check") @@ -29,8 +29,7 @@ def run(self, options, args): class FakeCommandWithUnicode(FakeCommand): - name = 'fake_unicode' - summary = name + _name = 'fake_unicode' def run(self, options, args): logging.getLogger("pip.tests").info(b"bytes here \xE9") diff --git a/tests/unit/test_commands.py b/tests/unit/test_commands.py new file mode 100644 index 00000000000..324e322a3f8 --- /dev/null +++ b/tests/unit/test_commands.py @@ -0,0 +1,22 @@ +import pytest + +from pip._internal.commands import commands_dict, create_command + + +def test_commands_dict__order(): + """ + Check the ordering of commands_dict. + """ + names = list(commands_dict) + # A spot-check is sufficient to check that commands_dict encodes an + # ordering. + assert names[0] == 'install' + assert names[-1] == 'help' + + +@pytest.mark.parametrize('name', list(commands_dict)) +def test_create_command(name): + """Test creating an instance of each available command.""" + command = create_command(name) + assert command.name == name + assert command.summary == commands_dict[name].summary diff --git a/tests/unit/test_format_control.py b/tests/unit/test_format_control.py index 0b376624724..0b0e2bde221 100644 --- a/tests/unit/test_format_control.py +++ b/tests/unit/test_format_control.py @@ -6,11 +6,9 @@ class SimpleCommand(Command): - name = 'fake' - summary = name def __init__(self): - super(SimpleCommand, self).__init__() + super(SimpleCommand, self).__init__('fake', 'fake summary') self.cmd_opts.add_option(cmdoptions.no_binary()) self.cmd_opts.add_option(cmdoptions.only_binary()) diff --git a/tests/unit/test_options.py b/tests/unit/test_options.py index 0eb452ef4da..32509209869 100644 --- a/tests/unit/test_options.py +++ b/tests/unit/test_options.py @@ -5,7 +5,7 @@ import pip._internal.configuration from pip._internal import main -from pip._internal.commands import ConfigurationCommand, DownloadCommand +from pip._internal.commands import create_command from pip._internal.exceptions import PipError from tests.lib.options_helpers import AddFakeCommandMixin @@ -193,7 +193,7 @@ class TestUsePEP517Options(object): def parse_args(self, args): # We use DownloadCommand since that is one of the few Command # classes with the use_pep517 options. - command = DownloadCommand() + command = create_command('download') options, args = command.parse_args(args) return options @@ -411,7 +411,7 @@ def test_venv_config_file_found(self, monkeypatch): ) ) def test_config_file_options(self, monkeypatch, args, expect): - cmd = ConfigurationCommand() + cmd = create_command('config') # Replace a handler with a no-op to avoid side effects monkeypatch.setattr(cmd, "get_name", lambda *a: None) @@ -423,7 +423,7 @@ def test_config_file_options(self, monkeypatch, args, expect): assert expect == cmd._determine_file(options, need_value=False) def test_config_file_venv_option(self, monkeypatch): - cmd = ConfigurationCommand() + cmd = create_command('config') # Replace a handler with a no-op to avoid side effects monkeypatch.setattr(cmd, "get_name", lambda *a: None) diff --git a/tests/unit/test_req.py b/tests/unit/test_req.py index 2b1428686e1..4fe71cbfde5 100644 --- a/tests/unit/test_req.py +++ b/tests/unit/test_req.py @@ -9,7 +9,7 @@ from pip._vendor.packaging.markers import Marker from pip._vendor.packaging.requirements import Requirement -from pip._internal.commands.install import InstallCommand +from pip._internal.commands import create_command from pip._internal.download import PipSession from pip._internal.exceptions import ( HashErrors, @@ -186,7 +186,7 @@ def test_missing_hash_with_require_hashes_in_reqs_file(self, data, tmpdir): req_set = RequirementSet(require_hashes=False) finder = make_test_finder(find_links=[data.find_links]) session = finder.session - command = InstallCommand() + command = create_command('install') with requirements_file('--require-hashes', tmpdir) as reqs_file: options, args = command.parse_args(['-r', reqs_file]) command.populate_requirement_set(