summaryrefslogtreecommitdiff
path: root/lib/python2.7/site-packages/pip/baseparser.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python2.7/site-packages/pip/baseparser.py')
-rw-r--r--lib/python2.7/site-packages/pip/baseparser.py293
1 files changed, 293 insertions, 0 deletions
diff --git a/lib/python2.7/site-packages/pip/baseparser.py b/lib/python2.7/site-packages/pip/baseparser.py
new file mode 100644
index 0000000..2dd4533
--- /dev/null
+++ b/lib/python2.7/site-packages/pip/baseparser.py
@@ -0,0 +1,293 @@
+"""Base option parser setup"""
+from __future__ import absolute_import
+
+import sys
+import optparse
+import os
+import re
+import textwrap
+from distutils.util import strtobool
+
+from pip._vendor.six import string_types
+from pip._vendor.six.moves import configparser
+from pip.locations import (
+ legacy_config_file, config_basename, running_under_virtualenv,
+ site_config_files
+)
+from pip.utils import appdirs, get_terminal_size
+
+
+_environ_prefix_re = re.compile(r"^PIP_", re.I)
+
+
+class PrettyHelpFormatter(optparse.IndentedHelpFormatter):
+ """A prettier/less verbose help formatter for optparse."""
+
+ def __init__(self, *args, **kwargs):
+ # help position must be aligned with __init__.parseopts.description
+ kwargs['max_help_position'] = 30
+ kwargs['indent_increment'] = 1
+ kwargs['width'] = get_terminal_size()[0] - 2
+ optparse.IndentedHelpFormatter.__init__(self, *args, **kwargs)
+
+ def format_option_strings(self, option):
+ return self._format_option_strings(option, ' <%s>', ', ')
+
+ def _format_option_strings(self, option, mvarfmt=' <%s>', optsep=', '):
+ """
+ Return a comma-separated list of option strings and metavars.
+
+ :param option: tuple of (short opt, long opt), e.g: ('-f', '--format')
+ :param mvarfmt: metavar format string - evaluated as mvarfmt % metavar
+ :param optsep: separator
+ """
+ opts = []
+
+ if option._short_opts:
+ opts.append(option._short_opts[0])
+ if option._long_opts:
+ opts.append(option._long_opts[0])
+ if len(opts) > 1:
+ opts.insert(1, optsep)
+
+ if option.takes_value():
+ metavar = option.metavar or option.dest.lower()
+ opts.append(mvarfmt % metavar.lower())
+
+ return ''.join(opts)
+
+ def format_heading(self, heading):
+ if heading == 'Options':
+ return ''
+ return heading + ':\n'
+
+ def format_usage(self, usage):
+ """
+ Ensure there is only one newline between usage and the first heading
+ if there is no description.
+ """
+ msg = '\nUsage: %s\n' % self.indent_lines(textwrap.dedent(usage), " ")
+ return msg
+
+ def format_description(self, description):
+ # leave full control over description to us
+ if description:
+ if hasattr(self.parser, 'main'):
+ label = 'Commands'
+ else:
+ label = 'Description'
+ # some doc strings have initial newlines, some don't
+ description = description.lstrip('\n')
+ # some doc strings have final newlines and spaces, some don't
+ description = description.rstrip()
+ # dedent, then reindent
+ description = self.indent_lines(textwrap.dedent(description), " ")
+ description = '%s:\n%s\n' % (label, description)
+ return description
+ else:
+ return ''
+
+ def format_epilog(self, epilog):
+ # leave full control over epilog to us
+ if epilog:
+ return epilog
+ else:
+ return ''
+
+ def indent_lines(self, text, indent):
+ new_lines = [indent + line for line in text.split('\n')]
+ return "\n".join(new_lines)
+
+
+class UpdatingDefaultsHelpFormatter(PrettyHelpFormatter):
+ """Custom help formatter for use in ConfigOptionParser.
+
+ This is updates the defaults before expanding them, allowing
+ them to show up correctly in the help listing.
+ """
+
+ def expand_default(self, option):
+ if self.parser is not None:
+ self.parser._update_defaults(self.parser.defaults)
+ return optparse.IndentedHelpFormatter.expand_default(self, option)
+
+
+class CustomOptionParser(optparse.OptionParser):
+
+ def insert_option_group(self, idx, *args, **kwargs):
+ """Insert an OptionGroup at a given position."""
+ group = self.add_option_group(*args, **kwargs)
+
+ self.option_groups.pop()
+ self.option_groups.insert(idx, group)
+
+ return group
+
+ @property
+ def option_list_all(self):
+ """Get a list of all options, including those in option groups."""
+ res = self.option_list[:]
+ for i in self.option_groups:
+ res.extend(i.option_list)
+
+ return res
+
+
+class ConfigOptionParser(CustomOptionParser):
+ """Custom option parser which updates its defaults by checking the
+ configuration files and environmental variables"""
+
+ isolated = False
+
+ def __init__(self, *args, **kwargs):
+ self.config = configparser.RawConfigParser()
+ self.name = kwargs.pop('name')
+ self.isolated = kwargs.pop("isolated", False)
+ self.files = self.get_config_files()
+ if self.files:
+ self.config.read(self.files)
+ assert self.name
+ optparse.OptionParser.__init__(self, *args, **kwargs)
+
+ def get_config_files(self):
+ # the files returned by this method will be parsed in order with the
+ # first files listed being overridden by later files in standard
+ # ConfigParser fashion
+ config_file = os.environ.get('PIP_CONFIG_FILE', False)
+ if config_file == os.devnull:
+ return []
+
+ # at the base we have any site-wide configuration
+ files = list(site_config_files)
+
+ # per-user configuration next
+ if not self.isolated:
+ if config_file and os.path.exists(config_file):
+ files.append(config_file)
+ else:
+ # This is the legacy config file, we consider it to be a lower
+ # priority than the new file location.
+ files.append(legacy_config_file)
+
+ # This is the new config file, we consider it to be a higher
+ # priority than the legacy file.
+ files.append(
+ os.path.join(
+ appdirs.user_config_dir("pip"),
+ config_basename,
+ )
+ )
+
+ # finally virtualenv configuration first trumping others
+ if running_under_virtualenv():
+ venv_config_file = os.path.join(
+ sys.prefix,
+ config_basename,
+ )
+ if os.path.exists(venv_config_file):
+ files.append(venv_config_file)
+
+ return files
+
+ def check_default(self, option, key, val):
+ try:
+ return option.check_value(key, val)
+ except optparse.OptionValueError as exc:
+ print("An error occurred during configuration: %s" % exc)
+ sys.exit(3)
+
+ def _update_defaults(self, defaults):
+ """Updates the given defaults with values from the config files and
+ the environ. Does a little special handling for certain types of
+ options (lists)."""
+ # Then go and look for the other sources of configuration:
+ config = {}
+ # 1. config files
+ for section in ('global', self.name):
+ config.update(
+ self.normalize_keys(self.get_config_section(section))
+ )
+ # 2. environmental variables
+ if not self.isolated:
+ config.update(self.normalize_keys(self.get_environ_vars()))
+ # Accumulate complex default state.
+ self.values = optparse.Values(self.defaults)
+ late_eval = set()
+ # Then set the options with those values
+ for key, val in config.items():
+ # ignore empty values
+ if not val:
+ continue
+
+ option = self.get_option(key)
+ # Ignore options not present in this parser. E.g. non-globals put
+ # in [global] by users that want them to apply to all applicable
+ # commands.
+ if option is None:
+ continue
+
+ if option.action in ('store_true', 'store_false', 'count'):
+ val = strtobool(val)
+ elif option.action == 'append':
+ val = val.split()
+ val = [self.check_default(option, key, v) for v in val]
+ elif option.action == 'callback':
+ late_eval.add(option.dest)
+ opt_str = option.get_opt_string()
+ val = option.convert_value(opt_str, val)
+ # From take_action
+ args = option.callback_args or ()
+ kwargs = option.callback_kwargs or {}
+ option.callback(option, opt_str, val, self, *args, **kwargs)
+ else:
+ val = self.check_default(option, key, val)
+
+ defaults[option.dest] = val
+
+ for key in late_eval:
+ defaults[key] = getattr(self.values, key)
+ self.values = None
+ return defaults
+
+ def normalize_keys(self, items):
+ """Return a config dictionary with normalized keys regardless of
+ whether the keys were specified in environment variables or in config
+ files"""
+ normalized = {}
+ for key, val in items:
+ key = key.replace('_', '-')
+ if not key.startswith('--'):
+ key = '--%s' % key # only prefer long opts
+ normalized[key] = val
+ return normalized
+
+ def get_config_section(self, name):
+ """Get a section of a configuration"""
+ if self.config.has_section(name):
+ return self.config.items(name)
+ return []
+
+ def get_environ_vars(self):
+ """Returns a generator with all environmental vars with prefix PIP_"""
+ for key, val in os.environ.items():
+ if _environ_prefix_re.search(key):
+ yield (_environ_prefix_re.sub("", key).lower(), val)
+
+ def get_default_values(self):
+ """Overriding to make updating the defaults after instantiation of
+ the option parser possible, _update_defaults() does the dirty work."""
+ if not self.process_default_values:
+ # Old, pre-Optik 1.5 behaviour.
+ return optparse.Values(self.defaults)
+
+ defaults = self._update_defaults(self.defaults.copy()) # ours
+ for option in self._get_all_options():
+ default = defaults.get(option.dest)
+ if isinstance(default, string_types):
+ opt_str = option.get_opt_string()
+ defaults[option.dest] = option.check_value(opt_str, default)
+ return optparse.Values(defaults)
+
+ def error(self, msg):
+ self.print_usage(sys.stderr)
+ self.exit(2, "%s\n" % msg)