mirror of
https://github.com/gflags/gflags.git
synced 2025-04-05 13:35:04 +00:00
Wed Mar 26 15:20:18 2008 Google Inc. <opensource@google.com>
* google-gflags: version 0.8 * Export DescribeOneFlag() in the API * Add support for automatic line wrapping at 80 cols for gflags.py * Bugfix: do not treat an isolated "-" the same as an isolated "--" * Update rpm spec to point to Google Code rather than sourceforge (!) * Improve documentation (including documenting thread-safety) * Improve #include hygiene * Improve testing git-svn-id: https://gflags.googlecode.com/svn/trunk@21 6586e3c6-dcc4-952a-343f-ff74eb82781d
This commit is contained in:
parent
585a44a0c0
commit
83911c12f3
13 changed files with 849 additions and 113 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
|||
Wed Mar 26 15:20:18 2008 Google Inc. <opensource@google.com>
|
||||
|
||||
* google-gflags: version 0.8
|
||||
* Export DescribeOneFlag() in the API
|
||||
* Add support for automatic line wrapping at 80 cols for gflags.py
|
||||
* Bugfix: do not treat an isolated "-" the same as an isolated "--"
|
||||
* Update rpm spec to point to Google Code rather than sourceforge (!)
|
||||
* Improve documentation (including documenting thread-safety)
|
||||
* Improve #include hygiene
|
||||
* Improve testing
|
||||
|
||||
Thu Oct 18 11:33:20 2007 Google Inc. <opensource@google.com>
|
||||
|
||||
* google-gflags: version 0.7
|
||||
|
|
20
configure
vendored
20
configure
vendored
|
@ -1,6 +1,6 @@
|
|||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.59 for gflags 0.7.
|
||||
# Generated by GNU Autoconf 2.59 for gflags 0.8.
|
||||
#
|
||||
# Report bugs to <opensource@google.com>.
|
||||
#
|
||||
|
@ -423,8 +423,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
|||
# Identity of this package.
|
||||
PACKAGE_NAME='gflags'
|
||||
PACKAGE_TARNAME='gflags'
|
||||
PACKAGE_VERSION='0.7'
|
||||
PACKAGE_STRING='gflags 0.7'
|
||||
PACKAGE_VERSION='0.8'
|
||||
PACKAGE_STRING='gflags 0.8'
|
||||
PACKAGE_BUGREPORT='opensource@google.com'
|
||||
|
||||
ac_unique_file="README"
|
||||
|
@ -954,7 +954,7 @@ if test "$ac_init_help" = "long"; then
|
|||
# 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.7 to adapt to many kinds of systems.
|
||||
\`configure' configures gflags 0.8 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
|
@ -1020,7 +1020,7 @@ fi
|
|||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of gflags 0.7:";;
|
||||
short | recursive ) echo "Configuration of gflags 0.8:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
|
@ -1163,7 +1163,7 @@ fi
|
|||
test -n "$ac_init_help" && exit 0
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
gflags configure 0.7
|
||||
gflags configure 0.8
|
||||
generated by GNU Autoconf 2.59
|
||||
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
@ -1177,7 +1177,7 @@ cat >&5 <<_ACEOF
|
|||
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.7, which was
|
||||
It was created by gflags $as_me 0.8, which was
|
||||
generated by GNU Autoconf 2.59. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
|
@ -1823,7 +1823,7 @@ fi
|
|||
|
||||
# Define the identity of the package.
|
||||
PACKAGE='gflags'
|
||||
VERSION='0.7'
|
||||
VERSION='0.8'
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
|
@ -20943,7 +20943,7 @@ _ASBOX
|
|||
} >&5
|
||||
cat >&5 <<_CSEOF
|
||||
|
||||
This file was extended by gflags $as_me 0.7, which was
|
||||
This file was extended by gflags $as_me 0.8, which was
|
||||
generated by GNU Autoconf 2.59. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
|
@ -21006,7 +21006,7 @@ _ACEOF
|
|||
|
||||
cat >>$CONFIG_STATUS <<_ACEOF
|
||||
ac_cs_version="\\
|
||||
gflags config.status 0.7
|
||||
gflags config.status 0.8
|
||||
configured by $0, generated by GNU Autoconf 2.59,
|
||||
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# make sure we're interpreted by some minimal autoconf
|
||||
AC_PREREQ(2.57)
|
||||
|
||||
AC_INIT(gflags, 0.7, opensource@google.com)
|
||||
AC_INIT(gflags, 0.8, opensource@google.com)
|
||||
# The argument here is just something that should be in the current directory
|
||||
# (for sanity checking)
|
||||
AC_CONFIG_SRCDIR(README)
|
||||
|
|
|
@ -81,11 +81,11 @@ translates directly to Python.</p>
|
|||
|
||||
<p> Defining a flag is easy: just use the appropriate macro for the
|
||||
type you want the flag to be, as defined at the bottom of
|
||||
<code>base/commandlineflags.h</code>. Here's an example file,
|
||||
<code>google/gflags.h</code>. Here's an example file,
|
||||
<code>foo.cc</code>:</p>
|
||||
|
||||
<pre>
|
||||
#include "base/commandlineflags.h"
|
||||
#include <google/gflags.h>
|
||||
|
||||
DEFINE_bool(big_menu, true, "Include 'advanced' options in the menu listing");
|
||||
DEFINE_string(languages, "english,french,german",
|
||||
|
@ -131,7 +131,7 @@ be in the global namespace.</p>
|
|||
<h2> <A name=using>Accessing the Flag</A> </h2>
|
||||
|
||||
<p>All defined flags are available to the program as just a normal
|
||||
variable, with the prefix <code>FLAGS_</code> appended. In the above
|
||||
variable, with the prefix <code>FLAGS_</code> prepended. In the above
|
||||
example, the macros define two variables, <code>FLAGS_big_menu</code>
|
||||
(a bool), and <code>FLAGS_languages</code> (a C++ string).</p>
|
||||
|
||||
|
@ -145,7 +145,7 @@ variable:</p>
|
|||
</pre>
|
||||
|
||||
<p>You can also get and set flag values via special functions in
|
||||
<code>commandlineflags.h</code>. That's a rarer use case, though.</p>
|
||||
<code>gflags.h</code>. That's a rarer use case, though.</p>
|
||||
|
||||
|
||||
<h2> <A name=declare>DECLARE: Using the Flag in a Different File</A> </h2>
|
||||
|
@ -173,16 +173,21 @@ recommend the following guideline:</p>
|
|||
|
||||
<blockquote>
|
||||
If you DEFINE a flag in <code>foo.cc</code>, either don't DECLARE it
|
||||
at all, or only DECLARE it in <code>foo.h</code>.
|
||||
at all, only DECLARE it in tightly related tests, or only DECLARE
|
||||
it in <code>foo.h</code>.
|
||||
</blockquote>
|
||||
|
||||
<p>You should go the do-not-DECLARE route when the flag is only needed
|
||||
by <code>foo.cc</code>, and not in any other file. If the flag does
|
||||
span multiple files, DECLARE it in the associated <code>.h</code>
|
||||
file, and make others <code>#include</code> that <code>.h</code> file
|
||||
if they want to access the flag. The <code>#include</code> will make
|
||||
explicit the dependency between the two files.</p>
|
||||
by <code>foo.cc</code>, and not in any other file. If you want to
|
||||
modify the value of the flag in the related test file to see if it is
|
||||
functioning as expected, DECLARE it in the <code>foo_test.cc</code>
|
||||
file.
|
||||
|
||||
<p>If the flag does span multiple files, DECLARE it in the associated
|
||||
<code>.h</code> file, and make others <code>#include</code> that
|
||||
<code>.h</code> file if they want to access the flag. The
|
||||
<code>#include</code> will make explicit the dependency between the
|
||||
two files. This causes the flag to be a global variable.</p>
|
||||
|
||||
<h2> <A name=together>Putting It Together: How to Set Up Flags</A> </h2>
|
||||
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
google-gflags (0.8-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Google Inc. <opensource@google.com> Wed, 26 Mar 2008 15:20:18 -0700
|
||||
|
||||
google-gflags (0.7-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
%define ver %VERSION
|
||||
%define RELEASE 1
|
||||
%define rel %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE}
|
||||
%define prefix /usr
|
||||
|
||||
Name: %NAME
|
||||
Summary: A commandline flags library that allows for distributed flags
|
||||
Version: %ver
|
||||
Version: %VERSION
|
||||
Release: %rel
|
||||
Group: Development/Libraries
|
||||
URL: http://code.google.com/p/google-gflags
|
||||
URL: http://code.google.com/p/gflags
|
||||
License: BSD
|
||||
Vendor: Google
|
||||
Packager: Google Inc. <opensource@google.com>
|
||||
Source: http://google-gflags.googlecode.com/files/%{NAME}-%{PACKAGE_VERSION}.tar.gz
|
||||
Source: http://%{NAME}.googlecode.com/files/%{NAME}-%{VERSION}.tar.gz
|
||||
Distribution: Redhat 7 and above.
|
||||
Buildroot: %{_tmppath}/%{name}-root
|
||||
Prefix: %prefix
|
||||
|
@ -26,6 +25,7 @@ the ability to define flags in the source file in which they're used.
|
|||
%package devel
|
||||
Summary: A commandline flags library that allows for distributed flags
|
||||
Group: Development/Libraries
|
||||
Requires: %{NAME} = %{VERSION}
|
||||
|
||||
%description devel
|
||||
The %name-devel package contains static and debug libraries and header
|
||||
|
|
416
python/gflags.py
416
python/gflags.py
|
@ -116,6 +116,7 @@ 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.
|
||||
--undefok=f1,f2 ignore unrecognized option errors for f1,f2
|
||||
-- as in getopt(), terminates flag-processing
|
||||
|
||||
Note on --flagfile:
|
||||
|
@ -157,11 +158,10 @@ EXAMPLE USAGE:
|
|||
# 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")
|
||||
gflags.DEFINE_string('name', 'Mr. President', 'your name')
|
||||
gflags.DEFINE_integer('age', None, 'your age in years', lower_bound=0)
|
||||
gflags.DEFINE_boolean('debug', 0, 'produces debugging output')
|
||||
gflags.DEFINE_enum('gender', 'male', ['male', 'female'], 'your gender')
|
||||
|
||||
def main(argv):
|
||||
try:
|
||||
|
@ -172,13 +172,15 @@ EXAMPLE USAGE:
|
|||
if FLAGS.debug: print 'non-flag arguments:', argv
|
||||
print 'Happy Birthday', FLAGS.name
|
||||
if FLAGS.age is not None:
|
||||
print "You are a %s, who is %d years old" % (FLAGS.gender, FLAGS.age)
|
||||
print 'You are a %s, who is %d years old' % (FLAGS.gender, FLAGS.age)
|
||||
|
||||
if __name__ == '__main__': main(sys.argv)
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
||||
"""
|
||||
|
||||
import getopt
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
# Are we running at least python 2.2?
|
||||
|
@ -188,16 +190,256 @@ try:
|
|||
except AttributeError: # a very old python, that lacks sys.version_info
|
||||
raise NotImplementedError("requires python 2.2.0 or later")
|
||||
|
||||
# If we're not running at least python 2.3, define True and False
|
||||
# Thanks, Guido, for the code.
|
||||
try:
|
||||
True, False
|
||||
except NameError:
|
||||
False = 0
|
||||
True = 1
|
||||
|
||||
# Are we running under pychecker?
|
||||
_RUNNING_PYCHECKER = 'pychecker.python' in sys.modules
|
||||
|
||||
|
||||
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"
|
||||
|
||||
|
||||
# module exceptions:
|
||||
class FlagsError(Exception): "The base class for all flags errors"
|
||||
class DuplicateFlag(FlagsError): "Thrown if there is a flag naming conflict"
|
||||
class FlagsError(Exception):
|
||||
"""The base class for all flags errors"""
|
||||
|
||||
class DuplicateFlag(FlagsError):
|
||||
""""Raised if there is a flag naming conflict"""
|
||||
|
||||
# A DuplicateFlagError conveys more information than
|
||||
# a DuplicateFlag. Since there are external modules
|
||||
# that create DuplicateFlags, the interface to
|
||||
# DuplicateFlag shouldn't change.
|
||||
class DuplicateFlagError(DuplicateFlag):
|
||||
def __init__(self, flagname, flag_values):
|
||||
self.flagname = flagname
|
||||
message = "The flag '%s' is defined twice." % self.flagname
|
||||
flags_by_module = flag_values.__dict__['__flags_by_module']
|
||||
for module in flags_by_module:
|
||||
for flag in flags_by_module[module]:
|
||||
if flag.name == flagname:
|
||||
message = message + " First from " + module + ","
|
||||
break
|
||||
message = message + " Second from " + _GetCallingModule()
|
||||
Exception.__init__(self, message)
|
||||
|
||||
class IllegalFlagValue(FlagsError): "The flag command line argument is illegal"
|
||||
|
||||
class UnrecognizedFlag(FlagsError):
|
||||
"""Raised if a flag is unrecognized"""
|
||||
|
||||
# An UnrecognizedFlagError conveys more information than
|
||||
# an UnrecognizedFlag. Since there are external modules
|
||||
# that create DuplicateFlags, the interface to
|
||||
# DuplicateFlag shouldn't change.
|
||||
class UnrecognizedFlagError(UnrecognizedFlag):
|
||||
def __init__(self, flagname):
|
||||
self.flagname = flagname
|
||||
Exception.__init__(self, "Unknown command line flag '%s'" % flagname)
|
||||
|
||||
# Global variable used by expvar
|
||||
_exported_flags = {}
|
||||
_help_width = 80 # width of help output
|
||||
|
||||
|
||||
def GetHelpWidth():
|
||||
"""
|
||||
Length of help to be used in TextWrap
|
||||
"""
|
||||
global _help_width
|
||||
return _help_width
|
||||
|
||||
|
||||
def CutCommonSpacePrefix(text):
|
||||
"""
|
||||
Cut out a common space prefix. If the first line does not start with a space
|
||||
it is left as is and only in the remaining lines a common space prefix is
|
||||
being searched for. That means the first line will stay untouched. This is
|
||||
especially useful to turn doc strings into help texts. This is because some
|
||||
people prefer to have the doc comment start already after the apostrophy and
|
||||
then align the following lines while others have the apostrophies on a
|
||||
seperately line. The function also drops trailing empty lines and ignores
|
||||
empty lines following the initial content line while calculating the initial
|
||||
common whitespace.
|
||||
|
||||
Args:
|
||||
text: text to work on
|
||||
|
||||
Returns:
|
||||
the resulting text
|
||||
"""
|
||||
text_lines = text.splitlines()
|
||||
# Drop trailing empty lines
|
||||
while text_lines and not text_lines[-1]:
|
||||
text_lines = text_lines[:-1]
|
||||
if text_lines:
|
||||
# We got some content, is the first line starting with a space?
|
||||
if text_lines[0] and text_lines[0][0].isspace():
|
||||
text_first_line = []
|
||||
else:
|
||||
text_first_line = [text_lines.pop(0)]
|
||||
# Calculate length of common leading whitesppace (only over content lines)
|
||||
common_prefix = os.path.commonprefix([line for line in text_lines if line])
|
||||
space_prefix_len = len(common_prefix) - len(common_prefix.lstrip())
|
||||
# If we have a common space prefix, drop it from all lines
|
||||
if space_prefix_len:
|
||||
for index in xrange(len(text_lines)):
|
||||
if text_lines[index]:
|
||||
text_lines[index] = text_lines[index][space_prefix_len:]
|
||||
return '\n'.join(text_first_line + text_lines)
|
||||
return ''
|
||||
|
||||
|
||||
def TextWrap(text, length=None, indent='', firstline_indent=None, tabs=' '):
|
||||
"""
|
||||
Wrap a given text to a maximum line length and return it.
|
||||
We turn lines that only contain whitespace into empty lines.
|
||||
We keep new lines.
|
||||
We also keep tabs (e.g. we do not treat tabs as spaces).
|
||||
|
||||
Args:
|
||||
text: text to wrap
|
||||
length: maximum length of a line, includes indentation
|
||||
if this is None then use GetHelpWidth()
|
||||
indent: indent for all but first line
|
||||
firstline_indent: indent for first line, if None then fall back to indent
|
||||
tabs: replacement for tabs
|
||||
|
||||
Returns:
|
||||
wrapped text
|
||||
|
||||
Raises:
|
||||
CommandsError: if indent not shorter than length
|
||||
CommandsError: if firstline_indent not shorter than length
|
||||
"""
|
||||
# Get defaults where callee used None
|
||||
if length is None:
|
||||
length = GetHelpWidth()
|
||||
if indent is None:
|
||||
indent = ''
|
||||
if len(indent) >= length:
|
||||
raise CommandsError('Indent must be shorter than length')
|
||||
# In line we will be holding the current line which is to be started with
|
||||
# indent (or firstline_indent if available) and then appended with words.
|
||||
if firstline_indent is None:
|
||||
firstline_indent = ''
|
||||
line = indent
|
||||
else:
|
||||
line = firstline_indent
|
||||
if len(firstline_indent) >= length:
|
||||
raise CommandsError('First iline indent must be shorter than length')
|
||||
|
||||
# If the callee does not care about tabs we simply convert them to spaces
|
||||
# If callee wanted tabs to be single space then we do that already here.
|
||||
if not tabs or tabs == ' ':
|
||||
text = text.replace('\t', ' ')
|
||||
else:
|
||||
tabs_are_whitespace = not tabs.strip()
|
||||
|
||||
line_regex = re.compile('([ ]*)(\t*)([^ \t]+)', re.MULTILINE)
|
||||
|
||||
# Split the text into lines and the lines with the regex above. The resulting
|
||||
# lines are collected in result[]. For each split we get the spaces, the tabs
|
||||
# and the next non white space (e.g. next word).
|
||||
result = []
|
||||
for text_line in text.splitlines():
|
||||
# Store result length so we can find out whether processing the next line
|
||||
# gave any new content
|
||||
old_result_len = len(result)
|
||||
# Process next line with line_regex. For optimization we do an rstrip().
|
||||
# - process tabs (changes either line or word, see below)
|
||||
# - process word (first try to squeeze on line, then wrap or force wrap)
|
||||
# Spaces found on the line are ignored, they get added while wrapping as
|
||||
# needed.
|
||||
for spaces, current_tabs, word in line_regex.findall(text_line.rstrip()):
|
||||
# If tabs weren't converted to spaces, handle them now
|
||||
if current_tabs:
|
||||
# If the last thing we added was a space anyway then drop it. But
|
||||
# let's not get rid of the indentation.
|
||||
if (((result and line != indent) or
|
||||
(not result and line != firstline_indent)) and line[-1] == ' '):
|
||||
line = line[:-1]
|
||||
# Add the tabs, if that means adding whitespace, just add it at the
|
||||
# line, the rstrip() code while shorten the line down if necessary
|
||||
if tabs_are_whitespace:
|
||||
line += tabs * len(current_tabs)
|
||||
else:
|
||||
# if not all tab replacement is whitespace we prepend it to the word
|
||||
word = tabs * len(current_tabs) + word
|
||||
# Handle the case where word cannot be squeezed onto current last line
|
||||
if len(line) + len(word) > length and len(indent) + len(word) <= length:
|
||||
result.append(line.rstrip())
|
||||
line = indent + word
|
||||
word = ''
|
||||
# No space left on line or can we append a space?
|
||||
if len(line) + 1 >= length:
|
||||
result.append(line.rstrip())
|
||||
line = indent
|
||||
else:
|
||||
line += ' '
|
||||
# Add word and shorten it up to allowed line length. Restart next line
|
||||
# with indent and repeat, or add a space if we're done (word finished)
|
||||
# This deals with words that caanot fit on one line (e.g. indent + word
|
||||
# longer than allowed line length).
|
||||
while len(line) + len(word) >= length:
|
||||
line += word
|
||||
result.append(line[:length])
|
||||
word = line[length:]
|
||||
line = indent
|
||||
# Default case, simply append the word and a space
|
||||
if word:
|
||||
line += word + ' '
|
||||
# End of input line. If we have content we finish the line. If the
|
||||
# current line is just the indent but we had content in during this
|
||||
# original line then we need to add an emoty line.
|
||||
if (result and line != indent) or (not result and line != firstline_indent):
|
||||
result.append(line.rstrip())
|
||||
elif len(result) == old_result_len:
|
||||
result.append('')
|
||||
line = indent
|
||||
|
||||
return '\n'.join(result)
|
||||
|
||||
|
||||
def DocToHelp(doc):
|
||||
"""
|
||||
Takes a __doc__ string and reformats it as help.
|
||||
"""
|
||||
# Get rid of starting and ending white space. Using lstrip() or even strip()
|
||||
# could drop more than maximum of first line and right space of last line.
|
||||
doc = doc.strip()
|
||||
|
||||
# Get rid of all empty lines
|
||||
whitespace_only_line = re.compile('^[ \t]+$', re.M)
|
||||
doc = whitespace_only_line.sub('', doc)
|
||||
|
||||
# Cut out common space at line beginnings
|
||||
doc = CutCommonSpacePrefix(doc)
|
||||
|
||||
# Just like this module's comment, comments tend to be aligned somehow.
|
||||
# In other words they all start with the same amount of white space
|
||||
# 1) keep double new lines
|
||||
# 2) keep ws after new lines if not empty line
|
||||
# 3) all other new lines shall be changed to a space
|
||||
# Solution: Match new lines between non white space and replace with space.
|
||||
doc = re.sub('(?<=\S)\n(?=\S)', ' ', doc, re.M)
|
||||
|
||||
return doc
|
||||
|
||||
|
||||
def __GetModuleName(globals_dict):
|
||||
|
@ -209,16 +451,6 @@ def __GetModuleName(globals_dict):
|
|||
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()):
|
||||
|
@ -262,6 +494,7 @@ class FlagValues:
|
|||
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__
|
||||
|
@ -279,6 +512,15 @@ class FlagValues:
|
|||
flags_by_module = self.__dict__['__flags_by_module']
|
||||
flags_by_module.setdefault(module_name, []).append(flag)
|
||||
|
||||
def AppendFlagValues(self, flag_values):
|
||||
"""Append flags registered in another FlagValues instance.
|
||||
|
||||
Args:
|
||||
flag_values: registry to copy from
|
||||
"""
|
||||
for flag_name, flag in flag_values.FlagDict().iteritems():
|
||||
self[flag_name] = flag
|
||||
|
||||
def __setitem__(self, name, flag):
|
||||
"""
|
||||
Register a new flag variable.
|
||||
|
@ -294,12 +536,12 @@ class FlagValues:
|
|||
# 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
|
||||
raise DuplicateFlagError(name, self)
|
||||
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
|
||||
raise DuplicateFlagError(short_name, self)
|
||||
fl[short_name] = flag
|
||||
fl[name] = flag
|
||||
global _exported_flags
|
||||
|
@ -365,8 +607,16 @@ class FlagValues:
|
|||
Argument Syntax Conventions, using getopt:
|
||||
|
||||
http://www.gnu.org/software/libc/manual/html_mono/libc.html#Getopt
|
||||
"""
|
||||
|
||||
Args:
|
||||
argv: argument list. Can be of any type that may be converted to a list.
|
||||
|
||||
Returns:
|
||||
The list of arguments not parsed as options, including argv[0]
|
||||
|
||||
Raises:
|
||||
FlagsError: on any parsing error
|
||||
"""
|
||||
# Support any sequence type that can be converted to a list
|
||||
argv = list(argv)
|
||||
|
||||
|
@ -384,7 +634,7 @@ class FlagValues:
|
|||
# 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)
|
||||
original_argv = list(argv) # list() makes a copy
|
||||
shortest_matches = None
|
||||
for name, flag in fl.items():
|
||||
if not flag.boolean:
|
||||
|
@ -412,16 +662,45 @@ class FlagValues:
|
|||
# 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
|
||||
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
|
||||
longopts.append('undefok=')
|
||||
undefok_flags = []
|
||||
|
||||
# In case --undefok is specified, loop to pick up unrecognized
|
||||
# options one by one.
|
||||
unrecognized_opts = []
|
||||
args = argv[1:]
|
||||
while True:
|
||||
try:
|
||||
optlist, unparsed_args = getopt.getopt(args, shortopts, longopts)
|
||||
break
|
||||
except getopt.GetoptError, e:
|
||||
if not e.opt or e.opt in fl:
|
||||
# Not an unrecognized option, reraise the exception as a FlagsError
|
||||
raise FlagsError(e)
|
||||
# Handle an unrecognized option.
|
||||
unrecognized_opts.append(e.opt)
|
||||
# Remove offender from args and try again
|
||||
for arg_index in range(len(args)):
|
||||
if ((args[arg_index] == '--' + e.opt) or
|
||||
(args[arg_index] == '-' + e.opt) or
|
||||
args[arg_index].startswith('--' + e.opt + '=')):
|
||||
args = args[0:arg_index] + args[arg_index+1:]
|
||||
break
|
||||
else:
|
||||
# We should have found the option, so we don't expect to get
|
||||
# here. We could assert, but raising the original exception
|
||||
# might work better.
|
||||
raise FlagsError(e)
|
||||
|
||||
for name, arg in optlist:
|
||||
if name == '--undefok':
|
||||
undefok_flags.extend(arg.split(','))
|
||||
continue
|
||||
if name.startswith('--'):
|
||||
# long option
|
||||
name = name[2:]
|
||||
|
@ -435,6 +714,12 @@ class FlagValues:
|
|||
if flag.boolean and short_option: arg = 1
|
||||
flag.Parse(arg)
|
||||
|
||||
# If there were unrecognized options, raise an exception unless
|
||||
# the options were named via --undefok.
|
||||
for opt in unrecognized_opts:
|
||||
if opt not in undefok_flags:
|
||||
raise UnrecognizedFlagError(opt)
|
||||
|
||||
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,
|
||||
|
@ -469,6 +754,12 @@ class FlagValues:
|
|||
return flag_values
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
Generate a help string for all known flags.
|
||||
"""
|
||||
return self.GetHelp()
|
||||
|
||||
def GetHelp(self, prefix=""):
|
||||
"""
|
||||
Generate a help string for all known flags.
|
||||
"""
|
||||
|
@ -487,33 +778,47 @@ class FlagValues:
|
|||
modules = [ main_module ] + modules
|
||||
|
||||
for module in modules:
|
||||
self.__RenderModuleFlags(module, helplist)
|
||||
self.__RenderOurModuleFlags(module, helplist)
|
||||
|
||||
self.__RenderModuleFlags('google3.pyglib.flags',
|
||||
_SPECIAL_FLAGS.FlagDict().values(),
|
||||
helplist)
|
||||
|
||||
else:
|
||||
# Just print one long list of flags.
|
||||
self.__RenderFlagList(self.FlagDict().values(), helplist)
|
||||
self.__RenderFlagList(
|
||||
self.FlagDict().values() + _SPECIAL_FLAGS.FlagDict().values(),
|
||||
helplist, prefix)
|
||||
|
||||
return '\n'.join(helplist)
|
||||
|
||||
def __RenderModuleFlags(self, module, output_lines):
|
||||
def __RenderModuleFlags(self, module, flags, output_lines, prefix=""):
|
||||
"""
|
||||
Generate a help string for a given module.
|
||||
"""
|
||||
output_lines.append('\n%s%s:' % (prefix, module))
|
||||
self.__RenderFlagList(flags, output_lines, prefix + " ")
|
||||
|
||||
def __RenderOurModuleFlags(self, module, output_lines, prefix=""):
|
||||
"""
|
||||
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)
|
||||
self.__RenderModuleFlags(module, flags_by_module[module],
|
||||
output_lines, prefix)
|
||||
|
||||
def MainModuleHelp(self):
|
||||
"""
|
||||
Generate a help string for all known flags of the main module.
|
||||
"""
|
||||
helplist = []
|
||||
self.__RenderModuleFlags(_GetMainModule(), helplist)
|
||||
self.__RenderOurModuleFlags(_GetMainModule(), helplist)
|
||||
return '\n'.join(helplist)
|
||||
|
||||
def __RenderFlagList(self, flaglist, output_lines):
|
||||
def __RenderFlagList(self, flaglist, output_lines, prefix=" "):
|
||||
fl = self.FlagDict()
|
||||
special_fl = _SPECIAL_FLAGS.FlagDict()
|
||||
flaglist = [(flag.name, flag) for flag in flaglist]
|
||||
flaglist.sort()
|
||||
flagset = {}
|
||||
|
@ -521,12 +826,13 @@ class FlagValues:
|
|||
# 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
|
||||
if fl.get(name, None) != flag and special_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 = " "
|
||||
flaghelp = ""
|
||||
if flag.short_name: flaghelp += "-%s," % flag.short_name
|
||||
if flag.boolean:
|
||||
flaghelp += "--[no]%s" % flag.name + ":"
|
||||
|
@ -535,10 +841,16 @@ class FlagValues:
|
|||
flaghelp += " "
|
||||
if flag.help:
|
||||
flaghelp += flag.help
|
||||
flaghelp = TextWrap(flaghelp, indent=prefix+" ",
|
||||
firstline_indent=prefix)
|
||||
if flag.default_as_str:
|
||||
flaghelp += "\n (default: %s)" % flag.default_as_str
|
||||
flaghelp += "\n"
|
||||
flaghelp += TextWrap("(default: %s)" % flag.default_as_str,
|
||||
indent=prefix+" ")
|
||||
if flag.parser.syntactic_help:
|
||||
flaghelp += "\n (%s)" % flag.parser.syntactic_help
|
||||
flaghelp += "\n"
|
||||
flaghelp += TextWrap("(%s)" % flag.parser.syntactic_help,
|
||||
indent=prefix+" ")
|
||||
output_lines.append(flaghelp)
|
||||
|
||||
def get(self, name, default):
|
||||
|
@ -730,7 +1042,7 @@ class FlagValues:
|
|||
|
||||
def FlagsIntoString(self):
|
||||
"""
|
||||
Retreive a string version of all the flags with assignments stored
|
||||
Retrieve 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.
|
||||
|
@ -751,9 +1063,7 @@ class FlagValues:
|
|||
out_file = open(filename, 'a')
|
||||
out_file.write(self.FlagsIntoString())
|
||||
out_file.close()
|
||||
|
||||
#end of the FLAGS registry class
|
||||
|
||||
# end of FlagValues definition
|
||||
|
||||
# The global FlagValues instance
|
||||
FLAGS = FlagValues()
|
||||
|
@ -869,6 +1179,7 @@ class Flag:
|
|||
self.value = None
|
||||
self.default = value
|
||||
self.default_as_str = self.__GetParsedValueAsString(value)
|
||||
# End of Flag definition
|
||||
|
||||
class ArgumentParser:
|
||||
"""
|
||||
|
@ -929,7 +1240,7 @@ def DEFINE_flag(flag, flag_values=FLAGS):
|
|||
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
|
||||
functions, such as DEFINE_string or DEFINE_integer. But developers
|
||||
who need to create Flag objects themselves should use this function to
|
||||
register their flags.
|
||||
"""
|
||||
|
@ -944,7 +1255,7 @@ def DEFINE_flag(flag, flag_values=FLAGS):
|
|||
# of which module is creating the flags.
|
||||
|
||||
# Tell FLAGS who's defining flag.
|
||||
FLAGS._RegisterFlagByModule(__GetCallingModule(), flag)
|
||||
FLAGS._RegisterFlagByModule(_GetCallingModule(), flag)
|
||||
|
||||
|
||||
###############################
|
||||
|
@ -1369,3 +1680,18 @@ def DEFINE_multi_int(name, default, help, lower_bound=None, upper_bound=None,
|
|||
# these flagnames for their own purposes, if they want.
|
||||
DEFINE_flag(HelpFlag())
|
||||
DEFINE_flag(HelpshortFlag())
|
||||
|
||||
# Define special flags here so that help may be generated for them.
|
||||
_SPECIAL_FLAGS = FlagValues()
|
||||
|
||||
DEFINE_string(
|
||||
'flagfile', "",
|
||||
"Insert flag definitions from the given file into the command line.",
|
||||
_SPECIAL_FLAGS)
|
||||
|
||||
DEFINE_string(
|
||||
'undefok', "",
|
||||
"comma-separated list of flag names that it is okay to specify "
|
||||
"on the command line even if the program does not define a flag "
|
||||
"with that name. IMPORTANT: flags in this list that have "
|
||||
"arguments MUST use the --flag=value format.", _SPECIAL_FLAGS)
|
||||
|
|
|
@ -44,6 +44,15 @@ import unittest
|
|||
import gflags as flags
|
||||
FLAGS=flags.FLAGS
|
||||
|
||||
# If we're not running at least python 2.3, as is the case when
|
||||
# invoked from flags_unittest_2_2, define True and False.
|
||||
# Thanks, Guido, for the code.
|
||||
try:
|
||||
True, False
|
||||
except NameError:
|
||||
False = 0
|
||||
True = 1
|
||||
|
||||
class FlagsUnitTest(unittest.TestCase):
|
||||
"Flags Unit Test"
|
||||
|
||||
|
@ -179,10 +188,10 @@ class FlagsUnitTest(unittest.TestCase):
|
|||
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
|
||||
assert FLAGS['debug'].value
|
||||
FLAGS.Reset()
|
||||
assert FLAGS['debug'].present == 0
|
||||
assert FLAGS['debug'].value == False
|
||||
assert not FLAGS['debug'].value
|
||||
|
||||
# Test that reset restores default value when default value is None.
|
||||
argv = ('./program', '--kwery=who')
|
||||
|
@ -531,11 +540,32 @@ class FlagsUnitTest(unittest.TestCase):
|
|||
self.assert_(str(FLAGS).find('runhelp d31') == -1)
|
||||
self.assert_(str(FLAGS).find('runhelp d32') != -1)
|
||||
|
||||
# Make sure AppendFlagValues works
|
||||
new_flags = flags.FlagValues()
|
||||
flags.DEFINE_boolean("new1", 0, "runhelp n1", flag_values=new_flags)
|
||||
flags.DEFINE_boolean("new2", 0, "runhelp n2", flag_values=new_flags)
|
||||
self.assertEqual(len(new_flags.FlagDict()), 2)
|
||||
old_len = len(FLAGS.FlagDict())
|
||||
FLAGS.AppendFlagValues(new_flags)
|
||||
self.assertEqual(len(FLAGS.FlagDict())-old_len, 2)
|
||||
self.assertEqual("new1" in FLAGS.FlagDict(), True)
|
||||
self.assertEqual("new2" in FLAGS.FlagDict(), True)
|
||||
|
||||
# Make sure AppendFlagValues fails on duplicates
|
||||
flags.DEFINE_boolean("dup4", 0, "runhelp d41")
|
||||
new_flags = flags.FlagValues()
|
||||
flags.DEFINE_boolean("dup4", 0, "runhelp d42", flag_values=new_flags)
|
||||
try:
|
||||
FLAGS.AppendFlagValues(new_flags)
|
||||
raise AssertionError("ignore_copy was not set but caused no exception")
|
||||
except flags.DuplicateFlag, e:
|
||||
pass
|
||||
|
||||
# Integer out of bounds
|
||||
try:
|
||||
argv = ('./program', '--repeat=-4')
|
||||
FLAGS(argv)
|
||||
raise AssertionError('integer bounds exception not thrown:'
|
||||
raise AssertionError('integer bounds exception not raised:'
|
||||
+ str(FLAGS.repeat))
|
||||
except flags.IllegalFlagValue:
|
||||
pass
|
||||
|
@ -544,7 +574,7 @@ class FlagsUnitTest(unittest.TestCase):
|
|||
try:
|
||||
argv = ('./program', '--repeat=2.5')
|
||||
FLAGS(argv)
|
||||
raise AssertionError("malformed integer value exception not thrown")
|
||||
raise AssertionError("malformed integer value exception not raised")
|
||||
except flags.IllegalFlagValue:
|
||||
pass
|
||||
|
||||
|
@ -552,7 +582,7 @@ class FlagsUnitTest(unittest.TestCase):
|
|||
try:
|
||||
argv = ('./program', '--name')
|
||||
FLAGS(argv)
|
||||
raise AssertionError("Flag argument required exception not thrown")
|
||||
raise AssertionError("Flag argument required exception not raised")
|
||||
except flags.FlagsError:
|
||||
pass
|
||||
|
||||
|
@ -560,23 +590,16 @@ class FlagsUnitTest(unittest.TestCase):
|
|||
try:
|
||||
argv = ('./program', '--debug=goofup')
|
||||
FLAGS(argv)
|
||||
raise AssertionError("No argument allowed exception not thrown")
|
||||
raise AssertionError("No argument allowed exception not raised")
|
||||
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")
|
||||
raise AssertionError("Illegal flag value exception not raised")
|
||||
except flags.IllegalFlagValue:
|
||||
pass
|
||||
|
||||
|
@ -708,7 +731,7 @@ class FlagsUnitTest(unittest.TestCase):
|
|||
# end testThree def
|
||||
|
||||
def testMethod_flagfiles_4(self):
|
||||
"""Tests parsing self referetial files + arguments of simulated argv.
|
||||
"""Tests parsing self-referential files + arguments of simulated argv.
|
||||
This test should print a warning to stderr of some sort.
|
||||
"""
|
||||
self.__DeclareSomeFlags()
|
||||
|
@ -854,6 +877,303 @@ class FlagsUnitTest(unittest.TestCase):
|
|||
FLAGS.__delattr__('zz')
|
||||
FLAGS.__delattr__('nozz')
|
||||
|
||||
def test_twodasharg_first(self):
|
||||
flags.DEFINE_string("twodash_name", "Bob", "namehelp")
|
||||
flags.DEFINE_string("twodash_blame", "Rob", "blamehelp")
|
||||
argv = ('./program',
|
||||
'--',
|
||||
'--twodash_name=Harry')
|
||||
argv = FLAGS(argv)
|
||||
self.assertEqual('Bob', FLAGS.twodash_name)
|
||||
self.assertEqual(argv[1], '--twodash_name=Harry')
|
||||
|
||||
def test_twodasharg_middle(self):
|
||||
flags.DEFINE_string("twodash2_name", "Bob", "namehelp")
|
||||
flags.DEFINE_string("twodash2_blame", "Rob", "blamehelp")
|
||||
argv = ('./program',
|
||||
'--twodash2_blame=Larry',
|
||||
'--',
|
||||
'--twodash2_name=Harry')
|
||||
argv = FLAGS(argv)
|
||||
self.assertEqual('Bob', FLAGS.twodash2_name)
|
||||
self.assertEqual('Larry', FLAGS.twodash2_blame)
|
||||
self.assertEqual(argv[1], '--twodash2_name=Harry')
|
||||
|
||||
def test_onedasharg_first(self):
|
||||
flags.DEFINE_string("onedash_name", "Bob", "namehelp")
|
||||
flags.DEFINE_string("onedash_blame", "Rob", "blamehelp")
|
||||
argv = ('./program',
|
||||
'-',
|
||||
'--onedash_name=Harry')
|
||||
argv = FLAGS(argv)
|
||||
self.assertEqual(argv[1], '-')
|
||||
# TODO(csilvers): we should still parse --onedash_name=Harry as a
|
||||
# flag, but currently we don't (we stop flag processing as soon as
|
||||
# we see the first non-flag).
|
||||
|
||||
def test_unrecognized_flags(self):
|
||||
# Unknown flag --nosuchflag
|
||||
try:
|
||||
argv = ('./program', '--nosuchflag', '--name=Bob', 'extra')
|
||||
FLAGS(argv)
|
||||
raise AssertionError("Unknown flag exception not raised")
|
||||
except flags.UnrecognizedFlag, e:
|
||||
assert e.flagname == 'nosuchflag'
|
||||
|
||||
# Unknown flag -w (short option)
|
||||
try:
|
||||
argv = ('./program', '-w', '--name=Bob', 'extra')
|
||||
FLAGS(argv)
|
||||
raise AssertionError("Unknown flag exception not raised")
|
||||
except flags.UnrecognizedFlag, e:
|
||||
assert e.flagname == 'w'
|
||||
|
||||
# Unknown flag --nosuchflagwithparam=foo
|
||||
try:
|
||||
argv = ('./program', '--nosuchflagwithparam=foo', '--name=Bob', 'extra')
|
||||
FLAGS(argv)
|
||||
raise AssertionError("Unknown flag exception not raised")
|
||||
except flags.UnrecognizedFlag, e:
|
||||
assert e.flagname == 'nosuchflagwithparam'
|
||||
|
||||
# Allow unknown flag --nosuchflag if specified with undefok
|
||||
argv = ('./program', '--nosuchflag', '--name=Bob',
|
||||
'--undefok=nosuchflag', '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"
|
||||
|
||||
# But not if the flagname is misspelled:
|
||||
try:
|
||||
argv = ('./program', '--nosuchflag', '--name=Bob',
|
||||
'--undefok=nosuchfla', 'extra')
|
||||
FLAGS(argv)
|
||||
raise AssertionError("Unknown flag exception not raised")
|
||||
except flags.UnrecognizedFlag, e:
|
||||
assert e.flagname == 'nosuchflag'
|
||||
|
||||
try:
|
||||
argv = ('./program', '--nosuchflag', '--name=Bob',
|
||||
'--undefok=nosuchflagg', 'extra')
|
||||
FLAGS(argv)
|
||||
raise AssertionError("Unknown flag exception not raised")
|
||||
except flags.UnrecognizedFlag:
|
||||
assert e.flagname == 'nosuchflag'
|
||||
|
||||
# Allow unknown short flag -w if specified with undefok
|
||||
argv = ('./program', '-w', '--name=Bob', '--undefok=w', '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"
|
||||
|
||||
# Allow unknown flag --nosuchflagwithparam=foo if specified
|
||||
# with undefok
|
||||
argv = ('./program', '--nosuchflagwithparam=foo', '--name=Bob',
|
||||
'--undefok=nosuchflagwithparam', '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"
|
||||
|
||||
# Even if undefok specifies multiple flags
|
||||
argv = ('./program', '--nosuchflag', '-w', '--nosuchflagwithparam=foo',
|
||||
'--name=Bob',
|
||||
'--undefok=nosuchflag,w,nosuchflagwithparam',
|
||||
'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"
|
||||
|
||||
# However, not if undefok doesn't specify the flag
|
||||
try:
|
||||
argv = ('./program', '--nosuchflag', '--name=Bob',
|
||||
'--undefok=another_such', 'extra')
|
||||
FLAGS(argv)
|
||||
raise AssertionError("Unknown flag exception not raised")
|
||||
except flags.UnrecognizedFlag, e:
|
||||
assert e.flagname == 'nosuchflag'
|
||||
|
||||
# Make sure --undefok doesn't mask other option errors.
|
||||
try:
|
||||
# Provide an option requiring a parameter but not giving it one.
|
||||
argv = ('./program', '--undefok=name', '--name')
|
||||
FLAGS(argv)
|
||||
raise AssertionError("Missing option parameter exception not raised")
|
||||
except flags.UnrecognizedFlag:
|
||||
raise AssertionError("Wrong kind of error exception raised")
|
||||
except flags.FlagsError:
|
||||
pass
|
||||
|
||||
# Test --undefok <list>
|
||||
argv = ('./program', '--nosuchflag', '-w', '--nosuchflagwithparam=foo',
|
||||
'--name=Bob',
|
||||
'--undefok',
|
||||
'nosuchflag,w,nosuchflagwithparam',
|
||||
'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"
|
||||
|
||||
def test_nonglobal_flags(self):
|
||||
"""Test use of non-global FlagValues"""
|
||||
nonglobal_flags = flags.FlagValues()
|
||||
flags.DEFINE_string("nonglobal_flag", "Bob", "flaghelp", nonglobal_flags)
|
||||
argv = ('./program',
|
||||
'--nonglobal_flag=Mary',
|
||||
'extra')
|
||||
argv = nonglobal_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 nonglobal_flags['nonglobal_flag'].value == 'Mary'
|
||||
|
||||
def test_unrecognized_nonglobal_flags(self):
|
||||
"""Test unrecognized non-global flags"""
|
||||
nonglobal_flags = flags.FlagValues()
|
||||
argv = ('./program',
|
||||
'--nosuchflag')
|
||||
try:
|
||||
argv = nonglobal_flags(argv)
|
||||
raise AssertionError("Unknown flag exception not raised")
|
||||
except flags.UnrecognizedFlag, e:
|
||||
assert e.flagname == 'nosuchflag'
|
||||
pass
|
||||
|
||||
argv = ('./program',
|
||||
'--nosuchflag',
|
||||
'--undefok=nosuchflag')
|
||||
|
||||
argv = nonglobal_flags(argv)
|
||||
assert len(argv) == 1, "wrong number of arguments pulled"
|
||||
assert argv[0]=='./program', "program name not preserved"
|
||||
|
||||
def test_main_module_help(self):
|
||||
"""Test MainModuleHelp()"""
|
||||
help = FLAGS.MainModuleHelp()
|
||||
|
||||
# When this test is invoked on behalf of flags_unittest_2_2,
|
||||
# the main module has not defined any flags. Since there's
|
||||
# no easy way to run this script in our test environment
|
||||
# directly from python2.2, don't bother to test the output
|
||||
# of MainModuleHelp() in that scenario.
|
||||
if sys.version.startswith('2.2.'):
|
||||
return
|
||||
|
||||
expected_help = "\n" + sys.argv[0] + ':' + """
|
||||
--[no]debug: debughelp
|
||||
(default: 'false')
|
||||
-u,--[no]dup1: runhelp d12
|
||||
(default: 'true')
|
||||
-u,--[no]dup2: runhelp d22
|
||||
(default: 'true')
|
||||
-u,--[no]dup3: runhelp d32
|
||||
(default: 'true')
|
||||
--[no]dup4: runhelp d41
|
||||
(default: 'false')
|
||||
-?,--[no]help: show this help
|
||||
--[no]helpshort: show usage only for this module
|
||||
--kwery: <who|what|why|where|when>: ?
|
||||
--l: how long to be
|
||||
(default: '9223372032559808512')
|
||||
(an integer)
|
||||
--letters: a list of letters
|
||||
(default: 'a,b,c')
|
||||
(a comma separated list)
|
||||
-m,--m_str: string option that can occur multiple times;
|
||||
repeat this option to specify a list of values
|
||||
(default: "['def1', 'def2']")
|
||||
--name: namehelp
|
||||
(default: 'Bob')
|
||||
--[no]noexec: boolean flag with no as prefix
|
||||
(default: 'true')
|
||||
--[no]q: quiet mode
|
||||
(default: 'true')
|
||||
--[no]quack: superstring of 'q'
|
||||
(default: 'false')
|
||||
-r,--repeat: how many times to repeat (0-5)
|
||||
(default: '4')
|
||||
(a non-negative integer)
|
||||
-s,--s_str: string option that can occur multiple times;
|
||||
repeat this option to specify a list of values
|
||||
(default: "['sing1']")
|
||||
--[no]test0: test boolean parsing
|
||||
--[no]test1: test boolean parsing
|
||||
--[no]testget1: test parsing with defaults
|
||||
--[no]testget2: test parsing with defaults
|
||||
--[no]testget3: test parsing with defaults
|
||||
--testget4: test parsing with defaults
|
||||
(an integer)
|
||||
--testlist: test lists parsing
|
||||
(default: '')
|
||||
(a comma separated list)
|
||||
--[no]testnone: test boolean parsing
|
||||
--testspacelist: tests space lists parsing
|
||||
(default: '')
|
||||
(a whitespace separated list)
|
||||
--x: how eXtreme to be
|
||||
(default: '3')
|
||||
(an integer)
|
||||
-z,--[no]zoom1: runhelp z1
|
||||
(default: 'false')"""
|
||||
|
||||
if help != expected_help:
|
||||
print "Error: FLAGS.MainModuleHelp() didn't return the expected result."
|
||||
print "Got:"
|
||||
print help
|
||||
print "[End of got]"
|
||||
|
||||
help_lines = help.split('\n')
|
||||
expected_help_lines = expected_help.split('\n')
|
||||
|
||||
num_help_lines = len(help_lines)
|
||||
num_expected_help_lines = len(expected_help_lines)
|
||||
|
||||
if num_help_lines != num_expected_help_lines:
|
||||
print "Number of help lines = %d, expected %d" % (
|
||||
num_help_lines, num_expected_help_lines)
|
||||
|
||||
num_to_match = min(num_help_lines, num_expected_help_lines)
|
||||
|
||||
for i in range(num_to_match):
|
||||
if help_lines[i] != expected_help_lines[i]:
|
||||
print "One discrepancy: Got:"
|
||||
print help_lines[i]
|
||||
print "Expected:"
|
||||
print expected_help_lines[i]
|
||||
break
|
||||
else:
|
||||
# If we got here, found no discrepancy, print first new line.
|
||||
if num_help_lines > num_expected_help_lines:
|
||||
print "New help line:"
|
||||
print help_lines[num_expected_help_lines]
|
||||
elif num_expected_help_lines > num_help_lines:
|
||||
print "Missing expected help line:"
|
||||
print expected_help_lines[num_help_lines]
|
||||
else:
|
||||
print "Bug in this test -- discrepancy detected but not found."
|
||||
|
||||
self.fail()
|
||||
|
||||
def test_create_flag_errors(self):
|
||||
# Since the exception classes are exposed, nothing stops users
|
||||
# from creating their own instances. This test makes sure that
|
||||
# people modifying the flags module understand that the external
|
||||
# mechanisms for creating the exceptions should continue to work.
|
||||
e = flags.FlagsError()
|
||||
e = flags.FlagsError("message")
|
||||
e = flags.DuplicateFlag()
|
||||
e = flags.DuplicateFlag("message")
|
||||
e = flags.IllegalFlagValue()
|
||||
e = flags.IllegalFlagValue("message")
|
||||
e = flags.UnrecognizedFlag()
|
||||
e = flags.UnrecognizedFlag("message")
|
||||
|
||||
def main():
|
||||
unittest.main()
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
main()
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
from distutils.core import setup
|
||||
|
||||
setup(name='gflags',
|
||||
version='0.6',
|
||||
version='0.8',
|
||||
description='Google Commandline Flags Module',
|
||||
license='BSD',
|
||||
author='Google Inc.',
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <fnmatch.h>
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
|
@ -96,8 +95,7 @@ static const char kError[] = "ERROR: ";
|
|||
// The help message indicating that the commandline flag has been
|
||||
// 'stripped'. It will not show up when doing "-help" and its
|
||||
// variants. The flag is stripped if STRIP_FLAG_HELP is set to 1
|
||||
// before including base/commandlineflags.h (or in
|
||||
// base/global_strip_options.h).
|
||||
// before including google/gflags.h.
|
||||
|
||||
const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
|
||||
|
||||
|
@ -105,7 +103,7 @@ const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
|
|||
// Enables deferred processing of flags in dynamically loaded libraries.
|
||||
static bool allow_command_line_reparsing = false;
|
||||
|
||||
static bool logging_is_probably_set_up = false; // google3-specific
|
||||
static bool logging_is_probably_set_up = false;
|
||||
|
||||
// This is used by the unittest to test error-exit code
|
||||
void (*commandlineflags_exitfunc)(int) = &exit; // from stdlib.h
|
||||
|
@ -114,7 +112,7 @@ void (*commandlineflags_exitfunc)(int) = &exit; // from stdlib.h
|
|||
// FlagValue
|
||||
// This represent the value a single flag might have. The major
|
||||
// functionality is to convert from a string to an object of a
|
||||
// given type, and back.
|
||||
// given type, and back. Thread-compatible.
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
class FlagValue {
|
||||
|
@ -375,21 +373,19 @@ CommandLineFlag::~CommandLineFlag() {
|
|||
const char* CommandLineFlag::CleanFileName() const {
|
||||
// Compute top-level directory & file that this appears in
|
||||
// search full path backwards.
|
||||
// Stop going backwards at kGoogle; and skip by the first slash.
|
||||
// E.g.
|
||||
// filename_where_defined = "froogle/wrapping/autowrap/clustering/**.cc"
|
||||
// filename_where_defined = "file/util/fileutil.cc"
|
||||
static const char kGoogle[] = ""; // can set this to whatever
|
||||
// Stop going backwards at kRootDir; and skip by the first slash.
|
||||
static const char kRootDir[] = ""; // can set this to root directory,
|
||||
// e.g. "myproject"
|
||||
|
||||
if (sizeof(kGoogle)-1 == 0) // no prefix to strip
|
||||
if (sizeof(kRootDir)-1 == 0) // no prefix to strip
|
||||
return filename();
|
||||
|
||||
const char* clean_name = filename() + strlen(filename()) - 1;
|
||||
while ( clean_name > filename() ) {
|
||||
if (*clean_name == PATH_SEPARATOR) {
|
||||
if (strncmp(clean_name, kGoogle, sizeof(kGoogle)-1) == 0) {
|
||||
// ".../google/base/logging.cc" ==> "base/logging.cc"
|
||||
clean_name += sizeof(kGoogle)-1; // past "/google/"
|
||||
if (strncmp(clean_name, kRootDir, sizeof(kRootDir)-1) == 0) {
|
||||
// ".../myproject/base/logging.cc" ==> "base/logging.cc"
|
||||
clean_name += sizeof(kRootDir)-1; // past "/myproject/"
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -790,7 +786,7 @@ const char* ProgramInvocationName() { // like the GNU libc fn
|
|||
}
|
||||
const char* ProgramInvocationShortName() { // like the GNU libc fn
|
||||
const char* slash = strrchr(argv0, '/');
|
||||
#ifdef OS_WINDOWS
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
||||
if (!slash) slash = strrchr(argv0, '\\');
|
||||
#endif
|
||||
return slash ? slash + 1 : argv0;
|
||||
|
@ -939,7 +935,8 @@ uint32 CommandLineFlagParser::ParseNewCommandLineFlags(int* argc, char*** argv,
|
|||
char* arg = (*argv)[i];
|
||||
|
||||
// Like getopt(), we permute non-option flags to be at the end.
|
||||
if (arg[0] != '-') { // must be a program argument
|
||||
if (arg[0] != '-' || // must be a program argument
|
||||
(arg[0] == '-' && arg[1] == '\0')) { // "-" is an argument, not a flag
|
||||
memmove((*argv) + i, (*argv) + i+1, (*argc - (i+1)) * sizeof((*argv)[i]));
|
||||
(*argv)[*argc-1] = arg; // we go last
|
||||
first_nonopt--; // we've been pushed onto the stack
|
||||
|
@ -950,7 +947,7 @@ uint32 CommandLineFlagParser::ParseNewCommandLineFlags(int* argc, char*** argv,
|
|||
if (arg[0] == '-') arg++; // allow leading '-'
|
||||
if (arg[0] == '-') arg++; // or leading '--'
|
||||
|
||||
// - and -- alone mean what they do for GNU: stop options parsing
|
||||
// -- alone means what it does for GNU: stop options parsing
|
||||
if (*arg == '\0') {
|
||||
first_nonopt = i+1;
|
||||
break;
|
||||
|
|
|
@ -37,8 +37,8 @@
|
|||
// reporting flags, but we also have flags like --helpxml, etc.
|
||||
//
|
||||
// There's only one function that's meant to be called externally:
|
||||
// HandleCommandLineHelpFlags(). (Well, actually,
|
||||
// ShowUsageWithFlags() and ShowUsageWithFlagsRestrict() can be called
|
||||
// HandleCommandLineHelpFlags(). (Well, actually, ShowUsageWithFlags(),
|
||||
// ShowUsageWithFlagsRestrict(), and DescribeOneFlag() can be called
|
||||
// externally too, but there's little need for it.) These are all
|
||||
// declared in the main commandlineflags.h header file.
|
||||
//
|
||||
|
@ -110,7 +110,7 @@ static void AddString(const string& s,
|
|||
|
||||
// Create a descriptive string for a flag.
|
||||
// Goes to some trouble to make pretty line breaks.
|
||||
static string DescribeOneFlag(const CommandLineFlagInfo& flag) {
|
||||
string DescribeOneFlag(const CommandLineFlagInfo& flag) {
|
||||
string main_part = (string(" -") + flag.name +
|
||||
" (" + flag.description + ')');
|
||||
const char* c_string = main_part.c_str();
|
||||
|
@ -242,8 +242,8 @@ static bool FileMatchesSubstring(const string& filename,
|
|||
|
||||
// Show help for every filename which matches any of the target substrings.
|
||||
// If substrings is empty, shows help for every file. If a flag's help message
|
||||
// has been stripped (e.g. by adding '#define STRIP_FLAG_HELP 1' to
|
||||
// base/global_strip_options.h), then this flag will not be displayed by
|
||||
// has been stripped (e.g. by adding '#define STRIP_FLAG_HELP 1' before
|
||||
// including google/gflags.h), then this flag will not be displayed by
|
||||
// '--help' and its variants.
|
||||
static void ShowUsageWithFlagsMatching(const char *argv0,
|
||||
const vector<string> &substrings) {
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> // for &exit
|
||||
#include <string.h>
|
||||
#include <unistd.h> // for unlink()
|
||||
#include <sys/stat.h> // for mkdir()
|
||||
|
@ -46,8 +47,7 @@
|
|||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
// Returns the number of elements in an array. We don't use the safer
|
||||
// version in base/basictypes.h as commandlineflags is open-sourced.
|
||||
// Returns the number of elements in an array.
|
||||
#define GET_ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr)))
|
||||
|
||||
DECLARE_string(tryfromenv); // in commandlineflags.cc
|
||||
|
@ -1109,6 +1109,43 @@ TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
|
|||
EXPECT_EQ(3, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
|
||||
}
|
||||
|
||||
TEST(ParseCommandLineFlagsAndDashArgs, TwoDashArgFirst) {
|
||||
const char* argv[] = {
|
||||
"my_test",
|
||||
"--",
|
||||
"--test_flag=0",
|
||||
NULL,
|
||||
};
|
||||
|
||||
EXPECT_EQ(-1, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
|
||||
EXPECT_EQ(-1, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
|
||||
}
|
||||
|
||||
TEST(ParseCommandLineFlagsAndDashArgs, TwoDashArgMiddle) {
|
||||
const char* argv[] = {
|
||||
"my_test",
|
||||
"--test_flag=7",
|
||||
"--",
|
||||
"--test_flag=0",
|
||||
NULL,
|
||||
};
|
||||
|
||||
EXPECT_EQ(7, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
|
||||
EXPECT_EQ(7, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
|
||||
}
|
||||
|
||||
TEST(ParseCommandLineFlagsAndDashArgs, OneDashArg) {
|
||||
const char* argv[] = {
|
||||
"my_test",
|
||||
"-",
|
||||
"--test_flag=0",
|
||||
NULL,
|
||||
};
|
||||
|
||||
EXPECT_EQ(0, ParseTestFlag(true, GET_ARRAY_SIZE(argv) - 1, argv));
|
||||
EXPECT_EQ(0, ParseTestFlag(false, GET_ARRAY_SIZE(argv) - 1, argv));
|
||||
}
|
||||
|
||||
static int Main(int argc, char **argv) {
|
||||
// We need to call SetArgv before InitGoogle, so our "test" argv will
|
||||
// win out over this executable's real argv. That makes running this
|
||||
|
|
|
@ -50,6 +50,24 @@
|
|||
//
|
||||
// For more details, see
|
||||
// doc/gflags.html
|
||||
//
|
||||
// --- A note about thread-safety:
|
||||
//
|
||||
// We describe many functions in this routine as being thread-hostile,
|
||||
// thread-compatible, or thread-safe. Here are the meanings we use:
|
||||
//
|
||||
// thread-safe: it is safe for multiple threads to call this routine
|
||||
// (or, when referring to a class, methods of this class)
|
||||
// concurrently.
|
||||
// thread-hostile: it is not safe for multiple threads to call this
|
||||
// routine (or methods of this class) concurrently. In gflags,
|
||||
// most thread-hostile routines are intended to be called early in,
|
||||
// or even before, main() -- that is, before threads are spawned.
|
||||
// thread-compatible: it is safe for multiple threads to read from
|
||||
// this variable (when applied to variables), or to call const
|
||||
// methods of this class (when applied to classes), as long as no
|
||||
// other thread is writing to the variable or calling non-const
|
||||
// methods of this class.
|
||||
|
||||
#ifndef BASE_COMMANDLINEFLAGS_H__
|
||||
#define BASE_COMMANDLINEFLAGS_H__
|
||||
|
@ -120,13 +138,22 @@ extern void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
|
|||
extern void ShowUsageWithFlags(const char *argv0); // what --help does
|
||||
extern void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict);
|
||||
|
||||
// Create a descriptive string for a flag.
|
||||
// Goes to some trouble to make pretty line breaks.
|
||||
extern std::string DescribeOneFlag(const CommandLineFlagInfo& flag);
|
||||
|
||||
// Thread-hostile; meant to be called before any threads are spawned.
|
||||
extern void SetArgv(int argc, const char** argv);
|
||||
// The following functions are thread-safe as long as SetArgv() is
|
||||
// only called before any threads start.
|
||||
extern const std::vector<std::string>& GetArgvs(); // all of argv as a vector
|
||||
extern const char* GetArgv(); // all of argv as a string
|
||||
extern const char* GetArgv0(); // only argv0
|
||||
extern uint32 GetArgvSum(); // simple checksum of argv
|
||||
extern const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
|
||||
extern const char* ProgramInvocationShortName(); // basename(argv0)
|
||||
// ProgramUsage() is thread-safe as long as SetUsageMessage() is only
|
||||
// called before any threads start.
|
||||
extern const char* ProgramUsage(); // string set by SetUsageMessage()
|
||||
|
||||
|
||||
|
@ -135,6 +162,8 @@ extern const char* ProgramUsage(); // string set by SetUsageMessage()
|
|||
// or whatever, and set them by calling "FLAGS_foo = bar" (or, more
|
||||
// commonly, via the DEFINE_foo macro). But if you need a bit more
|
||||
// control, we have programmatic ways to get/set the flags as well.
|
||||
// These programmatic ways to access flags are thread-safe, but direct
|
||||
// access is only thread-compatible.
|
||||
|
||||
// Return true iff the flagname was found.
|
||||
// OUTPUT is set to the flag's value, or unchanged if we return false.
|
||||
|
@ -196,6 +225,8 @@ extern std::string SetCommandLineOptionWithMode(const char* name, const char* va
|
|||
// work is done in the constructor and destructor, so in the standard
|
||||
// usage example above, the compiler would complain that it's an
|
||||
// unused variable.
|
||||
//
|
||||
// This class is thread-safe.
|
||||
|
||||
class FlagSaver {
|
||||
public:
|
||||
|
@ -251,6 +282,7 @@ extern const char *StringFromEnv(const char *varname, const char *defval);
|
|||
// usage += argv[0] + " <uselessarg1> <uselessarg2>";
|
||||
// SetUsageMessage(usage);
|
||||
// Do not include commandline flags in the usage: we do that for you!
|
||||
// Thread-hostile; meant to be called before any threads are spawned.
|
||||
extern void SetUsageMessage(const std::string& usage);
|
||||
|
||||
// Looks for flags in argv and parses them. Rearranges argv to put
|
||||
|
@ -280,8 +312,10 @@ extern uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv,
|
|||
// it's too late to change that now. :-(
|
||||
extern void HandleCommandLineHelpFlags(); // in commandlineflags_reporting.cc
|
||||
|
||||
// Allow command line reparsing. Disables the error normaly generated
|
||||
// when an unknown flag is found, since it may be found in a later parse.
|
||||
// Allow command line reparsing. Disables the error normally
|
||||
// generated when an unknown flag is found, since it may be found in a
|
||||
// later parse. Thread-hostile; meant to be called before any threads
|
||||
// are spawned.
|
||||
extern void AllowCommandLineReparsing();
|
||||
|
||||
// Reparse the flags that have not yet been recognized.
|
||||
|
|
Loading…
Add table
Reference in a new issue