Path: blob/master/venv/Lib/site-packages/pip/_internal/commands/configuration.py
811 views
# The following comment should be removed at some point in the future.1# mypy: disallow-untyped-defs=False23import logging4import os5import subprocess67from pip._internal.cli.base_command import Command8from pip._internal.cli.status_codes import ERROR, SUCCESS9from pip._internal.configuration import (10Configuration,11get_configuration_files,12kinds,13)14from pip._internal.exceptions import PipError15from pip._internal.utils.misc import get_prog, write_output1617logger = logging.getLogger(__name__)181920class ConfigurationCommand(Command):21"""Manage local and global configuration.2223Subcommands:2425list: List the active configuration (or from the file specified)26edit: Edit the configuration file in an editor27get: Get the value associated with name28set: Set the name=value29unset: Unset the value associated with name3031If none of --user, --global and --site are passed, a virtual32environment configuration file is used if one is active and the file33exists. Otherwise, all modifications happen on the to the user file by34default.35"""3637ignore_require_venv = True38usage = """39%prog [<file-option>] list40%prog [<file-option>] [--editor <editor-path>] edit4142%prog [<file-option>] get name43%prog [<file-option>] set name value44%prog [<file-option>] unset name45"""4647def __init__(self, *args, **kwargs):48super(ConfigurationCommand, self).__init__(*args, **kwargs)4950self.configuration = None5152self.cmd_opts.add_option(53'--editor',54dest='editor',55action='store',56default=None,57help=(58'Editor to use to edit the file. Uses VISUAL or EDITOR '59'environment variables if not provided.'60)61)6263self.cmd_opts.add_option(64'--global',65dest='global_file',66action='store_true',67default=False,68help='Use the system-wide configuration file only'69)7071self.cmd_opts.add_option(72'--user',73dest='user_file',74action='store_true',75default=False,76help='Use the user configuration file only'77)7879self.cmd_opts.add_option(80'--site',81dest='site_file',82action='store_true',83default=False,84help='Use the current environment configuration file only'85)8687self.parser.insert_option_group(0, self.cmd_opts)8889def run(self, options, args):90handlers = {91"list": self.list_values,92"edit": self.open_in_editor,93"get": self.get_name,94"set": self.set_name_value,95"unset": self.unset_name96}9798# Determine action99if not args or args[0] not in handlers:100logger.error("Need an action ({}) to perform.".format(101", ".join(sorted(handlers)))102)103return ERROR104105action = args[0]106107# Determine which configuration files are to be loaded108# Depends on whether the command is modifying.109try:110load_only = self._determine_file(111options, need_value=(action in ["get", "set", "unset", "edit"])112)113except PipError as e:114logger.error(e.args[0])115return ERROR116117# Load a new configuration118self.configuration = Configuration(119isolated=options.isolated_mode, load_only=load_only120)121self.configuration.load()122123# Error handling happens here, not in the action-handlers.124try:125handlers[action](options, args[1:])126except PipError as e:127logger.error(e.args[0])128return ERROR129130return SUCCESS131132def _determine_file(self, options, need_value):133file_options = [key for key, value in (134(kinds.USER, options.user_file),135(kinds.GLOBAL, options.global_file),136(kinds.SITE, options.site_file),137) if value]138139if not file_options:140if not need_value:141return None142# Default to user, unless there's a site file.143elif any(144os.path.exists(site_config_file)145for site_config_file in get_configuration_files()[kinds.SITE]146):147return kinds.SITE148else:149return kinds.USER150elif len(file_options) == 1:151return file_options[0]152153raise PipError(154"Need exactly one file to operate upon "155"(--user, --site, --global) to perform."156)157158def list_values(self, options, args):159self._get_n_args(args, "list", n=0)160161for key, value in sorted(self.configuration.items()):162write_output("%s=%r", key, value)163164def get_name(self, options, args):165key = self._get_n_args(args, "get [name]", n=1)166value = self.configuration.get_value(key)167168write_output("%s", value)169170def set_name_value(self, options, args):171key, value = self._get_n_args(args, "set [name] [value]", n=2)172self.configuration.set_value(key, value)173174self._save_configuration()175176def unset_name(self, options, args):177key = self._get_n_args(args, "unset [name]", n=1)178self.configuration.unset_value(key)179180self._save_configuration()181182def open_in_editor(self, options, args):183editor = self._determine_editor(options)184185fname = self.configuration.get_file_to_edit()186if fname is None:187raise PipError("Could not determine appropriate file.")188189try:190subprocess.check_call([editor, fname])191except subprocess.CalledProcessError as e:192raise PipError(193"Editor Subprocess exited with exit code {}"194.format(e.returncode)195)196197def _get_n_args(self, args, example, n):198"""Helper to make sure the command got the right number of arguments199"""200if len(args) != n:201msg = (202'Got unexpected number of arguments, expected {}. '203'(example: "{} config {}")'204).format(n, get_prog(), example)205raise PipError(msg)206207if n == 1:208return args[0]209else:210return args211212def _save_configuration(self):213# We successfully ran a modifying command. Need to save the214# configuration.215try:216self.configuration.save()217except Exception:218logger.error(219"Unable to save configuration. Please report this as a bug.",220exc_info=1221)222raise PipError("Internal Error.")223224def _determine_editor(self, options):225if options.editor is not None:226return options.editor227elif "VISUAL" in os.environ:228return os.environ["VISUAL"]229elif "EDITOR" in os.environ:230return os.environ["EDITOR"]231else:232raise PipError("Could not determine editor to use.")233234235