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

Side by Side Diff: tools/nixysa/third_party/gflags-1.0/python/gflags.py

Issue 2043006: WTF NPAPI extension. Early draft. Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 10 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 unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 #!/usr/bin/env python
2
3 # Copyright (c) 2007, Google Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are
8 # met:
9 #
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above
13 # copyright notice, this list of conditions and the following disclaimer
14 # in the documentation and/or other materials provided with the
15 # distribution.
16 # * Neither the name of Google Inc. nor the names of its
17 # contributors may be used to endorse or promote products derived from
18 # this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #
32 # ---
33 # Author: Chad Lester
34 # Design and style contributions by:
35 # Amit Patel, Bogdan Cocosel, Daniel Dulitz, Eric Tiedemann,
36 # Eric Veach, Laurence Gonsalves, Matthew Springer
37 # Code reorganized a bit by Craig Silverstein
38
39 """
40 This module is used to define and parse command line flags.
41
42 This module defines a *distributed* flag-definition policy: rather
43 than an application having to define all flags in or near main(), each
44 python module defines flags that are useful to it. When one python
45 module imports another, it gains access to the other's flags. (This
46 is implemented by having all modules share a common, global registry
47 object containing all the flag information.)
48
49 Flags are defined through the use of one of the DEFINE_xxx functions.
50 The specific function used determines how the flag is parsed, checked,
51 and optionally type-converted, when it's seen on the command line.
52
53
54 IMPLEMENTATION: DEFINE_* creates a 'Flag' object and registers it with
55 a 'FlagValues' object (typically the global FlagValues FLAGS, defined
56 here). The 'FlagValues' object can scan the command line arguments
57 and pass flag arguments to the corresponding 'Flag' objects for
58 value-checking and type conversion. The converted flag values are
59 available as members of the 'FlagValues' object.
60
61 Code can access the flag through a FlagValues object, for instancee
62 gflags.FLAGS.myflag. Typically, the __main__ module passes the
63 command line arguments to gflags.FLAGS for parsing.
64
65 At bottom, this module calls getopt(), so getopt functionality is
66 supported, including short- and long-style flags, and the use of -- to
67 terminate flags.
68
69 Methods defined by the flag module will throw 'FlagsError' exceptions.
70 The exception argument will be a human-readable string.
71
72
73 FLAG TYPES: This is a list of the DEFINE_*'s that you can do. All
74 flags take a name, default value, help-string, and optional 'short'
75 name (one-letter name). Some flags have other arguments, which are
76 described with the flag.
77
78 DEFINE_string: takes any input, and interprets it as a string.
79
80 DEFINE_boolean: typically does not take an argument: say --myflag to
81 set FLAGS.myflag to true, or --nomyflag to set
82 FLAGS.myflag to false. Alternately, you can say
83 --myflag=true or --myflag=t or --myflag=1 or
84 --myflag=false or --myflag=f or --myflag=0
85
86 DEFINE_float: takes an input and interprets it as a floating point
87 number. Takes optional args lower_bound and
88 upper_bound; if the number specified on the command line
89 is out of range, it will raise a FlagError.
90
91 DEFINE_integer: takes an input and interprets it as an integer. Takes
92 optional args lower_bound and upper_bound as for floats.
93
94 DEFINE_enum: takes a list of strings which represents legal values. If
95 the command-line value is not in this list, raise a flag
96 error. Otherwise, assign to FLAGS.flag as a string.
97
98 DEFINE_list: Takes a comma-separated list of strings on the commandline.
99 Stores them in a python list object.
100
101 DEFINE_spaceseplist: Takes a space-separated list of strings on the
102 commandline. Stores them in a python list object.
103
104 DEFINE_multistring: The same as DEFINE_string, except the flag can be
105 specified more than once on the commandline. The
106 result is a python list object (list of strings),
107 even if the flag is only on the command line once.
108
109 DEFINE_multi_int: The same as DEFINE_integer, except the flag can be
110 specified more than once on the commandline. The
111 result is a python list object (list of ints),
112 even if the flag is only on the command line once.
113
114
115 SPECIAL FLAGS: There are a few flags that have special meaning:
116 --help (or -?) prints a list of all the flags in a human-readable fashion
117 --helpshort prints a list of all the flags in the 'main' .py file only
118 --flagfile=foo read flags from foo.
119 --undefok=f1,f2 ignore unrecognized option errors for f1,f2
120 -- as in getopt(), terminates flag-processing
121
122 Note on --flagfile:
123
124 Flags may be loaded from text files in addition to being specified on
125 the commandline.
126
127 Any flags you don't feel like typing, throw them in a file, one flag
128 per line, for instance:
129 --myflag=myvalue
130 --nomyboolean_flag
131 You then specify your file with the special flag
132 '--flagfile=somefile'. You CAN recursively nest flagfile= tokens OR
133 use multiple files on the command line. Lines beginning with a single
134 hash '#' or a double slash '//' are comments in your flagfile.
135
136 Any flagfile=<file> will be interpreted as having a relative path from
137 the current working directory rather than from the place the file was
138 included from:
139 myPythonScript.py --flagfile=config/somefile.cfg
140
141 If somefile.cfg includes further --flagfile= directives, these will be
142 referenced relative to the original CWD, not from the directory the
143 including flagfile was found in!
144
145 The caveat applies to people who are including a series of nested
146 files in a different dir than they are executing out of. Relative
147 path names are always from CWD, not from the directory of the parent
148 include flagfile. We do now support '~' expanded directory names.
149
150 Absolute path names ALWAYS work!
151
152
153 EXAMPLE USAGE:
154
155 import gflags
156 FLAGS = gflags.FLAGS
157
158 # Flag names are globally defined! So in general, we need to be
159 # careful to pick names that are unlikely to be used by other libraries.
160 # If there is a conflict, we'll get an error at import time.
161 gflags.DEFINE_string('name', 'Mr. President', 'your name')
162 gflags.DEFINE_integer('age', None, 'your age in years', lower_bound=0)
163 gflags.DEFINE_boolean('debug', 0, 'produces debugging output')
164 gflags.DEFINE_enum('gender', 'male', ['male', 'female'], 'your gender')
165
166 def main(argv):
167 try:
168 argv = FLAGS(argv) # parse flags
169 except gflags.FlagsError, e:
170 print '%s\\nUsage: %s ARGS\\n%s' % (e, sys.argv[0], FLAGS)
171 sys.exit(1)
172 if FLAGS.debug: print 'non-flag arguments:', argv
173 print 'Happy Birthday', FLAGS.name
174 if FLAGS.age is not None:
175 print 'You are a %s, who is %d years old' % (FLAGS.gender, FLAGS.age)
176
177 if __name__ == '__main__':
178 main(sys.argv)
179 """
180
181 import getopt
182 import os
183 import re
184 import sys
185
186 # Are we running at least python 2.2?
187 try:
188 if tuple(sys.version_info[:3]) < (2,2,0):
189 raise NotImplementedError("requires python 2.2.0 or later")
190 except AttributeError: # a very old python, that lacks sys.version_info
191 raise NotImplementedError("requires python 2.2.0 or later")
192
193 # If we're not running at least python 2.2.1, define True, False, and bool.
194 # Thanks, Guido, for the code.
195 try:
196 True, False, bool
197 except NameError:
198 False = 0
199 True = 1
200 def bool(x):
201 if x:
202 return True
203 else:
204 return False
205
206 # Are we running under pychecker?
207 _RUNNING_PYCHECKER = 'pychecker.python' in sys.modules
208
209
210 def _GetCallingModule():
211 """
212 Get the name of the module that's calling into this module; e.g.,
213 the module calling a DEFINE_foo... function.
214 """
215 # Walk down the stack to find the first globals dict that's not ours.
216 for depth in range(1, sys.getrecursionlimit()):
217 if not sys._getframe(depth).f_globals is globals():
218 return __GetModuleName(sys._getframe(depth).f_globals)
219 raise AssertionError, "No module was found"
220
221
222 # module exceptions:
223 class FlagsError(Exception):
224 """The base class for all flags errors"""
225
226 class DuplicateFlag(FlagsError):
227 """Raised if there is a flag naming conflict"""
228
229 # A DuplicateFlagError conveys more information than
230 # a DuplicateFlag. Since there are external modules
231 # that create DuplicateFlags, the interface to
232 # DuplicateFlag shouldn't change.
233 class DuplicateFlagError(DuplicateFlag):
234 def __init__(self, flagname, flag_values):
235 self.flagname = flagname
236 message = "The flag '%s' is defined twice." % self.flagname
237 flags_by_module = flag_values.__dict__['__flags_by_module']
238 for module in flags_by_module:
239 for flag in flags_by_module[module]:
240 if flag.name == flagname:
241 message = message + " First from " + module + ","
242 break
243 message = message + " Second from " + _GetCallingModule()
244 Exception.__init__(self, message)
245
246 class IllegalFlagValue(FlagsError): "The flag command line argument is illegal"
247
248 class UnrecognizedFlag(FlagsError):
249 """Raised if a flag is unrecognized"""
250
251 # An UnrecognizedFlagError conveys more information than
252 # an UnrecognizedFlag. Since there are external modules
253 # that create DuplicateFlags, the interface to
254 # DuplicateFlag shouldn't change.
255 class UnrecognizedFlagError(UnrecognizedFlag):
256 def __init__(self, flagname):
257 self.flagname = flagname
258 Exception.__init__(self, "Unknown command line flag '%s'" % flagname)
259
260 # Global variable used by expvar
261 _exported_flags = {}
262 _help_width = 80 # width of help output
263
264
265 def GetHelpWidth():
266 """
267 Length of help to be used in TextWrap
268 """
269 global _help_width
270 return _help_width
271
272
273 def CutCommonSpacePrefix(text):
274 """
275 Cut out a common space prefix. If the first line does not start with a space
276 it is left as is and only in the remaining lines a common space prefix is
277 being searched for. That means the first line will stay untouched. This is
278 especially useful to turn doc strings into help texts. This is because some
279 people prefer to have the doc comment start already after the apostrophy and
280 then align the following lines while others have the apostrophies on a
281 seperately line. The function also drops trailing empty lines and ignores
282 empty lines following the initial content line while calculating the initial
283 common whitespace.
284
285 Args:
286 text: text to work on
287
288 Returns:
289 the resulting text
290 """
291 text_lines = text.splitlines()
292 # Drop trailing empty lines
293 while text_lines and not text_lines[-1]:
294 text_lines = text_lines[:-1]
295 if text_lines:
296 # We got some content, is the first line starting with a space?
297 if text_lines[0] and text_lines[0][0].isspace():
298 text_first_line = []
299 else:
300 text_first_line = [text_lines.pop(0)]
301 # Calculate length of common leading whitesppace (only over content lines)
302 common_prefix = os.path.commonprefix([line for line in text_lines if line])
303 space_prefix_len = len(common_prefix) - len(common_prefix.lstrip())
304 # If we have a common space prefix, drop it from all lines
305 if space_prefix_len:
306 for index in xrange(len(text_lines)):
307 if text_lines[index]:
308 text_lines[index] = text_lines[index][space_prefix_len:]
309 return '\n'.join(text_first_line + text_lines)
310 return ''
311
312
313 def TextWrap(text, length=None, indent='', firstline_indent=None, tabs=' '):
314 """
315 Wrap a given text to a maximum line length and return it.
316 We turn lines that only contain whitespace into empty lines.
317 We keep new lines.
318 We also keep tabs (e.g. we do not treat tabs as spaces).
319
320 Args:
321 text: text to wrap
322 length: maximum length of a line, includes indentation
323 if this is None then use GetHelpWidth()
324 indent: indent for all but first line
325 firstline_indent: indent for first line, if None then fall back to indent
326 tabs: replacement for tabs
327
328 Returns:
329 wrapped text
330
331 Raises:
332 CommandsError: if indent not shorter than length
333 CommandsError: if firstline_indent not shorter than length
334 """
335 # Get defaults where callee used None
336 if length is None:
337 length = GetHelpWidth()
338 if indent is None:
339 indent = ''
340 if len(indent) >= length:
341 raise CommandsError('Indent must be shorter than length')
342 # In line we will be holding the current line which is to be started with
343 # indent (or firstline_indent if available) and then appended with words.
344 if firstline_indent is None:
345 firstline_indent = ''
346 line = indent
347 else:
348 line = firstline_indent
349 if len(firstline_indent) >= length:
350 raise CommandsError('First iline indent must be shorter than length')
351
352 # If the callee does not care about tabs we simply convert them to spaces
353 # If callee wanted tabs to be single space then we do that already here.
354 if not tabs or tabs == ' ':
355 text = text.replace('\t', ' ')
356 else:
357 tabs_are_whitespace = not tabs.strip()
358
359 line_regex = re.compile('([ ]*)(\t*)([^ \t]+)', re.MULTILINE)
360
361 # Split the text into lines and the lines with the regex above. The resulting
362 # lines are collected in result[]. For each split we get the spaces, the tabs
363 # and the next non white space (e.g. next word).
364 result = []
365 for text_line in text.splitlines():
366 # Store result length so we can find out whether processing the next line
367 # gave any new content
368 old_result_len = len(result)
369 # Process next line with line_regex. For optimization we do an rstrip().
370 # - process tabs (changes either line or word, see below)
371 # - process word (first try to squeeze on line, then wrap or force wrap)
372 # Spaces found on the line are ignored, they get added while wrapping as
373 # needed.
374 for spaces, current_tabs, word in line_regex.findall(text_line.rstrip()):
375 # If tabs weren't converted to spaces, handle them now
376 if current_tabs:
377 # If the last thing we added was a space anyway then drop it. But
378 # let's not get rid of the indentation.
379 if (((result and line != indent) or
380 (not result and line != firstline_indent)) and line[-1] == ' '):
381 line = line[:-1]
382 # Add the tabs, if that means adding whitespace, just add it at the
383 # line, the rstrip() code while shorten the line down if necessary
384 if tabs_are_whitespace:
385 line += tabs * len(current_tabs)
386 else:
387 # if not all tab replacement is whitespace we prepend it to the word
388 word = tabs * len(current_tabs) + word
389 # Handle the case where word cannot be squeezed onto current last line
390 if len(line) + len(word) > length and len(indent) + len(word) <= length:
391 result.append(line.rstrip())
392 line = indent + word
393 word = ''
394 # No space left on line or can we append a space?
395 if len(line) + 1 >= length:
396 result.append(line.rstrip())
397 line = indent
398 else:
399 line += ' '
400 # Add word and shorten it up to allowed line length. Restart next line
401 # with indent and repeat, or add a space if we're done (word finished)
402 # This deals with words that caanot fit on one line (e.g. indent + word
403 # longer than allowed line length).
404 while len(line) + len(word) >= length:
405 line += word
406 result.append(line[:length])
407 word = line[length:]
408 line = indent
409 # Default case, simply append the word and a space
410 if word:
411 line += word + ' '
412 # End of input line. If we have content we finish the line. If the
413 # current line is just the indent but we had content in during this
414 # original line then we need to add an emoty line.
415 if (result and line != indent) or (not result and line != firstline_indent):
416 result.append(line.rstrip())
417 elif len(result) == old_result_len:
418 result.append('')
419 line = indent
420
421 return '\n'.join(result)
422
423
424 def DocToHelp(doc):
425 """
426 Takes a __doc__ string and reformats it as help.
427 """
428 # Get rid of starting and ending white space. Using lstrip() or even strip()
429 # could drop more than maximum of first line and right space of last line.
430 doc = doc.strip()
431
432 # Get rid of all empty lines
433 whitespace_only_line = re.compile('^[ \t]+$', re.M)
434 doc = whitespace_only_line.sub('', doc)
435
436 # Cut out common space at line beginnings
437 doc = CutCommonSpacePrefix(doc)
438
439 # Just like this module's comment, comments tend to be aligned somehow.
440 # In other words they all start with the same amount of white space
441 # 1) keep double new lines
442 # 2) keep ws after new lines if not empty line
443 # 3) all other new lines shall be changed to a space
444 # Solution: Match new lines between non white space and replace with space.
445 doc = re.sub('(?<=\S)\n(?=\S)', ' ', doc, re.M)
446
447 return doc
448
449
450 def __GetModuleName(globals_dict):
451 """Given a globals dict, find the module in which it's defined."""
452 for name, module in sys.modules.iteritems():
453 if getattr(module, '__dict__', None) is globals_dict:
454 if name == '__main__':
455 return sys.argv[0]
456 return name
457 raise AssertionError, "No module was found"
458
459 def _GetMainModule():
460 """Get the module name from which execution started."""
461 for depth in range(1, sys.getrecursionlimit()):
462 try:
463 globals_of_main = sys._getframe(depth).f_globals
464 except ValueError:
465 return __GetModuleName(globals_of_main)
466 raise AssertionError, "No module was found"
467
468
469 class FlagValues:
470 """
471 Used as a registry for 'Flag' objects.
472
473 A 'FlagValues' can then scan command line arguments, passing flag
474 arguments through to the 'Flag' objects that it owns. It also
475 provides easy access to the flag values. Typically only one
476 'FlagValues' object is needed by an application: gflags.FLAGS
477
478 This class is heavily overloaded:
479
480 'Flag' objects are registered via __setitem__:
481 FLAGS['longname'] = x # register a new flag
482
483 The .value member of the registered 'Flag' objects can be accessed as
484 members of this 'FlagValues' object, through __getattr__. Both the
485 long and short name of the original 'Flag' objects can be used to
486 access its value:
487 FLAGS.longname # parsed flag value
488 FLAGS.x # parsed flag value (short name)
489
490 Command line arguments are scanned and passed to the registered 'Flag'
491 objects through the __call__ method. Unparsed arguments, including
492 argv[0] (e.g. the program name) are returned.
493 argv = FLAGS(sys.argv) # scan command line arguments
494
495 The original registered Flag objects can be retrieved through the use
496 of the dictionary-like operator, __getitem__:
497 x = FLAGS['longname'] # access the registered Flag object
498
499 The str() operator of a 'FlagValues' object provides help for all of
500 the registered 'Flag' objects.
501 """
502
503 def __init__(self):
504 # Since everything in this class is so heavily overloaded,
505 # the only way of defining and using fields is to access __dict__
506 # directly.
507 self.__dict__['__flags'] = {}
508 self.__dict__['__flags_by_module'] = {} # A dict module -> list of flag
509
510 def FlagDict(self):
511 return self.__dict__['__flags']
512
513 def _RegisterFlagByModule(self, module_name, flag):
514 """We keep track of which flag is defined by which module so that
515 we can later sort the flags by module.
516 """
517 flags_by_module = self.__dict__['__flags_by_module']
518 flags_by_module.setdefault(module_name, []).append(flag)
519
520 def AppendFlagValues(self, flag_values):
521 """Append flags registered in another FlagValues instance.
522
523 Args:
524 flag_values: registry to copy from
525 """
526 for flag_name, flag in flag_values.FlagDict().iteritems():
527 # Flags with shortnames will appear here twice (once with under
528 # its normal name, and again with its short name). To prevent
529 # problems (DuplicateFlagError) that occur when doubly
530 # registering flags, we perform a check to make sure that the
531 # entry we're looking at is for its normal name.
532 if flag_name == flag.name:
533 self[flag_name] = flag
534
535 def __setitem__(self, name, flag):
536 """
537 Register a new flag variable.
538 """
539 fl = self.FlagDict()
540 if not isinstance(flag, Flag):
541 raise IllegalFlagValue, flag
542 if not isinstance(name, type("")):
543 raise FlagsError, "Flag name must be a string"
544 if len(name) == 0:
545 raise FlagsError, "Flag name cannot be empty"
546 # If running under pychecker, duplicate keys are likely to be defined.
547 # Disable check for duplicate keys when pycheck'ing.
548 if (fl.has_key(name) and not flag.allow_override and
549 not fl[name].allow_override and not _RUNNING_PYCHECKER):
550 raise DuplicateFlagError(name, self)
551 short_name = flag.short_name
552 if short_name is not None:
553 if (fl.has_key(short_name) and not flag.allow_override and
554 not fl[short_name].allow_override and not _RUNNING_PYCHECKER):
555 raise DuplicateFlagError(short_name, self)
556 fl[short_name] = flag
557 fl[name] = flag
558 global _exported_flags
559 _exported_flags[name] = flag
560
561 def __getitem__(self, name):
562 """
563 Retrieve the flag object.
564 """
565 return self.FlagDict()[name]
566
567 def __getattr__(self, name):
568 """
569 Retrieve the .value member of a flag object.
570 """
571 fl = self.FlagDict()
572 if not fl.has_key(name):
573 raise AttributeError, name
574 return fl[name].value
575
576 def __setattr__(self, name, value):
577 """
578 Set the .value member of a flag object.
579 """
580 fl = self.FlagDict()
581 fl[name].value = value
582 return value
583
584 def __delattr__(self, name):
585 """
586 Delete a previously-defined flag from a flag object.
587 """
588 fl = self.FlagDict()
589 if not fl.has_key(name):
590 raise AttributeError, name
591 del fl[name]
592
593 def SetDefault(self, name, value):
594 """
595 Change the default value of the named flag object.
596 """
597 fl = self.FlagDict()
598 if not fl.has_key(name):
599 raise AttributeError, name
600 fl[name].SetDefault(value)
601
602 def __contains__(self, name):
603 """
604 Return True if name is a value (flag) in the dict.
605 """
606 return name in self.FlagDict()
607
608 has_key = __contains__ # a synonym for __contains__()
609
610 def __iter__(self):
611 return self.FlagDict().iterkeys()
612
613 def __call__(self, argv):
614 """
615 Searches argv for flag arguments, parses them and then sets the flag
616 values as attributes of this FlagValues object. All unparsed
617 arguments are returned. Flags are parsed using the GNU Program
618 Argument Syntax Conventions, using getopt:
619
620 http://www.gnu.org/software/libc/manual/html_mono/libc.html#Getopt
621
622 Args:
623 argv: argument list. Can be of any type that may be converted to a list.
624
625 Returns:
626 The list of arguments not parsed as options, including argv[0]
627
628 Raises:
629 FlagsError: on any parsing error
630 """
631 # Support any sequence type that can be converted to a list
632 argv = list(argv)
633
634 shortopts = ""
635 longopts = []
636
637 fl = self.FlagDict()
638
639 # This pre parses the argv list for --flagfile=<> options.
640 argv = self.ReadFlagsFromFiles(argv)
641
642 # Correct the argv to support the google style of passing boolean
643 # parameters. Boolean parameters may be passed by using --mybool,
644 # --nomybool, --mybool=(true|false|1|0). getopt does not support
645 # having options that may or may not have a parameter. We replace
646 # instances of the short form --mybool and --nomybool with their
647 # full forms: --mybool=(true|false).
648 original_argv = list(argv) # list() makes a copy
649 shortest_matches = None
650 for name, flag in fl.items():
651 if not flag.boolean:
652 continue
653 if shortest_matches is None:
654 # Determine the smallest allowable prefix for all flag names
655 shortest_matches = self.ShortestUniquePrefixes(fl)
656 no_name = 'no' + name
657 prefix = shortest_matches[name]
658 no_prefix = shortest_matches[no_name]
659
660 # Replace all occurences of this boolean with extended forms
661 for arg_idx in range(1, len(argv)):
662 arg = argv[arg_idx]
663 if arg.find('=') >= 0: continue
664 if arg.startswith('--'+prefix) and ('--'+name).startswith(arg):
665 argv[arg_idx] = ('--%s=true' % name)
666 elif arg.startswith('--'+no_prefix) and ('--'+no_name).startswith(arg):
667 argv[arg_idx] = ('--%s=false' % name)
668
669 # Loop over all of the flags, building up the lists of short options and
670 # long options that will be passed to getopt. Short options are
671 # specified as a string of letters, each letter followed by a colon if it
672 # takes an argument. Long options are stored in an array of strings.
673 # Each string ends with an '=' if it takes an argument.
674 for name, flag in fl.items():
675 longopts.append(name + "=")
676 if len(name) == 1: # one-letter option: allow short flag type also
677 shortopts += name
678 if not flag.boolean:
679 shortopts += ":"
680
681 longopts.append('undefok=')
682 undefok_flags = []
683
684 # In case --undefok is specified, loop to pick up unrecognized
685 # options one by one.
686 unrecognized_opts = []
687 args = argv[1:]
688 while True:
689 try:
690 optlist, unparsed_args = getopt.getopt(args, shortopts, longopts)
691 break
692 except getopt.GetoptError, e:
693 if not e.opt or e.opt in fl:
694 # Not an unrecognized option, reraise the exception as a FlagsError
695 raise FlagsError(e)
696 # Handle an unrecognized option.
697 unrecognized_opts.append(e.opt)
698 # Remove offender from args and try again
699 for arg_index in range(len(args)):
700 if ((args[arg_index] == '--' + e.opt) or
701 (args[arg_index] == '-' + e.opt) or
702 args[arg_index].startswith('--' + e.opt + '=')):
703 args = args[0:arg_index] + args[arg_index+1:]
704 break
705 else:
706 # We should have found the option, so we don't expect to get
707 # here. We could assert, but raising the original exception
708 # might work better.
709 raise FlagsError(e)
710
711 for name, arg in optlist:
712 if name == '--undefok':
713 undefok_flags.extend(arg.split(','))
714 continue
715 if name.startswith('--'):
716 # long option
717 name = name[2:]
718 short_option = 0
719 else:
720 # short option
721 name = name[1:]
722 short_option = 1
723 if fl.has_key(name):
724 flag = fl[name]
725 if flag.boolean and short_option: arg = 1
726 flag.Parse(arg)
727
728 # If there were unrecognized options, raise an exception unless
729 # the options were named via --undefok.
730 for opt in unrecognized_opts:
731 if opt not in undefok_flags:
732 raise UnrecognizedFlagError(opt)
733
734 if unparsed_args:
735 # unparsed_args becomes the first non-flag detected by getopt to
736 # the end of argv. Because argv may have been modified above,
737 # return original_argv for this region.
738 return argv[:1] + original_argv[-len(unparsed_args):]
739 else:
740 return argv[:1]
741
742 def Reset(self):
743 """
744 Reset the values to the point before FLAGS(argv) was called.
745 """
746 for f in self.FlagDict().values():
747 f.Unparse()
748
749 def RegisteredFlags(self):
750 """
751 Return a list of all registered flags.
752 """
753 return self.FlagDict().keys()
754
755 def FlagValuesDict(self):
756 """
757 Return a dictionary with flag names as keys and flag values as values.
758 """
759 flag_values = {}
760
761 for flag_name in self.RegisteredFlags():
762 flag = self.FlagDict()[flag_name]
763 flag_values[flag_name] = flag.value
764
765 return flag_values
766
767 def __str__(self):
768 """
769 Generate a help string for all known flags.
770 """
771 return self.GetHelp()
772
773 def GetHelp(self, prefix=""):
774 """
775 Generate a help string for all known flags.
776 """
777 helplist = []
778
779 flags_by_module = self.__dict__['__flags_by_module']
780 if flags_by_module:
781
782 modules = flags_by_module.keys()
783 modules.sort()
784
785 # Print the help for the main module first, if possible.
786 main_module = _GetMainModule()
787 if main_module in modules:
788 modules.remove(main_module)
789 modules = [ main_module ] + modules
790
791 for module in modules:
792 self.__RenderOurModuleFlags(module, helplist)
793
794 self.__RenderModuleFlags('google3.pyglib.flags',
795 _SPECIAL_FLAGS.FlagDict().values(),
796 helplist)
797
798 else:
799 # Just print one long list of flags.
800 self.__RenderFlagList(
801 self.FlagDict().values() + _SPECIAL_FLAGS.FlagDict().values(),
802 helplist, prefix)
803
804 return '\n'.join(helplist)
805
806 def __RenderModuleFlags(self, module, flags, output_lines, prefix=""):
807 """
808 Generate a help string for a given module.
809 """
810 output_lines.append('\n%s%s:' % (prefix, module))
811 self.__RenderFlagList(flags, output_lines, prefix + " ")
812
813 def __RenderOurModuleFlags(self, module, output_lines, prefix=""):
814 """
815 Generate a help string for a given module.
816 """
817 flags_by_module = self.__dict__['__flags_by_module']
818 if module in flags_by_module:
819 self.__RenderModuleFlags(module, flags_by_module[module],
820 output_lines, prefix)
821
822 def MainModuleHelp(self):
823 """
824 Generate a help string for all known flags of the main module.
825 """
826 helplist = []
827 self.__RenderOurModuleFlags(_GetMainModule(), helplist)
828 return '\n'.join(helplist)
829
830 def __RenderFlagList(self, flaglist, output_lines, prefix=" "):
831 fl = self.FlagDict()
832 special_fl = _SPECIAL_FLAGS.FlagDict()
833 flaglist = [(flag.name, flag) for flag in flaglist]
834 flaglist.sort()
835 flagset = {}
836 for (name, flag) in flaglist:
837 # It's possible this flag got deleted or overridden since being
838 # registered in the per-module flaglist. Check now against the
839 # canonical source of current flag information, the FlagDict.
840 if fl.get(name, None) != flag and special_fl.get(name, None) != flag:
841 # a different flag is using this name now
842 continue
843 # only print help once
844 if flagset.has_key(flag): continue
845 flagset[flag] = 1
846 flaghelp = ""
847 if flag.short_name: flaghelp += "-%s," % flag.short_name
848 if flag.boolean:
849 flaghelp += "--[no]%s" % flag.name + ":"
850 else:
851 flaghelp += "--%s" % flag.name + ":"
852 flaghelp += " "
853 if flag.help:
854 flaghelp += flag.help
855 flaghelp = TextWrap(flaghelp, indent=prefix+" ",
856 firstline_indent=prefix)
857 if flag.default_as_str:
858 flaghelp += "\n"
859 flaghelp += TextWrap("(default: %s)" % flag.default_as_str,
860 indent=prefix+" ")
861 if flag.parser.syntactic_help:
862 flaghelp += "\n"
863 flaghelp += TextWrap("(%s)" % flag.parser.syntactic_help,
864 indent=prefix+" ")
865 output_lines.append(flaghelp)
866
867 def get(self, name, default):
868 """
869 Retrieve the .value member of a flag object, or default if .value is None
870 """
871
872 value = self.__getattr__(name)
873 if value is not None: # Can't do if not value, b/c value might be '0' or ""
874 return value
875 else:
876 return default
877
878 def ShortestUniquePrefixes(self, fl):
879 """
880 Returns a dictionary mapping flag names to their shortest unique prefix.
881 """
882 # Sort the list of flag names
883 sorted_flags = []
884 for name, flag in fl.items():
885 sorted_flags.append(name)
886 if flag.boolean:
887 sorted_flags.append('no%s' % name)
888 sorted_flags.sort()
889
890 # For each name in the sorted list, determine the shortest unique prefix
891 # by comparing itself to the next name and to the previous name (the latter
892 # check uses cached info from the previous loop).
893 shortest_matches = {}
894 prev_idx = 0
895 for flag_idx in range(len(sorted_flags)):
896 curr = sorted_flags[flag_idx]
897 if flag_idx == (len(sorted_flags) - 1):
898 next = None
899 else:
900 next = sorted_flags[flag_idx+1]
901 next_len = len(next)
902 for curr_idx in range(len(curr)):
903 if (next is None
904 or curr_idx >= next_len
905 or curr[curr_idx] != next[curr_idx]):
906 # curr longer than next or no more chars in common
907 shortest_matches[curr] = curr[:max(prev_idx, curr_idx) + 1]
908 prev_idx = curr_idx
909 break
910 else:
911 # curr shorter than (or equal to) next
912 shortest_matches[curr] = curr
913 prev_idx = curr_idx + 1 # next will need at least one more char
914 return shortest_matches
915
916 def __IsFlagFileDirective(self, flag_string):
917 """ Detects the --flagfile= token.
918 Takes a string which might contain a '--flagfile=<foo>' directive.
919 Returns a Boolean.
920 """
921 if isinstance(flag_string, type("")):
922 if flag_string.startswith('--flagfile='):
923 return 1
924 elif flag_string == '--flagfile':
925 return 1
926 elif flag_string.startswith('-flagfile='):
927 return 1
928 elif flag_string == '-flagfile':
929 return 1
930 else:
931 return 0
932 return 0
933
934 def ExtractFilename(self, flagfile_str):
935 """Function to remove the --flagfile= (or variant) and return just the
936 filename part. We can get strings that look like:
937 --flagfile=foo, -flagfile=foo.
938 The case of --flagfile foo and -flagfile foo shouldn't be hitting this
939 function, as they are dealt with in the level above this funciton.
940 """
941 if flagfile_str.startswith('--flagfile='):
942 return os.path.expanduser((flagfile_str[(len('--flagfile=')):]).strip())
943 elif flagfile_str.startswith('-flagfile='):
944 return os.path.expanduser((flagfile_str[(len('-flagfile=')):]).strip())
945 else:
946 raise FlagsError('Hit illegal --flagfile type: %s' % flagfile_str)
947 return ''
948
949
950 def __GetFlagFileLines(self, filename, parsed_file_list):
951 """Function to open a flag file, return its useful (!=comments,etc) lines.
952 Takes:
953 A filename to open and read
954 A list of files we have already read THAT WILL BE CHANGED
955 Returns:
956 List of strings. See the note below.
957
958 NOTE(springer): This function checks for a nested --flagfile=<foo>
959 tag and handles the lower file recursively. It returns a list off
960 all the lines that _could_ contain command flags. This is
961 EVERYTHING except whitespace lines and comments (lines starting
962 with '#' or '//').
963 """
964 line_list = [] # All line from flagfile.
965 flag_line_list = [] # Subset of lines w/o comments, blanks, flagfile= tags.
966 try:
967 file_obj = open(filename, 'r')
968 except IOError, e_msg:
969 print e_msg
970 print 'ERROR:: Unable to open flagfile: %s' % (filename)
971 return flag_line_list
972
973 line_list = file_obj.readlines()
974 file_obj.close()
975 parsed_file_list.append(filename)
976
977 # This is where we check each line in the file we just read.
978 for line in line_list:
979 if line.isspace():
980 pass
981 # Checks for comment (a line that starts with '#').
982 elif (line.startswith('#') or line.startswith('//')):
983 pass
984 # Checks for a nested "--flagfile=<bar>" flag in the current file.
985 # If we find one, recursively parse down into that file.
986 elif self.__IsFlagFileDirective(line):
987 sub_filename = self.ExtractFilename(line)
988 # We do a little safety check for reparsing a file we've already done.
989 if not sub_filename in parsed_file_list:
990 included_flags = self.__GetFlagFileLines(sub_filename, parsed_file_lis t)
991 flag_line_list.extend(included_flags)
992 else: # Case of hitting a circularly included file.
993 print >>sys.stderr, ('Warning: Hit circular flagfile dependency: %s'
994 % sub_filename)
995 else:
996 # Any line that's not a comment or a nested flagfile should
997 # get copied into 2nd position, this leaves earlier arguements
998 # further back in the list, which makes them have higher priority.
999 flag_line_list.append(line.strip())
1000 return flag_line_list
1001
1002 def ReadFlagsFromFiles(self, argv):
1003 """Process command line args, but also allow args to be read from file
1004 Usage:
1005 Takes: a list of strings, usually sys.argv, which may contain one or more
1006 flagfile directives of the form --flagfile="./filename"
1007 References: Global gflags.FLAG class instance
1008 Returns: a new list which has the original list combined with what we
1009 read from any flagfile(s).
1010
1011 This function should be called before the normal FLAGS(argv) call.
1012 This function simply scans the input list for a flag that looks like:
1013 --flagfile=<somefile>
1014 Then it opens <somefile>, reads all valid key and value pairs and inserts
1015 them into the input list between the first item of the list and any
1016 subsequent items in the list.
1017 Note that your application's flags are still defined the usual way using
1018 gflags DEFINE_flag() type functions.
1019
1020 Notes (assuming we're getting a commandline of some sort as our input):
1021 --> Any flags on the command line we were passed in _should_ always take
1022 precedence!!!
1023 --> a further "--flagfile=<otherfile.cfg>" CAN be nested in a flagfile.
1024 It will be processed after the parent flag file is done.
1025 --> For duplicate flags, first one we hit should "win".
1026 --> In a flagfile, a line beginning with # or // is a comment
1027 --> Entirely blank lines _should_ be ignored
1028 """
1029 parsed_file_list = []
1030 rest_of_args = argv
1031 new_argv = []
1032 while rest_of_args:
1033 current_arg = rest_of_args[0]
1034 rest_of_args = rest_of_args[1:]
1035 if self.__IsFlagFileDirective(current_arg):
1036 # This handles the case of -(-)flagfile foo. Inthis case the next arg
1037 # really is part of this one.
1038 if current_arg == '--flagfile' or current_arg =='-flagfile':
1039 if not rest_of_args:
1040 raise IllegalFlagValue, '--flagfile with no argument'
1041 flag_filename = os.path.expanduser(rest_of_args[0])
1042 rest_of_args = rest_of_args[1:]
1043 else:
1044 # This handles the case of (-)-flagfile=foo.
1045 flag_filename = self.ExtractFilename(current_arg)
1046 new_argv = (new_argv[:1] +
1047 self.__GetFlagFileLines(flag_filename, parsed_file_list) +
1048 new_argv[1:])
1049 else:
1050 new_argv.append(current_arg)
1051
1052 return new_argv
1053
1054 def FlagsIntoString(self):
1055 """
1056 Retrieve a string version of all the flags with assignments stored
1057 in this FlagValues object. Should mirror the behavior of the c++
1058 version of FlagsIntoString. Each flag assignment is seperated by
1059 a newline.
1060 """
1061 s = ''
1062 for flag in self.FlagDict().values():
1063 if flag.value is not None:
1064 s += flag.Serialize() + '\n'
1065 return s
1066
1067 def AppendFlagsIntoFile(self, filename):
1068 """
1069 Appends all flags found in this FlagInfo object to the file
1070 specified. Output will be in the format of a flagfile. This
1071 should mirror the behavior of the c++ version of
1072 AppendFlagsIntoFile.
1073 """
1074 out_file = open(filename, 'a')
1075 out_file.write(self.FlagsIntoString())
1076 out_file.close()
1077 # end of FlagValues definition
1078
1079 # The global FlagValues instance
1080 FLAGS = FlagValues()
1081
1082
1083 class Flag:
1084 """
1085 'Flag' objects define the following fields:
1086 .name - the name for this flag
1087 .default - the default value for this flag
1088 .default_as_str - default value as repr'd string, e.g., "'true'" (or None)
1089 .value - the most recent parsed value of this flag; set by Parse()
1090 .help - a help string or None if no help is available
1091 .short_name - the single letter alias for this flag (or None)
1092 .boolean - if 'true', this flag does not accept arguments
1093 .present - true if this flag was parsed from command line flags.
1094 .parser - an ArgumentParser object
1095 .serializer - an ArgumentSerializer object
1096 .allow_override - the flag may be redefined without raising an error
1097
1098 The only public method of a 'Flag' object is Parse(), but it is
1099 typically only called by a 'FlagValues' object. The Parse() method is
1100 a thin wrapper around the 'ArgumentParser' Parse() method. The parsed
1101 value is saved in .value, and the .present member is updated. If this
1102 flag was already present, a FlagsError is raised.
1103
1104 Parse() is also called during __init__ to parse the default value and
1105 initialize the .value member. This enables other python modules to
1106 safely use flags even if the __main__ module neglects to parse the
1107 command line arguments. The .present member is cleared after __init__
1108 parsing. If the default value is set to None, then the __init__
1109 parsing step is skipped and the .value member is initialized to None.
1110
1111 Note: The default value is also presented to the user in the help
1112 string, so it is important that it be a legal value for this flag.
1113 """
1114 def __init__(self, parser, serializer, name, default, help_string,
1115 short_name=None, boolean=0, allow_override=0):
1116 self.name = name
1117
1118 if not help_string:
1119 help_string = '(no help available)'
1120
1121 self.help = help_string
1122 self.short_name = short_name
1123 self.boolean = boolean
1124 self.present = 0
1125 self.parser = parser
1126 self.serializer = serializer
1127 self.allow_override = allow_override
1128 self.value = None
1129
1130 self.SetDefault(default)
1131
1132 def __GetParsedValueAsString(self, value):
1133 if value is None:
1134 return None
1135 if self.serializer:
1136 return repr(self.serializer.Serialize(value))
1137 if self.boolean:
1138 if value:
1139 return repr('true')
1140 else:
1141 return repr('false')
1142 return repr(str(value))
1143
1144 def Parse(self, argument):
1145 try:
1146 self.value = self.parser.Parse(argument)
1147 except ValueError, e: # recast ValueError as IllegalFlagValue
1148 raise IllegalFlagValue, ("flag --%s: " % self.name) + str(e)
1149 self.present += 1
1150
1151 def Unparse(self):
1152 if self.default is None:
1153 self.value = None
1154 else:
1155 self.Parse(self.default)
1156 self.present = 0
1157
1158 def Serialize(self):
1159 if self.value is None:
1160 return ''
1161 if self.boolean:
1162 if self.value:
1163 return "--%s" % self.name
1164 else:
1165 return "--no%s" % self.name
1166 else:
1167 if not self.serializer:
1168 raise FlagsError, "Serializer not present for flag %s" % self.name
1169 return "--%s=%s" % (self.name, self.serializer.Serialize(self.value))
1170
1171 def SetDefault(self, value):
1172 """
1173 Change the default value, and current value, of this flag object
1174 """
1175 # We can't allow a None override because it may end up not being
1176 # passed to C++ code when we're overriding C++ flags. So we
1177 # cowardly bail out until someone fixes the semantics of trying to
1178 # pass None to a C++ flag. See swig_flags.Init() for details on
1179 # this behavior.
1180 if value is None and self.allow_override:
1181 raise DuplicateFlag, self.name
1182
1183 self.default = value
1184 self.Unparse()
1185 self.default_as_str = self.__GetParsedValueAsString(self.value)
1186 # End of Flag definition
1187
1188 class ArgumentParser:
1189 """
1190 This is a base class used to parse and convert arguments.
1191
1192 The Parse() method checks to make sure that the string argument is a
1193 legal value and convert it to a native type. If the value cannot be
1194 converted, it should throw a 'ValueError' exception with a human
1195 readable explanation of why the value is illegal.
1196
1197 Subclasses should also define a syntactic_help string which may be
1198 presented to the user to describe the form of the legal values.
1199 """
1200 syntactic_help = ""
1201 def Parse(self, argument):
1202 """
1203 The default implementation of Parse() accepts any value of argument,
1204 simply returning it unmodified.
1205 """
1206 return argument
1207
1208 class ArgumentSerializer:
1209 """
1210 This is the base class for generating string representations of a
1211 flag value
1212 """
1213 def Serialize(self, value):
1214 return str(value)
1215
1216 class ListSerializer(ArgumentSerializer):
1217 def __init__(self, list_sep):
1218 self.list_sep = list_sep
1219
1220 def Serialize(self, value):
1221 return self.list_sep.join([str(x) for x in value])
1222
1223
1224 # The DEFINE functions are explained in the module doc string.
1225
1226 def DEFINE(parser, name, default, help, flag_values=FLAGS, serializer=None,
1227 **args):
1228 """
1229 This creates a generic 'Flag' object that parses its arguments with a
1230 'Parser' and registers it with a 'FlagValues' object.
1231
1232 Developers who need to create their own 'Parser' classes should call
1233 this module function. to register their flags. For example:
1234
1235 DEFINE(DatabaseSpec(), "dbspec", "mysql:db0:readonly:hr",
1236 "The primary database")
1237 """
1238 DEFINE_flag(Flag(parser, serializer, name, default, help, **args),
1239 flag_values)
1240
1241 def DEFINE_flag(flag, flag_values=FLAGS):
1242 """
1243 This registers a 'Flag' object with a 'FlagValues' object. By
1244 default, the global FLAGS 'FlagValue' object is used.
1245
1246 Typical users will use one of the more specialized DEFINE_xxx
1247 functions, such as DEFINE_string or DEFINE_integer. But developers
1248 who need to create Flag objects themselves should use this function to
1249 register their flags.
1250 """
1251 # copying the reference to flag_values prevents pychecker warnings
1252 fv = flag_values
1253 fv[flag.name] = flag
1254
1255 if flag_values == FLAGS:
1256 # We are using the global flags dictionary, so we'll want to sort the
1257 # usage output by calling module in FlagValues.__str__ (FLAGS is an
1258 # instance of FlagValues). This requires us to keep track
1259 # of which module is creating the flags.
1260
1261 # Tell FLAGS who's defining flag.
1262 FLAGS._RegisterFlagByModule(_GetCallingModule(), flag)
1263
1264
1265 ###############################
1266 ################# STRING FLAGS
1267 ###############################
1268
1269 def DEFINE_string(name, default, help, flag_values=FLAGS, **args):
1270 """
1271 This registers a flag whose value can be any string.
1272 """
1273 parser = ArgumentParser()
1274 serializer = ArgumentSerializer()
1275 DEFINE(parser, name, default, help, flag_values, serializer, **args)
1276
1277
1278 ###############################
1279 ################ BOOLEAN FLAGS
1280 ###############################
1281 #### and the special HELP flag
1282 ###############################
1283
1284 class BooleanParser(ArgumentParser):
1285 """
1286 A boolean value
1287 """
1288
1289 def Convert(self, argument):
1290 """
1291 convert the argument to a boolean; raise ValueError on errors
1292 """
1293 if type(argument) == str:
1294 if argument.lower() in ['true', 't', '1']:
1295 return True
1296 elif argument.lower() in ['false', 'f', '0']:
1297 return False
1298
1299 bool_argument = bool(argument)
1300 if argument == bool_argument:
1301 # The argument is a valid boolean (True, False, 0, or 1), and not just
1302 # something that always converts to bool (list, string, int, etc.).
1303 return bool_argument
1304
1305 raise ValueError('Non-boolean argument to boolean flag', argument)
1306
1307 def Parse(self, argument):
1308 val = self.Convert(argument)
1309 return val
1310
1311 class BooleanFlag(Flag):
1312 """
1313 A basic boolean flag. Boolean flags do not take any arguments, and
1314 their value is either True (1) or False (0). The false value is
1315 specified on the command line by prepending the word 'no' to either
1316 the long or short flag name.
1317
1318 For example, if a Boolean flag was created whose long name was 'update'
1319 and whose short name was 'x', then this flag could be explicitly unset
1320 through either --noupdate or --nox.
1321 """
1322 def __init__(self, name, default, help, short_name=None, **args):
1323 p = BooleanParser()
1324 Flag.__init__(self, p, None, name, default, help, short_name, 1, **args)
1325 if not self.help: self.help = "a boolean value"
1326
1327 def DEFINE_boolean(name, default, help, flag_values=FLAGS, **args):
1328 """
1329 This registers a boolean flag - one that does not take an argument.
1330 If a user wants to specify a false value explicitly, the long option
1331 beginning with 'no' must be used: i.e. --noflag
1332
1333 This flag will have a value of None, True or False. None is possible if
1334 default=None and the user does not specify the flag on the command
1335 line.
1336 """
1337 DEFINE_flag(BooleanFlag(name, default, help, **args), flag_values)
1338
1339 class HelpFlag(BooleanFlag):
1340 """
1341 HelpFlag is a special boolean flag that prints usage information and
1342 raises a SystemExit exception if it is ever found in the command
1343 line arguments. Note this is called with allow_override=1, so other
1344 apps can define their own --help flag, replacing this one, if they want.
1345 """
1346 def __init__(self):
1347 BooleanFlag.__init__(self, "help", 0, "show this help",
1348 short_name="?", allow_override=1)
1349 def Parse(self, arg):
1350 if arg:
1351 doc = sys.modules["__main__"].__doc__
1352 flags = str(FLAGS)
1353 print doc or ("\nUSAGE: %s [flags]\n" % sys.argv[0])
1354 if flags:
1355 print "flags:"
1356 print flags
1357 sys.exit(1)
1358
1359 class HelpshortFlag(BooleanFlag):
1360 """
1361 HelpshortFlag is a special boolean flag that prints usage
1362 information for the "main" module, and rasies a SystemExit exception
1363 if it is ever found in the command line arguments. Note this is
1364 called with allow_override=1, so other apps can define their own
1365 --helpshort flag, replacing this one, if they want.
1366 """
1367 def __init__(self):
1368 BooleanFlag.__init__(self, "helpshort", 0,
1369 "show usage only for this module", allow_override=1)
1370 def Parse(self, arg):
1371 if arg:
1372 doc = sys.modules["__main__"].__doc__
1373 flags = FLAGS.MainModuleHelp()
1374 print doc or ("\nUSAGE: %s [flags]\n" % sys.argv[0])
1375 if flags:
1376 print "flags:"
1377 print flags
1378 sys.exit(1)
1379
1380
1381 ###############################
1382 ################## FLOAT FLAGS
1383 ###############################
1384
1385 class FloatParser(ArgumentParser):
1386 """
1387 A floating point value; optionally bounded to a given upper and lower
1388 bound.
1389 """
1390 number_article = "a"
1391 number_name = "number"
1392 syntactic_help = " ".join((number_article, number_name))
1393
1394 def __init__(self, lower_bound=None, upper_bound=None):
1395 self.lower_bound = lower_bound
1396 self.upper_bound = upper_bound
1397 sh = self.syntactic_help
1398 if lower_bound != None and upper_bound != None:
1399 sh = ("%s in the range [%s, %s]" % (sh, lower_bound, upper_bound))
1400 elif lower_bound == 1:
1401 sh = "a positive %s" % self.number_name
1402 elif upper_bound == -1:
1403 sh = "a negative %s" % self.number_name
1404 elif lower_bound == 0:
1405 sh = "a non-negative %s" % self.number_name
1406 elif upper_bound != None:
1407 sh = "%s <= %s" % (self.number_name, upper_bound)
1408 elif lower_bound != None:
1409 sh = "%s >= %s" % (self.number_name, lower_bound)
1410 self.syntactic_help = sh
1411
1412 def Convert(self, argument):
1413 """
1414 convert the argument to a float; raise ValueError on errors
1415 """
1416 return float(argument)
1417
1418 def Parse(self, argument):
1419 val = self.Convert(argument)
1420 if ((self.lower_bound != None and val < self.lower_bound) or
1421 (self.upper_bound != None and val > self.upper_bound)):
1422 raise ValueError, "%s is not %s" % (val, self.syntactic_help)
1423 return val
1424
1425 def DEFINE_float(name, default, help, lower_bound=None, upper_bound=None,
1426 flag_values = FLAGS, **args):
1427 """
1428 This registers a flag whose value must be a float. If lower_bound,
1429 or upper_bound are set, then this flag must be within the given range.
1430 """
1431 parser = FloatParser(lower_bound, upper_bound)
1432 serializer = ArgumentSerializer()
1433 DEFINE(parser, name, default, help, flag_values, serializer, **args)
1434
1435
1436 ###############################
1437 ################ INTEGER FLAGS
1438 ###############################
1439
1440 class IntegerParser(FloatParser):
1441 """
1442 An integer value; optionally bounded to a given upper or lower bound.
1443 """
1444 number_article = "an"
1445 number_name = "integer"
1446 syntactic_help = " ".join((number_article, number_name))
1447 def Convert(self, argument):
1448 __pychecker__ = 'no-returnvalues'
1449 if type(argument) == str:
1450 base = 10
1451 if len(argument) > 2 and argument[0] == "0" and argument[1] == "x":
1452 base=16
1453 try:
1454 return int(argument, base)
1455 # ValueError is thrown when argument is a string, and overflows an int.
1456 except ValueError:
1457 return long(argument, base)
1458 else:
1459 try:
1460 return int(argument)
1461 # OverflowError is thrown when argument is numeric, and overflows an int.
1462 except OverflowError:
1463 return long(argument)
1464
1465 def DEFINE_integer(name, default, help, lower_bound=None, upper_bound=None,
1466 flag_values = FLAGS, **args):
1467 """
1468 This registers a flag whose value must be an integer. If lower_bound,
1469 or upper_bound are set, then this flag must be within the given range.
1470 """
1471 parser = IntegerParser(lower_bound, upper_bound)
1472 serializer = ArgumentSerializer()
1473 DEFINE(parser, name, default, help, flag_values, serializer, **args)
1474
1475
1476 ###############################
1477 ################### ENUM FLAGS
1478 ###############################
1479
1480 class EnumParser(ArgumentParser):
1481 """
1482 A string enum value
1483 """
1484
1485 def __init__(self, enum_values=None):
1486 self.enum_values = enum_values
1487
1488 def Parse(self, argument):
1489 """
1490 If enum_values is not specified, any string is allowed
1491 """
1492 if self.enum_values and argument not in self.enum_values:
1493 raise ValueError, ("value should be one of <%s>"
1494 % "|".join(self.enum_values))
1495 return argument
1496
1497 class EnumFlag(Flag):
1498 """
1499 A basic enum flag. The flag's value can be any string from the list
1500 of enum_values.
1501 """
1502 def __init__(self, name, default, help, enum_values=[],
1503 short_name=None, **args):
1504 p = EnumParser(enum_values)
1505 g = ArgumentSerializer()
1506 Flag.__init__(self, p, g, name, default, help, short_name, **args)
1507 if not self.help: self.help = "an enum string"
1508 self.help = "<%s>: %s" % ("|".join(enum_values), self.help)
1509
1510 def DEFINE_enum(name, default, enum_values, help, flag_values=FLAGS,
1511 **args):
1512 """
1513 This registers a flag whose value can be a string from a set of
1514 specified values.
1515 """
1516 DEFINE_flag(EnumFlag(name, default, help, enum_values, ** args),
1517 flag_values)
1518
1519
1520 ###############################
1521 ################### LIST FLAGS
1522 ###############################
1523
1524 class BaseListParser(ArgumentParser):
1525 """
1526 A base class for a string list parser.
1527 To extend, inherit from this class, and call
1528
1529 BaseListParser.__init__(self, token, name)
1530
1531 where token is a character used to tokenize, and
1532 name is a description of the separator
1533 """
1534
1535 def __init__(self, token=None, name=None):
1536 assert name
1537 self._token = token
1538 self._name = name
1539 self.syntactic_help = "a %s separated list" % self._name
1540
1541 def Parse(self, argument):
1542 if argument == '':
1543 return []
1544 else:
1545 return [s.strip() for s in argument.split(self._token)]
1546
1547
1548 class ListParser(BaseListParser):
1549 """
1550 A string list parser (comma-separated)
1551 """
1552
1553 def __init__(self):
1554 BaseListParser.__init__(self, ',', 'comma')
1555
1556 class WhitespaceSeparatedListParser(BaseListParser):
1557 """
1558 A string list parser (whitespace-separated)
1559 """
1560
1561 def __init__(self):
1562 BaseListParser.__init__(self, None, 'whitespace')
1563
1564
1565 def DEFINE_list(name, default, help, flag_values=FLAGS, **args):
1566 """
1567 This registers a flag whose value is a list of strings, separated by commas
1568 """
1569 parser = ListParser()
1570 serializer = ListSerializer(',')
1571 DEFINE(parser, name, default, help, flag_values, serializer, **args)
1572
1573 def DEFINE_spaceseplist(name, default, help, flag_values=FLAGS, **args):
1574 """
1575 This registers a flag whose value is a list of strings, separated by any
1576 whitespace
1577 """
1578 parser = WhitespaceSeparatedListParser()
1579 serializer = ListSerializer(' ')
1580 DEFINE(parser, name, default, help, flag_values, serializer, **args)
1581
1582
1583 ###############################
1584 ################## MULTI FLAGS
1585 ###############################
1586
1587 class MultiFlag(Flag):
1588 """
1589 MultiFlag is a specialized subclass of Flag that accumulates
1590 multiple values in a list when a command-line option appears
1591 multiple times.
1592
1593 See the __doc__ for Flag for most behavior of this class. Only
1594 differences in behavior are described here:
1595 * the default value may be a single value -OR- a list of values
1596 * the value of the flag is always a list, even if the option was only
1597 supplied once, and even if the default value is a single value
1598 """
1599 def __init__(self, *args, **kwargs):
1600 Flag.__init__(self, *args, **kwargs)
1601
1602 self.help = (self.help +
1603 ';\n repeat this option to specify a list of values')
1604
1605 def Parse(self, arguments):
1606 """Parse one or more arguments with the installed parser.
1607
1608 Arguments:
1609 arguments: a single argument or a list of arguments (typically a list
1610 of default values); single arguments will be converted internally into
1611 a list containing one item
1612 """
1613 if not isinstance(arguments, list):
1614 # Default value may be a list of values. Most other arguments will not
1615 # be, so convert them into a single-item list to make processing simpler
1616 # below.
1617 arguments = [ arguments ]
1618
1619 if self.present:
1620 # keep a backup reference to list of previously supplied option values
1621 values = self.value
1622 else:
1623 # "erase" the defaults with an empty list
1624 values = []
1625
1626 for item in arguments:
1627 # have Flag superclass parse argument, overwriting self.value reference
1628 Flag.Parse(self, item) # also increments self.present
1629 values.append(self.value)
1630
1631 # put list of option values back in member variable
1632 self.value = values
1633
1634 def Serialize(self):
1635 if not self.serializer:
1636 raise FlagsError, "Serializer not present for flag %s" % self.name
1637 if self.value is None:
1638 return ''
1639
1640 s = ''
1641
1642 multi_value = self.value
1643
1644 for self.value in multi_value:
1645 if s: s += ' '
1646 s += Flag.Serialize(self)
1647
1648 self.value = multi_value
1649
1650 return s
1651
1652
1653 def DEFINE_multi(parser, serializer, name, default, help, flag_values=FLAGS,
1654 **args):
1655 """
1656 This creates a generic 'MultiFlag' object that parses its arguments with a
1657 'Parser' and registers it with a 'FlagValues' object.
1658
1659 Developers who need to create their own 'Parser' classes for options which
1660 can appear multiple times can call this module function to register their
1661 flags.
1662 """
1663 DEFINE_flag(MultiFlag(parser, serializer, name, default, help, **args), flag_v alues)
1664
1665 def DEFINE_multistring(name, default, help, flag_values=FLAGS, **args):
1666 """
1667 This registers a flag whose value can be a list of any strings. Use the flag
1668 on the command line multiple times to place multiple string values into the
1669 list. The 'default' may be a single string (which will be converted into a
1670 single-element list) or a list of strings.
1671 """
1672 parser = ArgumentParser()
1673 serializer = ArgumentSerializer()
1674 DEFINE_multi(parser, serializer, name, default, help, flag_values, **args)
1675
1676 def DEFINE_multi_int(name, default, help, lower_bound=None, upper_bound=None,
1677 flag_values=FLAGS, **args):
1678 """
1679 This registers a flag whose value can be a list of any integers. Use the
1680 flag on the command line multiple times to place multiple integer values
1681 into the list. The 'default' may be a single integer (which will be
1682 converted into a single-element list) or a list of integers.
1683 """
1684 parser = IntegerParser(lower_bound, upper_bound)
1685 serializer = ArgumentSerializer()
1686 DEFINE_multi(parser, serializer, name, default, help, flag_values, **args)
1687
1688
1689 # Now register the flags that we want to exist in all applications.
1690 # These are all defined with allow_override=1, so user-apps can use
1691 # these flagnames for their own purposes, if they want.
1692 DEFINE_flag(HelpFlag())
1693 DEFINE_flag(HelpshortFlag())
1694
1695 # Define special flags here so that help may be generated for them.
1696 _SPECIAL_FLAGS = FlagValues()
1697
1698 DEFINE_string(
1699 'flagfile', "",
1700 "Insert flag definitions from the given file into the command line.",
1701 _SPECIAL_FLAGS)
1702
1703 DEFINE_string(
1704 'undefok', "",
1705 "comma-separated list of flag names that it is okay to specify "
1706 "on the command line even if the program does not define a flag "
1707 "with that name. IMPORTANT: flags in this list that have "
1708 "arguments MUST use the --flag=value format.", _SPECIAL_FLAGS)
OLDNEW
« no previous file with comments | « tools/nixysa/third_party/gflags-1.0/packages/rpm/rpm.spec ('k') | tools/nixysa/third_party/gflags-1.0/python/gflags2man.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698