OLD | NEW |
1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. | 1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr | 2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
3 # | 3 # |
4 # This file is part of logilab-common. | 4 # This file is part of logilab-common. |
5 # | 5 # |
6 # logilab-common is free software: you can redistribute it and/or modify it unde
r | 6 # logilab-common is free software: you can redistribute it and/or modify it unde
r |
7 # the terms of the GNU Lesser General Public License as published by the Free | 7 # the terms of the GNU Lesser General Public License as published by the Free |
8 # Software Foundation, either version 2.1 of the License, or (at your option) an
y | 8 # Software Foundation, either version 2.1 of the License, or (at your option) an
y |
9 # later version. | 9 # later version. |
10 # | 10 # |
(...skipping 28 matching lines...) Expand all Loading... |
39 * color | 39 * color |
40 argument of this type wont be converted but checked its either a | 40 argument of this type wont be converted but checked its either a |
41 named color or a color specified using hexadecimal notation (preceded by a #
) | 41 named color or a color specified using hexadecimal notation (preceded by a #
) |
42 * time | 42 * time |
43 argument of this type will be converted to a float value in seconds | 43 argument of this type will be converted to a float value in seconds |
44 according to time units (ms, s, min, h, d) | 44 according to time units (ms, s, min, h, d) |
45 * bytes | 45 * bytes |
46 argument of this type will be converted to a float value in bytes | 46 argument of this type will be converted to a float value in bytes |
47 according to byte units (b, kb, mb, gb, tb) | 47 according to byte units (b, kb, mb, gb, tb) |
48 """ | 48 """ |
49 from __future__ import print_function | |
50 | |
51 __docformat__ = "restructuredtext en" | 49 __docformat__ = "restructuredtext en" |
52 | 50 |
53 import re | 51 import re |
54 import sys | 52 import sys |
55 import time | 53 import time |
56 from copy import copy | 54 from copy import copy |
57 from os.path import exists | 55 from os.path import exists |
58 | 56 |
59 # python >= 2.3 | 57 # python >= 2.3 |
60 from optparse import OptionParser as BaseParser, Option as BaseOption, \ | 58 from optparse import OptionParser as BaseParser, Option as BaseOption, \ |
61 OptionGroup, OptionContainer, OptionValueError, OptionError, \ | 59 OptionGroup, OptionContainer, OptionValueError, OptionError, \ |
62 Values, HelpFormatter, NO_DEFAULT, SUPPRESS_HELP | 60 Values, HelpFormatter, NO_DEFAULT, SUPPRESS_HELP |
63 | 61 |
64 try: | 62 try: |
65 from mx import DateTime | 63 from mx import DateTime |
66 HAS_MX_DATETIME = True | 64 HAS_MX_DATETIME = True |
67 except ImportError: | 65 except ImportError: |
68 HAS_MX_DATETIME = False | 66 HAS_MX_DATETIME = False |
69 | 67 |
70 from logilab.common.textutils import splitstrip, TIME_UNITS, BYTE_UNITS, \ | |
71 apply_units | |
72 | 68 |
| 69 OPTPARSE_FORMAT_DEFAULT = sys.version_info >= (2, 4) |
| 70 |
| 71 from logilab.common.textutils import splitstrip |
73 | 72 |
74 def check_regexp(option, opt, value): | 73 def check_regexp(option, opt, value): |
75 """check a regexp value by trying to compile it | 74 """check a regexp value by trying to compile it |
76 return the compiled regexp | 75 return the compiled regexp |
77 """ | 76 """ |
78 if hasattr(value, 'pattern'): | 77 if hasattr(value, 'pattern'): |
79 return value | 78 return value |
80 try: | 79 try: |
81 return re.compile(value) | 80 return re.compile(value) |
82 except ValueError: | 81 except ValueError: |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 return value | 161 return value |
163 # Case (2) : only accepts hexadecimal forms | 162 # Case (2) : only accepts hexadecimal forms |
164 if re.match('#[a-f0-9]{6}', value, re.I): | 163 if re.match('#[a-f0-9]{6}', value, re.I): |
165 return value | 164 return value |
166 # Else : not a color label neither a valid hexadecimal form => error | 165 # Else : not a color label neither a valid hexadecimal form => error |
167 msg = "option %s: invalid color : %r, should be either hexadecimal \ | 166 msg = "option %s: invalid color : %r, should be either hexadecimal \ |
168 value or predefined color" | 167 value or predefined color" |
169 raise OptionValueError(msg % (opt, value)) | 168 raise OptionValueError(msg % (opt, value)) |
170 | 169 |
171 def check_time(option, opt, value): | 170 def check_time(option, opt, value): |
| 171 from logilab.common.textutils import TIME_UNITS, apply_units |
172 if isinstance(value, (int, long, float)): | 172 if isinstance(value, (int, long, float)): |
173 return value | 173 return value |
174 return apply_units(value, TIME_UNITS) | 174 return apply_units(value, TIME_UNITS) |
175 | 175 |
176 def check_bytes(option, opt, value): | 176 def check_bytes(option, opt, value): |
| 177 from logilab.common.textutils import BYTE_UNITS, apply_units |
177 if hasattr(value, '__int__'): | 178 if hasattr(value, '__int__'): |
178 return value | 179 return value |
179 return apply_units(value, BYTE_UNITS) | 180 return apply_units(value, BYTE_UNITS) |
180 | 181 |
| 182 import types |
181 | 183 |
182 class Option(BaseOption): | 184 class Option(BaseOption): |
183 """override optik.Option to add some new option types | 185 """override optik.Option to add some new option types |
184 """ | 186 """ |
185 TYPES = BaseOption.TYPES + ('regexp', 'csv', 'yn', 'named', 'password', | 187 TYPES = BaseOption.TYPES + ('regexp', 'csv', 'yn', 'named', 'password', |
186 'multiple_choice', 'file', 'color', | 188 'multiple_choice', 'file', 'color', |
187 'time', 'bytes') | 189 'time', 'bytes') |
188 ATTRS = BaseOption.ATTRS + ['hide', 'level'] | 190 ATTRS = BaseOption.ATTRS + ['hide', 'level'] |
189 TYPE_CHECKER = copy(BaseOption.TYPE_CHECKER) | 191 TYPE_CHECKER = copy(BaseOption.TYPE_CHECKER) |
190 TYPE_CHECKER['regexp'] = check_regexp | 192 TYPE_CHECKER['regexp'] = check_regexp |
(...skipping 14 matching lines...) Expand all Loading... |
205 BaseOption.__init__(self, *opts, **attrs) | 207 BaseOption.__init__(self, *opts, **attrs) |
206 if hasattr(self, "hide") and self.hide: | 208 if hasattr(self, "hide") and self.hide: |
207 self.help = SUPPRESS_HELP | 209 self.help = SUPPRESS_HELP |
208 | 210 |
209 def _check_choice(self): | 211 def _check_choice(self): |
210 """FIXME: need to override this due to optik misdesign""" | 212 """FIXME: need to override this due to optik misdesign""" |
211 if self.type in ("choice", "multiple_choice"): | 213 if self.type in ("choice", "multiple_choice"): |
212 if self.choices is None: | 214 if self.choices is None: |
213 raise OptionError( | 215 raise OptionError( |
214 "must supply a list of choices for type 'choice'", self) | 216 "must supply a list of choices for type 'choice'", self) |
215 elif not isinstance(self.choices, (tuple, list)): | 217 elif type(self.choices) not in (types.TupleType, types.ListType): |
216 raise OptionError( | 218 raise OptionError( |
217 "choices must be a list of strings ('%s' supplied)" | 219 "choices must be a list of strings ('%s' supplied)" |
218 % str(type(self.choices)).split("'")[1], self) | 220 % str(type(self.choices)).split("'")[1], self) |
219 elif self.choices is not None: | 221 elif self.choices is not None: |
220 raise OptionError( | 222 raise OptionError( |
221 "must not supply choices for type %r" % self.type, self) | 223 "must not supply choices for type %r" % self.type, self) |
222 BaseOption.CHECK_METHODS[2] = _check_choice | 224 BaseOption.CHECK_METHODS[2] = _check_choice |
223 | 225 |
224 | 226 |
225 def process(self, opt, value, values, parser): | 227 def process(self, opt, value, values, parser): |
226 # First, convert the value(s) to the right type. Howl if any | 228 # First, convert the value(s) to the right type. Howl if any |
227 # value(s) are bogus. | 229 # value(s) are bogus. |
228 value = self.convert_value(opt, value) | 230 try: |
| 231 value = self.convert_value(opt, value) |
| 232 except AttributeError: # py < 2.4 |
| 233 value = self.check_value(opt, value) |
229 if self.type == 'named': | 234 if self.type == 'named': |
230 existant = getattr(values, self.dest) | 235 existant = getattr(values, self.dest) |
231 if existant: | 236 if existant: |
232 existant.update(value) | 237 existant.update(value) |
233 value = existant | 238 value = existant |
234 # And then take whatever action is expected of us. | 239 # And then take whatever action is expected of us. |
235 # This is a separate method to make life easier for | 240 # This is a separate method to make life easier for |
236 # subclasses to add new actions. | 241 # subclasses to add new actions. |
237 return self.take_action( | 242 return self.take_action( |
238 self.action, self.dest, opt, value, values, parser) | 243 self.action, self.dest, opt, value, values, parser) |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 %s | 381 %s |
377 ''' % pkginfo.copyright | 382 ''' % pkginfo.copyright |
378 | 383 |
379 return tail | 384 return tail |
380 | 385 |
381 def generate_manpage(optparser, pkginfo, section=1, stream=sys.stdout, level=0): | 386 def generate_manpage(optparser, pkginfo, section=1, stream=sys.stdout, level=0): |
382 """generate a man page from an optik parser""" | 387 """generate a man page from an optik parser""" |
383 formatter = ManHelpFormatter() | 388 formatter = ManHelpFormatter() |
384 formatter.output_level = level | 389 formatter.output_level = level |
385 formatter.parser = optparser | 390 formatter.parser = optparser |
386 print(formatter.format_head(optparser, pkginfo, section), file=stream) | 391 print >> stream, formatter.format_head(optparser, pkginfo, section) |
387 print(optparser.format_option_help(formatter), file=stream) | 392 print >> stream, optparser.format_option_help(formatter) |
388 print(formatter.format_tail(pkginfo), file=stream) | 393 print >> stream, formatter.format_tail(pkginfo) |
389 | 394 |
390 | 395 |
391 __all__ = ('OptionParser', 'Option', 'OptionGroup', 'OptionValueError', | 396 __all__ = ('OptionParser', 'Option', 'OptionGroup', 'OptionValueError', |
392 'Values') | 397 'Values') |
OLD | NEW |