1"""
2Package containing all pip commands
3"""
4
5import importlib
6from collections import OrderedDict, namedtuple
7from typing import Any, Dict, Optional
8
9from pip._internal.cli.base_command import Command
10
11CommandInfo = namedtuple('CommandInfo', 'module_path, class_name, summary')
12
13# The ordering matters for help display.
14#    Also, even though the module path starts with the same
15# "pip._internal.commands" prefix in each case, we include the full path
16# because it makes testing easier (specifically when modifying commands_dict
17# in test setup / teardown by adding info for a FakeCommand class defined
18# in a test-related module).
19#    Finally, we need to pass an iterable of pairs here rather than a dict
20# so that the ordering won't be lost when using Python 2.7.
21commands_dict: Dict[str, CommandInfo] = OrderedDict([
22    ('install', CommandInfo(
23        'pip._internal.commands.install', 'InstallCommand',
24        'Install packages.',
25    )),
26    ('download', CommandInfo(
27        'pip._internal.commands.download', 'DownloadCommand',
28        'Download packages.',
29    )),
30    ('uninstall', CommandInfo(
31        'pip._internal.commands.uninstall', 'UninstallCommand',
32        'Uninstall packages.',
33    )),
34    ('freeze', CommandInfo(
35        'pip._internal.commands.freeze', 'FreezeCommand',
36        'Output installed packages in requirements format.',
37    )),
38    ('list', CommandInfo(
39        'pip._internal.commands.list', 'ListCommand',
40        'List installed packages.',
41    )),
42    ('show', CommandInfo(
43        'pip._internal.commands.show', 'ShowCommand',
44        'Show information about installed packages.',
45    )),
46    ('check', CommandInfo(
47        'pip._internal.commands.check', 'CheckCommand',
48        'Verify installed packages have compatible dependencies.',
49    )),
50    ('config', CommandInfo(
51        'pip._internal.commands.configuration', 'ConfigurationCommand',
52        'Manage local and global configuration.',
53    )),
54    ('search', CommandInfo(
55        'pip._internal.commands.search', 'SearchCommand',
56        'Search PyPI for packages.',
57    )),
58    ('cache', CommandInfo(
59        'pip._internal.commands.cache', 'CacheCommand',
60        "Inspect and manage pip's wheel cache.",
61    )),
62    ('index', CommandInfo(
63        'pip._internal.commands.index', 'IndexCommand',
64        "Inspect information available from package indexes.",
65    )),
66    ('wheel', CommandInfo(
67        'pip._internal.commands.wheel', 'WheelCommand',
68        'Build wheels from your requirements.',
69    )),
70    ('hash', CommandInfo(
71        'pip._internal.commands.hash', 'HashCommand',
72        'Compute hashes of package archives.',
73    )),
74    ('completion', CommandInfo(
75        'pip._internal.commands.completion', 'CompletionCommand',
76        'A helper command used for command completion.',
77    )),
78    ('debug', CommandInfo(
79        'pip._internal.commands.debug', 'DebugCommand',
80        'Show information useful for debugging.',
81    )),
82    ('help', CommandInfo(
83        'pip._internal.commands.help', 'HelpCommand',
84        'Show help for commands.',
85    )),
86])
87
88
89def create_command(name: str, **kwargs: Any) -> Command:
90    """
91    Create an instance of the Command class with the given name.
92    """
93    module_path, class_name, summary = commands_dict[name]
94    module = importlib.import_module(module_path)
95    command_class = getattr(module, class_name)
96    command = command_class(name=name, summary=summary, **kwargs)
97
98    return command
99
100
101def get_similar_commands(name: str) -> Optional[str]:
102    """Command name auto-correct."""
103    from difflib import get_close_matches
104
105    name = name.lower()
106
107    close_commands = get_close_matches(name, commands_dict.keys())
108
109    if close_commands:
110        return close_commands[0]
111    else:
112        return None
113