| Viewing file:  configuration.py (9.13 KB)      -rw-r--r-- Select action/file-type:
 
  (+) |  (+) |  (+) | Code (+) | Session (+) |  (+) | SDB (+) |  (+) |  (+) |  (+) |  (+) |  (+) | 
 
import loggingimport os
 import subprocess
 
 from pip._internal.cli.base_command import Command
 from pip._internal.cli.status_codes import ERROR, SUCCESS
 from pip._internal.configuration import (
 Configuration,
 get_configuration_files,
 kinds,
 )
 from pip._internal.exceptions import PipError
 from pip._internal.utils.logging import indent_log
 from pip._internal.utils.misc import get_prog, write_output
 from pip._internal.utils.typing import MYPY_CHECK_RUNNING
 
 if MYPY_CHECK_RUNNING:
 from typing import List, Any, Optional
 from optparse import Values
 
 from pip._internal.configuration import Kind
 
 logger = logging.getLogger(__name__)
 
 
 class ConfigurationCommand(Command):
 """
 Manage local and global configuration.
 
 Subcommands:
 
 - list: List the active configuration (or from the file specified)
 - edit: Edit the configuration file in an editor
 - get: Get the value associated with name
 - set: Set the name=value
 - unset: Unset the value associated with name
 - debug: List the configuration files and values defined under them
 
 If none of --user, --global and --site are passed, a virtual
 environment configuration file is used if one is active and the file
 exists. Otherwise, all modifications happen on the to the user file by
 default.
 """
 
 ignore_require_venv = True
 usage = """
 %prog [<file-option>] list
 %prog [<file-option>] [--editor <editor-path>] edit
 
 %prog [<file-option>] get name
 %prog [<file-option>] set name value
 %prog [<file-option>] unset name
 %prog [<file-option>] debug
 """
 
 def add_options(self):
 # type: () -> None
 self.cmd_opts.add_option(
 '--editor',
 dest='editor',
 action='store',
 default=None,
 help=(
 'Editor to use to edit the file. Uses VISUAL or EDITOR '
 'environment variables if not provided.'
 )
 )
 
 self.cmd_opts.add_option(
 '--global',
 dest='global_file',
 action='store_true',
 default=False,
 help='Use the system-wide configuration file only'
 )
 
 self.cmd_opts.add_option(
 '--user',
 dest='user_file',
 action='store_true',
 default=False,
 help='Use the user configuration file only'
 )
 
 self.cmd_opts.add_option(
 '--site',
 dest='site_file',
 action='store_true',
 default=False,
 help='Use the current environment configuration file only'
 )
 
 self.parser.insert_option_group(0, self.cmd_opts)
 
 def run(self, options, args):
 # type: (Values, List[str]) -> int
 handlers = {
 "list": self.list_values,
 "edit": self.open_in_editor,
 "get": self.get_name,
 "set": self.set_name_value,
 "unset": self.unset_name,
 "debug": self.list_config_values,
 }
 
 # Determine action
 if not args or args[0] not in handlers:
 logger.error(
 "Need an action (%s) to perform.",
 ", ".join(sorted(handlers)),
 )
 return ERROR
 
 action = args[0]
 
 # Determine which configuration files are to be loaded
 #    Depends on whether the command is modifying.
 try:
 load_only = self._determine_file(
 options, need_value=(action in ["get", "set", "unset", "edit"])
 )
 except PipError as e:
 logger.error(e.args[0])
 return ERROR
 
 # Load a new configuration
 self.configuration = Configuration(
 isolated=options.isolated_mode, load_only=load_only
 )
 self.configuration.load()
 
 # Error handling happens here, not in the action-handlers.
 try:
 handlers[action](options, args[1:])
 except PipError as e:
 logger.error(e.args[0])
 return ERROR
 
 return SUCCESS
 
 def _determine_file(self, options, need_value):
 # type: (Values, bool) -> Optional[Kind]
 file_options = [key for key, value in (
 (kinds.USER, options.user_file),
 (kinds.GLOBAL, options.global_file),
 (kinds.SITE, options.site_file),
 ) if value]
 
 if not file_options:
 if not need_value:
 return None
 # Default to user, unless there's a site file.
 elif any(
 os.path.exists(site_config_file)
 for site_config_file in get_configuration_files()[kinds.SITE]
 ):
 return kinds.SITE
 else:
 return kinds.USER
 elif len(file_options) == 1:
 return file_options[0]
 
 raise PipError(
 "Need exactly one file to operate upon "
 "(--user, --site, --global) to perform."
 )
 
 def list_values(self, options, args):
 # type: (Values, List[str]) -> None
 self._get_n_args(args, "list", n=0)
 
 for key, value in sorted(self.configuration.items()):
 write_output("%s=%r", key, value)
 
 def get_name(self, options, args):
 # type: (Values, List[str]) -> None
 key = self._get_n_args(args, "get [name]", n=1)
 value = self.configuration.get_value(key)
 
 write_output("%s", value)
 
 def set_name_value(self, options, args):
 # type: (Values, List[str]) -> None
 key, value = self._get_n_args(args, "set [name] [value]", n=2)
 self.configuration.set_value(key, value)
 
 self._save_configuration()
 
 def unset_name(self, options, args):
 # type: (Values, List[str]) -> None
 key = self._get_n_args(args, "unset [name]", n=1)
 self.configuration.unset_value(key)
 
 self._save_configuration()
 
 def list_config_values(self, options, args):
 # type: (Values, List[str]) -> None
 """List config key-value pairs across different config files"""
 self._get_n_args(args, "debug", n=0)
 
 self.print_env_var_values()
 # Iterate over config files and print if they exist, and the
 # key-value pairs present in them if they do
 for variant, files in sorted(self.configuration.iter_config_files()):
 write_output("%s:", variant)
 for fname in files:
 with indent_log():
 file_exists = os.path.exists(fname)
 write_output("%s, exists: %r",
 fname, file_exists)
 if file_exists:
 self.print_config_file_values(variant)
 
 def print_config_file_values(self, variant):
 # type: (Kind) -> None
 """Get key-value pairs from the file of a variant"""
 for name, value in self.configuration.\
 get_values_in_config(variant).items():
 with indent_log():
 write_output("%s: %s", name, value)
 
 def print_env_var_values(self):
 # type: () -> None
 """Get key-values pairs present as environment variables"""
 write_output("%s:", 'env_var')
 with indent_log():
 for key, value in sorted(self.configuration.get_environ_vars()):
 env_var = 'PIP_{}'.format(key.upper())
 write_output("%s=%r", env_var, value)
 
 def open_in_editor(self, options, args):
 # type: (Values, List[str]) -> None
 editor = self._determine_editor(options)
 
 fname = self.configuration.get_file_to_edit()
 if fname is None:
 raise PipError("Could not determine appropriate file.")
 
 try:
 subprocess.check_call([editor, fname])
 except subprocess.CalledProcessError as e:
 raise PipError(
 "Editor Subprocess exited with exit code {}"
 .format(e.returncode)
 )
 
 def _get_n_args(self, args, example, n):
 # type: (List[str], str, int) -> Any
 """Helper to make sure the command got the right number of arguments
 """
 if len(args) != n:
 msg = (
 'Got unexpected number of arguments, expected {}. '
 '(example: "{} config {}")'
 ).format(n, get_prog(), example)
 raise PipError(msg)
 
 if n == 1:
 return args[0]
 else:
 return args
 
 def _save_configuration(self):
 # type: () -> None
 # We successfully ran a modifying command. Need to save the
 # configuration.
 try:
 self.configuration.save()
 except Exception:
 logger.exception(
 "Unable to save configuration. Please report this as a bug."
 )
 raise PipError("Internal Error.")
 
 def _determine_editor(self, options):
 # type: (Values) -> str
 if options.editor is not None:
 return options.editor
 elif "VISUAL" in os.environ:
 return os.environ["VISUAL"]
 elif "EDITOR" in os.environ:
 return os.environ["EDITOR"]
 else:
 raise PipError("Could not determine editor to use.")
 
 |