gflags 0.2

git-svn-id: https://gflags.googlecode.com/svn/trunk@9 6586e3c6-dcc4-952a-343f-ff74eb82781d
diff --git a/ChangeLog b/ChangeLog
index 6574aaa..e5f126b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,3 +6,9 @@
 	has increased flexibility, including built-in support for C++
 	types like string, and the ability to define flags in the source
 	file in which they're used.
+
+Mon Jan 22 15:33:06 2007  Google Inc. <opensource@google.com>
+
+	* google-gflags: version 0.2
+	* added support for python commandlineflags, as well as c++
+	* gflags2man, a script to turn flags into a man page (dchristian)
diff --git a/README b/README
index 1333ed7..d6dd30a 100644
--- a/README
+++ b/README
@@ -1 +1,16 @@
-TODO
+This repository contains both a C++ and a python implementation of the
+Google commandline flags module.  Documentation for the C++
+implementation is in doc/.  Documentation for the python
+implementation is at the top of gflags/flags.py.
+
+See INSTALL for (generic) installation instructions for C++: basically
+   ./configure && make && make install
+
+To install the python module, run
+   cd python; python ./setup.py install
+
+When you install the python library, you also get a helper
+application, gflags2man.py, installed into /usr/local/bin.  You can
+run gflags2man.py to create an instant man page, with all the
+commandline flags and their docs, for any C++ or python program you've
+written using the gflags library.
diff --git a/configure b/configure
index d2a8453..590bdff 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59 for gflags 0.1.
+# Generated by GNU Autoconf 2.59 for gflags 0.2.
 #
 # Report bugs to <opensource@google.com>.
 #
@@ -423,8 +423,8 @@
 # Identity of this package.
 PACKAGE_NAME='gflags'
 PACKAGE_TARNAME='gflags'
-PACKAGE_VERSION='0.1'
-PACKAGE_STRING='gflags 0.1'
+PACKAGE_VERSION='0.2'
+PACKAGE_STRING='gflags 0.2'
 PACKAGE_BUGREPORT='opensource@google.com'
 
 ac_unique_file="README"
