Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(640)

Unified Diff: third_party/logilab/logilab/common/optik_ext.py

Issue 1920403002: [content/test/gpu] Run pylint check of gpu tests in unittest instead of PRESUBMIT (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update path to LICENSE.txt of logilab/README.chromium Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/logilab/logilab/common/modutils.py ('k') | third_party/logilab/logilab/common/optparser.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/logilab/logilab/common/optik_ext.py
diff --git a/third_party/logilab/logilab/common/optik_ext.py b/third_party/logilab/logilab/common/optik_ext.py
new file mode 100644
index 0000000000000000000000000000000000000000..1fd2a7f8cc02eeb037671a9d4a59f8daf38de5a2
--- /dev/null
+++ b/third_party/logilab/logilab/common/optik_ext.py
@@ -0,0 +1,392 @@
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of logilab-common.
+#
+# logilab-common is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option) any
+# later version.
+#
+# logilab-common is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with logilab-common. If not, see <http://www.gnu.org/licenses/>.
+"""Add an abstraction level to transparently import optik classes from optparse
+(python >= 2.3) or the optik package.
+
+It also defines three new types for optik/optparse command line parser :
+
+ * regexp
+ argument of this type will be converted using re.compile
+ * csv
+ argument of this type will be converted using split(',')
+ * yn
+ argument of this type will be true if 'y' or 'yes', false if 'n' or 'no'
+ * named
+ argument of this type are in the form <NAME>=<VALUE> or <NAME>:<VALUE>
+ * password
+ argument of this type wont be converted but this is used by other tools
+ such as interactive prompt for configuration to double check value and
+ use an invisible field
+ * multiple_choice
+ same as default "choice" type but multiple choices allowed
+ * file
+ argument of this type wont be converted but checked that the given file exists
+ * color
+ argument of this type wont be converted but checked its either a
+ named color or a color specified using hexadecimal notation (preceded by a #)
+ * time
+ argument of this type will be converted to a float value in seconds
+ according to time units (ms, s, min, h, d)
+ * bytes
+ argument of this type will be converted to a float value in bytes
+ according to byte units (b, kb, mb, gb, tb)
+"""
+from __future__ import print_function
+
+__docformat__ = "restructuredtext en"
+
+import re
+import sys
+import time
+from copy import copy
+from os.path import exists
+
+# python >= 2.3
+from optparse import OptionParser as BaseParser, Option as BaseOption, \
+ OptionGroup, OptionContainer, OptionValueError, OptionError, \
+ Values, HelpFormatter, NO_DEFAULT, SUPPRESS_HELP
+
+try:
+ from mx import DateTime
+ HAS_MX_DATETIME = True
+except ImportError:
+ HAS_MX_DATETIME = False
+
+from logilab.common.textutils import splitstrip, TIME_UNITS, BYTE_UNITS, \
+ apply_units
+
+
+def check_regexp(option, opt, value):
+ """check a regexp value by trying to compile it
+ return the compiled regexp
+ """
+ if hasattr(value, 'pattern'):
+ return value
+ try:
+ return re.compile(value)
+ except ValueError:
+ raise OptionValueError(
+ "option %s: invalid regexp value: %r" % (opt, value))
+
+def check_csv(option, opt, value):
+ """check a csv value by trying to split it
+ return the list of separated values
+ """
+ if isinstance(value, (list, tuple)):
+ return value
+ try:
+ return splitstrip(value)
+ except ValueError:
+ raise OptionValueError(
+ "option %s: invalid csv value: %r" % (opt, value))
+
+def check_yn(option, opt, value):
+ """check a yn value
+ return true for yes and false for no
+ """
+ if isinstance(value, int):
+ return bool(value)
+ if value in ('y', 'yes'):
+ return True
+ if value in ('n', 'no'):
+ return False
+ msg = "option %s: invalid yn value %r, should be in (y, yes, n, no)"
+ raise OptionValueError(msg % (opt, value))
+
+def check_named(option, opt, value):
+ """check a named value
+ return a dictionary containing (name, value) associations
+ """
+ if isinstance(value, dict):
+ return value
+ values = []
+ for value in check_csv(option, opt, value):
+ if value.find('=') != -1:
+ values.append(value.split('=', 1))
+ elif value.find(':') != -1:
+ values.append(value.split(':', 1))
+ if values:
+ return dict(values)
+ msg = "option %s: invalid named value %r, should be <NAME>=<VALUE> or \
+<NAME>:<VALUE>"
+ raise OptionValueError(msg % (opt, value))
+
+def check_password(option, opt, value):
+ """check a password value (can't be empty)
+ """
+ # no actual checking, monkey patch if you want more
+ return value
+
+def check_file(option, opt, value):
+ """check a file value
+ return the filepath
+ """
+ if exists(value):
+ return value
+ msg = "option %s: file %r does not exist"
+ raise OptionValueError(msg % (opt, value))
+
+# XXX use python datetime
+def check_date(option, opt, value):
+ """check a file value
+ return the filepath
+ """
+ try:
+ return DateTime.strptime(value, "%Y/%m/%d")
+ except DateTime.Error :
+ raise OptionValueError(
+ "expected format of %s is yyyy/mm/dd" % opt)
+
+def check_color(option, opt, value):
+ """check a color value and returns it
+ /!\ does *not* check color labels (like 'red', 'green'), only
+ checks hexadecimal forms
+ """
+ # Case (1) : color label, we trust the end-user
+ if re.match('[a-z0-9 ]+$', value, re.I):
+ return value
+ # Case (2) : only accepts hexadecimal forms
+ if re.match('#[a-f0-9]{6}', value, re.I):
+ return value
+ # Else : not a color label neither a valid hexadecimal form => error
+ msg = "option %s: invalid color : %r, should be either hexadecimal \
+ value or predefined color"
+ raise OptionValueError(msg % (opt, value))
+
+def check_time(option, opt, value):
+ if isinstance(value, (int, long, float)):
+ return value
+ return apply_units(value, TIME_UNITS)
+
+def check_bytes(option, opt, value):
+ if hasattr(value, '__int__'):
+ return value
+ return apply_units(value, BYTE_UNITS)
+
+
+class Option(BaseOption):
+ """override optik.Option to add some new option types
+ """
+ TYPES = BaseOption.TYPES + ('regexp', 'csv', 'yn', 'named', 'password',
+ 'multiple_choice', 'file', 'color',
+ 'time', 'bytes')
+ ATTRS = BaseOption.ATTRS + ['hide', 'level']
+ TYPE_CHECKER = copy(BaseOption.TYPE_CHECKER)
+ TYPE_CHECKER['regexp'] = check_regexp
+ TYPE_CHECKER['csv'] = check_csv
+ TYPE_CHECKER['yn'] = check_yn
+ TYPE_CHECKER['named'] = check_named
+ TYPE_CHECKER['multiple_choice'] = check_csv
+ TYPE_CHECKER['file'] = check_file
+ TYPE_CHECKER['color'] = check_color
+ TYPE_CHECKER['password'] = check_password
+ TYPE_CHECKER['time'] = check_time
+ TYPE_CHECKER['bytes'] = check_bytes
+ if HAS_MX_DATETIME:
+ TYPES += ('date',)
+ TYPE_CHECKER['date'] = check_date
+
+ def __init__(self, *opts, **attrs):
+ BaseOption.__init__(self, *opts, **attrs)
+ if hasattr(self, "hide") and self.hide:
+ self.help = SUPPRESS_HELP
+
+ def _check_choice(self):
+ """FIXME: need to override this due to optik misdesign"""
+ if self.type in ("choice", "multiple_choice"):
+ if self.choices is None:
+ raise OptionError(
+ "must supply a list of choices for type 'choice'", self)
+ elif not isinstance(self.choices, (tuple, list)):
+ raise OptionError(
+ "choices must be a list of strings ('%s' supplied)"
+ % str(type(self.choices)).split("'")[1], self)
+ elif self.choices is not None:
+ raise OptionError(
+ "must not supply choices for type %r" % self.type, self)
+ BaseOption.CHECK_METHODS[2] = _check_choice
+
+
+ def process(self, opt, value, values, parser):
+ # First, convert the value(s) to the right type. Howl if any
+ # value(s) are bogus.
+ value = self.convert_value(opt, value)
+ if self.type == 'named':
+ existant = getattr(values, self.dest)
+ if existant:
+ existant.update(value)
+ value = existant
+ # And then take whatever action is expected of us.
+ # This is a separate method to make life easier for
+ # subclasses to add new actions.
+ return self.take_action(
+ self.action, self.dest, opt, value, values, parser)
+
+
+class OptionParser(BaseParser):
+ """override optik.OptionParser to use our Option class
+ """
+ def __init__(self, option_class=Option, *args, **kwargs):
+ BaseParser.__init__(self, option_class=Option, *args, **kwargs)
+
+ def format_option_help(self, formatter=None):
+ if formatter is None:
+ formatter = self.formatter
+ outputlevel = getattr(formatter, 'output_level', 0)
+ formatter.store_option_strings(self)
+ result = []
+ result.append(formatter.format_heading("Options"))
+ formatter.indent()
+ if self.option_list:
+ result.append(OptionContainer.format_option_help(self, formatter))
+ result.append("\n")
+ for group in self.option_groups:
+ if group.level <= outputlevel and (
+ group.description or level_options(group, outputlevel)):
+ result.append(group.format_help(formatter))
+ result.append("\n")
+ formatter.dedent()
+ # Drop the last "\n", or the header if no options or option groups:
+ return "".join(result[:-1])
+
+
+OptionGroup.level = 0
+
+def level_options(group, outputlevel):
+ return [option for option in group.option_list
+ if (getattr(option, 'level', 0) or 0) <= outputlevel
+ and not option.help is SUPPRESS_HELP]
+
+def format_option_help(self, formatter):
+ result = []
+ outputlevel = getattr(formatter, 'output_level', 0) or 0
+ for option in level_options(self, outputlevel):
+ result.append(formatter.format_option(option))
+ return "".join(result)
+OptionContainer.format_option_help = format_option_help
+
+
+class ManHelpFormatter(HelpFormatter):
+ """Format help using man pages ROFF format"""
+
+ def __init__ (self,
+ indent_increment=0,
+ max_help_position=24,
+ width=79,
+ short_first=0):
+ HelpFormatter.__init__ (
+ self, indent_increment, max_help_position, width, short_first)
+
+ def format_heading(self, heading):
+ return '.SH %s\n' % heading.upper()
+
+ def format_description(self, description):
+ return description
+
+ def format_option(self, option):
+ try:
+ optstring = option.option_strings
+ except AttributeError:
+ optstring = self.format_option_strings(option)
+ if option.help:
+ help_text = self.expand_default(option)
+ help = ' '.join([l.strip() for l in help_text.splitlines()])
+ else:
+ help = ''
+ return '''.IP "%s"
+%s
+''' % (optstring, help)
+
+ def format_head(self, optparser, pkginfo, section=1):
+ long_desc = ""
+ try:
+ pgm = optparser._get_prog_name()
+ except AttributeError:
+ # py >= 2.4.X (dunno which X exactly, at least 2)
+ pgm = optparser.get_prog_name()
+ short_desc = self.format_short_description(pgm, pkginfo.description)
+ if hasattr(pkginfo, "long_desc"):
+ long_desc = self.format_long_description(pgm, pkginfo.long_desc)
+ return '%s\n%s\n%s\n%s' % (self.format_title(pgm, section),
+ short_desc, self.format_synopsis(pgm),
+ long_desc)
+
+ def format_title(self, pgm, section):
+ date = '-'.join([str(num) for num in time.localtime()[:3]])
+ return '.TH %s %s "%s" %s' % (pgm, section, date, pgm)
+
+ def format_short_description(self, pgm, short_desc):
+ return '''.SH NAME
+.B %s
+\- %s
+''' % (pgm, short_desc.strip())
+
+ def format_synopsis(self, pgm):
+ return '''.SH SYNOPSIS
+.B %s
+[
+.I OPTIONS
+] [
+.I <arguments>
+]
+''' % pgm
+
+ def format_long_description(self, pgm, long_desc):
+ long_desc = '\n'.join([line.lstrip()
+ for line in long_desc.splitlines()])
+ long_desc = long_desc.replace('\n.\n', '\n\n')
+ if long_desc.lower().startswith(pgm):
+ long_desc = long_desc[len(pgm):]
+ return '''.SH DESCRIPTION
+.B %s
+%s
+''' % (pgm, long_desc.strip())
+
+ def format_tail(self, pkginfo):
+ tail = '''.SH SEE ALSO
+/usr/share/doc/pythonX.Y-%s/
+
+.SH BUGS
+Please report bugs on the project\'s mailing list:
+%s
+
+.SH AUTHOR
+%s <%s>
+''' % (getattr(pkginfo, 'debian_name', pkginfo.modname),
+ pkginfo.mailinglist, pkginfo.author, pkginfo.author_email)
+
+ if hasattr(pkginfo, "copyright"):
+ tail += '''
+.SH COPYRIGHT
+%s
+''' % pkginfo.copyright
+
+ return tail
+
+def generate_manpage(optparser, pkginfo, section=1, stream=sys.stdout, level=0):
+ """generate a man page from an optik parser"""
+ formatter = ManHelpFormatter()
+ formatter.output_level = level
+ formatter.parser = optparser
+ print(formatter.format_head(optparser, pkginfo, section), file=stream)
+ print(optparser.format_option_help(formatter), file=stream)
+ print(formatter.format_tail(pkginfo), file=stream)
+
+
+__all__ = ('OptionParser', 'Option', 'OptionGroup', 'OptionValueError',
+ 'Values')
« no previous file with comments | « third_party/logilab/logilab/common/modutils.py ('k') | third_party/logilab/logilab/common/optparser.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698