| 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 |