comparison venv/lib/python2.7/site-packages/pip/baseparser.py @ 0:d67268158946 draft

planemo upload commit a3f181f5f126803c654b3a66dd4e83a48f7e203b
author bcclaywell
date Mon, 12 Oct 2015 17:43:33 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:d67268158946
1 """Base option parser setup"""
2 from __future__ import absolute_import
3
4 import sys
5 import optparse
6 import os
7 import re
8 import textwrap
9 from distutils.util import strtobool
10
11 from pip._vendor.six import string_types
12 from pip._vendor.six.moves import configparser
13 from pip.locations import (
14 legacy_config_file, config_basename, running_under_virtualenv,
15 site_config_files
16 )
17 from pip.utils import appdirs, get_terminal_size
18
19
20 _environ_prefix_re = re.compile(r"^PIP_", re.I)
21
22
23 class PrettyHelpFormatter(optparse.IndentedHelpFormatter):
24 """A prettier/less verbose help formatter for optparse."""
25
26 def __init__(self, *args, **kwargs):
27 # help position must be aligned with __init__.parseopts.description
28 kwargs['max_help_position'] = 30
29 kwargs['indent_increment'] = 1
30 kwargs['width'] = get_terminal_size()[0] - 2
31 optparse.IndentedHelpFormatter.__init__(self, *args, **kwargs)
32
33 def format_option_strings(self, option):
34 return self._format_option_strings(option, ' <%s>', ', ')
35
36 def _format_option_strings(self, option, mvarfmt=' <%s>', optsep=', '):
37 """
38 Return a comma-separated list of option strings and metavars.
39
40 :param option: tuple of (short opt, long opt), e.g: ('-f', '--format')
41 :param mvarfmt: metavar format string - evaluated as mvarfmt % metavar
42 :param optsep: separator
43 """
44 opts = []
45
46 if option._short_opts:
47 opts.append(option._short_opts[0])
48 if option._long_opts:
49 opts.append(option._long_opts[0])
50 if len(opts) > 1:
51 opts.insert(1, optsep)
52
53 if option.takes_value():
54 metavar = option.metavar or option.dest.lower()
55 opts.append(mvarfmt % metavar.lower())
56
57 return ''.join(opts)
58
59 def format_heading(self, heading):
60 if heading == 'Options':
61 return ''
62 return heading + ':\n'
63
64 def format_usage(self, usage):
65 """
66 Ensure there is only one newline between usage and the first heading
67 if there is no description.
68 """
69 msg = '\nUsage: %s\n' % self.indent_lines(textwrap.dedent(usage), " ")
70 return msg
71
72 def format_description(self, description):
73 # leave full control over description to us
74 if description:
75 if hasattr(self.parser, 'main'):
76 label = 'Commands'
77 else:
78 label = 'Description'
79 # some doc strings have initial newlines, some don't
80 description = description.lstrip('\n')
81 # some doc strings have final newlines and spaces, some don't
82 description = description.rstrip()
83 # dedent, then reindent
84 description = self.indent_lines(textwrap.dedent(description), " ")
85 description = '%s:\n%s\n' % (label, description)
86 return description
87 else:
88 return ''
89
90 def format_epilog(self, epilog):
91 # leave full control over epilog to us
92 if epilog:
93 return epilog
94 else:
95 return ''
96
97 def indent_lines(self, text, indent):
98 new_lines = [indent + line for line in text.split('\n')]
99 return "\n".join(new_lines)
100
101
102 class UpdatingDefaultsHelpFormatter(PrettyHelpFormatter):
103 """Custom help formatter for use in ConfigOptionParser that updates
104 the defaults before expanding them, allowing them to show up correctly
105 in the help listing"""
106
107 def expand_default(self, option):
108 if self.parser is not None:
109 self.parser.update_defaults(self.parser.defaults)
110 return optparse.IndentedHelpFormatter.expand_default(self, option)
111
112
113 class CustomOptionParser(optparse.OptionParser):
114 def insert_option_group(self, idx, *args, **kwargs):
115 """Insert an OptionGroup at a given position."""
116 group = self.add_option_group(*args, **kwargs)
117
118 self.option_groups.pop()
119 self.option_groups.insert(idx, group)
120
121 return group
122
123 @property
124 def option_list_all(self):
125 """Get a list of all options, including those in option groups."""
126 res = self.option_list[:]
127 for i in self.option_groups:
128 res.extend(i.option_list)
129
130 return res
131
132
133 class ConfigOptionParser(CustomOptionParser):
134 """Custom option parser which updates its defaults by checking the
135 configuration files and environmental variables"""
136
137 isolated = False
138
139 def __init__(self, *args, **kwargs):
140 self.config = configparser.RawConfigParser()
141 self.name = kwargs.pop('name')
142 self.isolated = kwargs.pop("isolated", False)
143 self.files = self.get_config_files()
144 if self.files:
145 self.config.read(self.files)
146 assert self.name
147 optparse.OptionParser.__init__(self, *args, **kwargs)
148
149 def get_config_files(self):
150 # the files returned by this method will be parsed in order with the
151 # first files listed being overridden by later files in standard
152 # ConfigParser fashion
153 config_file = os.environ.get('PIP_CONFIG_FILE', False)
154 if config_file == os.devnull:
155 return []
156
157 # at the base we have any site-wide configuration
158 files = list(site_config_files)
159
160 # per-user configuration next
161 if not self.isolated:
162 if config_file and os.path.exists(config_file):
163 files.append(config_file)
164 else:
165 # This is the legacy config file, we consider it to be a lower
166 # priority than the new file location.
167 files.append(legacy_config_file)
168
169 # This is the new config file, we consider it to be a higher
170 # priority than the legacy file.
171 files.append(
172 os.path.join(
173 appdirs.user_config_dir("pip"),
174 config_basename,
175 )
176 )
177
178 # finally virtualenv configuration first trumping others
179 if running_under_virtualenv():
180 venv_config_file = os.path.join(
181 sys.prefix,
182 config_basename,
183 )
184 if os.path.exists(venv_config_file):
185 files.append(venv_config_file)
186
187 return files
188
189 def check_default(self, option, key, val):
190 try:
191 return option.check_value(key, val)
192 except optparse.OptionValueError as exc:
193 print("An error occurred during configuration: %s" % exc)
194 sys.exit(3)
195
196 def update_defaults(self, defaults):
197 """Updates the given defaults with values from the config files and
198 the environ. Does a little special handling for certain types of
199 options (lists)."""
200 # Then go and look for the other sources of configuration:
201 config = {}
202 # 1. config files
203 for section in ('global', self.name):
204 config.update(
205 self.normalize_keys(self.get_config_section(section))
206 )
207 # 2. environmental variables
208 if not self.isolated:
209 config.update(self.normalize_keys(self.get_environ_vars()))
210 # Then set the options with those values
211 for key, val in config.items():
212 option = self.get_option(key)
213 if option is not None:
214 # ignore empty values
215 if not val:
216 continue
217 if option.action in ('store_true', 'store_false', 'count'):
218 val = strtobool(val)
219 if option.action == 'append':
220 val = val.split()
221 val = [self.check_default(option, key, v) for v in val]
222 else:
223 val = self.check_default(option, key, val)
224
225 defaults[option.dest] = val
226 return defaults
227
228 def normalize_keys(self, items):
229 """Return a config dictionary with normalized keys regardless of
230 whether the keys were specified in environment variables or in config
231 files"""
232 normalized = {}
233 for key, val in items:
234 key = key.replace('_', '-')
235 if not key.startswith('--'):
236 key = '--%s' % key # only prefer long opts
237 normalized[key] = val
238 return normalized
239
240 def get_config_section(self, name):
241 """Get a section of a configuration"""
242 if self.config.has_section(name):
243 return self.config.items(name)
244 return []
245
246 def get_environ_vars(self):
247 """Returns a generator with all environmental vars with prefix PIP_"""
248 for key, val in os.environ.items():
249 if _environ_prefix_re.search(key):
250 yield (_environ_prefix_re.sub("", key).lower(), val)
251
252 def get_default_values(self):
253 """Overridding to make updating the defaults after instantiation of
254 the option parser possible, update_defaults() does the dirty work."""
255 if not self.process_default_values:
256 # Old, pre-Optik 1.5 behaviour.
257 return optparse.Values(self.defaults)
258
259 defaults = self.update_defaults(self.defaults.copy()) # ours
260 for option in self._get_all_options():
261 default = defaults.get(option.dest)
262 if isinstance(default, string_types):
263 opt_str = option.get_opt_string()
264 defaults[option.dest] = option.check_value(opt_str, default)
265 return optparse.Values(defaults)
266
267 def error(self, msg):
268 self.print_usage(sys.stderr)
269 self.exit(2, "%s\n" % msg)