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