@@ -954,7 +954,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures gflags 0.1 to adapt to many kinds of systems.
+\`configure' configures gflags 0.2 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1020,7 +1020,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of gflags 0.1:";;
+     short | recursive ) echo "Configuration of gflags 0.2:";;
    esac
   cat <<\_ACEOF
 
@@ -1163,7 +1163,7 @@
 test -n "$ac_init_help" && exit 0
 if $ac_init_version; then
   cat <<\_ACEOF
-gflags configure 0.1
+gflags configure 0.2
 generated by GNU Autoconf 2.59
 
 Copyright (C) 2003 Free Software Foundation, Inc.
@@ -1177,7 +1177,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by gflags $as_me 0.1, which was
+It was created by gflags $as_me 0.2, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   $ $0 $@
@@ -1823,7 +1823,7 @@
 
 # Define the identity of the package.
  PACKAGE='gflags'
- VERSION='0.1'
+ VERSION='0.2'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -21158,7 +21158,7 @@
 } >&5
 cat >&5 <<_CSEOF
 
-This file was extended by gflags $as_me 0.1, which was
+This file was extended by gflags $as_me 0.2, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -21221,7 +21221,7 @@
 
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-gflags config.status 0.1
+gflags config.status 0.2
 configured by $0, generated by GNU Autoconf 2.59,
   with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
 
diff --git a/configure.ac b/configure.ac
index ae5c126..98a07c2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -10,7 +10,7 @@
 # make sure we're interpreted by some minimal autoconf
 AC_PREREQ(2.57)
 
-AC_INIT(gflags, 0.1, opensource@google.com)
+AC_INIT(gflags, 0.2, opensource@google.com)
 # The argument here is just something that should be in the current directory
 # (for sanity checking)
 AC_CONFIG_SRCDIR(README)
diff --git a/packages/rpm/rpm.spec b/packages/rpm/rpm.spec
index f47e23c..35d177d 100644
--- a/packages/rpm/rpm.spec
+++ b/packages/rpm/rpm.spec
@@ -8,11 +8,11 @@
 Version: %ver
 Release: %rel
 Group: Development/Libraries
-URL: http://goog-gflags.sourceforge.net
+URL: http://code.google.com/p/google-gflags
 License: BSD
 Vendor: Google
 Packager: Google Inc. <opensource@google.com>
-Source: http://goog-gflags.sourceforge.net/%{NAME}-%{PACKAGE_VERSION}.tar.gz
+Source: http://google-gflags.googlecode.com/files/%{NAME}-%{PACKAGE_VERSION}.tar.gz
 Distribution: Redhat 7 and above.
 Buildroot: %{_tmppath}/%{name}-root
 Prefix: %prefix
@@ -61,7 +61,6 @@
 %defattr(-,root,root)
 
 %{prefix}/include/google
-%{prefix}/lib/debug
 %{prefix}/lib/libgflags.a
 %{prefix}/lib/libgflags.la
 %{prefix}/lib/libgflags.so
diff --git a/python/gflags.py b/python/gflags.py
new file mode 100755
index 0000000..257b6f5
--- /dev/null
+++ b/python/gflags.py
@@ -0,0 +1,1368 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2007, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ---
+# Author: Chad Lester
+# Design and style contributions by:
+#   Amit Patel, Bogdan Cocosel, Daniel Dulitz, Eric Tiedemann,
+#   Eric Veach, Laurence Gonsalves, Matthew Springer
+# Code reorganized a bit by Craig Silverstein
+
+"""
+This module is used to define and parse command line flags.
+
+This module defines a *distributed* flag-definition policy: rather
+than an application having to define all flags in or near main(), each
+python module defines flags that are useful to it.  When one python
+module imports another, it gains access to the other's flags.  (This
+is implemented by having all modules share a common, global registry
+object containing all the flag information.)
+
+Flags are defined through the use of one of the DEFINE_xxx functions.
+The specific function used determines how the flag is parsed, checked,
+and optionally type-converted, when it's seen on the command line.
+
+
+IMPLEMENTATION: DEFINE_* creates a 'Flag' object and registers it with
+a 'FlagValues' object (typically the global FlagValues FLAGS, defined
+here).  The 'FlagValues' object can scan the command line arguments
+and pass flag arguments to the corresponding 'Flag' objects for
+value-checking and type conversion.  The converted flag values are
+available as members of the 'FlagValues' object.
+
+Code can access the flag through a FlagValues object, for instancee
+gflags.FLAGS.myflag.  Typically, the __main__ module passes the
+command line arguments to gflags.FLAGS for parsing.
+
+At bottom, this module calls getopt(), so getopt functionality is
+supported, including short- and long-style flags, and the use of -- to
+terminate flags.
+
+Methods defined by the flag module will throw 'FlagsError' exceptions.
+The exception argument will be a human-readable string.
+
+
+FLAG TYPES:  This is a list of the DEFINE_*'s that you can do.  All
+flags take a name, default value, help-string, and optional 'short'
+name (one-letter name).  Some flags have other arguments, which are
+described with the flag.
+
+DEFINE_string: takes any input, and interprets it as a string.
+
+DEFINE_boolean: typically does not take an argument: say --myflag to
+                set FLAGS.myflag to true, or --nomyflag to set
+                FLAGS.myflag to false.  Alternately, you can say
+                   --myflag=true  or --myflag=t or --myflag=1  or
+                   --myflag=false or --myflag=f or --myflag=0
+
+DEFINE_float: takes an input and interprets it as a floating point
+              number.  Takes optional args lower_bound and
+              upper_bound; if the number specified on the command line
+              is out of range, it will raise a FlagError.
+
+DEFINE_integer: takes an input and interprets it as an integer.  Takes
+                optional args lower_bound and upper_bound as for floats.
+
+DEFINE_enum: takes a list of strings which represents legal values.  If
+             the command-line value is not in this list, raise a flag
+             error.  Otherwise, assign to FLAGS.flag as a string.
+
+DEFINE_list: Takes a comma-separated list of strings on the commandline.
+             Stores them in a python list object.
+
+DEFINE_spaceseplist: Takes a space-separated list of strings on the
+                     commandline.  Stores them in a python list object.
+
+DEFINE_multistring: The same as DEFINE_string, except the flag can be
+                    specified more than once on the commandline.  The
+                    result is a python list object (list of strings),
+                    even if the flag is only on the command line once.
+
+DEFINE_multi_int: The same as DEFINE_integer, except the flag can be
+                  specified more than once on the commandline.  The
+                  result is a python list object (list of ints),
+                  even if the flag is only on the command line once.
+
+
+SPECIAL FLAGS: There are a few flags that have special meaning:
+   --help (or -?)  prints a list of all the flags in a human-readable fashion
+   --helpshort     prints a list of all the flags in the 'main' .py file only
+   --flagfile=foo  read flags from foo.
+   --              as in getopt(), terminates flag-processing
+
+Note on --flagfile:
+
+Flags may be loaded from text files in addition to being specified on
+the commandline.
+
+Any flags you don't feel like typing, throw them in a file, one flag
+per line, for instance:
+   --myflag=myvalue
+   --nomyboolean_flag
+You then specify your file with the special flag
+'--flagfile=somefile'.  You CAN recursively nest flagfile= tokens OR
+use multiple files on the command line.  Lines beginning with a single
+hash '#' or a double slash '//' are comments in your flagfile.
+
+Any flagfile=<file> will be interpreted as having a relative path from
+the current working directory rather than from the place the file was
+included from:
+   myPythonScript.py --flagfile=config/somefile.cfg
+
+If somefile.cfg includes further --flagfile= directives, these will be
+referenced relative to the original CWD, not from the directory the
+including flagfile was found in!
+
+The caveat applies to people who are including a series of nested
+files in a different dir than they are executing out of.  Relative
+path names are always from CWD, not from the directory of the parent
+include flagfile. We do now support '~' expanded directory names.
+
+Absolute path names ALWAYS work!
+
+
+EXAMPLE USAGE:
+
+  import gflags
+  FLAGS = gflags.FLAGS
+
+  # Flag names are globally defined!  So in general, we need to be
+  # careful to pick names that are unlikely to be used by other libraries.
+  # If there is a conflict, we'll get an error at import time.
+  gflags.DEFINE_string("name", "Mr. President" "NAME: your name")
+  gflags.DEFINE_integer("age", None, "AGE: your age in years", lower_bound=0)
+  gflags.DEFINE_boolean("debug", 0, "produces debugging output")
+  gflags.DEFINE_enum("gender", "male", ["male", "female"],
+                     "GENDER: your gender")
+
+  def main(argv):
+    try:
+      argv = FLAGS(argv)  # parse flags
+    except gflags.FlagsError, e:
+      print '%s\\nUsage: %s ARGS\\n%s' % (e, sys.argv[0], FLAGS)
+      sys.exit(1)
+    if FLAGS.debug: print 'non-flag arguments:', argv
+    print 'Happy Birthday', FLAGS.name
+    if FLAGS.age != None:
+      print "You are a %s, who is %d years old" % (FLAGS.gender, FLAGS.age)
+
+  if __name__ == '__main__': main(sys.argv)
+"""
+
+import getopt
+import os
+import sys
+
+# Are we running at least python 2.2?
+try:
+  if tuple(sys.version_info[:3]) < (2,2,0):
+    raise NotImplementedError("requires python 2.2.0 or later")
+except AttributeError:   # a very old python, that lacks sys.version_info
+  raise NotImplementedError("requires python 2.2.0 or later")
+
+# Are we running under pychecker?
+_RUNNING_PYCHECKER = 'pychecker.python' in sys.modules
+
+# module exceptions:
+class FlagsError(Exception): "The base class for all flags errors"
+class DuplicateFlag(FlagsError): "Thrown if there is a flag naming conflict"
+class IllegalFlagValue(FlagsError): "The flag command line argument is illegal"
+
+# Global variable used by expvar
+_exported_flags = {}
+
+
+def __GetModuleName(globals_dict):
+  """Given a globals dict, find the module in which it's defined."""
+  for name, module in sys.modules.iteritems():
+    if getattr(module, '__dict__', None) is globals_dict:
+      if name == '__main__':
+        return sys.argv[0]
+      return name
+  raise AssertionError, "No module was found"
+
+def __GetCallingModule():
+  """Get the name of the module that's calling into this module; e.g.,
+     the module calling a DEFINE_foo... function.
+  """
+  # Walk down the stack to find the first globals dict that's not ours.
+  for depth in range(1, sys.getrecursionlimit()):
+    if not sys._getframe(depth).f_globals is globals():
+      return __GetModuleName(sys._getframe(depth).f_globals)
+  raise AssertionError, "No module was found"
+
+def _GetMainModule():
+  """Get the module name from which execution started."""
+  for depth in range(1, sys.getrecursionlimit()):
+    try:
+      globals_of_main = sys._getframe(depth).f_globals
+    except ValueError:
+      return __GetModuleName(globals_of_main)
+  raise AssertionError, "No module was found"
+
+
+class FlagValues:
+  """
+  Used as a registry for 'Flag' objects.
+
+  A 'FlagValues' can then scan command line arguments, passing flag
+  arguments through to the 'Flag' objects that it owns.  It also
+  provides easy access to the flag values.  Typically only one
+  'FlagValues' object is needed by an application:  gflags.FLAGS
+
+  This class is heavily overloaded:
+
+  'Flag' objects are registered via __setitem__:
+       FLAGS['longname'] = x   # register a new flag
+
+  The .value member of the registered 'Flag' objects can be accessed as
+  members of this 'FlagValues' object, through __getattr__.  Both the
+  long and short name of the original 'Flag' objects can be used to
+  access its value:
+       FLAGS.longname          # parsed flag value
+       FLAGS.x                 # parsed flag value (short name)
+
+  Command line arguments are scanned and passed to the registered 'Flag'
+  objects through the __call__ method.  Unparsed arguments, including
+  argv[0] (e.g. the program name) are returned.
+       argv = FLAGS(sys.argv)  # scan command line arguments
+
+  The original registered Flag objects can be retrieved through the use
+  of the dictionary-like operator, __getitem__:
+       x = FLAGS['longname']   # access the registered Flag object
+
+  The str() operator of a 'FlagValues' object provides help for all of
+  the registered 'Flag' objects.
+  """
+  def __init__(self):
+    # Since everything in this class is so heavily overloaded,
+    # the only way of defining and using fields is to access __dict__
+    # directly.
+    self.__dict__['__flags'] = {}
+    self.__dict__['__flags_by_module'] = {} # A dict module -> list of flag
+
+  def FlagDict(self):
+    return self.__dict__['__flags']
+
+  def _RegisterFlagByModule(self, module_name, flag):
+    """We keep track of which flag is defined by which module so that
+       we can later sort the flags by module.
+    """
+    flags_by_module = self.__dict__['__flags_by_module']
+    flags_by_module.setdefault(module_name, []).append(flag)
+
+  def __setitem__(self, name, flag):
+    """
+    Register a new flag variable.
+    """
+    fl = self.FlagDict()
+    if not isinstance(flag, Flag):
+      raise IllegalFlagValue, flag
+    if not isinstance(name, type("")):
+      raise FlagsError, "Flag name must be a string"
+    if len(name) == 0:
+      raise FlagsError, "Flag name cannot be empty"
+    # If running under pychecker, duplicate keys are likely to be defined.
+    # Disable check for duplicate keys when pycheck'ing.
+    if (fl.has_key(name) and not flag.allow_override and
+        not fl[name].allow_override and not _RUNNING_PYCHECKER):
+      raise DuplicateFlag, name
+    short_name = flag.short_name
+    if short_name is not None:
+      if (fl.has_key(short_name) and not flag.allow_override and
+          not fl[short_name].allow_override and not _RUNNING_PYCHECKER):
+        raise DuplicateFlag, short_name
+      fl[short_name] = flag
+    fl[name] = flag
+    global _exported_flags
+    _exported_flags[name] = flag
+
+  def __getitem__(self, name):
+    """
+    Retrieve the flag object.
+    """
+    return self.FlagDict()[name]
+
+  def __getattr__(self, name):
+    """
+    Retrieve the .value member of a flag object.
+    """
+    fl = self.FlagDict()
+    if not fl.has_key(name):
+      raise AttributeError, name
+    return fl[name].value
+
+  def __setattr__(self, name, value):
+    """
+    Set the .value member of a flag object.
+    """
+    fl = self.FlagDict()
+    fl[name].value = value
+    return value
+
+  def __delattr__(self, name):
+    """
+    Delete a previously-defined flag from a flag object.
+    """
+    fl = self.FlagDict()
+    if not fl.has_key(name):
+      raise AttributeError, name
+    del fl[name]
+
+  def SetDefault(self, name, value):
+    """
+    Change the default value of the named flag object.
+    """
+    fl = self.FlagDict()
+    if not fl.has_key(name):
+      raise AttributeError, name
+    fl[name].SetDefault(value)
+
+  def __contains__(self, name):
+    """
+    Return True if name is a value (flag) in the dict.
+    """
+    return name in self.FlagDict()
+
+  has_key = __contains__  # a synonym for __contains__()
+
+  def __iter__(self):
+    return self.FlagDict().iterkeys()
+
+  def __call__(self, argv):
+    """
+    Searches argv for flag arguments, parses them and then sets the flag
+    values as attributes of this FlagValues object.  All unparsed
+    arguments are returned.  Flags are parsed using the GNU Program
+    Argument Syntax Conventions, using getopt:
+
+    http://www.gnu.org/software/libc/manual/html_mono/libc.html#Getopt
+    """
+
+    # Support any sequence type that can be converted to a list
+    argv = list(argv)
+
+    shortopts = ""
+    longopts = []
+
+    fl = self.FlagDict()
+
+    # This pre parses the argv list for --flagfile=<> options.
+    argv = self.ReadFlagsFromFiles(argv)
+
+    # Correct the argv to support the google style of passing boolean
+    # parameters.  Boolean parameters may be passed by using --mybool,
+    # --nomybool, --mybool=(true|false|1|0).  getopt does not support
+    # having options that may or may not have a parameter.  We replace
+    # instances of the short form --mybool and --nomybool with their
+    # full forms: --mybool=(true|false).
+    original_argv = list(argv)
+    shortest_matches = None
+    for name, flag in fl.items():
+      if not flag.boolean:
+        continue
+      if shortest_matches is None:
+        # Determine the smallest allowable prefix for all flag names
+        shortest_matches = self.ShortestUniquePrefixes(fl)
+      no_name = 'no' + name
+      prefix = shortest_matches[name]
+      no_prefix = shortest_matches[no_name]
+
+      # Replace all occurences of this boolean with extended forms
+      for arg_idx in range(1, len(argv)):
+        arg = argv[arg_idx]
+        if arg.find('=') >= 0: continue
+        if arg.startswith('--'+prefix) and ('--'+name).startswith(arg):
+          argv[arg_idx] = ('--%s=true' % name)
+        elif arg.startswith('--'+no_prefix) and ('--'+no_name).startswith(arg):
+          argv[arg_idx] = ('--%s=false' % name)
+
+    # Loop over all of the flags, building up the lists of short options and
+    # long options that will be passed to getopt.  Short options are
+    # specified as a string of letters, each letter followed by a colon if it
+    # takes an argument.  Long options are stored in an array of strings.
+    # Each string ends with an '=' if it takes an argument.
+    for name, flag in fl.items():
+      longopts.append(name + "=")
+      if len(name) == 1: # one-letter option: allow short flag type also
+        shortopts += name
+        if not flag.boolean:
+          shortopts += ":"
+
+    try:
+      optlist, unparsed_args = getopt.getopt(argv[1:], shortopts, longopts)
+    except getopt.GetoptError, e:
+      raise FlagsError, e
+    for name, arg in optlist:
+      if name.startswith('--'):
+        # long option
+        name = name[2:]
+        short_option = 0
+      else:
+        # short option
+        name = name[1:]
+        short_option = 1
+      if fl.has_key(name):
+        flag = fl[name]
+        if flag.boolean and short_option: arg = 1
+        flag.Parse(arg)
+
+    if unparsed_args:
+      # unparsed_args becomes the first non-flag detected by getopt to
+      # the end of argv.  Because argv may have been modified above,
+      # return original_argv for this region.
+      return argv[:1] + original_argv[-len(unparsed_args):]
+    else:
+      return argv[:1]
+
+  def Reset(self):
+    """
+    Reset the values to the point before FLAGS(argv) was called.
+    """
+    for f in self.FlagDict().values():
+      f.Unparse()
+
+  def RegisteredFlags(self):
+    """
+    Return a list of all registered flags.
+    """
+    return self.FlagDict().keys()
+
+  def FlagValuesDict(self):
+    """
+    Return a dictionary with flag names as keys and flag values as values.
+    """
+    flag_values = {}
+
+    for flag_name in self.RegisteredFlags():
+      flag = self.FlagDict()[flag_name]
+      flag_values[flag_name] = flag.value
+
+    return flag_values
+
+  def __str__(self):
+    """
+    Generate a help string for all known flags.
+    """
+    helplist = []
+
+    flags_by_module = self.__dict__['__flags_by_module']
+    if flags_by_module:
+
+      modules = flags_by_module.keys()
+      modules.sort()
+
+      # Print the help for the main module first, if possible.
+      main_module = _GetMainModule()
+      if main_module in modules:
+        modules.remove(main_module)
+        modules = [ main_module ] + modules
+
+      for module in modules:
+        self.__RenderModuleFlags(module, helplist)
+
+    else:
+      # Just print one long list of flags.
+      self.__RenderFlagList(self.FlagDict().values(), helplist)
+
+    return '\n'.join(helplist)
+
+  def __RenderModuleFlags(self, module, output_lines):
+    """
+    Generate a help string for a given module.
+    """
+    flags_by_module = self.__dict__['__flags_by_module']
+    if module in flags_by_module:
+      output_lines.append('\n%s:' % module)
+      self.__RenderFlagList(flags_by_module[module], output_lines)
+
+  def MainModuleHelp(self):
+    """
+    Generate a help string for all known flags of the main module.
+    """
+    helplist = []
+    self.__RenderModuleFlags(_GetMainModule(), helplist)
+    return '\n'.join(helplist)
+
+  def __RenderFlagList(self, flaglist, output_lines):
+    fl = self.FlagDict()
+    flaglist = [(flag.name, flag) for flag in flaglist]
+    flaglist.sort()
+    flagset = {}
+    for (name, flag) in flaglist:
+      # It's possible this flag got deleted or overridden since being
+      # registered in the per-module flaglist.  Check now against the
+      # canonical source of current flag information, the FlagDict.
+      if fl.get(name, None) != flag:   # a different flag is using this name now
+        continue
+      # only print help once
+      if flagset.has_key(flag): continue
+      flagset[flag] = 1
+      flaghelp = "  "
+      if flag.short_name: flaghelp += "-%s," % flag.short_name
+      if flag.boolean:
+        flaghelp += "--[no]%s" % flag.name + ":"
+      else:
+        flaghelp += "--%s" % flag.name + ":"
+      flaghelp += "  "
+      if flag.help:
+        flaghelp += flag.help
+      if flag.default_as_str:
+        flaghelp += "\n    (default: %s)" % flag.default_as_str
+      if flag.parser.syntactic_help:
+        flaghelp += "\n    (%s)" % flag.parser.syntactic_help
+      output_lines.append(flaghelp)
+
+  def get(self, name, default):
+    """
+    Retrieve the .value member of a flag object, or default if .value is None
+    """
+
+    value = self.__getattr__(name)
+    if value is not None: # Can't do if not value, b/c value might be '0' or ""
+      return value
+    else:
+      return default
+
+  def ShortestUniquePrefixes(self, fl):
+    """
+    Returns a dictionary mapping flag names to their shortest unique prefix.
+    """
+    # Sort the list of flag names
+    sorted_flags = []
+    for name, flag in fl.items():
+      sorted_flags.append(name)
+      if flag.boolean:
+        sorted_flags.append('no%s' % name)
+    sorted_flags.sort()
+
+    # For each name in the sorted list, determine the shortest unique prefix
+    # by comparing itself to the next name and to the previous name (the latter
+    # check uses cached info from the previous loop).
+    shortest_matches = {}
+    prev_idx = 0
+    for flag_idx in range(len(sorted_flags)):
+      curr = sorted_flags[flag_idx]
+      if flag_idx == (len(sorted_flags) - 1):
+        next = None
+      else:
+        next = sorted_flags[flag_idx+1]
+        next_len = len(next)
+      for curr_idx in range(len(curr)):
+        if (next is None
+            or curr_idx >= next_len
+            or curr[curr_idx] != next[curr_idx]):
+          # curr longer than next or no more chars in common
+          shortest_matches[curr] = curr[:max(prev_idx, curr_idx) + 1]
+          prev_idx = curr_idx
+          break
+      else:
+        # curr shorter than (or equal to) next
+        shortest_matches[curr] = curr
+        prev_idx = curr_idx + 1 # next will need at least one more char
+    return shortest_matches
+
+  def __IsFlagFileDirective(self, flag_string):
+    """ Detects the --flagfile= token.
+    Takes a string which might contain a '--flagfile=<foo>' directive.
+    Returns a Boolean.
+    """
+    if isinstance(flag_string, type("")):
+      if flag_string.startswith('--flagfile='):
+        return 1
+      elif flag_string == '--flagfile':
+        return 1
+      elif flag_string.startswith('-flagfile='):
+        return 1
+      elif flag_string == '-flagfile':
+        return 1
+      else:
+        return 0
+    return 0
+
+  def ExtractFilename(self, flagfile_str):
+    """Function to remove the --flagfile= (or variant) and return just the
+      filename part.  We can get strings that look like:
+        --flagfile=foo, -flagfile=foo.
+      The case of --flagfile foo and  -flagfile foo shouldn't be hitting this
+      function, as they are dealt with in the level above this funciton.
+    """
+    if flagfile_str.startswith('--flagfile='):
+      return os.path.expanduser((flagfile_str[(len('--flagfile=')):]).strip())
+    elif flagfile_str.startswith('-flagfile='):
+      return os.path.expanduser((flagfile_str[(len('-flagfile=')):]).strip())
+    else:
+      raise FlagsError('Hit illegal --flagfile type: %s' % flagfile_str)
+      return ''
+
+
+  def __GetFlagFileLines(self, filename, parsed_file_list):
+    """Function to open a flag file, return its useful (!=comments,etc) lines.
+    Takes:
+        A filename to open and read
+        A list of files we have already read THAT WILL BE CHANGED
+    Returns:
+        List of strings. See the note below.
+
+    NOTE(springer): This function checks for a nested --flagfile=<foo>
+    tag and handles the lower file recursively. It returns a list off
+    all the lines that _could_ contain command flags.  This is
+    EVERYTHING except whitespace lines and comments (lines starting
+    with '#' or '//').
+    """
+    line_list = []  # All line from flagfile.
+    flag_line_list = []  # Subset of lines w/o comments, blanks, flagfile= tags.
+    try:
+      file_obj = open(filename, 'r')
+    except IOError, e_msg:
+      print e_msg
+      print 'ERROR:: Unable to open flagfile: %s' % (filename)
+      return flag_line_list
+
+    line_list = file_obj.readlines()
+    file_obj.close()
+    parsed_file_list.append(filename)
+
+    # This is where we check each line in the file we just read.
+    for line in line_list:
+      if line.isspace():
+        pass
+      # Checks for comment (a line that starts with '#').
+      elif (line.startswith('#') or line.startswith('//')):
+        pass
+      # Checks for a nested "--flagfile=<bar>" flag in the current file.
+      # If we find one, recursively parse down into that file.
+      elif self.__IsFlagFileDirective(line):
+        sub_filename = self.ExtractFilename(line)
+        # We do a little safety check for reparsing a file we've already done.
+        if not sub_filename in parsed_file_list:
+          included_flags = self.__GetFlagFileLines(sub_filename, parsed_file_list)
+          flag_line_list.extend(included_flags)
+        else: # Case of hitting a circularly included file.
+          print >>sys.stderr, ('Warning: Hit circular flagfile dependency: %s'
+                                                                 % sub_filename)
+      else:
+        # Any line that's not a comment or a nested flagfile should
+        # get copied into 2nd position, this leaves earlier arguements
+        # further back in the list, which makes them have higher priority.
+        flag_line_list.append(line.strip())
+    return flag_line_list
+
+  def ReadFlagsFromFiles(self, argv):
+    """Process command line args, but also allow args to be read from file
+    Usage:
+      Takes: a list of strings, usually sys.argv, which may contain one or more
+            flagfile directives of the form --flagfile="./filename"
+      References: Global gflags.FLAG class instance
+      Returns: a new list which has the original list combined with what we
+                 read from any flagfile(s).
+
+      This function should be called  before the normal FLAGS(argv) call.
+      This function simply scans the input list for a flag that looks like:
+         --flagfile=<somefile>
+      Then it opens <somefile>, reads all valid key and value pairs and inserts
+      them into the input list between the first item of the list and any
+      subsequent items in the list.
+      Note that your application's flags are still defined the usual way using
+      gflags DEFINE_flag() type functions.
+
+      Notes (assuming we're getting a commandline of some sort as our input):
+      --> Any flags on the command line we were passed in _should_ always take
+              precedence!!!
+      --> a further "--flagfile=<otherfile.cfg>" CAN be nested in a flagfile.
+              It will be processed after the parent flag file is done.
+      --> For duplicate flags, first one we hit should "win".
+      --> In a flagfile, a line beginning with # or // is a comment
+      --> Entirely blank lines _should_ be ignored
+    """
+    parsed_file_list = []
+    rest_of_args = argv
+    new_argv = []
+    while rest_of_args:
+      current_arg = rest_of_args[0]
+      rest_of_args = rest_of_args[1:]
+      if self.__IsFlagFileDirective(current_arg):
+        # This handles the case of -(-)flagfile foo.  Inthis case the next arg
+        # really is part of this one.
+        if current_arg == '--flagfile' or current_arg =='-flagfile':
+          if not rest_of_args:
+            raise IllegalFlagValue, '--flagfile with no argument'
+          flag_filename = os.path.expanduser(rest_of_args[0])
+          rest_of_args = rest_of_args[1:]
+        else:
+          # This handles the case of (-)-flagfile=foo.
+          flag_filename = self.ExtractFilename(current_arg)
+        new_argv = (new_argv[:1] +
+                self.__GetFlagFileLines(flag_filename, parsed_file_list) +
+                new_argv[1:])
+      else:
+        new_argv.append(current_arg)
+
+    return new_argv
+
+  def FlagsIntoString(self):
+    """
+    Retreive a string version of all the flags with assignments stored
+    in this FlagValues object.  Should mirror the behavior of the c++
+    version of FlagsIntoString.  Each flag assignment is seperated by
+    a newline.
+    """
+    s = ''
+    for flag in self.FlagDict().values():
+      if flag.value is not None:
+        s += flag.Serialize() + '\n'
+    return s
+
+  def AppendFlagsIntoFile(self, filename):
+    """
+    Appends all flags found in this FlagInfo object to the file
+    specified.  Output will be in the format of a flagfile.  This
+    should mirror the behavior of the c++ version of
+    AppendFlagsIntoFile.
+    """
+    out_file = open(filename, 'a')
+    out_file.write(self.FlagsIntoString())
+    out_file.close()
+
+#end of the FLAGS registry class
+
+
+# The global FlagValues instance
+FLAGS = FlagValues()
+
+
+class Flag:
+  """
+  'Flag' objects define the following fields:
+    .name  - the name for this flag
+    .default - the default value for this flag
+    .default_as_str - default value as repr'd string, e.g., "'true'" (or None)
+    .value  - the most recent parsed value of this flag; set by Parse()
+    .help  - a help string or None if no help is available
+    .short_name  - the single letter alias for this flag (or None)
+    .boolean  - if 'true', this flag does not accept arguments
+    .present  - true if this flag was parsed from command line flags.
+    .parser  - an ArgumentParser object
+    .serializer - an ArgumentSerializer object
+    .allow_override - the flag may be redefined without raising an error
+
+  The only public method of a 'Flag' object is Parse(), but it is
+  typically only called by a 'FlagValues' object.  The Parse() method is
+  a thin wrapper around the 'ArgumentParser' Parse() method.  The parsed
+  value is saved in .value, and the .present member is updated.  If this
+  flag was already present, a FlagsError is raised.
+
+  Parse() is also called during __init__ to parse the default value and
+  initialize the .value member.  This enables other python modules to
+  safely use flags even if the __main__ module neglects to parse the
+  command line arguments.  The .present member is cleared after __init__
+  parsing.  If the default value is set to None, then the __init__
+  parsing step is skipped and the .value member is initialized to None.
+
+  Note: The default value is also presented to the user in the help
+  string, so it is important that it be a legal value for this flag.
+  """
+  def __init__(self, parser, serializer, name, default, help_string,
+               short_name=None, boolean=0, allow_override=0):
+    self.name = name
+    self.default = default
+
+    if not help_string:
+      help_string = '(no help available)'
+
+    self.help = help_string
+    self.short_name = short_name
+    self.boolean = boolean
+    self.present = 0
+    self.parser = parser
+    self.serializer = serializer
+    self.allow_override = allow_override
+    self.value = None
+
+    # We can't allow a None override because it may end up not being
+    # passed to C++ code when we're overriding C++ flags.  So we
+    # cowardly bail out until someone fixes the semantics of trying to
+    # pass None to a C++ flag.  See swig_flags.Init() for details on
+    # this behavior.
+    if default is None and allow_override:
+      raise DuplicateFlag, name
+
+    self.Unparse()
+
+    self.default_as_str = self.__GetParsedValueAsString(self.value)
+
+  def __GetParsedValueAsString(self, value):
+    if self.boolean:
+      if value:
+        return repr('true')
+      else:
+        return repr('false')
+    if value is None:
+      return None
+    return repr(str(value))
+
+  def Parse(self, argument):
+    try:
+      self.value = self.parser.Parse(argument)
+    except ValueError, e:  # recast ValueError as IllegalFlagValue
+      raise IllegalFlagValue, ("flag --%s: " % self.name) + str(e)
+    self.present += 1
+
+  def Unparse(self):
+    if self.default != None:
+      self.Parse(self.default)
+    self.present = 0
+
+  def Serialize(self):
+    if self.value is None:
+      return ''
+    if self.boolean:
+      if self.value:
+        return "--%s" % self.name
+      else:
+        return "--no%s" % self.name
+    else:
+      if not self.serializer:
+        raise FlagsError, "Serializer not present for flag %s" % self.name
+      return "--%s=%s" % (self.name, self.serializer.Serialize(self.value))
+
+  def SetDefault(self, value):
+    """
+    Change the default value, and current value, of this flag object
+    """
+    if value:     # See __init__ for logic details
+      self.Parse(value)
+      self.present -= 1 # reset .present after parsing new default value
+    else:
+      self.value = None
+    self.default = value
+    self.default_as_str = self.__GetParsedValueAsString(value)
+
+class ArgumentParser:
+  """
+  This is a base class used to parse and convert arguments.
+
+  The Parse() method checks to make sure that the string argument is a
+  legal value and convert it to a native type.  If the value cannot be
+  converted, it should throw a 'ValueError' exception with a human
+  readable explanation of why the value is illegal.
+
+  Subclasses should also define a syntactic_help string which may be
+  presented to the user to describe the form of the legal values.
+  """
+  syntactic_help = ""
+  def Parse(self, argument):
+    """
+    The default implementation of Parse() accepts any value of argument,
+    simply returning it unmodified.
+    """
+    return argument
+
+class ArgumentSerializer:
+  """
+  This is the base class for generating string representations of a
+  flag value
+  """
+  def Serialize(self, value):
+    return str(value)
+
+class ListSerializer(ArgumentSerializer):
+  def __init__(self, list_sep):
+    self.list_sep = list_sep
+
+  def Serialize(self, value):
+    return self.list_sep.join([str(x) for x in value])
+
+
+# The DEFINE functions are explained in the module doc string.
+
+def DEFINE(parser, name, default, help, flag_values=FLAGS, serializer=None,
+           **args):
+  """
+  This creates a generic 'Flag' object that parses its arguments with a
+  'Parser' and registers it with a 'FlagValues' object.
+
+  Developers who need to create their own 'Parser' classes should call
+  this module function. to register their flags.  For example:
+
+  DEFINE(DatabaseSpec(), "dbspec", "mysql:db0:readonly:hr",
+         "The primary database")
+  """
+  DEFINE_flag(Flag(parser, serializer, name, default, help, **args),
+              flag_values)
+
+def DEFINE_flag(flag, flag_values=FLAGS):
+  """
+  This registers a 'Flag' object with a 'FlagValues' object.  By
+  default, the global FLAGS 'FlagValue' object is used.
+
+  Typical users will use one of the more specialized DEFINE_xxx
+  functions, such as DEFINE_string or DEFINEE_integer.  But developers
+  who need to create Flag objects themselves should use this function to
+  register their flags.
+  """
+  # copying the reference to flag_values prevents pychecker warnings
+  fv = flag_values
+  fv[flag.name] = flag
+
+  if flag_values == FLAGS:
+    # We are using the global flags dictionary, so we'll want to sort the
+    # usage output by calling module in FlagValues.__str__ (FLAGS is an
+    # instance of FlagValues). This requires us to keep track
+    # of which module is creating the flags.
+
+    # Tell FLAGS who's defining flag.
+    FLAGS._RegisterFlagByModule(__GetCallingModule(), flag)
+
+
+###############################
+#################  STRING FLAGS
+###############################
+
+def DEFINE_string(name, default, help, flag_values=FLAGS, **args):
+  """
+  This registers a flag whose value can be any string.
+  """
+  parser = ArgumentParser()
+  serializer = ArgumentSerializer()
+  DEFINE(parser, name, default, help, flag_values, serializer, **args)
+
+
+###############################
+################  BOOLEAN FLAGS
+###############################
+####  and the special HELP flag
+###############################
+
+class BooleanParser(ArgumentParser):
+  """
+  A boolean value
+  """
+
+  def Convert(self, argument):
+    """
+    convert the argument to a boolean (integer); raise ValueError on errors
+    """
+    if type(argument) == str:
+      if argument.lower() in ['true', 't', '1']:
+        return 1
+      elif argument.lower() in ['false', 'f', '0']:
+        return 0
+    return int(argument)
+
+  def Parse(self, argument):
+    val = self.Convert(argument)
+    return val
+
+class BooleanFlag(Flag):
+  """
+  A basic boolean flag.  Boolean flags do not take any arguments, and
+  their value is either 0 (false) or 1 (true).  The false value is
+  specified on the command line by prepending the word 'no' to either
+  the long or short flag name.
+
+  For example, if a Boolean flag was created whose long name was 'update'
+  and whose short name was 'x', then this flag could be explicitly unset
+  through either --noupdate or --nox.
+  """
+  def __init__(self, name, default, help, short_name=None, **args):
+    p = BooleanParser()
+    g = ArgumentSerializer()
+    Flag.__init__(self, p, g, name, default, help, short_name, 1, **args)
+    if not self.help: self.help = "a boolean value"
+
+def DEFINE_boolean(name, default, help, flag_values=FLAGS, **args):
+  """
+  This registers a boolean flag - one that does not take an argument.
+  If a user wants to specify a false value explicitly, the long option
+  beginning with 'no' must be used: i.e. --noflag
+
+  This flag will have a value of None, 0 or 1.  None is possible if
+  default=None and the user does not specify the flag on the command
+  line.
+  """
+  DEFINE_flag(BooleanFlag(name, default, help, **args), flag_values)
+
+class HelpFlag(BooleanFlag):
+  """
+  HelpFlag is a special boolean flag that prints usage information and
+  raises a SystemExit exception if it is ever found in the command
+  line arguments.  Note this is called with allow_override=1, so other
+  apps can define their own --help flag, replacing this one, if they want.
+  """
+  def __init__(self):
+    BooleanFlag.__init__(self, "help", 0, "show this help",
+                         short_name="?", allow_override=1)
+  def Parse(self, arg):
+    if arg:
+      doc = sys.modules["__main__"].__doc__
+      flags = str(FLAGS)
+      print doc or ("\nUSAGE: %s [flags]\n" % sys.argv[0])
+      if flags:
+        print "flags:"
+        print flags
+      sys.exit(1)
+
+class HelpshortFlag(BooleanFlag):
+  """
+  HelpshortFlag is a special boolean flag that prints usage
+  information for the "main" module, and rasies a SystemExit exception
+  if it is ever found in the command line arguments.  Note this is
+  called with allow_override=1, so other apps can define their own
+  --helpshort flag, replacing this one, if they want.
+  """
+  def __init__(self):
+    BooleanFlag.__init__(self, "helpshort", 0,
+                         "show usage only for this module", allow_override=1)
+  def Parse(self, arg):
+    if arg:
+      doc = sys.modules["__main__"].__doc__
+      flags = FLAGS.MainModuleHelp()
+      print doc or ("\nUSAGE: %s [flags]\n" % sys.argv[0])
+      if flags:
+        print "flags:"
+        print flags
+      sys.exit(1)
+
+
+###############################
+##################  FLOAT FLAGS
+###############################
+
+class FloatParser(ArgumentParser):
+  """
+  A floating point value; optionally bounded to a given upper and lower
+  bound.
+  """
+  number_article = "a"
+  number_name = "number"
+  syntactic_help = " ".join((number_article, number_name))
+
+  def __init__(self, lower_bound=None, upper_bound=None):
+    self.lower_bound = lower_bound
+    self.upper_bound = upper_bound
+    sh = self.syntactic_help
+    if lower_bound != None and upper_bound != None:
+      sh = ("%s in the range [%s, %s]" % (sh, lower_bound, upper_bound))
+    elif lower_bound == 1:
+      sh = "a positive %s" % self.number_name
+    elif upper_bound == -1:
+      sh = "a negative %s" % self.number_name
+    elif lower_bound == 0:
+      sh = "a non-negative %s" % self.number_name
+    elif upper_bound != None:
+      sh = "%s <= %s" % (self.number_name, upper_bound)
+    elif lower_bound != None:
+      sh = "%s >= %s" % (self.number_name, lower_bound)
+    self.syntactic_help = sh
+
+  def Convert(self, argument):
+    """
+    convert the argument to a float; raise ValueError on errors
+    """
+    return float(argument)
+
+  def Parse(self, argument):
+    val = self.Convert(argument)
+    if ((self.lower_bound != None and val < self.lower_bound) or
+        (self.upper_bound != None and val > self.upper_bound)):
+      raise ValueError, "%s is not %s" % (val, self.syntactic_help)
+    return val
+
+def DEFINE_float(name, default, help, lower_bound=None, upper_bound=None,
+                 flag_values = FLAGS, **args):
+  """
+  This registers a flag whose value must be a float.  If lower_bound,
+  or upper_bound are set, then this flag must be within the given range.
+  """
+  parser = FloatParser(lower_bound, upper_bound)
+  serializer = ArgumentSerializer()
+  DEFINE(parser, name, default, help, flag_values, serializer, **args)
+
+
+###############################
+################  INTEGER FLAGS
+###############################
+
+class IntegerParser(FloatParser):
+  """
+  An integer value; optionally bounded to a given upper or lower bound.
+  """
+  number_article = "an"
+  number_name = "integer"
+  syntactic_help = " ".join((number_article, number_name))
+  def Convert(self, argument):
+    __pychecker__ = 'no-returnvalues'
+    if type(argument) == str:
+      base = 10
+      if len(argument) > 2 and argument[0] == "0" and argument[1] == "x":
+        base=16
+      try:
+        return int(argument, base)
+      # ValueError is thrown when argument is a string, and overflows an int.
+      except ValueError:
+        return long(argument, base)
+    else:
+      try:
+        return int(argument)
+      # OverflowError is thrown when argument is numeric, and overflows an int.
+      except OverflowError:
+        return long(argument)
+
+def DEFINE_integer(name, default, help, lower_bound=None, upper_bound=None,
+                   flag_values = FLAGS, **args):
+  """
+  This registers a flag whose value must be an integer.  If lower_bound,
+  or upper_bound are set, then this flag must be within the given range.
+  """
+  parser = IntegerParser(lower_bound, upper_bound)
+  serializer = ArgumentSerializer()
+  DEFINE(parser, name, default, help, flag_values, serializer, **args)
+
+
+###############################
+###################  ENUM FLAGS
+###############################
+
+class EnumParser(ArgumentParser):
+  """
+  A string enum value
+  """
+
+  def __init__(self, enum_values=None):
+    self.enum_values = enum_values
+
+  def Parse(self, argument):
+    """
+    If enum_values is not specified, any string is allowed
+    """
+    if self.enum_values and argument not in self.enum_values:
+      raise ValueError, ("value should be one of <%s>"
+                         % "|".join(self.enum_values))
+    return argument
+
+class EnumFlag(Flag):
+  """
+  A basic enum flag. The flag's value can be any string from the list
+  of enum_values.
+  """
+  def __init__(self, name, default, help, enum_values=[],
+               short_name=None, **args):
+    p = EnumParser(enum_values)
+    g = ArgumentSerializer()
+    Flag.__init__(self, p, g, name, default, help, short_name, **args)
+    if not self.help: self.help = "an enum string"
+    self.help = "<%s>: %s" % ("|".join(enum_values), self.help)
+
+def DEFINE_enum(name, default, enum_values, help, flag_values=FLAGS,
+                **args):
+  """
+  This registers a flag whose value can be a string from a set of
+  specified values.
+  """
+  DEFINE_flag(EnumFlag(name, default, help, enum_values, ** args),
+              flag_values)
+
+
+###############################
+###################  LIST FLAGS
+###############################
+
+class BaseListParser(ArgumentParser):
+  """
+  A base class for a string list parser.
+  To extend, inherit from this class, and call
+
+  BaseListParser.__init__(self, token, name)
+
+  where token is a character used to tokenize, and
+  name is a description of the separator
+  """
+
+  def __init__(self, token=None, name=None):
+    assert name
+    self._token = token
+    self._name = name
+    self.syntactic_help = "a %s separated list" % self._name
+
+  def Parse(self, argument):
+    if argument == '':
+      return []
+    else:
+      return [s.strip() for s in argument.split(self._token)]
+
+
+class ListParser(BaseListParser):
+  """
+  A string list parser (comma-separated)
+  """
+
+  def __init__(self):
+    BaseListParser.__init__(self, ',', 'comma')
+
+class WhitespaceSeparatedListParser(BaseListParser):
+  """
+  A string list parser (whitespace-separated)
+  """
+
+  def __init__(self):
+    BaseListParser.__init__(self, None, 'whitespace')
+
+
+def DEFINE_list(name, default, help, flag_values=FLAGS, **args):
+  """
+  This registers a flag whose value is a list of strings, separated by commas
+  """
+  parser = ListParser()
+  serializer = ListSerializer(',')
+  DEFINE(parser, name, default, help, flag_values, serializer, **args)
+
+def DEFINE_spaceseplist(name, default, help, flag_values=FLAGS, **args):
+  """
+  This registers a flag whose value is a list of strings, separated by any
+  whitespace
+  """
+  parser = WhitespaceSeparatedListParser()
+  serializer = ListSerializer(' ')
+  DEFINE(parser, name, default, help, flag_values, serializer, **args)
+
+
+###############################
+##################  MULTI FLAGS
+###############################
+
+class MultiFlag(Flag):
+  """
+  MultiFlag is a specialized subclass of Flag that accumulates
+  multiple values in a list when a command-line option appears
+  multiple times.
+
+  See the __doc__ for Flag for most behavior of this class.  Only
+  differences in behavior are described here:
+   * the default value may be a single value -OR- a list of values
+   * the value of the flag is always a list, even if the option was only
+     supplied once, and even if the default value is a single value
+  """
+  def __init__(self, *args, **kwargs):
+    Flag.__init__(self, *args, **kwargs)
+
+    self.help = (self.help +
+                 ';\n    repeat this option to specify a list of values')
+
+  def Parse(self, arguments):
+    """Parse one or more arguments with the installed parser.
+
+    Arguments:
+      arguments:  a single argument or a list of arguments (typically a list
+        of default values); single arguments will be converted internally into
+        a list containing one item
+    """
+    if not isinstance(arguments, list):
+      # Default value may be a list of values.  Most other arguments will not
+      # be, so convert them into a single-item list to make processing simpler
+      # below.
+      arguments = [ arguments ]
+
+    if self.present:
+      # keep a backup reference to list of previously supplied option values
+      values = self.value
+    else:
+      # "erase" the defaults with an empty list
+      values = []
+
+    for item in arguments:
+      # have Flag superclass parse argument, overwriting self.value reference
+      Flag.Parse(self, item)  # also increments self.present
+      values.append(self.value)
+
+    # put list of option values back in member variable
+    self.value = values
+
+  def Serialize(self):
+    if not self.serializer:
+      raise FlagsError, "Serializer not present for flag %s" % self.name
+    if self.value is None:
+      return ''
+
+    s = ''
+
+    multi_value = self.value
+
+    for self.value in multi_value:
+      if s: s += ' '
+      s += Flag.Serialize(self)
+
+    self.value = multi_value
+
+    return s
+
+
+def DEFINE_multi(parser, serializer, name, default, help, flag_values=FLAGS,
+                 **args):
+  """
+  This creates a generic 'MultiFlag' object that parses its arguments with a
+  'Parser' and registers it with a 'FlagValues' object.
+
+  Developers who need to create their own 'Parser' classes for options which
+  can appear multiple times can call this module function to register their
+  flags.
+  """
+  DEFINE_flag(MultiFlag(parser, serializer, name, default, help, **args), flag_values)
+
+def DEFINE_multistring(name, default, help, flag_values=FLAGS, **args):
+  """
+  This registers a flag whose value can be a list of any strings.  Use the flag
+  on the command line multiple times to place multiple string values into the
+  list.  The 'default' may be a single string (which will be converted into a
+  single-element list) or a list of strings.
+  """
+  parser = ArgumentParser()
+  serializer = ArgumentSerializer()
+  DEFINE_multi(parser, serializer, name, default, help, flag_values, **args)
+
+def DEFINE_multi_int(name, default, help, lower_bound=None, upper_bound=None,
+                     flag_values=FLAGS, **args):
+  """
+  This registers a flag whose value can be a list of any integers.  Use the
+  flag on the command line multiple times to place multiple integer values
+  into the list.  The 'default' may be a single integer (which will be
+  converted into a single-element list) or a list of integers.
+  """
+  parser = IntegerParser(lower_bound, upper_bound)
+  serializer = ArgumentSerializer()
+  DEFINE_multi(parser, serializer, name, default, help, flag_values, **args)
+
+
+# Now register the flags that we want to exist in all applications.
+# These are all defined with allow_override=1, so user-apps can use
+# these flagnames for their own purposes, if they want.
+DEFINE_flag(HelpFlag())
+DEFINE_flag(HelpshortFlag())
diff --git a/contrib/gflags2man.py b/python/gflags2man.py
similarity index 65%
rename from contrib/gflags2man.py
rename to python/gflags2man.py
index 9074559..4edac1c 100755
--- a/contrib/gflags2man.py
+++ b/python/gflags2man.py
@@ -1,6 +1,33 @@
-#!/usr/bin/python2.4
+#!/usr/bin/env python
 #
-# Copyright 2006 Google Inc. All Rights Reserved.
+# Copyright (c) 2007, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 """gflags2man runs a Google flags base program and generates a man page.
 
@@ -8,26 +35,29 @@
 page.
 
 Usage:
-  gflags2man program...
+  gflags2man <program> [program] ...
 """
 
+# TODO(csilvers): work with windows paths (\) as well as unix (/)
+
 # This may seem a bit of an end run, but it:  doesn't bloat flags, can
 # support python/java/C++, supports older executables, and can be
 # extended to other document formats.
 # Inspired by help2man.
 
-__author__ = 'dchristian@google.com (Dan Christian)'
+__author__ = 'Dan Christian'
 
 import os
 import re
 import sys
 import stat
-import datetime
+import time
 import subprocess
 
-from google3.pyglib import app
-from google3.pyglib import flags
-from google3.pyglib import logging
+import gflags
+
+_VERSION = '0.1'
+
 
 def _GetDefaultDestDir():
   home = os.environ.get('HOME', '')
@@ -35,17 +65,29 @@
   if home and os.path.exists(homeman):
     return homeman
   else:
-    return '/tmp'
+    return os.environ.get('TMPDIR', '/tmp')
 
-FLAGS = flags.FLAGS
-flags.DEFINE_string('dest_dir', _GetDefaultDestDir(),
-                    'Directory to write resulting manpage to.'
-                    ' Specify \'-\' for stdout')
-flags.DEFINE_string('help_flag', '--help',
-                    'Option to pass to target program in to get help')
+FLAGS = gflags.FLAGS
+gflags.DEFINE_string('dest_dir', _GetDefaultDestDir(),
+                     'Directory to write resulting manpage to.'
+                     ' Specify \'-\' for stdout')
+gflags.DEFINE_string('help_flag', '--help',
+                     'Option to pass to target program in to get help')
+gflags.DEFINE_integer('v', 0, 'verbosity level to use for output')
 
-MIN_VALID_USAGE_MSG = 9            # minimum output likely to be valid
-_version = '0.1'
+_MIN_VALID_USAGE_MSG = 9         # if fewer lines than this, help is suspect
+
+
+class Logging:
+  """A super-simple logging class"""
+  def error(self, msg): print >>sys.stderr, "ERROR: ", msg
+  def warn(self, msg): print >>sys.stderr, "WARNING: ", msg
+  def info(self, msg): print msg
+  def debug(self, msg): self.vlog(1, msg)
+  def vlog(self, level, msg):
+    if FLAGS.v >= level: print msg
+logging = Logging()
+
 
 def GetRealPath(filename):
   """Given an executable filename, find in the PATH or find absolute path.
@@ -55,7 +97,7 @@
     Absolute version of filename.
     None if filename could not be found locally, absolutely, or in PATH
   """
-  if '/' == filename[0]:                # already absolute
+  if os.path.isabs(filename):                # already absolute
     return filename
 
   if filename.startswith('./') or  filename.startswith('../'): # relative
@@ -65,7 +107,7 @@
   for directory in path.split(':'):
     tryname = os.path.join(directory, filename)
     if os.path.exists(tryname):
-      if not directory or '/' != directory[0]: # directory is relative
+      if not os.path.isabs(directory):  # relative directory
         return os.path.abspath(tryname)
       return tryname
   if os.path.exists(filename):
@@ -88,31 +130,31 @@
 
 
 class ProgramInfo(object):
-  """All the information gleened from running a program with --help."""
+  """All the information gleaned from running a program with --help."""
 
-  # Match a module block start
-  # google3.pyglib.logging:
+  # Match a module block start, for python scripts --help
+  # "goopy.logging:"
   module_py_re = re.compile(r'(\S.+):$')
   # match the start of a flag listing
-  #  -v,--verbosity:  Logging verbosity
+  # " -v,--verbosity:  Logging verbosity"
   flag_py_re         = re.compile(r'\s+(-\S+):\s+(.*)$')
-  #    (default: '0')
+  # "   (default: '0')"
   flag_default_py_re = re.compile(r'\s+\(default:\s+\'(.*)\'\)$')
-  #    (an integer)
+  # "   (an integer)"
   flag_tips_py_re    = re.compile(r'\s+\((.*)\)$')
 
-  # Match a module block start
-  # google3/base/commandlineflags
+  # Match a module block start, for c++ programs --help
+  # "google/base/commandlineflags"
   module_c_re = re.compile(r'\s+Flags from (\S.+):$')
   # match the start of a flag listing
-  #  -v,--verbosity:  Logging verbosity
+  # " -v,--verbosity:  Logging verbosity"
   flag_c_re         = re.compile(r'\s+(-\S+)\s+(.*)$')
 
-  # Match a module block start
-  # com.google.common.flags
+  # Match a module block start, for java programs --help
+  # "com.google.common.flags"
   module_java_re = re.compile(r'\s+Flags for (\S.+):$')
   # match the start of a flag listing
-  #  -v,--verbosity:  Logging verbosity
+  # " -v,--verbosity:  Logging verbosity"
   flag_java_re         = re.compile(r'\s+(-\S+)\s+(.*)$')
 
   def __init__(self, executable):
@@ -121,29 +163,29 @@
       executable  Program to execute (string)
     """
     self.long_name = executable
-    self.name = os.path.basename(executable) # name
+    self.name = os.path.basename(executable)  # name
     # Get name without extension (PAR files)
-    self.short_name, self.ext = os.path.splitext(self.name)
-    self.executable = GetRealPath(executable) # name of the program
-    self.output = []           # output from the program.  List of lines.
-    self.desc = []             # top level description.  List of lines
-    self.modules = {}     # { section_name(string), [ flags ] }
-    self.module_list = [] # list of module names in their original order
-    self.date = datetime.date.today()   # default date info
+    (self.short_name, self.ext) = os.path.splitext(self.name)
+    self.executable = GetRealPath(executable)  # name of the program
+    self.output = []          # output from the program.  List of lines.
+    self.desc = []            # top level description.  List of lines
+    self.modules = {}         # { section_name(string), [ flags ] }
+    self.module_list = []     # list of module names in their original order
+    self.date = time.localtime(time.time())   # default date info
 
   def Run(self):
     """Run it and collect output.
 
     Returns:
-      True   If everything went well.
-      False  If there were problems.
+      1 (true)   If everything went well.
+      0 (false)  If there were problems.
     """
     if not self.executable:
       logging.error('Could not locate "%s"' % self.long_name)
-      return False
+      return 0
 
     finfo = os.stat(self.executable)
-    self.date = datetime.date.fromtimestamp(finfo[stat.ST_MTIME])
+    self.date = time.localtime(finfo[stat.ST_MTIME])
 
     logging.info('Running: %s %s </dev/null 2>&1'
                  % (self.executable, FLAGS.help_flag))
@@ -157,70 +199,71 @@
         stdin=open('/dev/null', 'r'))
     except OSError, msg:
       logging.error('Error executing "%s": %s' % (self.name, msg))
-      return False
+      return 0
 
-    #read output progressively so the pipe doesn't fill up (fileutil).
+    # read output progressively so the pipe doesn't fill up (fileutil).
     self.output = runstate.stdout.readlines()
     status = runstate.wait()
     logging.debug('Program exited with %s' % status)
     output = runstate.communicate()[0]
     if output:
       self.output = output.splitlines()
-    if len(self.output) < MIN_VALID_USAGE_MSG:
+    if len(self.output) < _MIN_VALID_USAGE_MSG:
       logging.error(
         'Error: "%s %s" returned %d and only %d lines: %s'
         % (self.name, FLAGS.help_flag, status, len(self.output), output))
-      return False
-    return True
+      return 0
+    return 1
 
   def Parse(self):
     """Parse program output."""
-    cnt, lang = self.ParseDesc()
-    if cnt < 0:
+    (start_line, lang) = self.ParseDesc()
+    if start_line < 0:
       return
     if 'python' == lang:
-      self.ParsePythonFlags(cnt)
+      self.ParsePythonFlags(start_line)
     elif 'c' == lang:
-      self.ParseCFlags(cnt)
+      self.ParseCFlags(start_line)
     elif 'java' == lang:
-      self.ParseJavaFlags(cnt)
+      self.ParseJavaFlags(start_line)
 
-  def ParseDesc(self, cnt=0):
+  def ParseDesc(self, start_line=0):
     """Parse the initial description.
 
     This could be Python or C++.
 
     Returns:
-      (line_count, lang_type)
-        line_count  Line to start parsing flags on (int)
+      (start_line, lang_type)
+        start_line  Line to start parsing flags on (int)
         lang_type   Either 'python' or 'c'
        (-1, '')  if the flags start could not be found
     """
     exec_mod_start = self.executable + ':'
 
-    after_blank = False
-    cnt = 0
-    for cnt in range(cnt, len(self.output)): # collect top description
-      line = self.output[cnt].rstrip()
+    after_blank = 0
+    start_line = 0             # ignore the passed-in arg for now (?)
+    for start_line in range(start_line, len(self.output)): # collect top description
+      line = self.output[start_line].rstrip()
       # Python flags start with 'flags:\n'
       if ('flags:' == line
-          and len(self.output) > cnt+1 and '' == self.output[cnt+1].rstrip()):
-        cnt += 2
+          and len(self.output) > start_line+1
+          and '' == self.output[start_line+1].rstrip()):
+        start_line += 2
         logging.debug('Flags start (python): %s' % line)
-        return (cnt, 'python')
+        return (start_line, 'python')
       # SWIG flags just have the module name followed by colon.
       if exec_mod_start == line:
         logging.debug('Flags start (swig): %s' % line)
-        return (cnt, 'python')
+        return (start_line, 'python')
       # C++ flags begin after a blank line and with a constant string
       if after_blank and line.startswith('  Flags from '):
         logging.debug('Flags start (c): %s' % line)
-        return (cnt, 'c')
+        return (start_line, 'c')
       # java flags begin with a constant string
       if line == 'where flags are':
         logging.debug('Flags start (java): %s' % line)
-        cnt += 2                        # skip "Standard flags:"
-        return (cnt, 'java')
+        start_line += 2                        # skip "Standard flags:"
+        return (start_line, 'java')
 
       logging.debug('Desc: %s' % line)
       self.desc.append(line)
@@ -230,12 +273,13 @@
                    % self.long_name)
       return (-1, '')
 
-  def ParsePythonFlags(self, cnt=0):
+  def ParsePythonFlags(self, start_line=0):
     """Parse python/swig style flags."""
     modname = None                      # name of current module
+    modlist = []
     flag = None
-    for cnt in range(cnt, len(self.output)): # collect flags
-      line = self.output[cnt].rstrip()
+    for line_num in range(start_line, len(self.output)): # collect flags
+      line = self.output[line_num].rstrip()
       if not line:                      # blank
         continue
 
@@ -278,12 +322,13 @@
     if flag:
       modlist.append(flag)
 
-  def ParseCFlags(self, cnt=0):
+  def ParseCFlags(self, start_line=0):
     """Parse C style flags."""
     modname = None                      # name of current module
+    modlist = []
     flag = None
-    for cnt in range(cnt, len(self.output)): # collect flags
-      line = self.output[cnt].rstrip()
+    for line_num in range(start_line, len(self.output)):  # collect flags
+      line = self.output[line_num].rstrip()
       if not line:                      # blank lines terminate flags
         if flag:                        # save last flag
           modlist.append(flag)
@@ -318,7 +363,7 @@
     if flag:
       modlist.append(flag)
 
-  def ParseJavaFlags(self, cnt=0):
+  def ParseJavaFlags(self, start_line=0):
     """Parse Java style flags (com.google.common.flags)."""
     # The java flags prints starts with a "Standard flags" "module"
     # that doesn't follow the standard module syntax.
@@ -328,8 +373,8 @@
     modlist = self.modules[modname]
     flag = None
 
-    for cnt in range(cnt, len(self.output)): # collect flags
-      line = self.output[cnt].rstrip()
+    for line_num in range(start_line, len(self.output)): # collect flags
+      line = self.output[line_num].rstrip()
       logging.vlog(2, 'Line: "%s"' % line)
       if not line:                      # blank lines terminate module
         if flag:                        # save last flag
@@ -371,9 +416,9 @@
       self.short_desc = ''
       return
 
-    for cnt in range(len(self.desc)):   # replace full path with name
-      if self.desc[cnt].find(self.executable) >= 0:
-        self.desc[cnt] = self.desc[cnt].replace(self.executable, self.name)
+    for i in range(len(self.desc)):   # replace full path with name
+      if self.desc[i].find(self.executable) >= 0:
+        self.desc[i] = self.desc[i].replace(self.executable, self.name)
 
     self.short_desc = self.desc[0]
     word_list = self.short_desc.split(' ')
@@ -407,6 +452,11 @@
     self.Body()
     self.Footer()
 
+  def Open(self): raise NotImplementedError    # define in subclass
+  def Header(self): raise NotImplementedError  # define in subclass
+  def Body(self): raise NotImplementedError    # define in subclass
+  def Footer(self): raise NotImplementedError  # define in subclass
+
 
 class GenerateMan(GenerateDoc):
   """Output a man page."""
@@ -431,10 +481,10 @@
   def Header(self):
     self.fp.write(
       '.\\" DO NOT MODIFY THIS FILE!  It was generated by gflags2man %s\n'
-      % _version)
+      % _VERSION)
     self.fp.write(
       '.TH %s "1" "%s" "%s" "User Commands"\n'
-      % (self.info.name, self.info.date.strftime('%x'), self.info.name))
+      % (self.info.name, time.strftime('%x', self.info.date), self.info.name))
     self.fp.write(
       '.SH NAME\n%s \\- %s\n' % (self.info.name, self.info.short_desc))
     self.fp.write(
@@ -455,30 +505,33 @@
         mod = modname
       self.fp.write('\n.P\n.I %s\n' % mod)
       for flag in self.info.modules[modname]:
-        help = flag.help
+        help_string = flag.help
         if flag.default or flag.tips:
-          help += '\n.br\n'
+          help_string += '\n.br\n'
         if flag.default:
-          help += '  (default: \'%s\')' % flag.default
+          help_string += '  (default: \'%s\')' % flag.default
         if flag.tips:
-          help += '  (%s)' % flag.tips
+          help_string += '  (%s)' % flag.tips
         self.fp.write(
-          '.TP\n%s\n%s\n' % (flag.desc, help))
+          '.TP\n%s\n%s\n' % (flag.desc, help_string))
 
   def Footer(self):
     self.fp.write(
       '.SH COPYRIGHT\nCopyright \(co %s Google.\n'
-      % self.info.date.strftime('%Y'))
-    self.fp.write('Gflags2man.par created this page from "%s %s" output.\n'
+      % time.strftime('%Y', self.info.date))
+    self.fp.write('Gflags2man created this page from "%s %s" output.\n'
                   % (self.info.name, FLAGS.help_flag))
-    self.fp.write('\nGflags2man.par was written by Dan Christian'
-                  ' (dchristian@google.com).  Note that the date on this'
+    self.fp.write('\nGflags2man was written by Dan Christian. '
+                  ' Note that the date on this'
                   ' page is the modification date of %s.\n' % self.info.name)
 
 
 def main(argv):
+  argv = FLAGS(argv)           # handles help as well
   if len(argv) <= 1:
-    app.usage(shorthelp=1)
+    print >>sys.stderr, __doc__
+    print >>sys.stderr, "flags:"
+    print >>sys.stderr, str(FLAGS)
     return 1
 
   for arg in argv[1:]:
@@ -489,7 +542,7 @@
     prog.Filter()
     doc = GenerateMan(prog, FLAGS.dest_dir)
     doc.Output()
-
+  return 0
 
 if __name__ == '__main__':
-  app.run()
+  main(sys.argv)
diff --git a/python/gflags_unittest.py b/python/gflags_unittest.py
new file mode 100755
index 0000000..d55a26a
--- /dev/null
+++ b/python/gflags_unittest.py
@@ -0,0 +1,800 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2007, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"Unittest for flags.py module"
+
+__pychecker__ = "no-local" # for unittest
+
+
+import sys
+import os
+import shutil
+import unittest
+
+# We use the name 'flags' internally in this test, for historical reasons.
+# Don't do this yourself! :-)  Just do 'import gflags; FLAGS=gflags.FLAGS; etc'
+import gflags as flags
+FLAGS=flags.FLAGS
+
+class FlagsUnitTest(unittest.TestCase):
+  "Flags Unit Test"
+
+  def test_flags(self):
+    
+    ##############################################
+    # Test normal usage with no (expected) errors.
+
+    # Define flags
+    number_test_framework_flags = len(FLAGS.RegisteredFlags())
+    repeatHelp = "how many times to repeat (0-5)"
+    flags.DEFINE_integer("repeat", 4, repeatHelp,
+                         lower_bound=0, short_name='r')
+    flags.DEFINE_string("name", "Bob", "namehelp")
+    flags.DEFINE_boolean("debug", 0, "debughelp")
+    flags.DEFINE_boolean("q", 1, "quiet mode")
+    flags.DEFINE_boolean("quack", 0, "superstring of 'q'")
+    flags.DEFINE_boolean("noexec", 1, "boolean flag with no as prefix")
+    flags.DEFINE_integer("x", 3, "how eXtreme to be")
+    flags.DEFINE_integer("l", 0x7fffffff00000000L, "how long to be")
+    assert FLAGS.repeat == 4, "integer default values not set:" + FLAGS.repeat
+    assert FLAGS.name == 'Bob', "default values not set:" + FLAGS.name
+    assert FLAGS.debug == 0, "boolean default values not set:" + FLAGS.debug
+    assert FLAGS.q == 1, "boolean default values not set:" + FLAGS.q
+    assert FLAGS.x == 3, "integer default values not set:" + FLAGS.x
+    assert FLAGS.l == 0x7fffffff00000000L, "integer default values not set:" + FLAGS.l
+    
+    flag_values = FLAGS.FlagValuesDict()
+    assert flag_values['repeat'] == 4
+    assert flag_values['name'] == 'Bob'
+    assert flag_values['debug'] == 0
+    assert flag_values['r'] == 4       # short for of repeat
+    assert flag_values['q'] == 1
+    assert flag_values['quack'] == 0
+    assert flag_values['x'] == 3
+    assert flag_values['l'] == 0x7fffffff00000000L
+
+    # Verify string form of defaults
+    assert FLAGS['repeat'].default_as_str == "'4'"
+    assert FLAGS['name'].default_as_str == "'Bob'"
+    assert FLAGS['debug'].default_as_str == "'false'"
+    assert FLAGS['q'].default_as_str == "'true'"
+    assert FLAGS['quack'].default_as_str == "'false'"
+    assert FLAGS['noexec'].default_as_str == "'true'"
+    assert FLAGS['x'].default_as_str == "'3'"
+    assert FLAGS['l'].default_as_str == "'9223372032559808512'"
+
+    # Verify that the iterator for flags yields all the keys
+    keys = list(FLAGS)
+    keys.sort()
+    reg_flags = FLAGS.RegisteredFlags()
+    reg_flags.sort()
+    self.assertEqual(keys, reg_flags)
+    
+    # Parse flags
+    # .. empty command line
+    argv = ('./program',)
+    argv = FLAGS(argv)
+    assert len(argv) == 1, "wrong number of arguments pulled"
+    assert argv[0]=='./program', "program name not preserved"
+
+    # .. non-empty command line
+    argv = ('./program', '--debug', '--name=Bob', '-q', '--x=8')
+    argv = FLAGS(argv)
+    assert len(argv) == 1, "wrong number of arguments pulled"
+    assert argv[0]=='./program', "program name not preserved"
+    assert FLAGS['debug'].present == 1
+    FLAGS['debug'].present = 0 # Reset
+    assert FLAGS['name'].present == 1
+    FLAGS['name'].present = 0 # Reset
+    assert FLAGS['q'].present == 1
+    FLAGS['q'].present = 0 # Reset
+    assert FLAGS['x'].present == 1
+    FLAGS['x'].present = 0 # Reset
+
+    # Flags list
+    
+    assert len(FLAGS.RegisteredFlags()) == 9 + number_test_framework_flags
+    assert 'name' in FLAGS.RegisteredFlags()
+    assert 'debug' in FLAGS.RegisteredFlags()
+    assert 'repeat' in FLAGS.RegisteredFlags()
+    assert 'r' in FLAGS.RegisteredFlags()
+    assert 'q' in FLAGS.RegisteredFlags()
+    assert 'quack' in FLAGS.RegisteredFlags()
+    assert 'x' in FLAGS.RegisteredFlags()
+    assert 'l' in FLAGS.RegisteredFlags()
+
+    # has_key
+    assert FLAGS.has_key('name')
+    assert not FLAGS.has_key('name2')
+    assert 'name' in FLAGS
+    assert 'name2' not in FLAGS
+
+    # try deleting a flag
+    del FLAGS.r
+    assert len(FLAGS.RegisteredFlags()) == 8 + number_test_framework_flags
+    assert not 'r' in FLAGS.RegisteredFlags()
+
+    # .. command line with extra stuff
+    argv = ('./program', '--debug', '--name=Bob', 'extra')
+    argv = FLAGS(argv)
+    assert len(argv) == 2, "wrong number of arguments pulled"
+    assert argv[0]=='./program', "program name not preserved"
+    assert argv[1]=='extra', "extra argument not preserved"
+    assert FLAGS['debug'].present == 1
+    FLAGS['debug'].present = 0 # Reset
+    assert FLAGS['name'].present == 1
+    FLAGS['name'].present = 0 # Reset
+
+    # Test reset
+    argv = ('./program', '--debug')
+    argv = FLAGS(argv)
+    assert len(argv) == 1, "wrong number of arguments pulled"
+    assert argv[0] == './program', "program name not preserved"
+    assert FLAGS['debug'].present == 1
+    assert FLAGS['debug'].value == True
+    FLAGS.Reset()
+    assert FLAGS['debug'].present == 0
+    assert FLAGS['debug'].value == False
+
+    # Test integer argument passing
+    argv = ('./program', '--x', '0x12345')
+    argv = FLAGS(argv)
+    # 0x12345 == 74565
+    self.assertEquals(FLAGS.x, 74565)
+    self.assertEquals(type(FLAGS.x), int)
+
+    argv = ('./program', '--x', '0x123456789A')
+    argv = FLAGS(argv)
+    # 0x123456789A == 78187493530L
+    self.assertEquals(FLAGS.x, 78187493530L)
+    self.assertEquals(type(FLAGS.x), long)
+
+    # Treat 0-prefixed parameters as base-10, not base-8
+    argv = ('./program', '--x', '012345')
+    argv = FLAGS(argv)
+    self.assertEquals(FLAGS.x, 12345)
+    self.assertEquals(type(FLAGS.x), int)
+
+    argv = ('./program', '--x', '0123459')
+    argv = FLAGS(argv)
+    self.assertEquals(FLAGS.x, 123459)
+    self.assertEquals(type(FLAGS.x), int)
+
+    argv = ('./program', '--x', '0x123efg')
+    try:
+      argv = FLAGS(argv)
+      raise AssertionError("failed to detect invalid hex argument")
+    except flags.IllegalFlagValue:
+      pass
+
+    argv = ('./program', '--x', '0X123efg')
+    try:
+      argv = FLAGS(argv)
+      raise AssertionError("failed to detect invalid hex argument")
+    except flags.IllegalFlagValue:
+      pass
+
+    # Test boolean argument parsing
+    flags.DEFINE_boolean("test0", None, "test boolean parsing")
+    argv = ('./program', '--notest0')
+    argv = FLAGS(argv)
+    assert FLAGS.test0 == 0
+
+    flags.DEFINE_boolean("test1", None, "test boolean parsing")
+    argv = ('./program', '--test1')
+    argv = FLAGS(argv)
+    assert FLAGS.test1 == 1
+
+    FLAGS.test0 = None
+    argv = ('./program', '--test0=false')
+    argv = FLAGS(argv)
+    assert FLAGS.test0 == 0
+
+    FLAGS.test1 = None
+    argv = ('./program', '--test1=true')
+    argv = FLAGS(argv)
+    assert FLAGS.test1 == 1
+
+    FLAGS.test0 = None
+    argv = ('./program', '--test0=0')
+    argv = FLAGS(argv)
+    assert FLAGS.test0 == 0
+
+    FLAGS.test1 = None
+    argv = ('./program', '--test1=1')
+    argv = FLAGS(argv)
+    assert FLAGS.test1 == 1
+
+    # Test booleans that already have 'no' as a prefix
+    FLAGS.noexec = None
+    argv = ('./program', '--nonoexec', '--name', 'Bob')
+    argv = FLAGS(argv)
+    assert FLAGS.noexec == 0
+
+    FLAGS.noexec = None
+    argv = ('./program', '--name', 'Bob', '--noexec')
+    argv = FLAGS(argv)
+    assert FLAGS.noexec == 1
+
+    # Test unassigned booleans
+    flags.DEFINE_boolean("testnone", None, "test boolean parsing")
+    argv = ('./program',)
+    argv = FLAGS(argv)
+    assert FLAGS.testnone == None
+
+    # Test get with default
+    flags.DEFINE_boolean("testget1", None, "test parsing with defaults")
+    flags.DEFINE_boolean("testget2", None, "test parsing with defaults")
+    flags.DEFINE_boolean("testget3", None, "test parsing with defaults")
+    flags.DEFINE_integer("testget4", None, "test parsing with defaults")
+    argv = ('./program','--testget1','--notestget2')
+    argv = FLAGS(argv)
+    assert FLAGS.get('testget1', 'foo') == 1
+    assert FLAGS.get('testget2', 'foo') == 0
+    assert FLAGS.get('testget3', 'foo') == 'foo'
+    assert FLAGS.get('testget4', 'foo') == 'foo'
+
+    # test list code
+    lists = [['hello','moo','boo','1'],
+             [],]
+            
+    flags.DEFINE_list('testlist', '', 'test lists parsing')
+    flags.DEFINE_spaceseplist('testspacelist', '', 'tests space lists parsing')
+
+    for name, sep in (('testlist', ','), ('testspacelist', ' '), 
+                      ('testspacelist', '\n')):
+      for lst in lists:
+        argv = ('./program', '--%s=%s' % (name, sep.join(lst)))
+        argv = FLAGS(argv)
+        self.assertEquals(getattr(FLAGS, name), lst)
+   
+    # Test help text
+    flagsHelp = str(FLAGS)
+    assert flagsHelp.find("repeat") != -1, "cannot find flag in help"
+    assert flagsHelp.find(repeatHelp) != -1, "cannot find help string in help"
+
+    # Test flag specified twice
+    argv = ('./program', '--repeat=4', '--repeat=2', '--debug', '--nodebug')
+    argv = FLAGS(argv)
+    self.assertEqual(FLAGS.get('repeat', None), 2)
+    self.assertEqual(FLAGS.get('debug', None), 0)
+
+    # Test MultiFlag with single default value
+    flags.DEFINE_multistring('s_str', 'sing1',
+                             'string option that can occur multiple times',
+                             short_name='s')
+    self.assertEqual(FLAGS.get('s_str', None), [ 'sing1', ])
+    
+    # Test MultiFlag with list of default values
+    multi_string_defs = [ 'def1', 'def2', ]
+    flags.DEFINE_multistring('m_str', multi_string_defs,
+                             'string option that can occur multiple times',
+                             short_name='m')
+    self.assertEqual(FLAGS.get('m_str', None), multi_string_defs)
+    
+    # Test flag specified multiple times with a MultiFlag
+    argv = ('./program', '--m_str=str1', '-m', 'str2')
+    argv = FLAGS(argv)
+    self.assertEqual(FLAGS.get('m_str', None), [ 'str1', 'str2', ])
+    
+    # Test single-letter flags; should support both single and double dash
+    argv = ('./program', '-q', '-x8')
+    argv = FLAGS(argv)
+    self.assertEqual(FLAGS.get('q', None), 1)
+    self.assertEqual(FLAGS.get('x', None), 8)
+
+    argv = ('./program', '--q', '--x', '9', '--noqu')
+    argv = FLAGS(argv)
+    self.assertEqual(FLAGS.get('q', None), 1)
+    self.assertEqual(FLAGS.get('x', None), 9)
+    # --noqu should match '--noquack since it's a unique prefix
+    self.assertEqual(FLAGS.get('quack', None), 0)
+
+    argv = ('./program', '--noq', '--x=10', '--qu')
+    argv = FLAGS(argv)
+    self.assertEqual(FLAGS.get('q', None), 0)
+    self.assertEqual(FLAGS.get('x', None), 10)
+    self.assertEqual(FLAGS.get('quack', None), 1)
+
+    ####################################
+    # Test flag serialization code:
+
+    oldtestlist = FLAGS.testlist
+    oldtestspacelist = FLAGS.testspacelist
+    
+    argv = ('./program',
+            FLAGS['test0'].Serialize(),
+            FLAGS['test1'].Serialize(),
+            FLAGS['testnone'].Serialize(),
+            FLAGS['s_str'].Serialize())
+    argv = FLAGS(argv)
+    self.assertEqual(FLAGS['test0'].Serialize(), '--notest0')
+    self.assertEqual(FLAGS['test1'].Serialize(), '--test1')
+    self.assertEqual(FLAGS['testnone'].Serialize(), '')
+    self.assertEqual(FLAGS['s_str'].Serialize(), '--s_str=sing1')
+
+    testlist1 = ['aa', 'bb']
+    testspacelist1 = ['aa', 'bb', 'cc']
+    FLAGS.testlist = list(testlist1)
+    FLAGS.testspacelist = list(testspacelist1)
+    argv = ('./program',
+            FLAGS['testlist'].Serialize(),
+            FLAGS['testspacelist'].Serialize())    
+    argv = FLAGS(argv)
+    self.assertEqual(FLAGS.testlist, testlist1)
+    self.assertEqual(FLAGS.testspacelist, testspacelist1)
+
+    testlist1 = ['aa some spaces', 'bb']
+    testspacelist1 = ['aa', 'bb,some,commas,', 'cc']
+    FLAGS.testlist = list(testlist1)
+    FLAGS.testspacelist = list(testspacelist1)
+    argv = ('./program',
+            FLAGS['testlist'].Serialize(),
+            FLAGS['testspacelist'].Serialize())
+    argv = FLAGS(argv)
+    self.assertEqual(FLAGS.testlist, testlist1)
+    self.assertEqual(FLAGS.testspacelist, testspacelist1)
+
+    FLAGS.testlist = oldtestlist
+    FLAGS.testspacelist = oldtestspacelist
+
+    ####################################
+    # Test flag-update:
+
+    def ArgsString():
+      flagnames = FLAGS.RegisteredFlags()
+      flagnames.sort()
+      nonbool_flags = ['--%s %s' % (name, FLAGS.get(name, None))
+                      for name in flagnames
+                      if not isinstance(FLAGS[name], flags.BooleanFlag)]
+
+      truebool_flags = ['--%s' % (name)
+                       for name in flagnames
+                       if isinstance(FLAGS[name], flags.BooleanFlag) and
+                          FLAGS.get(name, None)]
+      falsebool_flags = ['--no%s' % (name)
+                        for name in flagnames
+                        if isinstance(FLAGS[name], flags.BooleanFlag) and
+                           not FLAGS.get(name, None)]
+      return ' '.join(nonbool_flags + truebool_flags + falsebool_flags)
+
+    argv = ('./program', '--repeat=3', '--name=giants', '--nodebug')
+    FLAGS(argv)
+    self.assertEqual(FLAGS.get('repeat', None), 3)
+    self.assertEqual(FLAGS.get('name', None), 'giants')
+    self.assertEqual(FLAGS.get('debug', None), 0)
+    self.assertEqual(ArgsString(),
+      "--l 9223372032559808512 "
+      "--m ['str1', 'str2'] --m_str ['str1', 'str2'] " 
+      "--name giants " 
+      "--repeat 3 " 
+      "--s ['sing1'] --s_str ['sing1'] "
+      "--testget4 None --testlist [] "
+      "--testspacelist [] --x 10 "
+      "--noexec --quack "
+      "--test1 "
+      "--testget1 --no? --nodebug --nohelp --nohelpshort "
+      "--noq --notest0 --notestget2 "
+      "--notestget3 --notestnone")
+
+    argv = ('./program', '--debug', '--m_str=upd1', '-s', 'upd2')
+    FLAGS(argv)
+    self.assertEqual(FLAGS.get('repeat', None), 3)
+    self.assertEqual(FLAGS.get('name', None), 'giants')
+    self.assertEqual(FLAGS.get('debug', None), 1)
+
+    # items appended to existing non-default value lists for --m/--m_str
+    # new value overwrites default value (not appended to it) for --s/--s_str
+    self.assertEqual(ArgsString(),
+      "--l 9223372032559808512 "
+      "--m ['str1', 'str2', 'upd1'] "
+      "--m_str ['str1', 'str2', 'upd1'] "
+      "--name giants " 
+      "--repeat 3 " 
+      "--s ['upd2'] --s_str ['upd2'] "
+      "--testget4 None --testlist [] "
+      "--testspacelist [] --x 10 "
+      "--debug --noexec --quack "
+      "--test1 "
+      "--testget1 --no? --nohelp --nohelpshort "
+      "--noq --notest0 --notestget2 "
+      "--notestget3 --notestnone")
+
+
+    ####################################
+    # Test all kind of error conditions.
+    
+    # Duplicate flag detection
+    try:
+      flags.DEFINE_boolean("run", 0, "runhelp", short_name='q')
+      raise AssertionError("duplicate flag detection failed")
+    except flags.DuplicateFlag, e:
+      pass
+
+    try:
+      flags.DEFINE_boolean("zoom1", 0, "runhelp z1", short_name='z')
+      flags.DEFINE_boolean("zoom2", 0, "runhelp z2", short_name='z')
+      raise AssertionError("duplicate flag detection failed")
+    except flags.DuplicateFlag, e:
+      pass
+
+    # Make sure allow_override works
+    try:
+      flags.DEFINE_boolean("dup1", 0, "runhelp d11", short_name='u',
+                           allow_override=0)
+      flag = FLAGS.FlagDict()['dup1']
+      self.assertEqual(flag.default, 0)
+
+      flags.DEFINE_boolean("dup1", 1, "runhelp d12", short_name='u',
+                           allow_override=1)
+      flag = FLAGS.FlagDict()['dup1']
+      self.assertEqual(flag.default, 1)
+    except flags.DuplicateFlag, e:
+      raise AssertionError("allow_override did not permit a flag duplication")
+
+    # Make sure allow_override works
+    try:
+      flags.DEFINE_boolean("dup2", 0, "runhelp d21", short_name='u',
+                           allow_override=1)
+      flag = FLAGS.FlagDict()['dup2']
+      self.assertEqual(flag.default, 0)
+
+      flags.DEFINE_boolean("dup2", 1, "runhelp d22", short_name='u',
+                           allow_override=0)
+      flag = FLAGS.FlagDict()['dup2']
+      self.assertEqual(flag.default, 1)
+    except flags.DuplicateFlag, e:
+      raise AssertionError("allow_override did not permit a flag duplication")
+
+    # Make sure allow_override doesn't work with None default
+    try:
+      flags.DEFINE_boolean("dup3", 0, "runhelp d31", short_name='u',
+                           allow_override=0)
+      flag = FLAGS.FlagDict()['dup3']
+      self.assertEqual(flag.default, 0)
+
+      flags.DEFINE_boolean("dup3", None, "runhelp d32", short_name='u',
+                           allow_override=1)
+      raise AssertionError('Cannot override a flag with a default of None')
+    except flags.DuplicateFlag, e:
+      pass
+
+    # Make sure that when we override, the help string gets updated correctly
+    flags.DEFINE_boolean("dup3", 0, "runhelp d31", short_name='u',
+                         allow_override=1)
+    flags.DEFINE_boolean("dup3", 1, "runhelp d32", short_name='u',
+                         allow_override=1)
+    self.assert_(str(FLAGS).find('runhelp d31') == -1)
+    self.assert_(str(FLAGS).find('runhelp d32') != -1)
+
+    # Integer out of bounds
+    try:
+      argv = ('./program', '--repeat=-4')
+      FLAGS(argv)
+      raise AssertionError('integer bounds exception not thrown:'
+                           + str(FLAGS.repeat))
+    except flags.IllegalFlagValue:
+      pass
+
+    # Non-integer
+    try:
+      argv = ('./program', '--repeat=2.5')
+      FLAGS(argv)
+      raise AssertionError("malformed integer value exception not thrown")
+    except flags.IllegalFlagValue:
+      pass
+
+    # Missing required arugment
+    try:
+      argv = ('./program', '--name')
+      FLAGS(argv)
+      raise AssertionError("Flag argument required exception not thrown")
+    except flags.FlagsError:
+      pass
+
+    # Argument erroneously supplied for boolean
+    try:
+      argv = ('./program', '--debug=goofup')
+      FLAGS(argv)
+      raise AssertionError("No argument allowed exception not thrown")
+    except flags.FlagsError:
+      pass
+
+    # Unknown argument --nosuchflag
+    try:
+      argv = ('./program', '--nosuchflag', '--name=Bob', 'extra')
+      FLAGS(argv)
+      raise AssertionError("Unknown argument exception not thrown")
+    except flags.FlagsError:
+      pass
+
+    # Non-numeric argument for integer flag --repeat
+    try:
+      argv = ('./program', '--repeat', 'Bob', 'extra')
+      FLAGS(argv)
+      raise AssertionError("Illegal flag value exception not thrown")
+    except flags.IllegalFlagValue:
+      pass
+      
+  ################################################
+  # Code to test the flagfile=<> loading behavior
+  ################################################
+  def _SetupTestFiles(self):  
+    """ Creates and sets up some dummy flagfile files with bogus flags"""
+    
+    # Figure out where to create temporary files
+    tmp_path = '/tmp/flags_unittest'
+    if os.path.exists(tmp_path):
+      shutil.rmtree(tmp_path)
+    os.makedirs(tmp_path)
+
+    try:
+      tmp_flag_file_1 = open((tmp_path + '/UnitTestFile1.tst'), 'w') 
+      tmp_flag_file_2 = open((tmp_path + '/UnitTestFile2.tst'), 'w')
+      tmp_flag_file_3 = open((tmp_path + '/UnitTestFile3.tst'), 'w')
+    except IOError, e_msg:
+      print e_msg
+      print 'FAIL\n File Creation problem in Unit Test' 
+      sys.exit(1)
+    
+    # put some dummy flags in our test files
+    tmp_flag_file_1.write('#A Fake Comment\n')
+    tmp_flag_file_1.write('--UnitTestMessage1=tempFile1!\n')
+    tmp_flag_file_1.write('\n')
+    tmp_flag_file_1.write('--UnitTestNumber=54321\n')
+    tmp_flag_file_1.write('--noUnitTestBoolFlag\n')
+    file_list = [tmp_flag_file_1.name]
+    # this one includes test file 1
+    tmp_flag_file_2.write('//A Different Fake Comment\n')
+    tmp_flag_file_2.write('--flagfile=%s\n' % tmp_flag_file_1.name)
+    tmp_flag_file_2.write('--UnitTestMessage2=setFromTempFile2\n')
+    tmp_flag_file_2.write('\t\t\n')
+    tmp_flag_file_2.write('--UnitTestNumber=6789a\n')
+    file_list.append(tmp_flag_file_2.name)
+    # this file points to itself
+    tmp_flag_file_3.write('--flagfile=%s\n' % tmp_flag_file_3.name)
+    tmp_flag_file_3.write('--UnitTestMessage1=setFromTempFile3\n')
+    tmp_flag_file_3.write('#YAFC\n')
+    tmp_flag_file_3.write('--UnitTestBoolFlag\n')
+    file_list.append(tmp_flag_file_3.name)
+    
+    tmp_flag_file_1.close() 
+    tmp_flag_file_2.close()
+    tmp_flag_file_3.close()
+
+    return file_list # these are just the file names
+  # end SetupFiles def
+  
+  def _RemoveTestFiles(self, tmp_file_list):
+    """Closes the files we just created.  tempfile deletes them for us """
+    for file_name in tmp_file_list: 
+      try:
+        os.remove(file_name) 
+      except OSError, e_msg:
+        print '%s\n, Problem deleting test file' % e_msg
+  #end RemoveTestFiles def
+  
+  def __DeclareSomeFlags(self):
+    flags.DEFINE_string('UnitTestMessage1', 'Foo!', 'You Add Here.')
+    flags.DEFINE_string('UnitTestMessage2', 'Bar!', 'Hello, Sailor!')
+    flags.DEFINE_boolean('UnitTestBoolFlag', 0, 'Some Boolean thing')
+    flags.DEFINE_integer('UnitTestNumber', 12345, 'Some integer',
+                         lower_bound=0)
+  
+  def _UndeclareSomeFlags(self): 
+    FLAGS.__delattr__('UnitTestMessage1')
+    FLAGS.__delattr__('UnitTestMessage2')
+    FLAGS.__delattr__('UnitTestBoolFlag')
+    FLAGS.__delattr__('UnitTestNumber')
+    
+  #### Flagfile Unit Tests ####  
+  def testMethod_flagfiles_1(self):
+    """ Test trivial case with no flagfile based options. """
+    self.__DeclareSomeFlags()
+    fake_cmd_line = 'fooScript --UnitTestBoolFlag'
+    fake_argv = fake_cmd_line.split(' ')
+    FLAGS(fake_argv)
+    self.assertEqual( FLAGS.UnitTestBoolFlag, 1)
+    self.assertEqual( fake_argv, FLAGS.ReadFlagsFromFiles(fake_argv))
+    self._UndeclareSomeFlags()
+  # end testMethodOne
+  
+  def testMethod_flagfiles_2(self):
+    """Tests parsing one file + arguments off simulated argv"""
+    self.__DeclareSomeFlags()
+    tmp_files = self._SetupTestFiles()
+    # specify our temp file on the fake cmd line
+    fake_cmd_line = 'fooScript --q --flagfile=%s' % tmp_files[0]
+    fake_argv = fake_cmd_line.split(' ')
+    
+    # We should see the original cmd line with the file's contents spliced in. 
+    # Note that these will be in REVERSE order from order encountered in file
+    # This is done so arguements we encounter sooner will have priority.
+    expected_results = ['fooScript',
+                          '--UnitTestMessage1=tempFile1!',
+                          '--UnitTestNumber=54321',
+                          '--noUnitTestBoolFlag',
+                          '--q']
+    test_results = FLAGS.ReadFlagsFromFiles(fake_argv)
+    self.assertEqual(expected_results, test_results) 
+    self._RemoveTestFiles(tmp_files)  
+    self._UndeclareSomeFlags()
+  # end testTwo def
+
+  def testMethod_flagfiles_3(self):
+    """Tests parsing nested files + arguments of simulated argv"""
+    self.__DeclareSomeFlags()
+    tmp_files = self._SetupTestFiles()
+    # specify our temp file on the fake cmd line
+    fake_cmd_line = ('fooScript --UnitTestNumber=77 --flagfile=%s'
+                     % tmp_files[1])
+    fake_argv = fake_cmd_line.split(' ')
+    
+    expected_results = ['fooScript',
+                          '--UnitTestMessage1=tempFile1!',
+                          '--UnitTestNumber=54321',
+                          '--noUnitTestBoolFlag',
+                          '--UnitTestMessage2=setFromTempFile2',
+                          '--UnitTestNumber=6789a',
+                          '--UnitTestNumber=77']
+    test_results = FLAGS.ReadFlagsFromFiles(fake_argv)
+    self.assertEqual(expected_results, test_results) 
+    self._RemoveTestFiles(tmp_files)
+    self._UndeclareSomeFlags()
+  # end testThree def
+    
+  def testMethod_flagfiles_4(self):
+    """Tests parsing self referetial files + arguments of simulated argv.
+      This test should print a warning to stderr of some sort.
+    """
+    self.__DeclareSomeFlags()
+    tmp_files = self._SetupTestFiles()
+    # specify our temp file on the fake cmd line
+    fake_cmd_line = ('fooScript --flagfile=%s --noUnitTestBoolFlag'
+                     % tmp_files[2])
+    fake_argv = fake_cmd_line.split(' ')
+    expected_results = ['fooScript',
+                          '--UnitTestMessage1=setFromTempFile3',
+                          '--UnitTestBoolFlag',
+                          '--noUnitTestBoolFlag' ]
+
+    test_results = FLAGS.ReadFlagsFromFiles(fake_argv)
+    self.assertEqual(expected_results, test_results) 
+    self._RemoveTestFiles(tmp_files)  
+    self._UndeclareSomeFlags()
+
+  def test_flagfiles_user_path_expansion(self):
+    """Test that user directory referenced paths (ie. ~/foo) are correctly 
+      expanded.  This test depends on whatever account's running the unit test 
+      to have read/write access to their own home directory, otherwise it'll 
+      FAIL.
+    """
+    self.__DeclareSomeFlags()
+    fake_flagfile_item_style_1 = '--flagfile=~/foo.file'
+    fake_flagfile_item_style_2 = '-flagfile=~/foo.file'
+    
+    expected_results = os.path.expanduser('~/foo.file')
+
+    test_results = FLAGS.ExtractFilename(fake_flagfile_item_style_1)
+    self.assertEqual(expected_results, test_results)
+
+    test_results = FLAGS.ExtractFilename(fake_flagfile_item_style_2)
+    self.assertEqual(expected_results, test_results)
+
+    self._UndeclareSomeFlags()
+
+  # end testFour def
+
+  def test_no_touchy_non_flags(self):
+    """
+    Test that the flags parser does not mutilate arguments which are
+    not supposed to be flags
+    """
+    self.__DeclareSomeFlags()
+    fake_argv = ['fooScript', '--UnitTestBoolFlag',
+                 'command', '--command_arg1', '--UnitTestBoom', '--UnitTestB']
+    argv = FLAGS(fake_argv)
+    self.assertEqual(argv, fake_argv[:1] + fake_argv[2:])
+    self._UndeclareSomeFlags()
+
+  def test_SetDefault(self):
+    """
+    Test changing flag defaults.
+    """
+    self.__DeclareSomeFlags()
+    # Test that SetDefault changes both the default and the value,
+    # and that the value is changed when one is given as an option.
+    FLAGS['UnitTestMessage1'].SetDefault('New value')
+    self.assertEqual(FLAGS.UnitTestMessage1, 'New value')
+    self.assertEqual(FLAGS['UnitTestMessage1'].default_as_str,"'New value'")
+    FLAGS([ 'dummyscript', '--UnitTestMessage1=Newer value' ])
+    self.assertEqual(FLAGS.UnitTestMessage1, 'Newer value')
+    # Test that setting the default to None works correctly.
+    FLAGS['UnitTestNumber'].SetDefault(None)
+    self.assertEqual(FLAGS.UnitTestNumber, None)
+    self.assertEqual(FLAGS['UnitTestNumber'].default_as_str, None)
+    FLAGS([ 'dummyscript', '--UnitTestNumber=56' ])
+    self.assertEqual(FLAGS.UnitTestNumber, 56)
+    # Test that setting invalid defaults raises exceptions
+    self.assertRaises(flags.IllegalFlagValue,
+                      FLAGS['UnitTestNumber'].SetDefault, 'oops')
+    self.assertRaises(flags.IllegalFlagValue,
+                      FLAGS['UnitTestNumber'].SetDefault, -1)
+    self.assertRaises(flags.IllegalFlagValue,
+                      FLAGS['UnitTestBoolFlag'].SetDefault, 'oops')
+    
+    self._UndeclareSomeFlags()
+
+  def testMethod_ShortestUniquePrefixes(self):
+    """
+    Test FlagValues.ShortestUniquePrefixes
+    """
+    flags.DEFINE_string('a', '', '')
+    flags.DEFINE_string('abc', '', '')
+    flags.DEFINE_string('common_a_string', '', '')
+    flags.DEFINE_boolean('common_b_boolean', 0, '')
+    flags.DEFINE_boolean('common_c_boolean', 0, '')
+    flags.DEFINE_boolean('common', 0, '')
+    flags.DEFINE_integer('commonly', 0, '')
+    flags.DEFINE_boolean('zz', 0, '')
+    flags.DEFINE_integer('nozz', 0, '')
+
+    shorter_flags = FLAGS.ShortestUniquePrefixes(FLAGS.FlagDict())
+
+    expected_results = {'nocommon_b_boolean': 'nocommon_b',
+                        'common_c_boolean': 'common_c',
+                        'common_b_boolean': 'common_b',
+                        'a': 'a',
+                        'abc': 'ab',
+                        'zz': 'z',
+                        'nozz': 'nozz',
+                        'common_a_string': 'common_a',
+                        'commonly': 'commonl',
+                        'nocommon_c_boolean': 'nocommon_c',
+                        'nocommon': 'nocommon',
+                        'common': 'common'}
+
+    for name, shorter in expected_results.iteritems():
+      self.assertEquals(shorter_flags[name], shorter)
+
+    FLAGS.__delattr__('a')
+    FLAGS.__delattr__('abc')
+    FLAGS.__delattr__('common_a_string')
+    FLAGS.__delattr__('common_b_boolean')
+    FLAGS.__delattr__('common_c_boolean')
+    FLAGS.__delattr__('common')
+    FLAGS.__delattr__('commonly')
+    FLAGS.__delattr__('zz')
+    FLAGS.__delattr__('nozz')
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/python/setup.py b/python/setup.py
new file mode 100755
index 0000000..c139338
--- /dev/null
+++ b/python/setup.py
@@ -0,0 +1,42 @@
+#!/usr/bin/python2.2
+
+# Copyright (c) 2007, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from distutils.core import setup
+
+setup(name='gflags',
+      version='0.2',
+      description='Google Commandline Flags Module',
+      license='BSD',
+      author='Google Inc.',
+      author_email='opensource@google.com',
+      url='http://code.google.com/p/google-gflags',
+      py_modules=["gflags"],
+      data_files=["/usr/local/bin", "gflags2man.py"])
diff --git a/src/google/gflags.h.in b/src/google/gflags.h.in
index 832a64f..13043f5 100644
--- a/src/google/gflags.h.in
+++ b/src/google/gflags.h.in
@@ -55,6 +55,7 @@
 #define BASE_COMMANDLINEFLAGS_H__
 
 #include <string>
+#include <vector>
 
 // We care a lot about number of bits things take up.  Unfortunately,
 // systems define their bit-specific ints in a lot of different ways.