import logging import 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.")
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
__pycache__ | Folder | 0755 |
|
|
.__init__.pyo.40009 | File | 3.48 KB | 0644 |
|
.cache.pyo.40009 | File | 5.45 KB | 0644 |
|
.check.pyo.40009 | File | 1.91 KB | 0644 |
|
.completion.pyo.40009 | File | 3.51 KB | 0644 |
|
.configuration.pyo.40009 | File | 9.52 KB | 0644 |
|
.debug.pyo.40009 | File | 7.9 KB | 0644 |
|
.download.pyo.40009 | File | 4.7 KB | 0644 |
|
.freeze.pyo.40009 | File | 3.69 KB | 0644 |
|
.hash.pyo.40009 | File | 2.67 KB | 0644 |
|
.help.pyo.40009 | File | 1.68 KB | 0644 |
|
.list.pyo.40009 | File | 10.33 KB | 0644 |
|
.show.pyo.40009 | File | 6.59 KB | 0644 |
|
.uninstall.pyo.40009 | File | 3.47 KB | 0644 |
|
__init__.py | File | 4 KB | 0644 |
|
__init__.pyc | File | 3.48 KB | 0644 |
|
__init__.pyo | File | 3.48 KB | 0644 |
|
cache.py | File | 5.54 KB | 0644 |
|
cache.pyc | File | 5.45 KB | 0644 |
|
cache.pyo | File | 5.45 KB | 0644 |
|
check.py | File | 1.64 KB | 0644 |
|
check.pyc | File | 1.91 KB | 0644 |
|
check.pyo | File | 1.91 KB | 0644 |
|
completion.py | File | 3.01 KB | 0644 |
|
completion.pyc | File | 3.51 KB | 0644 |
|
completion.pyo | File | 3.51 KB | 0644 |
|
configuration.py | File | 9.13 KB | 0644 |
|
configuration.pyc | File | 9.52 KB | 0644 |
|
configuration.pyo | File | 9.52 KB | 0644 |
|
debug.py | File | 7.14 KB | 0644 |
|
debug.pyc | File | 7.9 KB | 0644 |
|
debug.pyo | File | 7.9 KB | 0644 |
|
download.py | File | 4.8 KB | 0644 |
|
download.pyc | File | 4.7 KB | 0644 |
|
download.pyo | File | 4.7 KB | 0644 |
|
freeze.py | File | 3.37 KB | 0644 |
|
freeze.pyc | File | 3.69 KB | 0644 |
|
freeze.pyo | File | 3.69 KB | 0644 |
|
hash.py | File | 1.8 KB | 0644 |
|
hash.pyc | File | 2.67 KB | 0644 |
|
hash.pyo | File | 2.67 KB | 0644 |
|
help.py | File | 1.24 KB | 0644 |
|
help.pyc | File | 1.68 KB | 0644 |
|
help.pyo | File | 1.68 KB | 0644 |
|
install.py | File | 28.05 KB | 0644 |
|
install.pyc | File | 20.44 KB | 0644 |
|
install.pyo | File | 20.38 KB | 0644 |
|
list.py | File | 11.05 KB | 0644 |
|
list.pyc | File | 10.33 KB | 0644 |
|
list.pyo | File | 10.33 KB | 0644 |
|
search.py | File | 5.62 KB | 0644 |
|
search.pyc | File | 5.81 KB | 0644 |
|
search.pyo | File | 5.77 KB | 0644 |
|
show.py | File | 6.83 KB | 0644 |
|
show.pyc | File | 6.59 KB | 0644 |
|
show.pyo | File | 6.59 KB | 0644 |
|
uninstall.py | File | 3.23 KB | 0644 |
|
uninstall.pyc | File | 3.47 KB | 0644 |
|
uninstall.pyo | File | 3.47 KB | 0644 |
|
wheel.py | File | 6.27 KB | 0644 |
|
wheel.pyc | File | 5.8 KB | 0644 |
|
wheel.pyo | File | 5.72 KB | 0644 |
|