12da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#!/usr/bin/env python
22da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
32da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Copyright (c) 2002, Google Inc.
42da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# All rights reserved.
52da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
62da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Redistribution and use in source and binary forms, with or without
72da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# modification, are permitted provided that the following conditions are
82da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# met:
92da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#     * Redistributions of source code must retain the above copyright
112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# notice, this list of conditions and the following disclaimer.
122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#     * Redistributions in binary form must reproduce the above
132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# copyright notice, this list of conditions and the following disclaimer
142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# in the documentation and/or other materials provided with the
152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# distribution.
162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#     * Neither the name of Google Inc. nor the names of its
172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# contributors may be used to endorse or promote products derived from
182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# this software without specific prior written permission.
192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# ---
332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Author: Chad Lester
342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Design and style contributions by:
352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#   Amit Patel, Bogdan Cocosel, Daniel Dulitz, Eric Tiedemann,
362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#   Eric Veach, Laurence Gonsalves, Matthew Springer
372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Code reorganized a bit by Craig Silverstein
382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis"""This module is used to define and parse command line flags.
402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
412da489cd246702bee5938545b18a6f710ed214bcJamie GennisThis module defines a *distributed* flag-definition policy: rather than
422da489cd246702bee5938545b18a6f710ed214bcJamie Gennisan application having to define all flags in or near main(), each python
432da489cd246702bee5938545b18a6f710ed214bcJamie Gennismodule defines flags that are useful to it.  When one python module
442da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimports another, it gains access to the other's flags.  (This is
452da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimplemented by having all modules share a common, global registry object
462da489cd246702bee5938545b18a6f710ed214bcJamie Genniscontaining all the flag information.)
472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
482da489cd246702bee5938545b18a6f710ed214bcJamie GennisFlags are defined through the use of one of the DEFINE_xxx functions.
492da489cd246702bee5938545b18a6f710ed214bcJamie GennisThe specific function used determines how the flag is parsed, checked,
502da489cd246702bee5938545b18a6f710ed214bcJamie Gennisand optionally type-converted, when it's seen on the command line.
512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
532da489cd246702bee5938545b18a6f710ed214bcJamie GennisIMPLEMENTATION: DEFINE_* creates a 'Flag' object and registers it with a
542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis'FlagValues' object (typically the global FlagValues FLAGS, defined
552da489cd246702bee5938545b18a6f710ed214bcJamie Gennishere).  The 'FlagValues' object can scan the command line arguments and
562da489cd246702bee5938545b18a6f710ed214bcJamie Gennispass flag arguments to the corresponding 'Flag' objects for
572da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvalue-checking and type conversion.  The converted flag values are
582da489cd246702bee5938545b18a6f710ed214bcJamie Gennisavailable as attributes of the 'FlagValues' object.
592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
602da489cd246702bee5938545b18a6f710ed214bcJamie GennisCode can access the flag through a FlagValues object, for instance
612da489cd246702bee5938545b18a6f710ed214bcJamie Gennisgflags.FLAGS.myflag.  Typically, the __main__ module passes the command
622da489cd246702bee5938545b18a6f710ed214bcJamie Gennisline arguments to gflags.FLAGS for parsing.
632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
642da489cd246702bee5938545b18a6f710ed214bcJamie GennisAt bottom, this module calls getopt(), so getopt functionality is
652da489cd246702bee5938545b18a6f710ed214bcJamie Gennissupported, including short- and long-style flags, and the use of -- to
662da489cd246702bee5938545b18a6f710ed214bcJamie Gennisterminate flags.
672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
682da489cd246702bee5938545b18a6f710ed214bcJamie GennisMethods defined by the flag module will throw 'FlagsError' exceptions.
692da489cd246702bee5938545b18a6f710ed214bcJamie GennisThe exception argument will be a human-readable string.
702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
722da489cd246702bee5938545b18a6f710ed214bcJamie GennisFLAG TYPES: This is a list of the DEFINE_*'s that you can do.  All flags
732da489cd246702bee5938545b18a6f710ed214bcJamie Gennistake a name, default value, help-string, and optional 'short' name
742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis(one-letter name).  Some flags have other arguments, which are described
752da489cd246702bee5938545b18a6f710ed214bcJamie Genniswith the flag.
762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
772da489cd246702bee5938545b18a6f710ed214bcJamie GennisDEFINE_string: takes any input, and interprets it as a string.
782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
792da489cd246702bee5938545b18a6f710ed214bcJamie GennisDEFINE_bool or
802da489cd246702bee5938545b18a6f710ed214bcJamie GennisDEFINE_boolean: typically does not take an argument: say --myflag to
812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                set FLAGS.myflag to true, or --nomyflag to set
822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                FLAGS.myflag to false.  Alternately, you can say
832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                   --myflag=true  or --myflag=t or --myflag=1  or
842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                   --myflag=false or --myflag=f or --myflag=0
852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
862da489cd246702bee5938545b18a6f710ed214bcJamie GennisDEFINE_float: takes an input and interprets it as a floating point
872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              number.  Takes optional args lower_bound and upper_bound;
882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              if the number specified on the command line is out of
892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              range, it will raise a FlagError.
902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
912da489cd246702bee5938545b18a6f710ed214bcJamie GennisDEFINE_integer: takes an input and interprets it as an integer.  Takes
922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                optional args lower_bound and upper_bound as for floats.
932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
942da489cd246702bee5938545b18a6f710ed214bcJamie GennisDEFINE_enum: takes a list of strings which represents legal values.  If
952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis             the command-line value is not in this list, raise a flag
962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis             error.  Otherwise, assign to FLAGS.flag as a string.
972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
982da489cd246702bee5938545b18a6f710ed214bcJamie GennisDEFINE_list: Takes a comma-separated list of strings on the commandline.
992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis             Stores them in a python list object.
1002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1012da489cd246702bee5938545b18a6f710ed214bcJamie GennisDEFINE_spaceseplist: Takes a space-separated list of strings on the
1022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                     commandline.  Stores them in a python list object.
1032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                     Example: --myspacesepflag "foo bar baz"
1042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1052da489cd246702bee5938545b18a6f710ed214bcJamie GennisDEFINE_multistring: The same as DEFINE_string, except the flag can be
1062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                    specified more than once on the commandline.  The
1072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                    result is a python list object (list of strings),
1082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                    even if the flag is only on the command line once.
1092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1102da489cd246702bee5938545b18a6f710ed214bcJamie GennisDEFINE_multi_int: The same as DEFINE_integer, except the flag can be
1112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                  specified more than once on the commandline.  The
1122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                  result is a python list object (list of ints), even if
1132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                  the flag is only on the command line once.
1142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1162da489cd246702bee5938545b18a6f710ed214bcJamie GennisSPECIAL FLAGS: There are a few flags that have special meaning:
1172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   --help          prints a list of all the flags in a human-readable fashion
1182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   --helpshort     prints a list of all key flags (see below).
1192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   --helpxml       prints a list of all flags, in XML format.  DO NOT parse
1202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                   the output of --help and --helpshort.  Instead, parse
1212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                   the output of --helpxml.  For more info, see
1222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                   "OUTPUT FOR --helpxml" below.
1232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   --flagfile=foo  read flags from file foo.
1242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   --undefok=f1,f2 ignore unrecognized option errors for f1,f2.
1252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                   For boolean flags, you should use --undefok=boolflag, and
1262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                   --boolflag and --noboolflag will be accepted.  Do not use
1272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                   --undefok=noboolflag.
1282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   --              as in getopt(), terminates flag-processing
1292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1312da489cd246702bee5938545b18a6f710ed214bcJamie GennisFLAGS VALIDATORS: If your program:
1322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  - requires flag X to be specified
1332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  - needs flag Y to match a regular expression
1342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  - or requires any more general constraint to be satisfied
1352da489cd246702bee5938545b18a6f710ed214bcJamie Gennisthen validators are for you!
1362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1372da489cd246702bee5938545b18a6f710ed214bcJamie GennisEach validator represents a constraint over one flag, which is enforced
1382da489cd246702bee5938545b18a6f710ed214bcJamie Gennisstarting from the initial parsing of the flags and until the program
1392da489cd246702bee5938545b18a6f710ed214bcJamie Gennisterminates.
1402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1412da489cd246702bee5938545b18a6f710ed214bcJamie GennisAlso, lower_bound and upper_bound for numerical flags are enforced using flag
1422da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvalidators.
1432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1442da489cd246702bee5938545b18a6f710ed214bcJamie GennisHowto:
1452da489cd246702bee5938545b18a6f710ed214bcJamie GennisIf you want to enforce a constraint over one flag, use
1462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1472da489cd246702bee5938545b18a6f710ed214bcJamie Gennisgflags.RegisterValidator(flag_name,
1482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                        checker,
1492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                        message='Flag validation failed',
1502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                        flag_values=FLAGS)
1512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1522da489cd246702bee5938545b18a6f710ed214bcJamie GennisAfter flag values are initially parsed, and after any change to the specified
1532da489cd246702bee5938545b18a6f710ed214bcJamie Gennisflag, method checker(flag_value) will be executed. If constraint is not
1542da489cd246702bee5938545b18a6f710ed214bcJamie Gennissatisfied, an IllegalFlagValue exception will be raised. See
1552da489cd246702bee5938545b18a6f710ed214bcJamie GennisRegisterValidator's docstring for a detailed explanation on how to construct
1562da489cd246702bee5938545b18a6f710ed214bcJamie Gennisyour own checker.
1572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1592da489cd246702bee5938545b18a6f710ed214bcJamie GennisEXAMPLE USAGE:
1602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1612da489cd246702bee5938545b18a6f710ed214bcJamie GennisFLAGS = gflags.FLAGS
1622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1632da489cd246702bee5938545b18a6f710ed214bcJamie Gennisgflags.DEFINE_integer('my_version', 0, 'Version number.')
1642da489cd246702bee5938545b18a6f710ed214bcJamie Gennisgflags.DEFINE_string('filename', None, 'Input file name', short_name='f')
1652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1662da489cd246702bee5938545b18a6f710ed214bcJamie Gennisgflags.RegisterValidator('my_version',
1672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                        lambda value: value % 2 == 0,
1682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                        message='--my_version must be divisible by 2')
1692da489cd246702bee5938545b18a6f710ed214bcJamie Gennisgflags.MarkFlagAsRequired('filename')
1702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1722da489cd246702bee5938545b18a6f710ed214bcJamie GennisNOTE ON --flagfile:
1732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1742da489cd246702bee5938545b18a6f710ed214bcJamie GennisFlags may be loaded from text files in addition to being specified on
1752da489cd246702bee5938545b18a6f710ed214bcJamie Gennisthe commandline.
1762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1772da489cd246702bee5938545b18a6f710ed214bcJamie GennisAny flags you don't feel like typing, throw them in a file, one flag per
1782da489cd246702bee5938545b18a6f710ed214bcJamie Gennisline, for instance:
1792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   --myflag=myvalue
1802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   --nomyboolean_flag
1812da489cd246702bee5938545b18a6f710ed214bcJamie GennisYou then specify your file with the special flag '--flagfile=somefile'.
1822da489cd246702bee5938545b18a6f710ed214bcJamie GennisYou CAN recursively nest flagfile= tokens OR use multiple files on the
1832da489cd246702bee5938545b18a6f710ed214bcJamie Genniscommand line.  Lines beginning with a single hash '#' or a double slash
1842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis'//' are comments in your flagfile.
1852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1862da489cd246702bee5938545b18a6f710ed214bcJamie GennisAny flagfile=<file> will be interpreted as having a relative path from
1872da489cd246702bee5938545b18a6f710ed214bcJamie Gennisthe current working directory rather than from the place the file was
1882da489cd246702bee5938545b18a6f710ed214bcJamie Gennisincluded from:
1892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   myPythonScript.py --flagfile=config/somefile.cfg
1902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1912da489cd246702bee5938545b18a6f710ed214bcJamie GennisIf somefile.cfg includes further --flagfile= directives, these will be
1922da489cd246702bee5938545b18a6f710ed214bcJamie Gennisreferenced relative to the original CWD, not from the directory the
1932da489cd246702bee5938545b18a6f710ed214bcJamie Gennisincluding flagfile was found in!
1942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1952da489cd246702bee5938545b18a6f710ed214bcJamie GennisThe caveat applies to people who are including a series of nested files
1962da489cd246702bee5938545b18a6f710ed214bcJamie Gennisin a different dir than they are executing out of.  Relative path names
1972da489cd246702bee5938545b18a6f710ed214bcJamie Gennisare always from CWD, not from the directory of the parent include
1982da489cd246702bee5938545b18a6f710ed214bcJamie Gennisflagfile. We do now support '~' expanded directory names.
1992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2002da489cd246702bee5938545b18a6f710ed214bcJamie GennisAbsolute path names ALWAYS work!
2012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2032da489cd246702bee5938545b18a6f710ed214bcJamie GennisEXAMPLE USAGE:
2042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  FLAGS = gflags.FLAGS
2072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Flag names are globally defined!  So in general, we need to be
2092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # careful to pick names that are unlikely to be used by other libraries.
2102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # If there is a conflict, we'll get an error at import time.
2112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  gflags.DEFINE_string('name', 'Mr. President', 'your name')
2122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  gflags.DEFINE_integer('age', None, 'your age in years', lower_bound=0)
2132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  gflags.DEFINE_boolean('debug', False, 'produces debugging output')
2142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  gflags.DEFINE_enum('gender', 'male', ['male', 'female'], 'your gender')
2152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def main(argv):
2172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    try:
2182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      argv = FLAGS(argv)  # parse flags
2192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    except gflags.FlagsError, e:
2202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      print '%s\\nUsage: %s ARGS\\n%s' % (e, sys.argv[0], FLAGS)
2212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sys.exit(1)
2222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if FLAGS.debug: print 'non-flag arguments:', argv
2232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    print 'Happy Birthday', FLAGS.name
2242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if FLAGS.age is not None:
2252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      print 'You are a %d year old %s' % (FLAGS.age, FLAGS.gender)
2262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if __name__ == '__main__':
2282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    main(sys.argv)
2292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2312da489cd246702bee5938545b18a6f710ed214bcJamie GennisKEY FLAGS:
2322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2332da489cd246702bee5938545b18a6f710ed214bcJamie GennisAs we already explained, each module gains access to all flags defined
2342da489cd246702bee5938545b18a6f710ed214bcJamie Gennisby all the other modules it transitively imports.  In the case of
2352da489cd246702bee5938545b18a6f710ed214bcJamie Gennisnon-trivial scripts, this means a lot of flags ...  For documentation
2362da489cd246702bee5938545b18a6f710ed214bcJamie Gennispurposes, it is good to identify the flags that are key (i.e., really
2372da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimportant) to a module.  Clearly, the concept of "key flag" is a
2382da489cd246702bee5938545b18a6f710ed214bcJamie Gennissubjective one.  When trying to determine whether a flag is key to a
2392da489cd246702bee5938545b18a6f710ed214bcJamie Gennismodule or not, assume that you are trying to explain your module to a
2402da489cd246702bee5938545b18a6f710ed214bcJamie Gennispotential user: which flags would you really like to mention first?
2412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2422da489cd246702bee5938545b18a6f710ed214bcJamie GennisWe'll describe shortly how to declare which flags are key to a module.
2432da489cd246702bee5938545b18a6f710ed214bcJamie GennisFor the moment, assume we know the set of key flags for each module.
2442da489cd246702bee5938545b18a6f710ed214bcJamie GennisThen, if you use the app.py module, you can use the --helpshort flag to
2452da489cd246702bee5938545b18a6f710ed214bcJamie Gennisprint only the help for the flags that are key to the main module, in a
2462da489cd246702bee5938545b18a6f710ed214bcJamie Gennishuman-readable format.
2472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2482da489cd246702bee5938545b18a6f710ed214bcJamie GennisNOTE: If you need to parse the flag help, do NOT use the output of
2492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis--help / --helpshort.  That output is meant for human consumption, and
2502da489cd246702bee5938545b18a6f710ed214bcJamie Gennismay be changed in the future.  Instead, use --helpxml; flags that are
2512da489cd246702bee5938545b18a6f710ed214bcJamie Genniskey for the main module are marked there with a <key>yes</key> element.
2522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2532da489cd246702bee5938545b18a6f710ed214bcJamie GennisThe set of key flags for a module M is composed of:
2542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis1. Flags defined by module M by calling a DEFINE_* function.
2562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis2. Flags that module M explictly declares as key by using the function
2582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     DECLARE_key_flag(<flag_name>)
2602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis3. Key flags of other modules that M specifies by using the function
2622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     ADOPT_module_key_flags(<other_module>)
2642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   This is a "bulk" declaration of key flags: each flag that is key for
2662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   <other_module> becomes key for the current module too.
2672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2682da489cd246702bee5938545b18a6f710ed214bcJamie GennisNotice that if you do not use the functions described at points 2 and 3
2692da489cd246702bee5938545b18a6f710ed214bcJamie Gennisabove, then --helpshort prints information only about the flags defined
2702da489cd246702bee5938545b18a6f710ed214bcJamie Gennisby the main module of our script.  In many cases, this behavior is good
2712da489cd246702bee5938545b18a6f710ed214bcJamie Gennisenough.  But if you move part of the main module code (together with the
2722da489cd246702bee5938545b18a6f710ed214bcJamie Gennisrelated flags) into a different module, then it is nice to use
2732da489cd246702bee5938545b18a6f710ed214bcJamie GennisDECLARE_key_flag / ADOPT_module_key_flags and make sure --helpshort
2742da489cd246702bee5938545b18a6f710ed214bcJamie Gennislists all relevant flags (otherwise, your code refactoring may confuse
2752da489cd246702bee5938545b18a6f710ed214bcJamie Gennisyour users).
2762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2772da489cd246702bee5938545b18a6f710ed214bcJamie GennisNote: each of DECLARE_key_flag / ADOPT_module_key_flags has its own
2782da489cd246702bee5938545b18a6f710ed214bcJamie Gennispluses and minuses: DECLARE_key_flag is more targeted and may lead a
2792da489cd246702bee5938545b18a6f710ed214bcJamie Gennismore focused --helpshort documentation.  ADOPT_module_key_flags is good
2802da489cd246702bee5938545b18a6f710ed214bcJamie Gennisfor cases when an entire module is considered key to the current script.
2812da489cd246702bee5938545b18a6f710ed214bcJamie GennisAlso, it does not require updates to client scripts when a new flag is
2822da489cd246702bee5938545b18a6f710ed214bcJamie Gennisadded to the module.
2832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2852da489cd246702bee5938545b18a6f710ed214bcJamie GennisEXAMPLE USAGE 2 (WITH KEY FLAGS):
2862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2872da489cd246702bee5938545b18a6f710ed214bcJamie GennisConsider an application that contains the following three files (two
2882da489cd246702bee5938545b18a6f710ed214bcJamie Gennisauxiliary modules and a main module)
2892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2902da489cd246702bee5938545b18a6f710ed214bcJamie GennisFile libfoo.py:
2912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  import gflags
2932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  gflags.DEFINE_integer('num_replicas', 3, 'Number of replicas to start')
2952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  gflags.DEFINE_boolean('rpc2', True, 'Turn on the usage of RPC2.')
2962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  ... some code ...
2982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2992da489cd246702bee5938545b18a6f710ed214bcJamie GennisFile libbar.py:
3002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  import gflags
3022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  gflags.DEFINE_string('bar_gfs_path', '/gfs/path',
3042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                      'Path to the GFS files for libbar.')
3052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  gflags.DEFINE_string('email_for_bar_errors', 'bar-team@google.com',
3062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                      'Email address for bug reports about module libbar.')
3072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  gflags.DEFINE_boolean('bar_risky_hack', False,
3082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                       'Turn on an experimental and buggy optimization.')
3092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  ... some code ...
3112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3122da489cd246702bee5938545b18a6f710ed214bcJamie GennisFile myscript.py:
3132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  import gflags
3152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  import libfoo
3162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  import libbar
3172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  gflags.DEFINE_integer('num_iterations', 0, 'Number of iterations.')
3192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Declare that all flags that are key for libfoo are
3212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # key for this module too.
3222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  gflags.ADOPT_module_key_flags(libfoo)
3232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Declare that the flag --bar_gfs_path (defined in libbar) is key
3252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # for this module.
3262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  gflags.DECLARE_key_flag('bar_gfs_path')
3272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  ... some code ...
3292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3302da489cd246702bee5938545b18a6f710ed214bcJamie GennisWhen myscript is invoked with the flag --helpshort, the resulted help
3312da489cd246702bee5938545b18a6f710ed214bcJamie Gennismessage lists information about all the key flags for myscript:
3322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis--num_iterations, --num_replicas, --rpc2, and --bar_gfs_path.
3332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3342da489cd246702bee5938545b18a6f710ed214bcJamie GennisOf course, myscript uses all the flags declared by it (in this case,
3352da489cd246702bee5938545b18a6f710ed214bcJamie Gennisjust --num_replicas) or by any of the modules it transitively imports
3362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis(e.g., the modules libfoo, libbar).  E.g., it can access the value of
3372da489cd246702bee5938545b18a6f710ed214bcJamie GennisFLAGS.bar_risky_hack, even if --bar_risky_hack is not declared as a key
3382da489cd246702bee5938545b18a6f710ed214bcJamie Gennisflag for myscript.
3392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3412da489cd246702bee5938545b18a6f710ed214bcJamie GennisOUTPUT FOR --helpxml:
3422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3432da489cd246702bee5938545b18a6f710ed214bcJamie GennisThe --helpxml flag generates output with the following structure:
3442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis<?xml version="1.0"?>
3462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis<AllFlags>
3472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  <program>PROGRAM_BASENAME</program>
3482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  <usage>MAIN_MODULE_DOCSTRING</usage>
3492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  (<flag>
3502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    [<key>yes</key>]
3512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    <file>DECLARING_MODULE</file>
3522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    <name>FLAG_NAME</name>
3532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    <meaning>FLAG_HELP_MESSAGE</meaning>
3542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    <default>DEFAULT_FLAG_VALUE</default>
3552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    <current>CURRENT_FLAG_VALUE</current>
3562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    <type>FLAG_TYPE</type>
3572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    [OPTIONAL_ELEMENTS]
3582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  </flag>)*
3592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis</AllFlags>
3602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3612da489cd246702bee5938545b18a6f710ed214bcJamie GennisNotes:
3622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis1. The output is intentionally similar to the output generated by the
3642da489cd246702bee5938545b18a6f710ed214bcJamie GennisC++ command-line flag library.  The few differences are due to the
3652da489cd246702bee5938545b18a6f710ed214bcJamie GennisPython flags that do not have a C++ equivalent (at least not yet),
3662da489cd246702bee5938545b18a6f710ed214bcJamie Gennise.g., DEFINE_list.
3672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis2. New XML elements may be added in the future.
3692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis3. DEFAULT_FLAG_VALUE is in serialized form, i.e., the string you can
3712da489cd246702bee5938545b18a6f710ed214bcJamie Gennispass for this flag on the command-line.  E.g., for a flag defined
3722da489cd246702bee5938545b18a6f710ed214bcJamie Gennisusing DEFINE_list, this field may be foo,bar, not ['foo', 'bar'].
3732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis4. CURRENT_FLAG_VALUE is produced using str().  This means that the
3752da489cd246702bee5938545b18a6f710ed214bcJamie Gennisstring 'false' will be represented in the same way as the boolean
3762da489cd246702bee5938545b18a6f710ed214bcJamie GennisFalse.  Using repr() would have removed this ambiguity and simplified
3772da489cd246702bee5938545b18a6f710ed214bcJamie Gennisparsing, but would have broken the compatibility with the C++
3782da489cd246702bee5938545b18a6f710ed214bcJamie Genniscommand-line flags.
3792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis5. OPTIONAL_ELEMENTS describe elements relevant for certain kinds of
3812da489cd246702bee5938545b18a6f710ed214bcJamie Gennisflags: lower_bound, upper_bound (for flags that specify bounds),
3822da489cd246702bee5938545b18a6f710ed214bcJamie Gennisenum_value (for enum flags), list_separator (for flags that consist of
3832da489cd246702bee5938545b18a6f710ed214bcJamie Gennisa list of values, separated by a special token).
3842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis6. We do not provide any example here: please use --helpxml instead.
3862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3872da489cd246702bee5938545b18a6f710ed214bcJamie GennisThis module requires at least python 2.2.1 to run.
3882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis"""
3892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3902da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport cgi
3912da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport getopt
3922da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport os
3932da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport re
3942da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport string
3952da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport struct
3962da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport sys
3972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# pylint: disable-msg=C6204
3982da489cd246702bee5938545b18a6f710ed214bcJamie Gennistry:
3992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  import fcntl
4002da489cd246702bee5938545b18a6f710ed214bcJamie Gennisexcept ImportError:
4012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  fcntl = None
4022da489cd246702bee5938545b18a6f710ed214bcJamie Gennistry:
4032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Importing termios will fail on non-unix platforms.
4042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  import termios
4052da489cd246702bee5938545b18a6f710ed214bcJamie Gennisexcept ImportError:
4062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  termios = None
4072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4082da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport gflags_validators
4092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# pylint: enable-msg=C6204
4102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Are we running under pychecker?
4132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis_RUNNING_PYCHECKER = 'pychecker.python' in sys.modules
4142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4162da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _GetCallingModuleObjectAndName():
4172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Returns the module that's calling into this module.
4182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  We generally use this function to get the name of the module calling a
4202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  DEFINE_foo... function.
4212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
4222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Walk down the stack to find the first globals dict that's not ours.
4232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  for depth in range(1, sys.getrecursionlimit()):
4242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if not sys._getframe(depth).f_globals is globals():
4252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      globals_for_frame = sys._getframe(depth).f_globals
4262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      module, module_name = _GetModuleObjectAndName(globals_for_frame)
4272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if module_name is not None:
4282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return module, module_name
4292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  raise AssertionError("No module was found")
4302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4322da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _GetCallingModule():
4332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Returns the name of the module that's calling into this module."""
4342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  return _GetCallingModuleObjectAndName()[1]
4352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4372da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _GetThisModuleObjectAndName():
4382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Returns: (module object, module name) for this module."""
4392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  return _GetModuleObjectAndName(globals())
4402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# module exceptions:
4432da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass FlagsError(Exception):
4442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """The base class for all flags errors."""
4452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  pass
4462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4482da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass DuplicateFlag(FlagsError):
4492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Raised if there is a flag naming conflict."""
4502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  pass
4512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4522da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass CantOpenFlagFileError(FlagsError):
4532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Raised if flagfile fails to open: doesn't exist, wrong permissions, etc."""
4542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  pass
4552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4572da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass DuplicateFlagCannotPropagateNoneToSwig(DuplicateFlag):
4582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Special case of DuplicateFlag -- SWIG flag value can't be set to None.
4592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  This can be raised when a duplicate flag is created. Even if allow_override is
4612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  True, we still abort if the new value is None, because it's currently
4622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  impossible to pass None default value back to SWIG. See FlagValues.SetDefault
4632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  for details.
4642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
4652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  pass
4662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4682da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass DuplicateFlagError(DuplicateFlag):
4692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """A DuplicateFlag whose message cites the conflicting definitions.
4702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  A DuplicateFlagError conveys more information than a DuplicateFlag,
4722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  namely the modules where the conflicting definitions occur. This
4732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  class was created to avoid breaking external modules which depend on
4742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  the existing DuplicateFlags interface.
4752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
4762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self, flagname, flag_values, other_flag_values=None):
4782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Create a DuplicateFlagError.
4792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
4812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flagname: Name of the flag being redefined.
4822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag_values: FlagValues object containing the first definition of
4832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          flagname.
4842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      other_flag_values: If this argument is not None, it should be the
4852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          FlagValues object where the second definition of flagname occurs.
4862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          If it is None, we assume that we're being called when attempting
4872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          to create the flag a second time, and we use the module calling
4882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          this one as the source of the second definition.
4892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
4902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.flagname = flagname
4912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    first_module = flag_values.FindModuleDefiningFlag(
4922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flagname, default='<unknown>')
4932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if other_flag_values is None:
4942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      second_module = _GetCallingModule()
4952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    else:
4962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      second_module = other_flag_values.FindModuleDefiningFlag(
4972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          flagname, default='<unknown>')
4982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    msg = "The flag '%s' is defined twice. First from %s, Second from %s" % (
4992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.flagname, first_module, second_module)
5002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    DuplicateFlag.__init__(self, msg)
5012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5032da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass IllegalFlagValue(FlagsError):
5042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """The flag command line argument is illegal."""
5052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  pass
5062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5082da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass UnrecognizedFlag(FlagsError):
5092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Raised if a flag is unrecognized."""
5102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  pass
5112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# An UnrecognizedFlagError conveys more information than an UnrecognizedFlag.
5142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Since there are external modules that create DuplicateFlags, the interface to
5152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# DuplicateFlag shouldn't change.  The flagvalue will be assigned the full value
5162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# of the flag and its argument, if any, allowing handling of unrecognized flags
5172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# in an exception handler.
5182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# If flagvalue is the empty string, then this exception is an due to a
5192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# reference to a flag that was not already defined.
5202da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass UnrecognizedFlagError(UnrecognizedFlag):
5212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self, flagname, flagvalue=''):
5222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.flagname = flagname
5232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.flagvalue = flagvalue
5242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    UnrecognizedFlag.__init__(
5252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self, "Unknown command line flag '%s'" % flagname)
5262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Global variable used by expvar
5282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis_exported_flags = {}
5292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis_help_width = 80  # width of help output
5302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5322da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef GetHelpWidth():
5332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Returns: an integer, the width of help lines that is used in TextWrap."""
5342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if (not sys.stdout.isatty()) or (termios is None) or (fcntl is None):
5352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return _help_width
5362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  try:
5372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    data = fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ, '1234')
5382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    columns = struct.unpack('hh', data)[1]
5392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Emacs mode returns 0.
5402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Here we assume that any value below 40 is unreasonable
5412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if columns >= 40:
5422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return columns
5432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Returning an int as default is fine, int(int) just return the int.
5442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return int(os.getenv('COLUMNS', _help_width))
5452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  except (TypeError, IOError, struct.error):
5472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return _help_width
5482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5502da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef CutCommonSpacePrefix(text):
5512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Removes a common space prefix from the lines of a multiline text.
5522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  If the first line does not start with a space, it is left as it is and
5542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  only in the remaining lines a common space prefix is being searched
5552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  for. That means the first line will stay untouched. This is especially
5562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  useful to turn doc strings into help texts. This is because some
5572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  people prefer to have the doc comment start already after the
5582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  apostrophe and then align the following lines while others have the
5592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  apostrophes on a separate line.
5602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  The function also drops trailing empty lines and ignores empty lines
5622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  following the initial content line while calculating the initial
5632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  common whitespace.
5642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Args:
5662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    text: text to work on
5672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Returns:
5692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    the resulting text
5702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
5712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  text_lines = text.splitlines()
5722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Drop trailing empty lines
5732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  while text_lines and not text_lines[-1]:
5742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    text_lines = text_lines[:-1]
5752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if text_lines:
5762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # We got some content, is the first line starting with a space?
5772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if text_lines[0] and text_lines[0][0].isspace():
5782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      text_first_line = []
5792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    else:
5802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      text_first_line = [text_lines.pop(0)]
5812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Calculate length of common leading whitespace (only over content lines)
5822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    common_prefix = os.path.commonprefix([line for line in text_lines if line])
5832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    space_prefix_len = len(common_prefix) - len(common_prefix.lstrip())
5842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # If we have a common space prefix, drop it from all lines
5852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if space_prefix_len:
5862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for index in xrange(len(text_lines)):
5872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if text_lines[index]:
5882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          text_lines[index] = text_lines[index][space_prefix_len:]
5892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return '\n'.join(text_first_line + text_lines)
5902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  return ''
5912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5932da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef TextWrap(text, length=None, indent='', firstline_indent=None, tabs='    '):
5942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Wraps a given text to a maximum line length and returns it.
5952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  We turn lines that only contain whitespace into empty lines.  We keep
5972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  new lines and tabs (e.g., we do not treat tabs as spaces).
5982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Args:
6002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    text:             text to wrap
6012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    length:           maximum length of a line, includes indentation
6022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                      if this is None then use GetHelpWidth()
6032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    indent:           indent for all but first line
6042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    firstline_indent: indent for first line; if None, fall back to indent
6052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    tabs:             replacement for tabs
6062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
6072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Returns:
6082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    wrapped text
6092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
6102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Raises:
6112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    FlagsError: if indent not shorter than length
6122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    FlagsError: if firstline_indent not shorter than length
6132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
6142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Get defaults where callee used None
6152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if length is None:
6162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    length = GetHelpWidth()
6172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if indent is None:
6182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    indent = ''
6192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if len(indent) >= length:
6202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    raise FlagsError('Indent must be shorter than length')
6212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # In line we will be holding the current line which is to be started
6222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # with indent (or firstline_indent if available) and then appended
6232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # with words.
6242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if firstline_indent is None:
6252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    firstline_indent = ''
6262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    line = indent
6272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  else:
6282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    line = firstline_indent
6292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if len(firstline_indent) >= length:
6302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      raise FlagsError('First line indent must be shorter than length')
6312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
6322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # If the callee does not care about tabs we simply convert them to
6332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # spaces If callee wanted tabs to be single space then we do that
6342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # already here.
6352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if not tabs or tabs == ' ':
6362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    text = text.replace('\t', ' ')
6372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  else:
6382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    tabs_are_whitespace = not tabs.strip()
6392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
6402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  line_regex = re.compile('([ ]*)(\t*)([^ \t]+)', re.MULTILINE)
6412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
6422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Split the text into lines and the lines with the regex above. The
6432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # resulting lines are collected in result[]. For each split we get the
6442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # spaces, the tabs and the next non white space (e.g. next word).
6452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  result = []
6462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  for text_line in text.splitlines():
6472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Store result length so we can find out whether processing the next
6482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # line gave any new content
6492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    old_result_len = len(result)
6502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Process next line with line_regex. For optimization we do an rstrip().
6512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # - process tabs (changes either line or word, see below)
6522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # - process word (first try to squeeze on line, then wrap or force wrap)
6532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Spaces found on the line are ignored, they get added while wrapping as
6542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # needed.
6552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for spaces, current_tabs, word in line_regex.findall(text_line.rstrip()):
6562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # If tabs weren't converted to spaces, handle them now
6572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if current_tabs:
6582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # If the last thing we added was a space anyway then drop
6592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # it. But let's not get rid of the indentation.
6602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if (((result and line != indent) or
6612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis             (not result and line != firstline_indent)) and line[-1] == ' '):
6622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          line = line[:-1]
6632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # Add the tabs, if that means adding whitespace, just add it at
6642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # the line, the rstrip() code while shorten the line down if
6652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # necessary
6662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if tabs_are_whitespace:
6672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          line += tabs * len(current_tabs)
6682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        else:
6692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          # if not all tab replacement is whitespace we prepend it to the word
6702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          word = tabs * len(current_tabs) + word
6712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # Handle the case where word cannot be squeezed onto current last line
6722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if len(line) + len(word) > length and len(indent) + len(word) <= length:
6732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        result.append(line.rstrip())
6742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        line = indent + word
6752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        word = ''
6762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # No space left on line or can we append a space?
6772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if len(line) + 1 >= length:
6782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          result.append(line.rstrip())
6792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          line = indent
6802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        else:
6812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          line += ' '
6822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # Add word and shorten it up to allowed line length. Restart next
6832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # line with indent and repeat, or add a space if we're done (word
6842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # finished) This deals with words that cannot fit on one line
6852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # (e.g. indent + word longer than allowed line length).
6862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      while len(line) + len(word) >= length:
6872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        line += word
6882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        result.append(line[:length])
6892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        word = line[length:]
6902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        line = indent
6912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # Default case, simply append the word and a space
6922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if word:
6932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        line += word + ' '
6942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # End of input line. If we have content we finish the line. If the
6952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # current line is just the indent but we had content in during this
6962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # original line then we need to add an empty line.
6972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if (result and line != indent) or (not result and line != firstline_indent):
6982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      result.append(line.rstrip())
6992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    elif len(result) == old_result_len:
7002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      result.append('')
7012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    line = indent
7022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  return '\n'.join(result)
7042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7062da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef DocToHelp(doc):
7072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Takes a __doc__ string and reformats it as help."""
7082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Get rid of starting and ending white space. Using lstrip() or even
7102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # strip() could drop more than maximum of first line and right space
7112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # of last line.
7122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  doc = doc.strip()
7132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Get rid of all empty lines
7152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  whitespace_only_line = re.compile('^[ \t]+$', re.M)
7162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  doc = whitespace_only_line.sub('', doc)
7172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Cut out common space at line beginnings
7192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  doc = CutCommonSpacePrefix(doc)
7202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Just like this module's comment, comments tend to be aligned somehow.
7222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # In other words they all start with the same amount of white space
7232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # 1) keep double new lines
7242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # 2) keep ws after new lines if not empty line
7252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # 3) all other new lines shall be changed to a space
7262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Solution: Match new lines between non white space and replace with space.
7272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  doc = re.sub('(?<=\S)\n(?=\S)', ' ', doc, re.M)
7282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  return doc
7302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7322da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _GetModuleObjectAndName(globals_dict):
7332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Returns the module that defines a global environment, and its name.
7342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Args:
7362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    globals_dict: A dictionary that should correspond to an environment
7372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      providing the values of the globals.
7382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Returns:
7402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    A pair consisting of (1) module object and (2) module name (a
7412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    string).  Returns (None, None) if the module could not be
7422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    identified.
7432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
7442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # The use of .items() (instead of .iteritems()) is NOT a mistake: if
7452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # a parallel thread imports a module while we iterate over
7462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # .iteritems() (not nice, but possible), we get a RuntimeError ...
7472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Hence, we use the slightly slower but safer .items().
7482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  for name, module in sys.modules.items():
7492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if getattr(module, '__dict__', None) is globals_dict:
7502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if name == '__main__':
7512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # Pick a more informative name for the main module.
7522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        name = sys.argv[0]
7532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return (module, name)
7542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  return (None, None)
7552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7572da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _GetMainModule():
7582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Returns: string, name of the module from which execution started."""
7592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # First, try to use the same logic used by _GetCallingModuleObjectAndName(),
7602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # i.e., call _GetModuleObjectAndName().  For that we first need to
7612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # find the dictionary that the main module uses to store the
7622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # globals.
7632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  #
7642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # That's (normally) the same dictionary object that the deepest
7652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # (oldest) stack frame is using for globals.
7662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  deepest_frame = sys._getframe(0)
7672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  while deepest_frame.f_back is not None:
7682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    deepest_frame = deepest_frame.f_back
7692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  globals_for_main_module = deepest_frame.f_globals
7702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  main_module_name = _GetModuleObjectAndName(globals_for_main_module)[1]
7712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # The above strategy fails in some cases (e.g., tools that compute
7722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # code coverage by redefining, among other things, the main module).
7732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # If so, just use sys.argv[0].  We can probably always do this, but
7742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # it's safest to try to use the same logic as _GetCallingModuleObjectAndName()
7752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if main_module_name is None:
7762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    main_module_name = sys.argv[0]
7772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  return main_module_name
7782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7802da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass FlagValues:
7812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Registry of 'Flag' objects.
7822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  A 'FlagValues' can then scan command line arguments, passing flag
7842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  arguments through to the 'Flag' objects that it owns.  It also
7852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  provides easy access to the flag values.  Typically only one
7862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  'FlagValues' object is needed by an application: gflags.FLAGS
7872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  This class is heavily overloaded:
7892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  'Flag' objects are registered via __setitem__:
7912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis       FLAGS['longname'] = x   # register a new flag
7922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  The .value attribute of the registered 'Flag' objects can be accessed
7942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  as attributes of this 'FlagValues' object, through __getattr__.  Both
7952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  the long and short name of the original 'Flag' objects can be used to
7962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  access its value:
7972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis       FLAGS.longname          # parsed flag value
7982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis       FLAGS.x                 # parsed flag value (short name)
7992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Command line arguments are scanned and passed to the registered 'Flag'
8012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  objects through the __call__ method.  Unparsed arguments, including
8022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  argv[0] (e.g. the program name) are returned.
8032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis       argv = FLAGS(sys.argv)  # scan command line arguments
8042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  The original registered Flag objects can be retrieved through the use
8062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  of the dictionary-like operator, __getitem__:
8072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis       x = FLAGS['longname']   # access the registered Flag object
8082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  The str() operator of a 'FlagValues' object provides help for all of
8102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  the registered 'Flag' objects.
8112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
8122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self):
8142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Since everything in this class is so heavily overloaded, the only
8152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # way of defining and using fields is to access __dict__ directly.
8162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Dictionary: flag name (string) -> Flag object.
8182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.__dict__['__flags'] = {}
8192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Dictionary: module name (string) -> list of Flag objects that are defined
8202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # by that module.
8212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.__dict__['__flags_by_module'] = {}
8222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Dictionary: module id (int) -> list of Flag objects that are defined by
8232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # that module.
8242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.__dict__['__flags_by_module_id'] = {}
8252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Dictionary: module name (string) -> list of Flag objects that are
8262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # key for that module.
8272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.__dict__['__key_flags_by_module'] = {}
8282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Set if we should use new style gnu_getopt rather than getopt when parsing
8302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # the args.  Only possible with Python 2.3+
8312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.UseGnuGetOpt(False)
8322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def UseGnuGetOpt(self, use_gnu_getopt=True):
8342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Use GNU-style scanning. Allows mixing of flag and non-flag arguments.
8352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    See http://docs.python.org/library/getopt.html#getopt.gnu_getopt
8372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
8392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      use_gnu_getopt: wether or not to use GNU style scanning.
8402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
8412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.__dict__['__use_gnu_getopt'] = use_gnu_getopt
8422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def IsGnuGetOpt(self):
8442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return self.__dict__['__use_gnu_getopt']
8452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def FlagDict(self):
8472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return self.__dict__['__flags']
8482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def FlagsByModuleDict(self):
8502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Returns the dictionary of module_name -> list of defined flags.
8512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Returns:
8532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      A dictionary.  Its keys are module names (strings).  Its values
8542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      are lists of Flag objects.
8552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
8562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return self.__dict__['__flags_by_module']
8572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def FlagsByModuleIdDict(self):
8592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Returns the dictionary of module_id -> list of defined flags.
8602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Returns:
8622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      A dictionary.  Its keys are module IDs (ints).  Its values
8632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      are lists of Flag objects.
8642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
8652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return self.__dict__['__flags_by_module_id']
8662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def KeyFlagsByModuleDict(self):
8682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Returns the dictionary of module_name -> list of key flags.
8692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Returns:
8712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      A dictionary.  Its keys are module names (strings).  Its values
8722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      are lists of Flag objects.
8732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
8742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return self.__dict__['__key_flags_by_module']
8752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def _RegisterFlagByModule(self, module_name, flag):
8772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Records the module that defines a specific flag.
8782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    We keep track of which flag is defined by which module so that we
8802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    can later sort the flags by module.
8812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
8832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      module_name: A string, the name of a Python module.
8842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag: A Flag object, a flag that is key to the module.
8852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
8862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flags_by_module = self.FlagsByModuleDict()
8872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flags_by_module.setdefault(module_name, []).append(flag)
8882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def _RegisterFlagByModuleId(self, module_id, flag):
8902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Records the module that defines a specific flag.
8912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
8932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      module_id: An int, the ID of the Python module.
8942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag: A Flag object, a flag that is key to the module.
8952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
8962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flags_by_module_id = self.FlagsByModuleIdDict()
8972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flags_by_module_id.setdefault(module_id, []).append(flag)
8982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
8992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def _RegisterKeyFlagForModule(self, module_name, flag):
9002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Specifies that a flag is a key flag for a module.
9012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
9032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      module_name: A string, the name of a Python module.
9042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag: A Flag object, a flag that is key to the module.
9052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
9062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    key_flags_by_module = self.KeyFlagsByModuleDict()
9072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # The list of key flags for the module named module_name.
9082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    key_flags = key_flags_by_module.setdefault(module_name, [])
9092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Add flag, but avoid duplicates.
9102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if flag not in key_flags:
9112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      key_flags.append(flag)
9122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def _GetFlagsDefinedByModule(self, module):
9142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Returns the list of flags defined by a module.
9152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
9172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      module: A module object or a module name (a string).
9182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Returns:
9202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      A new list of Flag objects.  Caller may update this list as he
9212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      wishes: none of those changes will affect the internals of this
9222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      FlagValue object.
9232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
9242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if not isinstance(module, str):
9252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      module = module.__name__
9262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return list(self.FlagsByModuleDict().get(module, []))
9282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def _GetKeyFlagsForModule(self, module):
9302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Returns the list of key flags for a module.
9312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
9332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      module: A module object or a module name (a string)
9342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Returns:
9362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      A new list of Flag objects.  Caller may update this list as he
9372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      wishes: none of those changes will affect the internals of this
9382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      FlagValue object.
9392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
9402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if not isinstance(module, str):
9412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      module = module.__name__
9422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Any flag is a key flag for the module that defined it.  NOTE:
9442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # key_flags is a fresh list: we can update it without affecting the
9452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # internals of this FlagValues object.
9462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    key_flags = self._GetFlagsDefinedByModule(module)
9472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Take into account flags explicitly declared as key for a module.
9492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for flag in self.KeyFlagsByModuleDict().get(module, []):
9502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if flag not in key_flags:
9512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        key_flags.append(flag)
9522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return key_flags
9532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def FindModuleDefiningFlag(self, flagname, default=None):
9552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Return the name of the module defining this flag, or default.
9562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
9582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flagname: Name of the flag to lookup.
9592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      default: Value to return if flagname is not defined. Defaults
9602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          to None.
9612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Returns:
9632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      The name of the module which registered the flag with this name.
9642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      If no such module exists (i.e. no flag with this name exists),
9652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      we return default.
9662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
9672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for module, flags in self.FlagsByModuleDict().iteritems():
9682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for flag in flags:
9692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if flag.name == flagname or flag.short_name == flagname:
9702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          return module
9712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return default
9722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def FindModuleIdDefiningFlag(self, flagname, default=None):
9742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Return the ID of the module defining this flag, or default.
9752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
9772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flagname: Name of the flag to lookup.
9782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      default: Value to return if flagname is not defined. Defaults
9792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          to None.
9802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Returns:
9822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      The ID of the module which registered the flag with this name.
9832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      If no such module exists (i.e. no flag with this name exists),
9842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      we return default.
9852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
9862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for module_id, flags in self.FlagsByModuleIdDict().iteritems():
9872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for flag in flags:
9882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if flag.name == flagname or flag.short_name == flagname:
9892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          return module_id
9902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return default
9912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def AppendFlagValues(self, flag_values):
9932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Appends flags registered in another FlagValues instance.
9942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
9952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
9962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag_values: registry to copy from
9972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
9982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for flag_name, flag in flag_values.FlagDict().iteritems():
9992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # Each flags with shortname appears here twice (once under its
10002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # normal name, and again with its short name).  To prevent
10012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # problems (DuplicateFlagError) with double flag registration, we
10022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # perform a check to make sure that the entry we're looking at is
10032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # for its normal name.
10042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if flag_name == flag.name:
10052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        try:
10062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          self[flag_name] = flag
10072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        except DuplicateFlagError:
10082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          raise DuplicateFlagError(flag_name, self,
10092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                                   other_flag_values=flag_values)
10102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
10112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def RemoveFlagValues(self, flag_values):
10122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Remove flags that were previously appended from another FlagValues.
10132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
10142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
10152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag_values: registry containing flags to remove.
10162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
10172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for flag_name in flag_values.FlagDict():
10182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      self.__delattr__(flag_name)
10192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
10202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __setitem__(self, name, flag):
10212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Registers a new flag variable."""
10222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    fl = self.FlagDict()
10232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if not isinstance(flag, Flag):
10242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      raise IllegalFlagValue(flag)
10252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if not isinstance(name, type("")):
10262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      raise FlagsError("Flag name must be a string")
10272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if len(name) == 0:
10282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      raise FlagsError("Flag name cannot be empty")
10292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # If running under pychecker, duplicate keys are likely to be
10302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # defined.  Disable check for duplicate keys when pycheck'ing.
10312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if (name in fl and not flag.allow_override and
10322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        not fl[name].allow_override and not _RUNNING_PYCHECKER):
10332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      module, module_name = _GetCallingModuleObjectAndName()
10342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (self.FindModuleDefiningFlag(name) == module_name and
10352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          id(module) != self.FindModuleIdDefiningFlag(name)):
10362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # If the flag has already been defined by a module with the same name,
10372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # but a different ID, we can stop here because it indicates that the
10382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # module is simply being imported a subsequent time.
10392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return
10402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      raise DuplicateFlagError(name, self)
10412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    short_name = flag.short_name
10422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if short_name is not None:
10432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (short_name in fl and not flag.allow_override and
10442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          not fl[short_name].allow_override and not _RUNNING_PYCHECKER):
10452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        raise DuplicateFlagError(short_name, self)
10462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      fl[short_name] = flag
10472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    fl[name] = flag
10482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    global _exported_flags
10492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    _exported_flags[name] = flag
10502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
10512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __getitem__(self, name):
10522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Retrieves the Flag object for the flag --name."""
10532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return self.FlagDict()[name]
10542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
10552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __getattr__(self, name):
10562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Retrieves the 'value' attribute of the flag --name."""
10572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    fl = self.FlagDict()
10582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if name not in fl:
10592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      raise AttributeError(name)
10602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return fl[name].value
10612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
10622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __setattr__(self, name, value):
10632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Sets the 'value' attribute of the flag --name."""
10642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    fl = self.FlagDict()
10652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    fl[name].value = value
10662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self._AssertValidators(fl[name].validators)
10672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return value
10682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
10692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def _AssertAllValidators(self):
10702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    all_validators = set()
10712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for flag in self.FlagDict().itervalues():
10722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for validator in flag.validators:
10732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        all_validators.add(validator)
10742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self._AssertValidators(all_validators)
10752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
10762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def _AssertValidators(self, validators):
10772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Assert if all validators in the list are satisfied.
10782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
10792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Asserts validators in the order they were created.
10802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
10812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      validators: Iterable(gflags_validators.Validator), validators to be
10822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        verified
10832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Raises:
10842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      AttributeError: if validators work with a non-existing flag.
10852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      IllegalFlagValue: if validation fails for at least one validator
10862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
10872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for validator in sorted(
10882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        validators, key=lambda validator: validator.insertion_index):
10892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      try:
10902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        validator.Verify(self)
10912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      except gflags_validators.Error, e:
10922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        message = validator.PrintFlagsWithValues(self)
10932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        raise IllegalFlagValue('%s: %s' % (message, str(e)))
10942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
10952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def _FlagIsRegistered(self, flag_obj):
10962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Checks whether a Flag object is registered under some name.
10972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
10982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Note: this is non trivial: in addition to its normal name, a flag
10992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    may have a short name too.  In self.FlagDict(), both the normal and
11002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    the short name are mapped to the same flag object.  E.g., calling
11012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    only "del FLAGS.short_name" is not unregistering the corresponding
11022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Flag object (it is still registered under the longer name).
11032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
11052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag_obj: A Flag object.
11062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Returns:
11082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      A boolean: True iff flag_obj is registered under some name.
11092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
11102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_dict = self.FlagDict()
11112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Check whether flag_obj is registered under its long name.
11122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    name = flag_obj.name
11132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if flag_dict.get(name, None) == flag_obj:
11142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return True
11152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Check whether flag_obj is registered under its short name.
11162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    short_name = flag_obj.short_name
11172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if (short_name is not None and
11182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flag_dict.get(short_name, None) == flag_obj):
11192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return True
11202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # The flag cannot be registered under any other name, so we do not
11212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # need to do a full search through the values of self.FlagDict().
11222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return False
11232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __delattr__(self, flag_name):
11252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Deletes a previously-defined flag from a flag object.
11262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    This method makes sure we can delete a flag by using
11282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      del flag_values_object.<flag_name>
11302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    E.g.,
11322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      gflags.DEFINE_integer('foo', 1, 'Integer flag.')
11342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      del gflags.FLAGS.foo
11352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
11372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag_name: A string, the name of the flag to be deleted.
11382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Raises:
11402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      AttributeError: When there is no registered flag named flag_name.
11412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
11422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    fl = self.FlagDict()
11432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if flag_name not in fl:
11442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      raise AttributeError(flag_name)
11452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_obj = fl[flag_name]
11472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    del fl[flag_name]
11482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if not self._FlagIsRegistered(flag_obj):
11502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # If the Flag object indicated by flag_name is no longer
11512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # registered (please see the docstring of _FlagIsRegistered), then
11522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # we delete the occurrences of the flag object in all our internal
11532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # dictionaries.
11542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      self.__RemoveFlagFromDictByModule(self.FlagsByModuleDict(), flag_obj)
11552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      self.__RemoveFlagFromDictByModule(self.FlagsByModuleIdDict(), flag_obj)
11562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      self.__RemoveFlagFromDictByModule(self.KeyFlagsByModuleDict(), flag_obj)
11572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __RemoveFlagFromDictByModule(self, flags_by_module_dict, flag_obj):
11592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Removes a flag object from a module -> list of flags dictionary.
11602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
11622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flags_by_module_dict: A dictionary that maps module names to lists of
11632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flags.
11642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag_obj: A flag object.
11652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
11662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for unused_module, flags_in_module in flags_by_module_dict.iteritems():
11672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # while (as opposed to if) takes care of multiple occurrences of a
11682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # flag in the list for the same module.
11692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      while flag_obj in flags_in_module:
11702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flags_in_module.remove(flag_obj)
11712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def SetDefault(self, name, value):
11732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Changes the default value of the named flag object."""
11742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    fl = self.FlagDict()
11752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if name not in fl:
11762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      raise AttributeError(name)
11772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    fl[name].SetDefault(value)
11782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self._AssertValidators(fl[name].validators)
11792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __contains__(self, name):
11812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Returns True if name is a value (flag) in the dict."""
11822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return name in self.FlagDict()
11832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  has_key = __contains__  # a synonym for __contains__()
11852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __iter__(self):
11872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return iter(self.FlagDict())
11882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __call__(self, argv):
11902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Parses flags from argv; stores parsed flags into this FlagValues object.
11912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    All unparsed arguments are returned.  Flags are parsed using the GNU
11932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Program Argument Syntax Conventions, using getopt:
11942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    http://www.gnu.org/software/libc/manual/html_mono/libc.html#Getopt
11962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
11982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis       argv: argument list. Can be of any type that may be converted to a list.
11992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
12002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Returns:
12012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis       The list of arguments not parsed as options, including argv[0]
12022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
12032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Raises:
12042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis       FlagsError: on any parsing error
12052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
12062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Support any sequence type that can be converted to a list
12072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    argv = list(argv)
12082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
12092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    shortopts = ""
12102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    longopts = []
12112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
12122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    fl = self.FlagDict()
12132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
12142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # This pre parses the argv list for --flagfile=<> options.
12152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    argv = argv[:1] + self.ReadFlagsFromFiles(argv[1:], force_gnu=False)
12162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
12172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Correct the argv to support the google style of passing boolean
12182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # parameters.  Boolean parameters may be passed by using --mybool,
12192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # --nomybool, --mybool=(true|false|1|0).  getopt does not support
12202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # having options that may or may not have a parameter.  We replace
12212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # instances of the short form --mybool and --nomybool with their
12222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # full forms: --mybool=(true|false).
12232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    original_argv = list(argv)  # list() makes a copy
12242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    shortest_matches = None
12252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for name, flag in fl.items():
12262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if not flag.boolean:
12272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        continue
12282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if shortest_matches is None:
12292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # Determine the smallest allowable prefix for all flag names
12302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        shortest_matches = self.ShortestUniquePrefixes(fl)
12312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      no_name = 'no' + name
12322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      prefix = shortest_matches[name]
12332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      no_prefix = shortest_matches[no_name]
12342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
12352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # Replace all occurrences of this boolean with extended forms
12362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for arg_idx in range(1, len(argv)):
12372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        arg = argv[arg_idx]
12382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if arg.find('=') >= 0: continue
12392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if arg.startswith('--'+prefix) and ('--'+name).startswith(arg):
12402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          argv[arg_idx] = ('--%s=true' % name)
12412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        elif arg.startswith('--'+no_prefix) and ('--'+no_name).startswith(arg):
12422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          argv[arg_idx] = ('--%s=false' % name)
12432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
12442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Loop over all of the flags, building up the lists of short options
12452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # and long options that will be passed to getopt.  Short options are
12462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # specified as a string of letters, each letter followed by a colon
12472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # if it takes an argument.  Long options are stored in an array of
12482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # strings.  Each string ends with an '=' if it takes an argument.
12492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for name, flag in fl.items():
12502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      longopts.append(name + "=")
12512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if len(name) == 1:  # one-letter option: allow short flag type also
12522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        shortopts += name
12532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if not flag.boolean:
12542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          shortopts += ":"
12552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
12562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    longopts.append('undefok=')
12572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    undefok_flags = []
12582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
12592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # In case --undefok is specified, loop to pick up unrecognized
12602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # options one by one.
12612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    unrecognized_opts = []
12622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    args = argv[1:]
12632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    while True:
12642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      try:
12652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if self.__dict__['__use_gnu_getopt']:
12662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          optlist, unparsed_args = getopt.gnu_getopt(args, shortopts, longopts)
12672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        else:
12682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          optlist, unparsed_args = getopt.getopt(args, shortopts, longopts)
12692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        break
12702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      except getopt.GetoptError, e:
12712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if not e.opt or e.opt in fl:
12722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          # Not an unrecognized option, re-raise the exception as a FlagsError
12732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          raise FlagsError(e)
12742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # Remove offender from args and try again
12752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        for arg_index in range(len(args)):
12762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          if ((args[arg_index] == '--' + e.opt) or
12772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              (args[arg_index] == '-' + e.opt) or
12782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              (args[arg_index].startswith('--' + e.opt + '='))):
12792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            unrecognized_opts.append((e.opt, args[arg_index]))
12802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            args = args[0:arg_index] + args[arg_index+1:]
12812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            break
12822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        else:
12832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          # We should have found the option, so we don't expect to get
12842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          # here.  We could assert, but raising the original exception
12852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          # might work better.
12862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          raise FlagsError(e)
12872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
12882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for name, arg in optlist:
12892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if name == '--undefok':
12902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flag_names = arg.split(',')
12912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        undefok_flags.extend(flag_names)
12922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # For boolean flags, if --undefok=boolflag is specified, then we should
12932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # also accept --noboolflag, in addition to --boolflag.
12942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # Since we don't know the type of the undefok'd flag, this will affect
12952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # non-boolean flags as well.
12962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # NOTE: You shouldn't use --undefok=noboolflag, because then we will
12972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # accept --nonoboolflag here.  We are choosing not to do the conversion
12982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # from noboolflag -> boolflag because of the ambiguity that flag names
12992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # can start with 'no'.
13002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        undefok_flags.extend('no' + name for name in flag_names)
13012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        continue
13022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if name.startswith('--'):
13032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # long option
13042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        name = name[2:]
13052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        short_option = 0
13062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      else:
13072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # short option
13082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        name = name[1:]
13092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        short_option = 1
13102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if name in fl:
13112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flag = fl[name]
13122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if flag.boolean and short_option: arg = 1
13132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flag.Parse(arg)
13142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # If there were unrecognized options, raise an exception unless
13162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # the options were named via --undefok.
13172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for opt, value in unrecognized_opts:
13182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if opt not in undefok_flags:
13192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        raise UnrecognizedFlagError(opt, value)
13202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if unparsed_args:
13222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if self.__dict__['__use_gnu_getopt']:
13232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # if using gnu_getopt just return the program name + remainder of argv.
13242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        ret_val = argv[:1] + unparsed_args
13252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      else:
13262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # unparsed_args becomes the first non-flag detected by getopt to
13272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # the end of argv.  Because argv may have been modified above,
13282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # return original_argv for this region.
13292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        ret_val = argv[:1] + original_argv[-len(unparsed_args):]
13302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    else:
13312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      ret_val = argv[:1]
13322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self._AssertAllValidators()
13342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return ret_val
13352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Reset(self):
13372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Resets the values to the point before FLAGS(argv) was called."""
13382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for f in self.FlagDict().values():
13392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      f.Unparse()
13402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def RegisteredFlags(self):
13422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Returns: a list of the names and short names of all registered flags."""
13432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return list(self.FlagDict())
13442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def FlagValuesDict(self):
13462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Returns: a dictionary that maps flag names to flag values."""
13472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_values = {}
13482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for flag_name in self.RegisteredFlags():
13502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag = self.FlagDict()[flag_name]
13512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag_values[flag_name] = flag.value
13522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return flag_values
13542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __str__(self):
13562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Generates a help string for all known flags."""
13572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return self.GetHelp()
13582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def GetHelp(self, prefix=''):
13602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Generates a help string for all known flags."""
13612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    helplist = []
13622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flags_by_module = self.FlagsByModuleDict()
13642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if flags_by_module:
13652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      modules = sorted(flags_by_module)
13672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # Print the help for the main module first, if possible.
13692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      main_module = _GetMainModule()
13702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if main_module in modules:
13712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        modules.remove(main_module)
13722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        modules = [main_module] + modules
13732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for module in modules:
13752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.__RenderOurModuleFlags(module, helplist)
13762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      self.__RenderModuleFlags('gflags',
13782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                               _SPECIAL_FLAGS.FlagDict().values(),
13792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                               helplist)
13802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    else:
13822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # Just print one long list of flags.
13832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      self.__RenderFlagList(
13842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          self.FlagDict().values() + _SPECIAL_FLAGS.FlagDict().values(),
13852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          helplist, prefix)
13862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return '\n'.join(helplist)
13882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __RenderModuleFlags(self, module, flags, output_lines, prefix=""):
13902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Generates a help string for a given module."""
13912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if not isinstance(module, str):
13922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      module = module.__name__
13932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    output_lines.append('\n%s%s:' % (prefix, module))
13942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.__RenderFlagList(flags, output_lines, prefix + "  ")
13952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
13962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __RenderOurModuleFlags(self, module, output_lines, prefix=""):
13972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Generates a help string for a given module."""
13982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flags = self._GetFlagsDefinedByModule(module)
13992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if flags:
14002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      self.__RenderModuleFlags(module, flags, output_lines, prefix)
14012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
14022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __RenderOurModuleKeyFlags(self, module, output_lines, prefix=""):
14032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Generates a help string for the key flags of a given module.
14042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
14052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
14062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      module: A module object or a module name (a string).
14072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      output_lines: A list of strings.  The generated help message
14082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        lines will be appended to this list.
14092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      prefix: A string that is prepended to each generated help line.
14102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
14112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    key_flags = self._GetKeyFlagsForModule(module)
14122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if key_flags:
14132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      self.__RenderModuleFlags(module, key_flags, output_lines, prefix)
14142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
14152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def ModuleHelp(self, module):
14162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Describe the key flags of a module.
14172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
14182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
14192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      module: A module object or a module name (a string).
14202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
14212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Returns:
14222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      string describing the key flags of a module.
14232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
14242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    helplist = []
14252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.__RenderOurModuleKeyFlags(module, helplist)
14262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return '\n'.join(helplist)
14272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
14282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def MainModuleHelp(self):
14292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Describe the key flags of the main module.
14302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
14312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Returns:
14322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      string describing the key flags of a module.
14332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
14342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return self.ModuleHelp(_GetMainModule())
14352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
14362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __RenderFlagList(self, flaglist, output_lines, prefix="  "):
14372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    fl = self.FlagDict()
14382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    special_fl = _SPECIAL_FLAGS.FlagDict()
14392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flaglist = [(flag.name, flag) for flag in flaglist]
14402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flaglist.sort()
14412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flagset = {}
14422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for (name, flag) in flaglist:
14432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # It's possible this flag got deleted or overridden since being
14442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # registered in the per-module flaglist.  Check now against the
14452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # canonical source of current flag information, the FlagDict.
14462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if fl.get(name, None) != flag and special_fl.get(name, None) != flag:
14472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # a different flag is using this name now
14482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        continue
14492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # only print help once
14502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if flag in flagset: continue
14512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flagset[flag] = 1
14522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flaghelp = ""
14532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if flag.short_name: flaghelp += "-%s," % flag.short_name
14542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if flag.boolean:
14552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flaghelp += "--[no]%s" % flag.name + ":"
14562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      else:
14572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flaghelp += "--%s" % flag.name + ":"
14582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flaghelp += "  "
14592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if flag.help:
14602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flaghelp += flag.help
14612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flaghelp = TextWrap(flaghelp, indent=prefix+"  ",
14622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                          firstline_indent=prefix)
14632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if flag.default_as_str:
14642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flaghelp += "\n"
14652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flaghelp += TextWrap("(default: %s)" % flag.default_as_str,
14662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                             indent=prefix+"  ")
14672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if flag.parser.syntactic_help:
14682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flaghelp += "\n"
14692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flaghelp += TextWrap("(%s)" % flag.parser.syntactic_help,
14702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                             indent=prefix+"  ")
14712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      output_lines.append(flaghelp)
14722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
14732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def get(self, name, default):
14742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Returns the value of a flag (if not None) or a default value.
14752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
14762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
14772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      name: A string, the name of a flag.
14782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      default: Default value to use if the flag value is None.
14792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
14802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
14812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    value = self.__getattr__(name)
14822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if value is not None:  # Can't do if not value, b/c value might be '0' or ""
14832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return value
14842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    else:
14852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return default
14862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
14872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def ShortestUniquePrefixes(self, fl):
14882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Returns: dictionary; maps flag names to their shortest unique prefix."""
14892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Sort the list of flag names
14902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    sorted_flags = []
14912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for name, flag in fl.items():
14922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sorted_flags.append(name)
14932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if flag.boolean:
14942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        sorted_flags.append('no%s' % name)
14952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    sorted_flags.sort()
14962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
14972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # For each name in the sorted list, determine the shortest unique
14982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # prefix by comparing itself to the next name and to the previous
14992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # name (the latter check uses cached info from the previous loop).
15002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    shortest_matches = {}
15012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    prev_idx = 0
15022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for flag_idx in range(len(sorted_flags)):
15032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      curr = sorted_flags[flag_idx]
15042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if flag_idx == (len(sorted_flags) - 1):
15052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        next = None
15062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      else:
15072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        next = sorted_flags[flag_idx+1]
15082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        next_len = len(next)
15092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for curr_idx in range(len(curr)):
15102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if (next is None
15112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            or curr_idx >= next_len
15122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            or curr[curr_idx] != next[curr_idx]):
15132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          # curr longer than next or no more chars in common
15142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          shortest_matches[curr] = curr[:max(prev_idx, curr_idx) + 1]
15152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          prev_idx = curr_idx
15162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          break
15172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      else:
15182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # curr shorter than (or equal to) next
15192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        shortest_matches[curr] = curr
15202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        prev_idx = curr_idx + 1  # next will need at least one more char
15212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return shortest_matches
15222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
15232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __IsFlagFileDirective(self, flag_string):
15242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Checks whether flag_string contain a --flagfile=<foo> directive."""
15252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if isinstance(flag_string, type("")):
15262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if flag_string.startswith('--flagfile='):
15272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return 1
15282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      elif flag_string == '--flagfile':
15292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return 1
15302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      elif flag_string.startswith('-flagfile='):
15312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return 1
15322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      elif flag_string == '-flagfile':
15332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return 1
15342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      else:
15352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return 0
15362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return 0
15372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
15382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def ExtractFilename(self, flagfile_str):
15392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Returns filename from a flagfile_str of form -[-]flagfile=filename.
15402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
15412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    The cases of --flagfile foo and -flagfile foo shouldn't be hitting
15422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    this function, as they are dealt with in the level above this
15432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    function.
15442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
15452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if flagfile_str.startswith('--flagfile='):
15462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return os.path.expanduser((flagfile_str[(len('--flagfile=')):]).strip())
15472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    elif flagfile_str.startswith('-flagfile='):
15482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return os.path.expanduser((flagfile_str[(len('-flagfile=')):]).strip())
15492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    else:
15502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      raise FlagsError('Hit illegal --flagfile type: %s' % flagfile_str)
15512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
15522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __GetFlagFileLines(self, filename, parsed_file_list):
15532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Returns the useful (!=comments, etc) lines from a file with flags.
15542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
15552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
15562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      filename: A string, the name of the flag file.
15572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      parsed_file_list: A list of the names of the files we have
15582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        already read.  MUTATED BY THIS FUNCTION.
15592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
15602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Returns:
15612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      List of strings. See the note below.
15622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
15632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    NOTE(springer): This function checks for a nested --flagfile=<foo>
15642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    tag and handles the lower file recursively. It returns a list of
15652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    all the lines that _could_ contain command flags. This is
15662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    EVERYTHING except whitespace lines and comments (lines starting
15672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    with '#' or '//').
15682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
15692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    line_list = []  # All line from flagfile.
15702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_line_list = []  # Subset of lines w/o comments, blanks, flagfile= tags.
15712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    try:
15722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      file_obj = open(filename, 'r')
15732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    except IOError, e_msg:
15742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      raise CantOpenFlagFileError('ERROR:: Unable to open flagfile: %s' % e_msg)
15752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
15762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    line_list = file_obj.readlines()
15772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    file_obj.close()
15782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    parsed_file_list.append(filename)
15792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
15802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # This is where we check each line in the file we just read.
15812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for line in line_list:
15822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if line.isspace():
15832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        pass
15842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # Checks for comment (a line that starts with '#').
15852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      elif line.startswith('#') or line.startswith('//'):
15862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        pass
15872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # Checks for a nested "--flagfile=<bar>" flag in the current file.
15882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # If we find one, recursively parse down into that file.
15892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      elif self.__IsFlagFileDirective(line):
15902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        sub_filename = self.ExtractFilename(line)
15912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # We do a little safety check for reparsing a file we've already done.
15922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if not sub_filename in parsed_file_list:
15932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          included_flags = self.__GetFlagFileLines(sub_filename,
15942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                                                   parsed_file_list)
15952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          flag_line_list.extend(included_flags)
15962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        else:  # Case of hitting a circularly included file.
15972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          sys.stderr.write('Warning: Hit circular flagfile dependency: %s\n' %
15982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                           (sub_filename,))
15992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      else:
16002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # Any line that's not a comment or a nested flagfile should get
16012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # copied into 2nd position.  This leaves earlier arguments
16022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # further back in the list, thus giving them higher priority.
16032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flag_line_list.append(line.strip())
16042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return flag_line_list
16052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
16062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def ReadFlagsFromFiles(self, argv, force_gnu=True):
16072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Processes command line args, but also allow args to be read from file.
16082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
16092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
16102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      argv: A list of strings, usually sys.argv[1:], which may contain one or
16112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        more flagfile directives of the form --flagfile="./filename".
16122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        Note that the name of the program (sys.argv[0]) should be omitted.
16132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      force_gnu: If False, --flagfile parsing obeys normal flag semantics.
16142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        If True, --flagfile parsing instead follows gnu_getopt semantics.
16152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        *** WARNING *** force_gnu=False may become the future default!
16162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
16172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Returns:
16182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
16192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      A new list which has the original list combined with what we read
16202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      from any flagfile(s).
16212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
16222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    References: Global gflags.FLAG class instance.
16232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
16242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    This function should be called before the normal FLAGS(argv) call.
16252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    This function scans the input list for a flag that looks like:
16262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    --flagfile=<somefile>. Then it opens <somefile>, reads all valid key
16272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    and value pairs and inserts them into the input list between the
16282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    first item of the list and any subsequent items in the list.
16292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
16302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Note that your application's flags are still defined the usual way
16312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    using gflags DEFINE_flag() type functions.
16322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
16332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Notes (assuming we're getting a commandline of some sort as our input):
16342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    --> Flags from the command line argv _should_ always take precedence!
16352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    --> A further "--flagfile=<otherfile.cfg>" CAN be nested in a flagfile.
16362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        It will be processed after the parent flag file is done.
16372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    --> For duplicate flags, first one we hit should "win".
16382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    --> In a flagfile, a line beginning with # or // is a comment.
16392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    --> Entirely blank lines _should_ be ignored.
16402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
16412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    parsed_file_list = []
16422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    rest_of_args = argv
16432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    new_argv = []
16442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    while rest_of_args:
16452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      current_arg = rest_of_args[0]
16462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      rest_of_args = rest_of_args[1:]
16472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if self.__IsFlagFileDirective(current_arg):
16482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # This handles the case of -(-)flagfile foo.  In this case the
16492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # next arg really is part of this one.
16502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if current_arg == '--flagfile' or current_arg == '-flagfile':
16512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          if not rest_of_args:
16522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            raise IllegalFlagValue('--flagfile with no argument')
16532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          flag_filename = os.path.expanduser(rest_of_args[0])
16542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          rest_of_args = rest_of_args[1:]
16552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        else:
16562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          # This handles the case of (-)-flagfile=foo.
16572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          flag_filename = self.ExtractFilename(current_arg)
16582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        new_argv.extend(
16592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self.__GetFlagFileLines(flag_filename, parsed_file_list))
16602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      else:
16612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        new_argv.append(current_arg)
16622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # Stop parsing after '--', like getopt and gnu_getopt.
16632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if current_arg == '--':
16642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          break
16652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # Stop parsing after a non-flag, like getopt.
16662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if not current_arg.startswith('-'):
16672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          if not force_gnu and not self.__dict__['__use_gnu_getopt']:
16682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            break
16692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
16702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if rest_of_args:
16712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      new_argv.extend(rest_of_args)
16722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
16732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return new_argv
16742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
16752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def FlagsIntoString(self):
16762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Returns a string with the flags assignments from this FlagValues object.
16772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
16782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    This function ignores flags whose value is None.  Each flag
16792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    assignment is separated by a newline.
16802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
16812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    NOTE: MUST mirror the behavior of the C++ CommandlineFlagsIntoString
16822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    from http://code.google.com/p/google-gflags
16832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
16842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    s = ''
16852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for flag in self.FlagDict().values():
16862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if flag.value is not None:
16872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        s += flag.Serialize() + '\n'
16882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return s
16892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
16902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def AppendFlagsIntoFile(self, filename):
16912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Appends all flags assignments from this FlagInfo object to a file.
16922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
16932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Output will be in the format of a flagfile.
16942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
16952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    NOTE: MUST mirror the behavior of the C++ AppendFlagsIntoFile
16962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    from http://code.google.com/p/google-gflags
16972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
16982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    out_file = open(filename, 'a')
16992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    out_file.write(self.FlagsIntoString())
17002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    out_file.close()
17012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def WriteHelpInXMLFormat(self, outfile=None):
17032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Outputs flag documentation in XML format.
17042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    NOTE: We use element names that are consistent with those used by
17062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    the C++ command-line flag library, from
17072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    http://code.google.com/p/google-gflags
17082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    We also use a few new elements (e.g., <key>), but we do not
17092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    interfere / overlap with existing XML elements used by the C++
17102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    library.  Please maintain this consistency.
17112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
17132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      outfile: File object we write to.  Default None means sys.stdout.
17142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
17152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    outfile = outfile or sys.stdout
17162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    outfile.write('<?xml version=\"1.0\"?>\n')
17182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    outfile.write('<AllFlags>\n')
17192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    indent = '  '
17202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    _WriteSimpleXMLElement(outfile, 'program', os.path.basename(sys.argv[0]),
17212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                           indent)
17222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    usage_doc = sys.modules['__main__'].__doc__
17242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if not usage_doc:
17252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      usage_doc = '\nUSAGE: %s [flags]\n' % sys.argv[0]
17262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    else:
17272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      usage_doc = usage_doc.replace('%s', sys.argv[0])
17282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    _WriteSimpleXMLElement(outfile, 'usage', usage_doc, indent)
17292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Get list of key flags for the main module.
17312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    key_flags = self._GetKeyFlagsForModule(_GetMainModule())
17322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Sort flags by declaring module name and next by flag name.
17342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flags_by_module = self.FlagsByModuleDict()
17352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    all_module_names = list(flags_by_module.keys())
17362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    all_module_names.sort()
17372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for module_name in all_module_names:
17382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag_list = [(f.name, f) for f in flags_by_module[module_name]]
17392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag_list.sort()
17402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for unused_flag_name, flag in flag_list:
17412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        is_key = flag in key_flags
17422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flag.WriteInfoInXMLFormat(outfile, module_name,
17432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                                  is_key=is_key, indent=indent)
17442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    outfile.write('</AllFlags>\n')
17462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    outfile.flush()
17472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def AddValidator(self, validator):
17492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Register new flags validator to be checked.
17502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
17522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      validator: gflags_validators.Validator
17532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Raises:
17542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      AttributeError: if validators work with a non-existing flag.
17552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
17562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for flag_name in validator.GetFlagsNames():
17572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag = self.FlagDict()[flag_name]
17582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag.validators.append(validator)
17592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# end of FlagValues definition
17612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# The global FlagValues instance
17642da489cd246702bee5938545b18a6f710ed214bcJamie GennisFLAGS = FlagValues()
17652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17672da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _StrOrUnicode(value):
17682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Converts value to a python string or, if necessary, unicode-string."""
17692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  try:
17702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return str(value)
17712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  except UnicodeEncodeError:
17722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return unicode(value)
17732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17752da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _MakeXMLSafe(s):
17762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Escapes <, >, and & from s, and removes XML 1.0-illegal chars."""
17772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  s = cgi.escape(s)  # Escape <, >, and &
17782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Remove characters that cannot appear in an XML 1.0 document
17792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # (http://www.w3.org/TR/REC-xml/#charsets).
17802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  #
17812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # NOTE: if there are problems with current solution, one may move to
17822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # XML 1.1, which allows such chars, if they're entity-escaped (&#xHH;).
17832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  s = re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f]', '', s)
17842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Convert non-ascii characters to entities.  Note: requires python >=2.3
17852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  s = s.encode('ascii', 'xmlcharrefreplace')   # u'\xce\x88' -> 'u&#904;'
17862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  return s
17872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17892da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _WriteSimpleXMLElement(outfile, name, value, indent):
17902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Writes a simple XML element.
17912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
17922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Args:
17932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    outfile: File object we write the XML element to.
17942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    name: A string, the name of XML element.
17952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    value: A Python object, whose string representation will be used
17962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      as the value of the XML element.
17972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    indent: A string, prepended to each line of generated output.
17982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
17992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  value_str = _StrOrUnicode(value)
18002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if isinstance(value, bool):
18012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Display boolean values as the C++ flag library does: no caps.
18022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    value_str = value_str.lower()
18032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  safe_value_str = _MakeXMLSafe(value_str)
18042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  outfile.write('%s<%s>%s</%s>\n' % (indent, name, safe_value_str, name))
18052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18072da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass Flag:
18082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Information about a command-line flag.
18092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  'Flag' objects define the following fields:
18112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    .name  - the name for this flag
18122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    .default - the default value for this flag
18132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    .default_as_str - default value as repr'd string, e.g., "'true'" (or None)
18142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    .value  - the most recent parsed value of this flag; set by Parse()
18152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    .help  - a help string or None if no help is available
18162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    .short_name  - the single letter alias for this flag (or None)
18172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    .boolean  - if 'true', this flag does not accept arguments
18182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    .present  - true if this flag was parsed from command line flags.
18192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    .parser  - an ArgumentParser object
18202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    .serializer - an ArgumentSerializer object
18212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    .allow_override - the flag may be redefined without raising an error
18222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  The only public method of a 'Flag' object is Parse(), but it is
18242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  typically only called by a 'FlagValues' object.  The Parse() method is
18252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  a thin wrapper around the 'ArgumentParser' Parse() method.  The parsed
18262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  value is saved in .value, and the .present attribute is updated.  If
18272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  this flag was already present, a FlagsError is raised.
18282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Parse() is also called during __init__ to parse the default value and
18302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  initialize the .value attribute.  This enables other python modules to
18312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  safely use flags even if the __main__ module neglects to parse the
18322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  command line arguments.  The .present attribute is cleared after
18332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  __init__ parsing.  If the default value is set to None, then the
18342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  __init__ parsing step is skipped and the .value attribute is
18352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  initialized to None.
18362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Note: The default value is also presented to the user in the help
18382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  string, so it is important that it be a legal value for this flag.
18392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
18402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self, parser, serializer, name, default, help_string,
18422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis               short_name=None, boolean=0, allow_override=0):
18432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.name = name
18442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if not help_string:
18462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      help_string = '(no help available)'
18472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.help = help_string
18492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.short_name = short_name
18502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.boolean = boolean
18512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.present = 0
18522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.parser = parser
18532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.serializer = serializer
18542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.allow_override = allow_override
18552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.value = None
18562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.validators = []
18572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.SetDefault(default)
18592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __hash__(self):
18612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return hash(id(self))
18622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __eq__(self, other):
18642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return self is other
18652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __lt__(self, other):
18672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if isinstance(other, Flag):
18682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return id(self) < id(other)
18692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return NotImplemented
18702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __GetParsedValueAsString(self, value):
18722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if value is None:
18732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return None
18742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if self.serializer:
18752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return repr(self.serializer.Serialize(value))
18762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if self.boolean:
18772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if value:
18782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return repr('true')
18792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      else:
18802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return repr('false')
18812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return repr(_StrOrUnicode(value))
18822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Parse(self, argument):
18842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    try:
18852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      self.value = self.parser.Parse(argument)
18862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    except ValueError, e:  # recast ValueError as IllegalFlagValue
18872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      raise IllegalFlagValue("flag --%s=%s: %s" % (self.name, argument, e))
18882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.present += 1
18892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Unparse(self):
18912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if self.default is None:
18922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      self.value = None
18932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    else:
18942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      self.Parse(self.default)
18952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.present = 0
18962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
18972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Serialize(self):
18982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if self.value is None:
18992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return ''
19002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if self.boolean:
19012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if self.value:
19022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return "--%s" % self.name
19032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      else:
19042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return "--no%s" % self.name
19052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    else:
19062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if not self.serializer:
19072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        raise FlagsError("Serializer not present for flag %s" % self.name)
19082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return "--%s=%s" % (self.name, self.serializer.Serialize(self.value))
19092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
19102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def SetDefault(self, value):
19112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Changes the default value (and current value too) for this Flag."""
19122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # We can't allow a None override because it may end up not being
19132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # passed to C++ code when we're overriding C++ flags.  So we
19142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # cowardly bail out until someone fixes the semantics of trying to
19152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # pass None to a C++ flag.  See swig_flags.Init() for details on
19162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # this behavior.
19172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # TODO(olexiy): Users can directly call this method, bypassing all flags
19182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # validators (we don't have FlagValues here, so we can not check
19192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # validators).
19202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # The simplest solution I see is to make this method private.
19212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Another approach would be to store reference to the corresponding
19222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # FlagValues with each flag, but this seems to be an overkill.
19232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if value is None and self.allow_override:
19242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      raise DuplicateFlagCannotPropagateNoneToSwig(self.name)
19252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
19262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.default = value
19272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.Unparse()
19282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.default_as_str = self.__GetParsedValueAsString(self.value)
19292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
19302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Type(self):
19312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Returns: a string that describes the type of this Flag."""
19322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # NOTE: we use strings, and not the types.*Type constants because
19332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # our flags can have more exotic types, e.g., 'comma separated list
19342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # of strings', 'whitespace separated list of strings', etc.
19352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return self.parser.Type()
19362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
19372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def WriteInfoInXMLFormat(self, outfile, module_name, is_key=False, indent=''):
19382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Writes common info about this flag, in XML format.
19392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
19402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    This is information that is relevant to all flags (e.g., name,
19412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    meaning, etc.).  If you defined a flag that has some other pieces of
19422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    info, then please override _WriteCustomInfoInXMLFormat.
19432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
19442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Please do NOT override this method.
19452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
19462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
19472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      outfile: File object we write to.
19482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      module_name: A string, the name of the module that defines this flag.
19492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      is_key: A boolean, True iff this flag is key for main module.
19502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      indent: A string that is prepended to each generated line.
19512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
19522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    outfile.write(indent + '<flag>\n')
19532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    inner_indent = indent + '  '
19542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if is_key:
19552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      _WriteSimpleXMLElement(outfile, 'key', 'yes', inner_indent)
19562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    _WriteSimpleXMLElement(outfile, 'file', module_name, inner_indent)
19572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Print flag features that are relevant for all flags.
19582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    _WriteSimpleXMLElement(outfile, 'name', self.name, inner_indent)
19592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if self.short_name:
19602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      _WriteSimpleXMLElement(outfile, 'short_name', self.short_name,
19612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                             inner_indent)
19622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if self.help:
19632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      _WriteSimpleXMLElement(outfile, 'meaning', self.help, inner_indent)
19642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # The default flag value can either be represented as a string like on the
19652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # command line, or as a Python object.  We serialize this value in the
19662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # latter case in order to remain consistent.
19672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if self.serializer and not isinstance(self.default, str):
19682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      default_serialized = self.serializer.Serialize(self.default)
19692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    else:
19702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      default_serialized = self.default
19712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    _WriteSimpleXMLElement(outfile, 'default', default_serialized, inner_indent)
19722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    _WriteSimpleXMLElement(outfile, 'current', self.value, inner_indent)
19732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    _WriteSimpleXMLElement(outfile, 'type', self.Type(), inner_indent)
19742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Print extra flag features this flag may have.
19752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self._WriteCustomInfoInXMLFormat(outfile, inner_indent)
19762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    outfile.write(indent + '</flag>\n')
19772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
19782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def _WriteCustomInfoInXMLFormat(self, outfile, indent):
19792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Writes extra info about this flag, in XML format.
19802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
19812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    "Extra" means "not already printed by WriteInfoInXMLFormat above."
19822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
19832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
19842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      outfile: File object we write to.
19852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      indent: A string that is prepended to each generated line.
19862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
19872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Usually, the parser knows the extra details about the flag, so
19882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # we just forward the call to it.
19892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.parser.WriteCustomInfoInXMLFormat(outfile, indent)
19902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# End of Flag definition
19912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
19922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
19932da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass _ArgumentParserCache(type):
19942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Metaclass used to cache and share argument parsers among flags."""
19952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
19962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  _instances = {}
19972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
19982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __call__(mcs, *args, **kwargs):
19992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Returns an instance of the argument parser cls.
20002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    This method overrides behavior of the __new__ methods in
20022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    all subclasses of ArgumentParser (inclusive). If an instance
20032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for mcs with the same set of arguments exists, this instance is
20042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    returned, otherwise a new instance is created.
20052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    If any keyword arguments are defined, or the values in args
20072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    are not hashable, this method always returns a new instance of
20082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    cls.
20092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
20112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      args: Positional initializer arguments.
20122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      kwargs: Initializer keyword arguments.
20132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Returns:
20152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      An instance of cls, shared or new.
20162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
20172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if kwargs:
20182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return type.__call__(mcs, *args, **kwargs)
20192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    else:
20202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      instances = mcs._instances
20212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      key = (mcs,) + tuple(args)
20222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      try:
20232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return instances[key]
20242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      except KeyError:
20252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # No cache entry for key exists, create a new one.
20262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return instances.setdefault(key, type.__call__(mcs, *args))
20272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      except TypeError:
20282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # An object in args cannot be hashed, always return
20292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # a new instance.
20302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return type.__call__(mcs, *args)
20312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20332da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass ArgumentParser(object):
20342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Base class used to parse and convert arguments.
20352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  The Parse() method checks to make sure that the string argument is a
20372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  legal value and convert it to a native type.  If the value cannot be
20382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  converted, it should throw a 'ValueError' exception with a human
20392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  readable explanation of why the value is illegal.
20402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Subclasses should also define a syntactic_help string which may be
20422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  presented to the user to describe the form of the legal values.
20432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Argument parser classes must be stateless, since instances are cached
20452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  and shared between flags. Initializer arguments are allowed, but all
20462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  member variables must be derived from initializer arguments only.
20472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
20482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  __metaclass__ = _ArgumentParserCache
20492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  syntactic_help = ""
20512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Parse(self, argument):
20532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Default implementation: always returns its argument unmodified."""
20542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return argument
20552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Type(self):
20572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return 'string'
20582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def WriteCustomInfoInXMLFormat(self, outfile, indent):
20602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    pass
20612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20632da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass ArgumentSerializer:
20642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Base class for generating string representations of a flag value."""
20652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Serialize(self, value):
20672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return _StrOrUnicode(value)
20682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20702da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass ListSerializer(ArgumentSerializer):
20712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self, list_sep):
20732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.list_sep = list_sep
20742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Serialize(self, value):
20762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return self.list_sep.join([_StrOrUnicode(x) for x in value])
20772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Flags validators
20802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20822da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef RegisterValidator(flag_name,
20832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                      checker,
20842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                      message='Flag validation failed',
20852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                      flag_values=FLAGS):
20862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Adds a constraint, which will be enforced during program execution.
20872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
20882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  The constraint is validated when flags are initially parsed, and after each
20892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  change of the corresponding flag's value.
20902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Args:
20912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_name: string, name of the flag to be checked.
20922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    checker: method to validate the flag.
20932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      input  - value of the corresponding flag (string, boolean, etc.
20942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        This value will be passed to checker by the library). See file's
20952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        docstring for examples.
20962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      output - Boolean.
20972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        Must return True if validator constraint is satisfied.
20982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        If constraint is not satisfied, it should either return False or
20992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          raise gflags_validators.Error(desired_error_message).
21002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    message: error text to be shown to the user if checker returns False.
21012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      If checker raises gflags_validators.Error, message from the raised
21022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        Error will be shown.
21032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_values: FlagValues
21042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Raises:
21052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    AttributeError: if flag_name is not registered as a valid flag name.
21062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
21072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  flag_values.AddValidator(gflags_validators.SimpleValidator(flag_name,
21082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                                                            checker,
21092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                                                            message))
21102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21122da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef MarkFlagAsRequired(flag_name, flag_values=FLAGS):
21132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Ensure that flag is not None during program execution.
21142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Registers a flag validator, which will follow usual validator
21162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  rules.
21172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Args:
21182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_name: string, name of the flag
21192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_values: FlagValues
21202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Raises:
21212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    AttributeError: if flag_name is not registered as a valid flag name.
21222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
21232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  RegisterValidator(flag_name,
21242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                    lambda value: value is not None,
21252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                    message='Flag --%s must be specified.' % flag_name,
21262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                    flag_values=flag_values)
21272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21292da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _RegisterBoundsValidatorIfNeeded(parser, name, flag_values):
21302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Enforce lower and upper bounds for numeric flags.
21312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Args:
21332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    parser: NumericParser (either FloatParser or IntegerParser). Provides lower
21342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      and upper bounds, and help text to display.
21352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    name: string, name of the flag
21362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_values: FlagValues
21372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
21382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if parser.lower_bound is not None or parser.upper_bound is not None:
21392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def Checker(value):
21412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if value is not None and parser.IsOutsideBounds(value):
21422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        message = '%s is not %s' % (value, parser.syntactic_help)
21432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        raise gflags_validators.Error(message)
21442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return True
21452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    RegisterValidator(name,
21472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                      Checker,
21482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                      flag_values=flag_values)
21492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# The DEFINE functions are explained in mode details in the module doc string.
21522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21542da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef DEFINE(parser, name, default, help, flag_values=FLAGS, serializer=None,
21552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis           **args):
21562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Registers a generic Flag object.
21572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  NOTE: in the docstrings of all DEFINE* functions, "registers" is short
21592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  for "creates a new flag and registers it".
21602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Auxiliary function: clients should use the specialized DEFINE_<type>
21622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  function instead.
21632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Args:
21652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    parser: ArgumentParser that is used to parse the flag arguments.
21662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    name: A string, the flag name.
21672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    default: The default value of the flag.
21682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    help: A help string.
21692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_values: FlagValues object the flag will be registered with.
21702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    serializer: ArgumentSerializer that serializes the flag value.
21712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    args: Dictionary with extra keyword args that are passes to the
21722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      Flag __init__.
21732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
21742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  DEFINE_flag(Flag(parser, serializer, name, default, help, **args),
21752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              flag_values)
21762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21782da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef DEFINE_flag(flag, flag_values=FLAGS):
21792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Registers a 'Flag' object with a 'FlagValues' object.
21802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  By default, the global FLAGS 'FlagValue' object is used.
21822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
21832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Typical users will use one of the more specialized DEFINE_xxx
21842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  functions, such as DEFINE_string or DEFINE_integer.  But developers
21852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  who need to create Flag objects themselves should use this function
21862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  to register their flags.
21872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
21882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # copying the reference to flag_values prevents pychecker warnings
21892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  fv = flag_values
21902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  fv[flag.name] = flag
21912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # Tell flag_values who's defining the flag.
21922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if isinstance(flag_values, FlagValues):
21932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Regarding the above isinstance test: some users pass funny
21942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # values of flag_values (e.g., {}) in order to avoid the flag
21952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # registration (in the past, there used to be a flag_values ==
21962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # FLAGS test here) and redefine flags with the same name (e.g.,
21972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # debug).  To avoid breaking their code, we perform the
21982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # registration only if flag_values is a real FlagValues object.
21992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    module, module_name = _GetCallingModuleObjectAndName()
22002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_values._RegisterFlagByModule(module_name, flag)
22012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_values._RegisterFlagByModuleId(id(module), flag)
22022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22042da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _InternalDeclareKeyFlags(flag_names,
22052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                             flag_values=FLAGS, key_flag_values=None):
22062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Declares a flag as key for the calling module.
22072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Internal function.  User code should call DECLARE_key_flag or
22092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  ADOPT_module_key_flags instead.
22102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Args:
22122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_names: A list of strings that are names of already-registered
22132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      Flag objects.
22142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_values: A FlagValues object that the flags listed in
22152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag_names have registered with (the value of the flag_values
22162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      argument from the DEFINE_* calls that defined those flags).
22172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      This should almost never need to be overridden.
22182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    key_flag_values: A FlagValues object that (among possibly many
22192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      other things) keeps track of the key flags for each module.
22202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      Default None means "same as flag_values".  This should almost
22212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      never need to be overridden.
22222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Raises:
22242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    UnrecognizedFlagError: when we refer to a flag that was not
22252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      defined yet.
22262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
22272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  key_flag_values = key_flag_values or flag_values
22282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  module = _GetCallingModule()
22302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  for flag_name in flag_names:
22322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if flag_name not in flag_values:
22332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      raise UnrecognizedFlagError(flag_name)
22342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag = flag_values.FlagDict()[flag_name]
22352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    key_flag_values._RegisterKeyFlagForModule(module, flag)
22362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22382da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef DECLARE_key_flag(flag_name, flag_values=FLAGS):
22392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Declares one flag as key to the current module.
22402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Key flags are flags that are deemed really important for a module.
22422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  They are important when listing help messages; e.g., if the
22432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  --helpshort command-line flag is used, then only the key flags of the
22442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  main module are listed (instead of all flags, as in the case of
22452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  --help).
22462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Sample usage:
22482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    gflags.DECLARED_key_flag('flag_1')
22502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Args:
22522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_name: A string, the name of an already declared flag.
22532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      (Redeclaring flags as key, including flags implicitly key
22542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      because they were declared in this module, is a no-op.)
22552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_values: A FlagValues object.  This should almost never
22562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      need to be overridden.
22572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
22582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if flag_name in _SPECIAL_FLAGS:
22592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Take care of the special flags, e.g., --flagfile, --undefok.
22602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # These flags are defined in _SPECIAL_FLAGS, and are treated
22612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # specially during flag parsing, taking precedence over the
22622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # user-defined flags.
22632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    _InternalDeclareKeyFlags([flag_name],
22642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                             flag_values=_SPECIAL_FLAGS,
22652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                             key_flag_values=flag_values)
22662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return
22672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  _InternalDeclareKeyFlags([flag_name], flag_values=flag_values)
22682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22702da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef ADOPT_module_key_flags(module, flag_values=FLAGS):
22712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Declares that all flags key to a module are key to the current module.
22722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Args:
22742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    module: A module object.
22752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    flag_values: A FlagValues object.  This should almost never need
22762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      to be overridden.
22772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
22782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Raises:
22792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    FlagsError: When given an argument that is a module name (a
22802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    string), instead of a module object.
22812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
22822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # NOTE(salcianu): an even better test would be if not
22832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # isinstance(module, types.ModuleType) but I didn't want to import
22842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # types for such a tiny use.
22852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if isinstance(module, str):
22862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    raise FlagsError('Received module name %s; expected a module object.'
22872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                     % module)
22882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  _InternalDeclareKeyFlags(
22892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      [f.name for f in flag_values._GetKeyFlagsForModule(module.__name__)],
22902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flag_values=flag_values)
22912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  # If module is this flag module, take _SPECIAL_FLAGS into account.
22922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if module == _GetThisModuleObjectAndName()[0]:
22932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    _InternalDeclareKeyFlags(
22942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # As we associate flags with _GetCallingModuleObjectAndName(), the
22952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # special flags defined in this module are incorrectly registered with
22962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # a different module.  So, we can't use _GetKeyFlagsForModule.
22972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # Instead, we take all flags from _SPECIAL_FLAGS (a private
22982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # FlagValues, where no other module should register flags).
22992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        [f.name for f in _SPECIAL_FLAGS.FlagDict().values()],
23002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        flag_values=_SPECIAL_FLAGS,
23012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        key_flag_values=flag_values)
23022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
23052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# STRING FLAGS
23062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
23072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23092da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef DEFINE_string(name, default, help, flag_values=FLAGS, **args):
23102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Registers a flag whose value can be any string."""
23112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  parser = ArgumentParser()
23122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  serializer = ArgumentSerializer()
23132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  DEFINE(parser, name, default, help, flag_values, serializer, **args)
23142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
23172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# BOOLEAN FLAGS
23182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
23192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23212da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass BooleanParser(ArgumentParser):
23222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Parser of boolean values."""
23232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Convert(self, argument):
23252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Converts the argument to a boolean; raise ValueError on errors."""
23262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if type(argument) == str:
23272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if argument.lower() in ['true', 't', '1']:
23282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return True
23292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      elif argument.lower() in ['false', 'f', '0']:
23302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return False
23312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    bool_argument = bool(argument)
23332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if argument == bool_argument:
23342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # The argument is a valid boolean (True, False, 0, or 1), and not just
23352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # something that always converts to bool (list, string, int, etc.).
23362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return bool_argument
23372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    raise ValueError('Non-boolean argument to boolean flag', argument)
23392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Parse(self, argument):
23412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    val = self.Convert(argument)
23422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return val
23432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Type(self):
23452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return 'bool'
23462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23482da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass BooleanFlag(Flag):
23492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Basic boolean flag.
23502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Boolean flags do not take any arguments, and their value is either
23522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  True (1) or False (0).  The false value is specified on the command
23532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  line by prepending the word 'no' to either the long or the short flag
23542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  name.
23552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  For example, if a Boolean flag was created whose long name was
23572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  'update' and whose short name was 'x', then this flag could be
23582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  explicitly unset through either --noupdate or --nox.
23592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
23602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self, name, default, help, short_name=None, **args):
23622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    p = BooleanParser()
23632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Flag.__init__(self, p, None, name, default, help, short_name, 1, **args)
23642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if not self.help: self.help = "a boolean value"
23652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23672da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef DEFINE_boolean(name, default, help, flag_values=FLAGS, **args):
23682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Registers a boolean flag.
23692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Such a boolean flag does not take an argument.  If a user wants to
23712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  specify a false value explicitly, the long option beginning with 'no'
23722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  must be used: i.e. --noflag
23732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  This flag will have a value of None, True or False.  None is possible
23752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if default=None and the user does not specify the flag on the command
23762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  line.
23772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
23782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  DEFINE_flag(BooleanFlag(name, default, help, **args), flag_values)
23792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Match C++ API to unconfuse C++ people.
23822da489cd246702bee5938545b18a6f710ed214bcJamie GennisDEFINE_bool = DEFINE_boolean
23832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23852da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass HelpFlag(BooleanFlag):
23862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
23872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  HelpFlag is a special boolean flag that prints usage information and
23882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  raises a SystemExit exception if it is ever found in the command
23892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  line arguments.  Note this is called with allow_override=1, so other
23902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  apps can define their own --help flag, replacing this one, if they want.
23912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
23922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self):
23932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    BooleanFlag.__init__(self, "help", 0, "show this help",
23942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                         short_name="?", allow_override=1)
23952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Parse(self, arg):
23962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if arg:
23972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      doc = sys.modules["__main__"].__doc__
23982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flags = str(FLAGS)
23992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      print doc or ("\nUSAGE: %s [flags]\n" % sys.argv[0])
24002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if flags:
24012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        print "flags:"
24022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        print flags
24032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sys.exit(1)
24042da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass HelpXMLFlag(BooleanFlag):
24052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Similar to HelpFlag, but generates output in XML format."""
24062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self):
24072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    BooleanFlag.__init__(self, 'helpxml', False,
24082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                         'like --help, but generates XML output',
24092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                         allow_override=1)
24102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Parse(self, arg):
24112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if arg:
24122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      FLAGS.WriteHelpInXMLFormat(sys.stdout)
24132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sys.exit(1)
24142da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass HelpshortFlag(BooleanFlag):
24152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
24162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  HelpshortFlag is a special boolean flag that prints usage
24172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  information for the "main" module, and rasies a SystemExit exception
24182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  if it is ever found in the command line arguments.  Note this is
24192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  called with allow_override=1, so other apps can define their own
24202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  --helpshort flag, replacing this one, if they want.
24212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
24222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self):
24232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    BooleanFlag.__init__(self, "helpshort", 0,
24242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                         "show usage only for this module", allow_override=1)
24252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Parse(self, arg):
24262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if arg:
24272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      doc = sys.modules["__main__"].__doc__
24282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      flags = FLAGS.MainModuleHelp()
24292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      print doc or ("\nUSAGE: %s [flags]\n" % sys.argv[0])
24302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if flags:
24312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        print "flags:"
24322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        print flags
24332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sys.exit(1)
24342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
24352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
24362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Numeric parser - base class for Integer and Float parsers
24372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
24382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
24392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
24402da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass NumericParser(ArgumentParser):
24412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Parser of numeric values.
24422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
24432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Parsed value may be bounded to a given upper and lower bound.
24442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
24452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
24462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def IsOutsideBounds(self, val):
24472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return ((self.lower_bound is not None and val < self.lower_bound) or
24482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            (self.upper_bound is not None and val > self.upper_bound))
24492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
24502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Parse(self, argument):
24512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    val = self.Convert(argument)
24522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if self.IsOutsideBounds(val):
24532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      raise ValueError("%s is not %s" % (val, self.syntactic_help))
24542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return val
24552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
24562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def WriteCustomInfoInXMLFormat(self, outfile, indent):
24572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if self.lower_bound is not None:
24582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      _WriteSimpleXMLElement(outfile, 'lower_bound', self.lower_bound, indent)
24592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if self.upper_bound is not None:
24602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      _WriteSimpleXMLElement(outfile, 'upper_bound', self.upper_bound, indent)
24612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
24622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Convert(self, argument):
24632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Default implementation: always returns its argument unmodified."""
24642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return argument
24652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
24662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# End of Numeric Parser
24672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
24682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
24692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# FLOAT FLAGS
24702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
24712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
24722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
24732da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass FloatParser(NumericParser):
24742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Parser of floating point values.
24752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
24762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Parsed value may be bounded to a given upper and lower bound.
24772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
24782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  number_article = "a"
24792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  number_name = "number"
24802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  syntactic_help = " ".join((number_article, number_name))
24812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
24822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self, lower_bound=None, upper_bound=None):
24832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    super(FloatParser, self).__init__()
24842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.lower_bound = lower_bound
24852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.upper_bound = upper_bound
24862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    sh = self.syntactic_help
24872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if lower_bound is not None and upper_bound is not None:
24882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sh = ("%s in the range [%s, %s]" % (sh, lower_bound, upper_bound))
24892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    elif lower_bound == 0:
24902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sh = "a non-negative %s" % self.number_name
24912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    elif upper_bound == 0:
24922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sh = "a non-positive %s" % self.number_name
24932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    elif upper_bound is not None:
24942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sh = "%s <= %s" % (self.number_name, upper_bound)
24952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    elif lower_bound is not None:
24962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sh = "%s >= %s" % (self.number_name, lower_bound)
24972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.syntactic_help = sh
24982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
24992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Convert(self, argument):
25002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Converts argument to a float; raises ValueError on errors."""
25012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return float(argument)
25022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Type(self):
25042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return 'float'
25052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# End of FloatParser
25062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25082da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef DEFINE_float(name, default, help, lower_bound=None, upper_bound=None,
25092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                 flag_values=FLAGS, **args):
25102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Registers a flag whose value must be a float.
25112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  If lower_bound or upper_bound are set, then this flag must be
25132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  within the given range.
25142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
25152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  parser = FloatParser(lower_bound, upper_bound)
25162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  serializer = ArgumentSerializer()
25172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  DEFINE(parser, name, default, help, flag_values, serializer, **args)
25182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  _RegisterBoundsValidatorIfNeeded(parser, name, flag_values=flag_values)
25192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
25212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# INTEGER FLAGS
25222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
25232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25252da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass IntegerParser(NumericParser):
25262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Parser of an integer value.
25272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Parsed value may be bounded to a given upper and lower bound.
25292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
25302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  number_article = "an"
25312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  number_name = "integer"
25322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  syntactic_help = " ".join((number_article, number_name))
25332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self, lower_bound=None, upper_bound=None):
25352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    super(IntegerParser, self).__init__()
25362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.lower_bound = lower_bound
25372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.upper_bound = upper_bound
25382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    sh = self.syntactic_help
25392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if lower_bound is not None and upper_bound is not None:
25402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sh = ("%s in the range [%s, %s]" % (sh, lower_bound, upper_bound))
25412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    elif lower_bound == 1:
25422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sh = "a positive %s" % self.number_name
25432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    elif upper_bound == -1:
25442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sh = "a negative %s" % self.number_name
25452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    elif lower_bound == 0:
25462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sh = "a non-negative %s" % self.number_name
25472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    elif upper_bound == 0:
25482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sh = "a non-positive %s" % self.number_name
25492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    elif upper_bound is not None:
25502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sh = "%s <= %s" % (self.number_name, upper_bound)
25512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    elif lower_bound is not None:
25522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      sh = "%s >= %s" % (self.number_name, lower_bound)
25532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.syntactic_help = sh
25542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Convert(self, argument):
25562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    __pychecker__ = 'no-returnvalues'
25572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if type(argument) == str:
25582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      base = 10
25592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if len(argument) > 2 and argument[0] == "0" and argument[1] == "x":
25602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        base = 16
25612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return int(argument, base)
25622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    else:
25632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return int(argument)
25642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Type(self):
25662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return 'int'
25672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25692da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef DEFINE_integer(name, default, help, lower_bound=None, upper_bound=None,
25702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                   flag_values=FLAGS, **args):
25712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Registers a flag whose value must be an integer.
25722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  If lower_bound, or upper_bound are set, then this flag must be
25742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  within the given range.
25752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
25762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  parser = IntegerParser(lower_bound, upper_bound)
25772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  serializer = ArgumentSerializer()
25782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  DEFINE(parser, name, default, help, flag_values, serializer, **args)
25792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  _RegisterBoundsValidatorIfNeeded(parser, name, flag_values=flag_values)
25802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
25832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# ENUM FLAGS
25842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
25852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25872da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass EnumParser(ArgumentParser):
25882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Parser of a string enum value (a string value from a given set).
25892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  If enum_values (see below) is not specified, any string is allowed.
25912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
25922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self, enum_values=None):
25942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    super(EnumParser, self).__init__()
25952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.enum_values = enum_values
25962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
25972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Parse(self, argument):
25982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if self.enum_values and argument not in self.enum_values:
25992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      raise ValueError("value should be one of <%s>" %
26002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                       "|".join(self.enum_values))
26012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return argument
26022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Type(self):
26042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return 'string enum'
26052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26072da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass EnumFlag(Flag):
26082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Basic enum flag; its value can be any string from list of enum_values."""
26092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self, name, default, help, enum_values=None,
26112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis               short_name=None, **args):
26122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    enum_values = enum_values or []
26132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    p = EnumParser(enum_values)
26142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    g = ArgumentSerializer()
26152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Flag.__init__(self, p, g, name, default, help, short_name, **args)
26162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if not self.help: self.help = "an enum string"
26172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.help = "<%s>: %s" % ("|".join(enum_values), self.help)
26182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def _WriteCustomInfoInXMLFormat(self, outfile, indent):
26202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for enum_value in self.parser.enum_values:
26212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      _WriteSimpleXMLElement(outfile, 'enum_value', enum_value, indent)
26222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26242da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef DEFINE_enum(name, default, enum_values, help, flag_values=FLAGS,
26252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                **args):
26262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Registers a flag whose value can be any string from enum_values."""
26272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  DEFINE_flag(EnumFlag(name, default, help, enum_values, ** args),
26282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              flag_values)
26292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
26322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# LIST FLAGS
26332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
26342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26362da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass BaseListParser(ArgumentParser):
26372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Base class for a parser of lists of strings.
26382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  To extend, inherit from this class; from the subclass __init__, call
26402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    BaseListParser.__init__(self, token, name)
26422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  where token is a character used to tokenize, and name is a description
26442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  of the separator.
26452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
26462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self, token=None, name=None):
26482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    assert name
26492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    super(BaseListParser, self).__init__()
26502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self._token = token
26512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self._name = name
26522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.syntactic_help = "a %s separated list" % self._name
26532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Parse(self, argument):
26552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if isinstance(argument, list):
26562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return argument
26572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    elif argument == '':
26582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return []
26592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    else:
26602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return [s.strip() for s in argument.split(self._token)]
26612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Type(self):
26632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return '%s separated list of strings' % self._name
26642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26662da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass ListParser(BaseListParser):
26672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Parser for a comma-separated list of strings."""
26682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self):
26702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    BaseListParser.__init__(self, ',', 'comma')
26712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def WriteCustomInfoInXMLFormat(self, outfile, indent):
26732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    BaseListParser.WriteCustomInfoInXMLFormat(self, outfile, indent)
26742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    _WriteSimpleXMLElement(outfile, 'list_separator', repr(','), indent)
26752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26772da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass WhitespaceSeparatedListParser(BaseListParser):
26782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Parser for a whitespace-separated list of strings."""
26792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self):
26812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    BaseListParser.__init__(self, None, 'whitespace')
26822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def WriteCustomInfoInXMLFormat(self, outfile, indent):
26842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    BaseListParser.WriteCustomInfoInXMLFormat(self, outfile, indent)
26852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    separators = list(string.whitespace)
26862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    separators.sort()
26872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for ws_char in string.whitespace:
26882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      _WriteSimpleXMLElement(outfile, 'list_separator', repr(ws_char), indent)
26892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26912da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef DEFINE_list(name, default, help, flag_values=FLAGS, **args):
26922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Registers a flag whose value is a comma-separated list of strings."""
26932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  parser = ListParser()
26942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  serializer = ListSerializer(',')
26952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  DEFINE(parser, name, default, help, flag_values, serializer, **args)
26962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26982da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef DEFINE_spaceseplist(name, default, help, flag_values=FLAGS, **args):
26992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Registers a flag whose value is a whitespace-separated list of strings.
27002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Any whitespace can be used as a separator.
27022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
27032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  parser = WhitespaceSeparatedListParser()
27042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  serializer = ListSerializer(' ')
27052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  DEFINE(parser, name, default, help, flag_values, serializer, **args)
27062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
27092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# MULTI FLAGS
27102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
27112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27132da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass MultiFlag(Flag):
27142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """A flag that can appear multiple time on the command-line.
27152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  The value of such a flag is a list that contains the individual values
27172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  from all the appearances of that flag on the command-line.
27182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  See the __doc__ for Flag for most behavior of this class.  Only
27202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  differences in behavior are described here:
27212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    * The default value may be either a single value or a list of values.
27232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      A single value is interpreted as the [value] singleton list.
27242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    * The value of the flag is always a list, even if the option was
27262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      only supplied once, and even if the default value is a single
27272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      value
27282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
27292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def __init__(self, *args, **kwargs):
27312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Flag.__init__(self, *args, **kwargs)
27322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.help += ';\n    repeat this option to specify a list of values'
27332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Parse(self, arguments):
27352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Parses one or more arguments with the installed parser.
27362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Args:
27382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      arguments: a single argument or a list of arguments (typically a
27392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        list of default values); a single argument is converted
27402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        internally into a list containing one item.
27412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
27422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if not isinstance(arguments, list):
27432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # Default value may be a list of values.  Most other arguments
27442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # will not be, so convert them into a single-item list to make
27452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # processing simpler below.
27462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      arguments = [arguments]
27472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if self.present:
27492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # keep a backup reference to list of previously supplied option values
27502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      values = self.value
27512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    else:
27522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # "erase" the defaults with an empty list
27532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      values = []
27542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for item in arguments:
27562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      # have Flag superclass parse argument, overwriting self.value reference
27572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      Flag.Parse(self, item)  # also increments self.present
27582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      values.append(self.value)
27592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # put list of option values back in the 'value' attribute
27612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.value = values
27622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Serialize(self):
27642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if not self.serializer:
27652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      raise FlagsError("Serializer not present for flag %s" % self.name)
27662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if self.value is None:
27672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return ''
27682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    s = ''
27702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    multi_value = self.value
27722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    for self.value in multi_value:
27742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if s: s += ' '
27752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      s += Flag.Serialize(self)
27762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    self.value = multi_value
27782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return s
27802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  def Type(self):
27822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    return 'multi ' + self.parser.Type()
27832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27852da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef DEFINE_multi(parser, serializer, name, default, help, flag_values=FLAGS,
27862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                 **args):
27872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Registers a generic MultiFlag that parses its args with a given parser.
27882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Auxiliary function.  Normal users should NOT use it directly.
27902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Developers who need to create their own 'Parser' classes for options
27922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  which can appear multiple times can call this module function to
27932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  register their flags.
27942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
27952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  DEFINE_flag(MultiFlag(parser, serializer, name, default, help, **args),
27962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              flag_values)
27972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27992da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef DEFINE_multistring(name, default, help, flag_values=FLAGS, **args):
28002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Registers a flag whose value can be a list of any strings.
28012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
28022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Use the flag on the command line multiple times to place multiple
28032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  string values into the list.  The 'default' may be a single string
28042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  (which will be converted into a single-element list) or a list of
28052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  strings.
28062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
28072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  parser = ArgumentParser()
28082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  serializer = ArgumentSerializer()
28092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  DEFINE_multi(parser, serializer, name, default, help, flag_values, **args)
28102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
28112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
28122da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef DEFINE_multi_int(name, default, help, lower_bound=None, upper_bound=None,
28132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                     flag_values=FLAGS, **args):
28142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Registers a flag whose value can be a list of arbitrary integers.
28152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
28162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Use the flag on the command line multiple times to place multiple
28172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  integer values into the list.  The 'default' may be a single integer
28182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  (which will be converted into a single-element list) or a list of
28192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  integers.
28202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
28212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  parser = IntegerParser(lower_bound, upper_bound)
28222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  serializer = ArgumentSerializer()
28232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  DEFINE_multi(parser, serializer, name, default, help, flag_values, **args)
28242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
28252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
28262da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef DEFINE_multi_float(name, default, help, lower_bound=None, upper_bound=None,
28272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                       flag_values=FLAGS, **args):
28282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """Registers a flag whose value can be a list of arbitrary floats.
28292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
28302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  Use the flag on the command line multiple times to place multiple
28312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  float values into the list.  The 'default' may be a single float
28322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  (which will be converted into a single-element list) or a list of
28332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  floats.
28342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  """
28352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  parser = FloatParser(lower_bound, upper_bound)
28362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  serializer = ArgumentSerializer()
28372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  DEFINE_multi(parser, serializer, name, default, help, flag_values, **args)
28382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
28392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
28402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Now register the flags that we want to exist in all applications.
28412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# These are all defined with allow_override=1, so user-apps can use
28422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# these flagnames for their own purposes, if they want.
28432da489cd246702bee5938545b18a6f710ed214bcJamie GennisDEFINE_flag(HelpFlag())
28442da489cd246702bee5938545b18a6f710ed214bcJamie GennisDEFINE_flag(HelpshortFlag())
28452da489cd246702bee5938545b18a6f710ed214bcJamie GennisDEFINE_flag(HelpXMLFlag())
28462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
28472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Define special flags here so that help may be generated for them.
28482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# NOTE: Please do NOT use _SPECIAL_FLAGS from outside this module.
28492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis_SPECIAL_FLAGS = FlagValues()
28502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
28512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
28522da489cd246702bee5938545b18a6f710ed214bcJamie GennisDEFINE_string(
28532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    'flagfile', "",
28542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    "Insert flag definitions from the given file into the command line.",
28552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    _SPECIAL_FLAGS)
28562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
28572da489cd246702bee5938545b18a6f710ed214bcJamie GennisDEFINE_string(
28582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    'undefok', "",
28592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    "comma-separated list of flag names that it is okay to specify "
28602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    "on the command line even if the program does not define a flag "
28612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    "with that name.  IMPORTANT: flags in this list that have "
28622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    "arguments MUST use the --flag=value format.", _SPECIAL_FLAGS)
2863