From 31c8edc53e5438121d70598bfa6c291880a6a375 Mon Sep 17 00:00:00 2001 From: Craig Silverstein Date: Tue, 5 Jan 2010 02:25:45 +0000 Subject: [PATCH] Mon Jan 4 18:09:30 2010 Google Inc. * google-gflags: version 1.3 * PORTABILITY: can now build and run tests under MSVC (csilvers) * Remove the python gflags code, which is now its own package (tansell) * Clarify that "last flag wins" in the docs (csilvers) * Comment danger of using GetAllFlags in validators (wojtekm) * PORTABILITY: Some fixes necessary for c++0x (mboerger) * Makefile fix: $(srcdir) -> $(top_srcdir) in one place (csilvres) * INSTALL: autotools to autoconf v2.64 + automake v1.11 (csilvers) git-svn-id: https://gflags.googlecode.com/svn/trunk@35 6586e3c6-dcc4-952a-343f-ff74eb82781d --- ChangeLog | 11 + Makefile.am | 11 +- Makefile.in | 14 +- README | 17 +- autogen.sh | 31 +- config.guess | 80 +- config.sub | 117 ++- configure | 20 +- configure.ac | 2 +- doc/gflags.html | 3 + ltmain.sh | 277 +++-- packages/deb/changelog | 6 + python/gflags.py | 2311 ----------------------------------------- python/gflags2man.py | 536 ---------- python/gflags_helpxml_test.py | 563 ---------- python/gflags_unittest.py | 1573 ---------------------------- python/setup.py | 42 - python/test_module_bar.py | 135 --- python/test_module_foo.py | 120 --- src/gflags.cc | 14 +- src/gflags_completions.cc | 8 +- src/gflags_reporting.cc | 6 +- src/gflags_unittest.cc | 155 +-- 23 files changed, 485 insertions(+), 5567 deletions(-) delete mode 100755 python/gflags.py delete mode 100755 python/gflags2man.py delete mode 100755 python/gflags_helpxml_test.py delete mode 100755 python/gflags_unittest.py delete mode 100755 python/setup.py delete mode 100755 python/test_module_bar.py delete mode 100755 python/test_module_foo.py diff --git a/ChangeLog b/ChangeLog index dd9decf..fa5599f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +Mon Jan 4 18:09:30 2010 Google Inc. + + * google-gflags: version 1.3 + * PORTABILITY: can now build and run tests under MSVC (csilvers) + * Remove the python gflags code, which is now its own package (tansell) + * Clarify that "last flag wins" in the docs (csilvers) + * Comment danger of using GetAllFlags in validators (wojtekm) + * PORTABILITY: Some fixes necessary for c++0x (mboerger) + * Makefile fix: $(srcdir) -> $(top_srcdir) in one place (csilvres) + * INSTALL: autotools to autoconf v2.64 + automake v1.11 (csilvers) + Thu Sep 10 12:53:04 2009 Google Inc. * google-gflags: version 1.2 diff --git a/Makefile.am b/Makefile.am index ab0b68c..01e3431 100644 --- a/Makefile.am +++ b/Makefile.am @@ -141,15 +141,6 @@ gflags_nc_test4: $(gflagsinclude_HEADERS) src/gflags_nc.cc # This file isn't covered under any rule that would cause it to be distributed. dist_noinst_DATA += src/gflags_nc.cc -# These aren't part of the c++ source, but we want them to be distributed -PYTHON = python/setup.py \ - python/gflags.py \ - python/gflags2man.py \ - python/gflags_unittest.py \ - python/gflags_helpxml_test.py \ - python/test_module_foo.py \ - python/test_module_bar.py - ## ^^^^ END OF RULES TO MAKE THE LIBRARIES, BINARIES, AND UNITTESTS @@ -167,7 +158,7 @@ deb: dist-gzip packages/deb.sh packages/deb/* libtool: $(LIBTOOL_DEPS) $(SHELL) ./config.status --recheck EXTRA_DIST = packages/rpm.sh packages/rpm/rpm.spec packages/deb.sh packages/deb \ - libtool $(SCRIPTS) $(PYTHON) \ + libtool $(SCRIPTS) \ src/windows/config.h src/windows/port.h src/windows/port.cc \ src/windows/gflags/gflags.h src/windows/gflags/gflags_completions.h \ $(WINDOWS_PROJECTS) \ diff --git a/Makefile.in b/Makefile.in index 3243c0c..b0390d2 100644 --- a/Makefile.in +++ b/Makefile.in @@ -368,18 +368,8 @@ gflags_unittest3_LDADD = libgflags_nothreads.la # This file isn't covered under any rule that would cause it to be distributed. dist_noinst_DATA = src/gflags_unittest_flagfile src/gflags_nc.cc - -# These aren't part of the c++ source, but we want them to be distributed -PYTHON = python/setup.py \ - python/gflags.py \ - python/gflags2man.py \ - python/gflags_unittest.py \ - python/gflags_helpxml_test.py \ - python/test_module_foo.py \ - python/test_module_bar.py - EXTRA_DIST = packages/rpm.sh packages/rpm/rpm.spec packages/deb.sh packages/deb \ - libtool $(SCRIPTS) $(PYTHON) \ + libtool $(SCRIPTS) \ src/windows/config.h src/windows/port.h src/windows/port.cc \ src/windows/gflags/gflags.h src/windows/gflags/gflags_completions.h \ $(WINDOWS_PROJECTS) \ @@ -834,7 +824,7 @@ check-TESTS: $(TESTS) distdir: $(DISTFILES) $(am__remove_distdir) mkdir $(distdir) - $(mkdir_p) $(distdir)/doc $(distdir)/m4 $(distdir)/packages $(distdir)/packages/rpm $(distdir)/python $(distdir)/src $(distdir)/src/gflags $(distdir)/src/google $(distdir)/src/solaris $(distdir)/src/windows $(distdir)/src/windows/gflags $(distdir)/vsprojects/gflags_unittest $(distdir)/vsprojects/libgflags + $(mkdir_p) $(distdir)/doc $(distdir)/m4 $(distdir)/packages $(distdir)/packages/rpm $(distdir)/src $(distdir)/src/gflags $(distdir)/src/google $(distdir)/src/solaris $(distdir)/src/windows $(distdir)/src/windows/gflags $(distdir)/vsprojects/gflags_unittest $(distdir)/vsprojects/libgflags @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ diff --git a/README b/README index 91bf248..b49fac9 100644 --- a/README +++ b/README @@ -1,19 +1,10 @@ -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. +This repository contains a C++ of the Google commandline flags module. +Documentation for the C++ implementation is in doc/. The python version of +gflags is now shipped seperately as it is completely independent of this +module. 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 - You can also compile this under Windows, if you want. The solution file (for VC 7.1 and later) is in this directory. - -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/autogen.sh b/autogen.sh index c595d49..09396a8 100755 --- a/autogen.sh +++ b/autogen.sh @@ -17,22 +17,21 @@ rm -rf autom4te.cache trap 'rm -f aclocal.m4.tmp' EXIT -# Use version 1.9 of aclocal and automake if available. -ACLOCAL=aclocal-1.9 -if test -z `which "$ACLOCAL"`; then - ACLOCAL=aclocal -fi - -AUTOMAKE=automake-1.9 -if test -z `which "$AUTOMAKE"`; then - AUTOMAKE=automake -fi +# Returns the first binary in $* that exists, or the last arg, if none exists. +WhichOf() { + for candidate in "$@"; do + if "$candidate" --version >/dev/null 2>&1; then + echo "$candidate" + return + fi + done + echo "$candidate" # the last one in $@ +} -# glibtoolize is used for Mac OS X -LIBTOOLIZE=libtoolize -if test -z `which "$LIBTOOLIZE"`; then - LIBTOOLIZE=glibtoolize -fi +# Use version 1.9 of aclocal and automake if available. +ACLOCAL=`WhichOf aclocal-1.9 aclocal` +AUTOMAKE=`WhichOf automake-1.9 automake` +LIBTOOLIZE=`WhichOf glibtoolize libtoolize15 libtoolize14 libtoolize` # aclocal tries to overwrite aclocal.m4 even if the contents haven't # changed, which is annoying when the file is not open for edit (in @@ -46,7 +45,7 @@ else mv aclocal.m4.tmp aclocal.m4 # we did set -e above, so we die if this fails fi -grep -q LIBTOOL configure.ac && "$LIBTOOLIZE" -c -f +grep -q '^[^#]*AC_PROG_LIBTOOL' configure.ac && "$LIBTOOLIZE" -c -f autoconf -f -W all,no-obsolete autoheader -f -W all "$AUTOMAKE" -a -c -f -W all diff --git a/config.guess b/config.guess index ad5281e..278f9e9 100755 --- a/config.guess +++ b/config.guess @@ -1,9 +1,10 @@ #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. -timestamp='2005-08-03' +timestamp='2007-07-22' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -106,7 +107,7 @@ set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; @@ -160,6 +161,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched @@ -206,8 +208,11 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; macppc:MirBSD:*:*) - echo powerppc-unknown-mirbsd${UNAME_RELEASE} + echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} @@ -325,7 +330,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; - i86pc:SunOS:5.*:*) + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) @@ -764,12 +769,19 @@ EOF echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; - i*:MINGW*:*) + *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:windows32*:*) @@ -779,9 +791,15 @@ EOF i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; - x86:Interix*:[34]*) - echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' - exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; @@ -817,6 +835,9 @@ EOF arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; cris:Linux:*:*) echo cris-axis-linux-gnu exit ;; @@ -851,7 +872,11 @@ EOF #endif #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; mips64:Linux:*:*) @@ -870,7 +895,11 @@ EOF #endif #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; or32:Linux:*:*) @@ -919,9 +948,15 @@ EOF sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit ;; + xtensa:Linux:*:*) + echo xtensa-unknown-linux-gnu + exit ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent @@ -964,7 +999,7 @@ EOF LIBC=gnulibc1 # endif #else - #ifdef __INTEL_COMPILER + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) LIBC=gnu #else LIBC=gnuaout @@ -974,7 +1009,11 @@ EOF LIBC=dietlibc #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" test x"${LIBC}" != x && { echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit @@ -1176,6 +1215,15 @@ EOF SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; @@ -1185,7 +1233,6 @@ EOF *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in - *86) UNAME_PROCESSOR=i686 ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} @@ -1264,6 +1311,9 @@ EOF i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 diff --git a/config.sub b/config.sub index 1c366df..1761d8b 100755 --- a/config.sub +++ b/config.sub @@ -1,9 +1,10 @@ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. -timestamp='2005-07-08' +timestamp='2007-06-28' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -119,8 +120,9 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ - kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; @@ -171,6 +173,10 @@ case $os in -hiux*) os=-hiuxwe2 ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` @@ -187,6 +193,10 @@ case $os in # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` @@ -231,15 +241,16 @@ case $basic_machine in | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ - | fr30 | frv \ + | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ - | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ @@ -257,28 +268,27 @@ case $basic_machine in | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ - | ms1 \ + | mt \ | msp430 \ + | nios | nios2 \ | ns16k | ns32k \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ - | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | score \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b \ - | strongarm \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ - | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; - m32c) - basic_machine=$basic_machine-unknown - ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown @@ -286,6 +296,9 @@ case $basic_machine in ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; + ms1) + basic_machine=mt-unknown + ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and @@ -305,18 +318,18 @@ case $basic_machine in | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* \ + | avr-* | avr32-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ - | m32r-* | m32rle-* \ + | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ @@ -336,31 +349,30 @@ case $basic_machine in | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ - | ms1-* \ + | mt-* \ | msp430-* \ + | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ - | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ | xstormy16-* | xtensa-* \ | ymp-* \ | z8k-*) ;; - m32c-*) - ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) @@ -463,8 +475,8 @@ case $basic_machine in basic_machine=craynv-cray os=-unicosmp ;; - cr16c) - basic_machine=cr16c-unknown + cr16) + basic_machine=cr16-unknown os=-elf ;; crds | unos) @@ -671,6 +683,10 @@ case $basic_machine in basic_machine=i386-pc os=-mingw32 ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; miniframe) basic_machine=m68000-convergent ;; @@ -696,6 +712,9 @@ case $basic_machine in basic_machine=i386-pc os=-msdos ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; mvs) basic_machine=i370-ibm os=-mvs @@ -803,6 +822,12 @@ case $basic_machine in pc532 | pc532-*) basic_machine=ns32k-pc532 ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; @@ -859,6 +884,10 @@ case $basic_machine in basic_machine=i586-unknown os=-pw32 ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; rom68k) basic_machine=m68k-rom68k os=-coff @@ -885,6 +914,10 @@ case $basic_machine in sb1el) basic_machine=mipsisa64sb1el-unknown ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; sei) basic_machine=mips-sei os=-seiux @@ -896,6 +929,9 @@ case $basic_machine in basic_machine=sh-hitachi os=-hms ;; + sh5el) + basic_machine=sh5le-unknown + ;; sh64) basic_machine=sh64-unknown ;; @@ -1101,7 +1137,7 @@ case $basic_machine in sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sparc | sparcv8 | sparcv9 | sparcv9b) + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) @@ -1174,21 +1210,23 @@ case $os in | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1340,6 +1378,12 @@ else # system, and we'll never get to this point. case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; *-acorn) os=-riscix1.2 ;; @@ -1349,9 +1393,9 @@ case $basic_machine in arm*-semi) os=-aout ;; - c4x-* | tic4x-*) - os=-coff - ;; + c4x-* | tic4x-*) + os=-coff + ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 @@ -1377,6 +1421,9 @@ case $basic_machine in m68*-cisco) os=-aout ;; + mep-*) + os=-elf + ;; mips*-cisco) os=-elf ;; diff --git a/configure b/configure index 5ad8f53..36c7951 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.64 for gflags 1.2. +# Generated by GNU Autoconf 2.64 for gflags 1.3. # # Report bugs to . # @@ -703,8 +703,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='gflags' PACKAGE_TARNAME='gflags' -PACKAGE_VERSION='1.2' -PACKAGE_STRING='gflags 1.2' +PACKAGE_VERSION='1.3' +PACKAGE_STRING='gflags 1.3' PACKAGE_BUGREPORT='opensource@google.com' PACKAGE_URL='' @@ -1439,7 +1439,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 1.2 to adapt to many kinds of systems. +\`configure' configures gflags 1.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1509,7 +1509,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of gflags 1.2:";; + short | recursive ) echo "Configuration of gflags 1.3:";; esac cat <<\_ACEOF @@ -1618,7 +1618,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -gflags configure 1.2 +gflags configure 1.3 generated by GNU Autoconf 2.64 Copyright (C) 2009 Free Software Foundation, Inc. @@ -2248,7 +2248,7 @@ cat >config.log <<_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 1.2, which was +It was created by gflags $as_me 1.3, which was generated by GNU Autoconf 2.64. Invocation command line was $ $0 $@ @@ -2910,7 +2910,7 @@ fi # Define the identity of the package. PACKAGE='gflags' - VERSION='1.2' + VERSION='1.3' cat >>confdefs.h <<_ACEOF @@ -20564,7 +20564,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by gflags $as_me 1.2, which was +This file was extended by gflags $as_me 1.3, which was generated by GNU Autoconf 2.64. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -20628,7 +20628,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ -gflags config.status 1.2 +gflags config.status 1.3 configured by $0, generated by GNU Autoconf 2.64, with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" diff --git a/configure.ac b/configure.ac index da2729f..43c7a1f 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ # make sure we're interpreted by some minimal autoconf AC_PREREQ(2.57) -AC_INIT(gflags, 1.2, opensource@google.com) +AC_INIT(gflags, 1.3, 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/doc/gflags.html b/doc/gflags.html index ec0b1c7..3de59ac 100644 --- a/doc/gflags.html +++ b/doc/gflags.html @@ -317,6 +317,9 @@ HREF="#special">--undefok to suppress the error.

processing. So in foo -f1 1 -- -f2 2, f1 is considered a flag, but -f2 is not.

+

If a flag is specified more than once, only the last specification +is used; the others are ignored.

+

Note that flags do not have single-letter synonyms, like they do in the getopt library, nor do we allow "combining" flags behind a single dash, as in ls -la.

diff --git a/ltmain.sh b/ltmain.sh index 8fc56db..e420fac 100644 --- a/ltmain.sh +++ b/ltmain.sh @@ -1,8 +1,8 @@ # ltmain.sh - Provide generalized library-building support services. # NOTE: Changing this file will not affect anything until you rerun configure. # -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 -# Free Software Foundation, Inc. +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, +# 2007, 2008 Free Software Foundation, Inc. # Originally by Gordon Matzigkeit , 1996 # # This program is free software; you can redistribute it and/or modify @@ -43,14 +43,22 @@ EXIT_FAILURE=1 PROGRAM=ltmain.sh PACKAGE=libtool -VERSION="1.5.22 Debian 1.5.22-2" -TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)" - -# See if we are running on zsh, and set the options which allow our -# commands through without removal of \ escapes. -if test -n "${ZSH_VERSION+set}" ; then +VERSION="1.5.26 Debian 1.5.26-1ubuntu1" +TIMESTAMP=" (1.1220.2.493 2008/02/01 16:58:18)" + +# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE). +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh # Check that we have a working $echo. if test "X$1" = X--no-reexec; then @@ -105,11 +113,19 @@ esac # These must not be set unconditionally because not all systems understand # e.g. LANG=C (notably SCO). # We save the old values to restore during execute mode. -if test "${LC_ALL+set}" = set; then - save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL -fi -if test "${LANG+set}" = set; then - save_LANG="$LANG"; LANG=C; export LANG +lt_env= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + lt_env=\"$lt_var=\$$lt_var \$lt_env\" + $lt_var=C + export $lt_var + fi" +done + +if test -n "$lt_env"; then + lt_env="env $lt_env" fi # Make sure IFS has a sensible default @@ -136,6 +152,8 @@ duplicate_deps=no preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" +extracted_archives= +extracted_serial=0 ##################################### # Shell function definitions: @@ -196,7 +214,13 @@ func_win32_libid () if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then win32_nmres=`eval $NM -f posix -A $1 | \ - $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'` + $SED -n -e '1,100{ + / I /{ + s,.*,import, + p + q + } + }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; @@ -327,7 +351,17 @@ func_extract_archives () *) my_xabs=`pwd`"/$my_xlib" ;; esac my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'` - my_xdir="$my_gentop/$my_xlib" + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + extracted_serial=`expr $extracted_serial + 1` + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" $show "${rm}r $my_xdir" $run ${rm}r "$my_xdir" @@ -454,11 +488,12 @@ do ;; --version) - $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" - $echo - $echo "Copyright (C) 2005 Free Software Foundation, Inc." - $echo "This is free software; see the source for copying conditions. There is NO" - $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + echo "\ +$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP + +Copyright (C) 2008 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." exit $? ;; @@ -755,9 +790,11 @@ if test -z "$show_help"; then *.class) xform=class ;; *.cpp) xform=cpp ;; *.cxx) xform=cxx ;; - *.f90) xform=f90 ;; + *.[fF][09]?) xform=[fF][09]. ;; *.for) xform=for ;; *.java) xform=java ;; + *.obj) xform=obj ;; + *.sx) xform=sx ;; esac libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` @@ -926,7 +963,7 @@ EOF $run $rm "$lobj" "$output_obj" $show "$command" - if $run eval "$command"; then : + if $run eval $lt_env "$command"; then : else test -n "$output_obj" && $run $rm $removelist exit $EXIT_FAILURE @@ -998,7 +1035,7 @@ EOF command="$command$suppress_output" $run $rm "$obj" "$output_obj" $show "$command" - if $run eval "$command"; then : + if $run eval $lt_env "$command"; then : else $run $rm $removelist exit $EXIT_FAILURE @@ -1131,6 +1168,7 @@ EOF thread_safe=no vinfo= vinfo_number=no + single_module="${wl}-single_module" func_infer_tag $base_compile @@ -1138,8 +1176,9 @@ EOF for arg do case $arg in - -all-static | -static) - if test "X$arg" = "X-all-static"; then + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2 fi @@ -1147,12 +1186,20 @@ EOF dlopen_self=$dlopen_self_static fi prefer_static_libs=yes - else + ;; + -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built - fi + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac build_libtool_libs=no build_old_libs=yes break @@ -1600,13 +1647,18 @@ EOF continue ;; - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) compiler_flags="$compiler_flags $arg" compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" continue ;; + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + -module) module=yes continue @@ -1620,10 +1672,11 @@ EOF # -m* pass through architecture-specific compiler args for GCC # -m*, -t[45]*, -txscale* pass through architecture-specific # compiler args for GCC - # -pg pass through profiling flag for GCC + # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC + # -F/path gives path to uninstalled frameworks, gcc on darwin # @file GCC response files - -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \ - -t[45]*|-txscale*|@*) + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. @@ -1651,9 +1704,9 @@ EOF -no-install) case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin*) # The PATH hackery in wrapper scripts is required on Windows - # in order for the loader to find any dlls it needs. + # and Darwin in order for the loader to find any dlls it needs. $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 fast_install=no @@ -1712,7 +1765,7 @@ EOF continue ;; - -static) + -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects @@ -2097,7 +2150,7 @@ EOF lib= found=no case $deplib in - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" @@ -2112,7 +2165,12 @@ EOF continue fi name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` - for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" @@ -2493,7 +2551,9 @@ EOF if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && - { test "$prefer_static_libs" = no || test -z "$old_library"; }; then + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. @@ -2906,12 +2966,18 @@ EOF # we do not want to link against static libs, # but need to link against shared eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + eval deplibdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done - if test -f "$path/$depdepl" ; then + if test -f "$deplibdir/$depdepl" ; then + depdepl="$deplibdir/$depdepl" + elif test -f "$path/$depdepl" ; then depdepl="$path/$depdepl" + else + # Can't find it, oh well... + depdepl= fi # do not add paths which are already there case " $newlib_search_path " in @@ -3059,9 +3125,10 @@ EOF case $linkmode in oldlib) - if test -n "$deplibs"; then - $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 - fi + case " $deplibs" in + *\ -l* | *\ -L*) + $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 ;; + esac if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 @@ -3189,7 +3256,7 @@ EOF # which has an extra 1 added just for fun # case $version_type in - darwin|linux|osf|windows) + darwin|linux|osf|windows|none) current=`expr $number_major + $number_minor` age="$number_minor" revision="$number_revision" @@ -3200,9 +3267,10 @@ EOF age="0" ;; irix|nonstopux) - current=`expr $number_major + $number_minor - 1` + current=`expr $number_major + $number_minor` age="$number_minor" revision="$number_minor" + lt_irix_increment=no ;; *) $echo "$modename: unknown library version type \`$version_type'" 1>&2 @@ -3266,7 +3334,8 @@ EOF versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... minor_current=`expr $current + 1` - verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) @@ -3280,8 +3349,11 @@ EOF ;; irix | nonstopux) - major=`expr $current - $age + 1` - + if test "X$lt_irix_increment" = "Xno"; then + major=`expr $current - $age` + else + major=`expr $current - $age + 1` + fi case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; @@ -3418,11 +3490,11 @@ EOF fi # Eliminate all temporary directories. - for path in $notinst_path; do - lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` - deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` - dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"` - done + #for path in $notinst_path; do + # lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` + # deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` + # dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"` + #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. @@ -3523,13 +3595,12 @@ EOF int main() { return 0; } EOF $rm conftest - $LTCC $LTCFLAGS -o conftest conftest.c $deplibs - if test "$?" -eq 0 ; then + if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then ldd_output=`ldd conftest` for i in $deplibs; do name=`expr $i : '-l\(.*\)'` # If $name is empty we are operating on a -L argument. - if test "$name" != "" && test "$name" -ne "0"; then + if test "$name" != "" && test "$name" != "0"; then if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $i "*) @@ -3568,9 +3639,7 @@ EOF # If $name is empty we are operating on a -L argument. if test "$name" != "" && test "$name" != "0"; then $rm conftest - $LTCC $LTCFLAGS -o conftest conftest.c $i - # Did it work? - if test "$?" -eq 0 ; then + if $LTCC $LTCFLAGS -o conftest conftest.c $i; then ldd_output=`ldd conftest` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in @@ -3602,7 +3671,7 @@ EOF droppeddeps=yes $echo $echo "*** Warning! Library $i is needed by this library but I was not able to" - $echo "*** make it link in! You will probably need to install it or some" + $echo "*** make it link in! You will probably need to install it or some" $echo "*** library that it depends on before this library will be fully" $echo "*** functional. Installing it before continuing would be even better." fi @@ -3888,7 +3957,10 @@ EOF test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" if test -n "$hardcode_libdir_flag_spec_ld"; then - eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + case $archive_cmds in + *\$LD*) eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" ;; + *) eval dep_rpath=\"$hardcode_libdir_flag_spec\" ;; + esac else eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi @@ -4198,9 +4270,10 @@ EOF ;; obj) - if test -n "$deplibs"; then - $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 - fi + case " $deplibs" in + *\ -l* | *\ -L*) + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 ;; + esac if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 @@ -4247,12 +4320,14 @@ EOF reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of - # -Wl from whole_archive_flag_spec + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then - eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$echo "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` else gentop="$output_objdir/${obj}x" generated="$generated $gentop" @@ -4700,16 +4775,16 @@ static const void *lt_preloaded_setup() { case $host in *cygwin* | *mingw* ) if test -f "$output_objdir/${outputname}.def" ; then - compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP` else - compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP` fi ;; * ) - compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP` ;; esac ;; @@ -4724,13 +4799,13 @@ static const void *lt_preloaded_setup() { # really was required. # Nullify the symbol file. - compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP` fi if test "$need_relink" = no || test "$build_libtool_libs" != yes; then # Replace the output file specification. - compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$output"'%g' | $NL2SP` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. @@ -4817,7 +4892,7 @@ static const void *lt_preloaded_setup() { if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then - relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $SP2NL | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g' | $NL2SP` else # fast_install is set to needless relink_command= @@ -4854,7 +4929,7 @@ static const void *lt_preloaded_setup() { fi done relink_command="(cd `pwd`; $relink_command)" - relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP` fi # Quote $echo for shipping. @@ -5261,6 +5336,20 @@ EOF Xsed='${SED} -e 1s/^X//' sed_quote_subst='$sed_quote_subst' +# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE). +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH @@ -5403,7 +5492,7 @@ else ;; esac $echo >> $output "\ - \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + \$echo \"\$0: cannot exec \$program \$*\" exit $EXIT_FAILURE fi else @@ -5589,7 +5678,7 @@ fi\ done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" - relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP` if test "$hardcode_automatic" = yes ; then relink_command= fi @@ -5934,9 +6023,9 @@ relink_command=\"$relink_command\"" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. - relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%" | $NL2SP` else - relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%%" | $NL2SP` fi $echo "$modename: warning: relinking \`$file'" 1>&2 @@ -6145,7 +6234,7 @@ relink_command=\"$relink_command\"" file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` outputname="$tmpdir/$file" # Replace the output file specification. - relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g' | $NL2SP` $show "$relink_command" if $run eval "$relink_command"; then : @@ -6356,8 +6445,10 @@ relink_command=\"$relink_command\"" if test -f "$dir/$objdir/$dlname"; then dir="$dir/$objdir" else - $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 - exit $EXIT_FAILURE + if test ! -f "$dir/$dlname"; then + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit $EXIT_FAILURE + fi fi ;; @@ -6421,12 +6512,12 @@ relink_command=\"$relink_command\"" fi # Restore saved environment variables - if test "${save_LC_ALL+set}" = set; then - LC_ALL="$save_LC_ALL"; export LC_ALL - fi - if test "${save_LANG+set}" = set; then - LANG="$save_LANG"; export LANG - fi + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + fi" + done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" @@ -6783,9 +6874,9 @@ The following components of LINK-COMMAND are treated specially: -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE - try to export only the symbols listed in SYMFILE + try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX - try to export only the symbols matching REGEX + try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened @@ -6799,9 +6890,11 @@ The following components of LINK-COMMAND are treated specially: -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries - -static do not do any dynamic linking of libtool libraries + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] - specify library version info [each variable defaults to 0] + specify library version info [each variable defaults to 0] All other options (arguments beginning with \`-') are ignored. diff --git a/packages/deb/changelog b/packages/deb/changelog index 07395ca..84f4e9b 100644 --- a/packages/deb/changelog +++ b/packages/deb/changelog @@ -1,3 +1,9 @@ +gflags (1.3-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Mon, 04 Jan 2010 18:09:30 -0800 + gflags (1.2-1) unstable; urgency=low * New upstream release. diff --git a/python/gflags.py b/python/gflags.py deleted file mode 100755 index 16e7651..0000000 --- a/python/gflags.py +++ /dev/null @@ -1,2311 +0,0 @@ -#!/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 attributes of the 'FlagValues' object. - -Code can access the flag through a FlagValues object, for instance -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_bool or -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. - Example: --myspacesepflag "foo bar baz" - -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 prints a list of all the flags in a human-readable fashion - --helpshort prints a list of all key flags (see below). - --helpxml prints a list of all flags, in XML format. DO NOT parse - the output of --help and --helpshort. Instead, parse - the output of --helpxml. As we add new flags, we may - add new XML elements. Hence, make sure your parser - does not crash when it encounters new XML elements. - --flagfile=foo read flags from foo. - --undefok=f1,f2 ignore unrecognized option errors for f1,f2. - For boolean flags, you should use --undefok=boolflag, and - --boolflag and --noboolflag will be accepted. Do not use - --undefok=noboolflag. - -- 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= 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', 'your name') - gflags.DEFINE_integer('age', None, 'your age in years', lower_bound=0) - gflags.DEFINE_boolean('debug', False, 'produces debugging output') - gflags.DEFINE_enum('gender', 'male', ['male', 'female'], '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 is not None: - print 'You are a %s, who is %d years old' % (FLAGS.gender, FLAGS.age) - - if __name__ == '__main__': - main(sys.argv) - - -KEY FLAGS: - -As we already explained, each module gains access to all flags defined -by all the other modules it transitively imports. In the case of -non-trivial scripts, this means a lot of flags ... For documentation -purposes, it is good to identify the flags that are key (i.e., really -important) to a module. Clearly, the concept of "key flag" is a -subjective one. When trying to determine whether a flag is key to a -module or not, assume that you are trying to explain your module to a -potential user: which flags would you really like to mention first? - -We'll describe shortly how to declare which flags are key to a module. -For the moment, assume we know the set of key flags for each module. -Then, if you use the app.py module, you can use the --helpshort flag to -print only the help for the flags that are key to the main module, in a -human-readable format. - -NOTE: If you need to parse the flag help, do NOT use the output of ---help / --helpshort. That output is meant for human consumption, and -may be changed in the future. Instead, use --helpxml; flags that are -key for the main module are marked there with a yes element. - -The set of key flags for a module M is composed of: - -1. Flags defined by module M by calling a DEFINE_* function. - -2. Flags that module M explictly declares as key by using the function - - DECLARE_key_flag() - -3. Key flags of other modules that M specifies by using the function - - ADOPT_module_key_flags() - - This is a "bulk" declaration of key flags: each flag that is key for - becomes key for the current module too. - -Notice that if you do not use the functions described at points 2 and 3 -above, then --helpshort prints information only about the flags defined -by the main module of our script. In many cases, this behavior is good -enough. But if you move part of the main module code (together with the -related flags) into a different module, then it is nice to use -DECLARE_key_flag / ADOPT_module_key_flags and make sure --helpshort -lists all relevant flags (otherwise, your code refactoring may confuse -your users). - -Note: each of DECLARE_key_flag / ADOPT_module_key_flags has its own -pluses and minuses: DECLARE_key_flag is more targeted and may lead a -more focused --helpshort documentation. ADOPT_module_key_flags is good -for cases when an entire module is considered key to the current script. -Also, it does not require updates to client scripts when a new flag is -added to the module. - - -EXAMPLE USAGE 2 (WITH KEY FLAGS): - -Consider an application that contains the following three files (two -auxiliary modules and a main module): - -File libfoo.py: - - import gflags - - gflags.DEFINE_integer('num_replicas', 3, 'Number of replicas to start') - gflags.DEFINE_boolean('rpc2', True, 'Turn on the usage of RPC2.') - - ... some code ... - -File libbar.py: - - import gflags - - gflags.DEFINE_string('bar_gfs_path', '/gfs/path', - 'Path to the GFS files for libbar.') - gflags.DEFINE_string('email_for_bar_errors', 'bar-team@google.com', - 'Email address for bug reports about module libbar.') - gflags.DEFINE_boolean('bar_risky_hack', False, - 'Turn on an experimental and buggy optimization.') - - ... some code ... - -File myscript.py: - - import gflags - import libfoo - import libbar - - gflags.DEFINE_integer('num_iterations', 0, 'Number of iterations.') - - # Declare that all flags that are key for libfoo are - # key for this module too. - gflags.ADOPT_module_key_flags(libfoo) - - # Declare that the flag --bar_gfs_path (defined in libbar) is key - # for this module. - gflags.DECLARE_key_flag('bar_gfs_path') - - ... some code ... - -When myscript is invoked with the flag --helpshort, the resulted help -message lists information about all the key flags for myscript: ---num_iterations, --num_replicas, --rpc2, and --bar_gfs_path (in -addition to the special flags --help and --helpshort). - -Of course, myscript uses all the flags declared by it (in this case, -just --num_replicas) or by any of the modules it transitively imports -(e.g., the modules libfoo, libbar). E.g., it can access the value of -FLAGS.bar_risky_hack, even if --bar_risky_hack is not declared as a key -flag for myscript. -""" - -import cgi -import getopt -import os -import re -import string -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") - -# If we're not running at least python 2.2.1, define True, False, and bool. -# Thanks, Guido, for the code. -try: - True, False, bool -except NameError: - False = 0 - True = 1 - def bool(x): - if x: - return True - else: - return False - -# Are we running under pychecker? -_RUNNING_PYCHECKER = 'pychecker.python' in sys.modules - - -def _GetCallingModule(): - """Returns the name of the module that's calling into this module. - - We generally use this function to get the name of 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(): - module_name = __GetModuleName(sys._getframe(depth).f_globals) - if module_name is not None: - return module_name - raise AssertionError("No module was found") - - -# module exceptions: -class FlagsError(Exception): - """The base class for all flags errors.""" - pass - - -class DuplicateFlag(FlagsError): - """Raised if there is a flag naming conflict.""" - pass - - -# 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.FlagsByModuleDict() - for module in flags_by_module: - for flag in flags_by_module[module]: - if flag.name == flagname or flag.short_name == flagname: - message = message + " First from " + module + "," - break - message = message + " Second from " + _GetCallingModule() - DuplicateFlag.__init__(self, message) - - -class IllegalFlagValue(FlagsError): - """The flag command line argument is illegal.""" - pass - - -class UnrecognizedFlag(FlagsError): - """Raised if a flag is unrecognized.""" - pass - - -# 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 - UnrecognizedFlag.__init__( - self, "Unknown command line flag '%s'" % flagname) - - -# Global variable used by expvar -_exported_flags = {} -_help_width = 80 # width of help output - - -def GetHelpWidth(): - """Returns: an integer, the width of help lines that is used in TextWrap.""" - return _help_width - - -def CutCommonSpacePrefix(text): - """Removes a common space prefix from the lines of a multiline text. - - If the first line does not start with a space, it is left as it 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=' '): - """Wraps a given text to a maximum line length and returns it. - - We turn lines that only contain whitespaces into empty lines. We keep - new lines and 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, fall back to indent - tabs: replacement for tabs - - Returns: - wrapped text - - Raises: - FlagsError: if indent not shorter than length - FlagsError: 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 FlagsError('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 FlagsError('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): - """Given a globals dict, returns the name of the module that defines it. - - Args: - globals_dict: A dictionary that should correspond to an environment - providing the values of the globals. - - Returns: - A string (the name of the module) or None (if the module could not - be identified. - """ - for name, module in sys.modules.iteritems(): - if getattr(module, '__dict__', None) is globals_dict: - if name == '__main__': - return sys.argv[0] - return name - return None - - -def _GetMainModule(): - """Returns the name of the module 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: - """Registry of '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 attribute of the registered 'Flag' objects can be accessed - as attributes 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. - - # Dictionary: flag name (string) -> Flag object. - self.__dict__['__flags'] = {} - # Dictionary: module name (string) -> list of Flag objects that are defined - # by that module. - self.__dict__['__flags_by_module'] = {} - # Dictionary: module name (string) -> list of Flag objects that are - # key for that module. - self.__dict__['__key_flags_by_module'] = {} - - # Set if we should use new style gnu_getopt rather than getopt when parsing - # the args. Only possible with Python 2.3+ - self.UseGnuGetOpt(False) - - def UseGnuGetOpt(self, use_gnu_getopt=True): - self.__dict__['__use_gnu_getopt'] = use_gnu_getopt - - def IsGnuGetOpt(self): - return self.__dict__['__use_gnu_getopt'] - - def FlagDict(self): - return self.__dict__['__flags'] - - def FlagsByModuleDict(self): - """Returns the dictionary of module_name -> list of defined flags. - - Returns: - A dictionary. Its keys are module names (strings). Its values - are lists of Flag objects. - """ - return self.__dict__['__flags_by_module'] - - def KeyFlagsByModuleDict(self): - """Returns the dictionary of module_name -> list of key flags. - - Returns: - A dictionary. Its keys are module names (strings). Its values - are lists of Flag objects. - """ - return self.__dict__['__key_flags_by_module'] - - def _RegisterFlagByModule(self, module_name, flag): - """Records the module that defines a specific flag. - - We keep track of which flag is defined by which module so that we - can later sort the flags by module. - - Args: - module_name: A string, the name of a Python module. - flag: A Flag object, a flag that is key to the module. - """ - flags_by_module = self.FlagsByModuleDict() - flags_by_module.setdefault(module_name, []).append(flag) - - def _RegisterKeyFlagForModule(self, module_name, flag): - """Specifies that a flag is a key flag for a module. - - Args: - module_name: A string, the name of a Python module. - flag: A Flag object, a flag that is key to the module. - """ - key_flags_by_module = self.KeyFlagsByModuleDict() - # The list of key flags for the module named module_name. - key_flags = key_flags_by_module.setdefault(module_name, []) - # Add flag, but avoid duplicates. - if flag not in key_flags: - key_flags.append(flag) - - def _GetFlagsDefinedByModule(self, module): - """Returns the list of flags defined by a module. - - Args: - module: A module object or a module name (a string). - - Returns: - A new list of Flag objects. Caller may update this list as he - wishes: none of those changes will affect the internals of this - FlagValue object. - """ - if not isinstance(module, str): - module = module.__name__ - - return list(self.FlagsByModuleDict().get(module, [])) - - def _GetKeyFlagsForModule(self, module): - """Returns the list of key flags for a module. - - Args: - module: A module object or a module name (a string) - - Returns: - A new list of Flag objects. Caller may update this list as he - wishes: none of those changes will affect the internals of this - FlagValue object. - """ - if not isinstance(module, str): - module = module.__name__ - - # Any flag is a key flag for the module that defined it. NOTE: - # key_flags is a fresh list: we can update it without affecting the - # internals of this FlagValues object. - key_flags = self._GetFlagsDefinedByModule(module) - - # Take into account flags explicitly declared as key for a module. - for flag in self.KeyFlagsByModuleDict().get(module, []): - if flag not in key_flags: - key_flags.append(flag) - return key_flags - - def AppendFlagValues(self, flag_values): - """Appends flags registered in another FlagValues instance. - - Args: - flag_values: registry to copy from - """ - for flag_name, flag in flag_values.FlagDict().iteritems(): - # Each flags with shortname appears here twice (once under its - # normal name, and again with its short name). To prevent - # problems (DuplicateFlagError) with double flag registration, we - # perform a check to make sure that the entry we're looking at is - # for its normal name. - if flag_name == flag.name: - self[flag_name] = flag - - def __setitem__(self, name, flag): - """Registers 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 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 DuplicateFlagError(short_name, self) - fl[short_name] = flag - fl[name] = flag - global _exported_flags - _exported_flags[name] = flag - - def __getitem__(self, name): - """Retrieves the Flag object for the flag --name.""" - return self.FlagDict()[name] - - def __getattr__(self, name): - """Retrieves the 'value' attribute of the flag --name.""" - fl = self.FlagDict() - if not fl.has_key(name): - raise AttributeError(name) - return fl[name].value - - def __setattr__(self, name, value): - """Sets the 'value' attribute of the flag --name.""" - fl = self.FlagDict() - fl[name].value = value - return value - - def _FlagIsRegistered(self, flag_obj): - """Checks whether a Flag object is registered under some name. - - Note: this is non trivial: in addition to its normal name, a flag - may have a short name too. In self.FlagDict(), both the normal and - the short name are mapped to the same flag object. E.g., calling - only "del FLAGS.short_name" is not unregistering the corresponding - Flag object (it is still registered under the longer name). - - Args: - flag_obj: A Flag object. - - Returns: - A boolean: True iff flag_obj is registered under some name. - """ - flag_dict = self.FlagDict() - # Check whether flag_obj is registered under its long name. - name = flag_obj.name - if flag_dict.get(name, None) == flag_obj: - return True - # Check whether flag_obj is registered under its short name. - short_name = flag_obj.short_name - if (short_name is not None and - flag_dict.get(short_name, None) == flag_obj): - return True - # The flag cannot be registered under any other name, so we do not - # need to do a full search through the values of self.FlagDict(). - return False - - def __delattr__(self, flag_name): - """Deletes a previously-defined flag from a flag object. - - This method makes sure we can delete a flag by using - - del flag_values_object. - - E.g., - - flags.DEFINE_integer('foo', 1, 'Integer flag.') - del flags.FLAGS.foo - - Args: - flag_name: A string, the name of the flag to be deleted. - - Raises: - AttributeError: When there is no registered flag named flag_name. - """ - fl = self.FlagDict() - if flag_name not in fl: - raise AttributeError(flag_name) - - flag_obj = fl[flag_name] - del fl[flag_name] - - if not self._FlagIsRegistered(flag_obj): - # If the Flag object indicated by flag_name is no longer - # registered (please see the docstring of _FlagIsRegistered), then - # we delete the occurences of the flag object in all our internal - # dictionaries. - self.__RemoveFlagFromDictByModule(self.FlagsByModuleDict(), flag_obj) - self.__RemoveFlagFromDictByModule(self.KeyFlagsByModuleDict(), flag_obj) - - def __RemoveFlagFromDictByModule(self, flags_by_module_dict, flag_obj): - """Removes a flag object from a module -> list of flags dictionary. - - Args: - flags_by_module_dict: A dictionary that maps module names to lists of - flags. - flag_obj: A flag object. - """ - for unused_module, flags_in_module in flags_by_module_dict.iteritems(): - # while (as opposed to if) takes care of multiple occurences of a - # flag in the list for the same module. - while flag_obj in flags_in_module: - flags_in_module.remove(flag_obj) - - def SetDefault(self, name, value): - """Changes 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): - """Returns 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): - """Parses flags from argv; stores parsed flags into 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 - - 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) - - 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) # list() makes a copy - 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 += ":" - - 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: - if self.__dict__['__use_gnu_getopt']: - optlist, unparsed_args = getopt.gnu_getopt(args, shortopts, longopts) - else: - 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': - flag_names = arg.split(',') - undefok_flags.extend(flag_names) - # For boolean flags, if --undefok=boolflag is specified, then we should - # also accept --noboolflag, in addition to --boolflag. - # Since we don't know the type of the undefok'd flag, this will affect - # non-boolean flags as well. - # NOTE: You shouldn't use --undefok=noboolflag, because then we will - # accept --nonoboolflag here. We are choosing not to do the conversion - # from noboolflag -> boolflag because of the ambiguity that flag names - # can start with 'no'. - undefok_flags.extend('no' + name for name in flag_names) - continue - 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 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: - if self.__dict__['__use_gnu_getopt']: - # if using gnu_getopt just return the program name + remainder of argv. - return argv[:1] + unparsed_args - else: - # 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): - """Resets the values to the point before FLAGS(argv) was called.""" - for f in self.FlagDict().values(): - f.Unparse() - - def RegisteredFlags(self): - """Returns: a list of the names and short names of all registered flags.""" - return self.FlagDict().keys() - - def FlagValuesDict(self): - """Returns: a dictionary that maps flag names to flag 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): - """Generates a help string for all known flags.""" - return self.GetHelp() - - def GetHelp(self, prefix=''): - """Generates a help string for all known flags.""" - helplist = [] - - flags_by_module = self.FlagsByModuleDict() - 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.__RenderOurModuleFlags(module, helplist) - - self.__RenderModuleFlags('gflags', - _SPECIAL_FLAGS.FlagDict().values(), - helplist) - - else: - # Just print one long list of flags. - self.__RenderFlagList( - self.FlagDict().values() + _SPECIAL_FLAGS.FlagDict().values(), - helplist, prefix) - - return '\n'.join(helplist) - - def __RenderModuleFlags(self, module, flags, output_lines, prefix=""): - """Generates 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=""): - """Generates a help string for a given module.""" - flags = self._GetFlagsDefinedByModule(module) - if flags: - self.__RenderModuleFlags(module, flags, output_lines, prefix) - - def __RenderOurModuleKeyFlags(self, module, output_lines, prefix=""): - """Generates a help string for the key flags of a given module. - - Args: - module: A module object or a module name (a string). - output_lines: A list of strings. The generated help message - lines will be appended to this list. - prefix: A string that is prepended to each generated help line. - """ - key_flags = self._GetKeyFlagsForModule(module) - if key_flags: - self.__RenderModuleFlags(module, key_flags, output_lines, prefix) - - def MainModuleHelp(self): - """Returns: A string describing the key flags of the main module.""" - helplist = [] - self.__RenderOurModuleKeyFlags(_GetMainModule(), helplist) - return '\n'.join(helplist) - - 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 = {} - 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 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 = "" - 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 - flaghelp = TextWrap(flaghelp, indent=prefix+" ", - firstline_indent=prefix) - if flag.default_as_str: - flaghelp += "\n" - flaghelp += TextWrap("(default: %s)" % flag.default_as_str, - indent=prefix+" ") - if flag.parser.syntactic_help: - flaghelp += "\n" - flaghelp += TextWrap("(%s)" % flag.parser.syntactic_help, - indent=prefix+" ") - output_lines.append(flaghelp) - - def get(self, name, default): - """Returns the value of a flag (if not None) or a default value. - - Args: - name: A string, the name of a flag. - default: Default value to use if the flag 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: dictionary; maps 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): - """Checks whether flag_string contain a --flagfile= directive.""" - 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): - """Returns filename from a flagfile_str of form -[-]flagfile=filename. - - The cases of --flagfile foo and -flagfile foo shouldn't be hitting - this function, as they are dealt with in the level above this - function. - """ - 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) - - def __GetFlagFileLines(self, filename, parsed_file_list): - """Returns the useful (!=comments, etc) lines from a file with flags. - - Args: - filename: A string, the name of the flag file. - parsed_file_list: A list of the names of the files we have - already read. MUTATED BY THIS FUNCTION. - - Returns: - List of strings. See the note below. - - NOTE(springer): This function checks for a nested --flagfile= - tag and handles the lower file recursively. It returns a list of - 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=" 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, thus giving them higher priority. - flag_line_list.append(line.strip()) - return flag_line_list - - def ReadFlagsFromFiles(self, argv): - """Processes command line args, but also allow args to be read from file. - Args: - argv: A list of strings, usually sys.argv, which may contain one - or more flagfile directives of the form --flagfile="./filename". - - Returns: - - A new list which has the original list combined with what we read - from any flagfile(s). - - References: Global gflags.FLAG class instance. - - This function should be called before the normal FLAGS(argv) call. - This function scans the input list for a flag that looks like: - --flagfile=. Then it opens , 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): - --> Flags from the command line argv _should_ always take precedence! - --> A further "--flagfile=" 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. In this 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): - """Returns a string with the flags assignments from this FlagValues object. - - This function ignores flags whose value is None. Each flag - assignment is separated by a newline. - - NOTE: MUST mirror the behavior of the C++ function - CommandlineFlagsIntoString from google3/base/commandlineflags.cc. - """ - 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 assignments from this FlagInfo object to a file. - - Output will be in the format of a flagfile. - - NOTE: MUST mirror the behavior of the C++ version of - AppendFlagsIntoFile from google3/base/commandlineflags.cc. - """ - out_file = open(filename, 'a') - out_file.write(self.FlagsIntoString()) - out_file.close() - - def WriteHelpInXMLFormat(self, outfile=None): - """Outputs flag documentation in XML format. - - NOTE: We use element names that are consistent with those used by - the C++ command-line flag library, from - google3/base/commandlineflags_reporting.cc. We also use a few new - elements (e.g., ), but we do not interfere / overlap with - existing XML elements used by the C++ library. Please maintain this - consistency. - - Args: - outfile: File object we write to. Default None means sys.stdout. - """ - outfile = outfile or sys.stdout - - outfile.write('\n') - outfile.write('\n') - indent = ' ' - _WriteSimpleXMLElement(outfile, 'program', os.path.basename(sys.argv[0]), - indent) - - usage_doc = sys.modules['__main__'].__doc__ - if not usage_doc: - usage_doc = '\nUSAGE: %s [flags]\n' % sys.argv[0] - else: - usage_doc = usage_doc.replace('%s', sys.argv[0]) - _WriteSimpleXMLElement(outfile, 'usage', usage_doc, indent) - - # Get list of key flags for the main module. - key_flags = self._GetKeyFlagsForModule(_GetMainModule()) - - # Sort flags by declaring module name and next by flag name. - flags_by_module = self.FlagsByModuleDict() - all_module_names = list(flags_by_module.keys()) - all_module_names.sort() - for module_name in all_module_names: - flag_list = [(f.name, f) for f in flags_by_module[module_name]] - flag_list.sort() - for unused_flag_name, flag in flag_list: - is_key = flag in key_flags - flag.WriteInfoInXMLFormat(outfile, module_name, - is_key=is_key, indent=indent) - - outfile.write('\n') - outfile.flush() -# end of FlagValues definition - - -# The global FlagValues instance -FLAGS = FlagValues() - - -def _MakeXMLSafe(s): - """Escapes <, >, and & from s, and removes XML 1.0-illegal chars.""" - s = cgi.escape(s) # Escape <, >, and & - # Remove characters that cannot appear in an XML 1.0 document - # (http://www.w3.org/TR/REC-xml/#charsets). - # - # NOTE: if there are problems with current solution, one may move to - # XML 1.1, which allows such chars, if they're entity-escaped (&#xHH;). - s = re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f]', '', s) - return s - - -def _WriteSimpleXMLElement(outfile, name, value, indent): - """Writes a simple XML element. - - Args: - outfile: File object we write the XML element to. - name: A string, the name of XML element. - value: A Python object, whose string representation will be used - as the value of the XML element. - indent: A string, prepended to each line of generated output. - """ - value_str = str(value) - if isinstance(value, bool): - # Display boolean values as the C++ flag library does: no caps. - value_str = value_str.lower() - outfile.write('%s<%s>%s\n' % - (indent, name, _MakeXMLSafe(value_str), name)) - - -class Flag: - """Information about a command-line 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 attribute 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 attribute. This enables other python modules to - safely use flags even if the __main__ module neglects to parse the - command line arguments. The .present attribute is cleared after - __init__ parsing. If the default value is set to None, then the - __init__ parsing step is skipped and the .value attribute 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 - - 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 - - self.SetDefault(default) - - def __GetParsedValueAsString(self, value): - if value is None: - return None - if self.serializer: - return repr(self.serializer.Serialize(value)) - if self.boolean: - if value: - return repr('true') - else: - return repr('false') - 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: %s" % (self.name, e)) - self.present += 1 - - def Unparse(self): - if self.default is None: - self.value = None - else: - 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): - """Changes the default value (and current value too) for this Flag.""" - # 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 value is None and self.allow_override: - raise DuplicateFlag(self.name) - - self.default = value - self.Unparse() - self.default_as_str = self.__GetParsedValueAsString(self.value) - - def Type(self): - """Returns: a string that describes the type of this Flag.""" - # NOTE: we use strings, and not the types.*Type constants because - # our flags can have more exotic types, e.g., 'comma separated list - # of strings', 'whitespace separated list of strings', etc. - return self.parser.Type() - - def WriteInfoInXMLFormat(self, outfile, module_name, is_key=False, indent=''): - """Writes common info about this flag, in XML format. - - This is information that is relevant to all flags (e.g., name, - meaning, etc.). If you defined a flag that has some other pieces of - info, then please override _WriteCustomInfoInXMLFormat. - - Please do NOT override this method. - - Args: - outfile: File object we write to. - module_name: A string, the name of the module that defines this flag. - is_key: A boolean, True iff this flag is key for main module. - indent: A string that is prepended to each generated line. - """ - outfile.write(indent + '\n') - inner_indent = indent + ' ' - if is_key: - _WriteSimpleXMLElement(outfile, 'key', 'yes', inner_indent) - _WriteSimpleXMLElement(outfile, 'file', module_name, inner_indent) - # Print flag features that are relevant for all flags. - _WriteSimpleXMLElement(outfile, 'name', self.name, inner_indent) - if self.short_name: - _WriteSimpleXMLElement(outfile, 'short_name', self.short_name, - inner_indent) - if self.help: - _WriteSimpleXMLElement(outfile, 'meaning', self.help, inner_indent) - _WriteSimpleXMLElement(outfile, 'default', self.default, inner_indent) - _WriteSimpleXMLElement(outfile, 'current', self.value, inner_indent) - _WriteSimpleXMLElement(outfile, 'type', self.Type(), inner_indent) - # Print extra flag features this flag may have. - self._WriteCustomInfoInXMLFormat(outfile, inner_indent) - outfile.write(indent + '\n') - - def _WriteCustomInfoInXMLFormat(self, outfile, indent): - """Writes extra info about this flag, in XML format. - - "Extra" means "not already printed by WriteInfoInXMLFormat above." - - Args: - outfile: File object we write to. - indent: A string that is prepended to each generated line. - """ - # Usually, the parser knows the extra details about the flag, so - # we just forward the call to it. - self.parser.WriteCustomInfoInXMLFormat(outfile, indent) -# End of Flag definition - - -class ArgumentParser: - """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): - """Default implementation: always returns its argument unmodified.""" - return argument - - def Type(self): - return 'string' - - def WriteCustomInfoInXMLFormat(self, outfile, indent): - pass - - -class ArgumentSerializer: - """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 mode details in the module doc string. - - -def DEFINE(parser, name, default, help, flag_values=FLAGS, serializer=None, - **args): - """Registers a generic Flag object. - - NOTE: in the docstrings of all DEFINE* functions, "registers" is short - for "creates a new flag and registers it". - - Auxiliary function: clients should use the specialized DEFINE_ - function instead. - - Args: - parser: ArgumentParser that is used to parse the flag arguments. - name: A string, the flag name. - default: The default value of the flag. - help: A help string. - flag_values: FlagValues object the flag will be registered with. - serializer: ArgumentSerializer that serializes the flag value. - args: Dictionary with extra keyword args that are passes to the - Flag __init__. - """ - DEFINE_flag(Flag(parser, serializer, name, default, help, **args), - flag_values) - - -def DEFINE_flag(flag, flag_values=FLAGS): - """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 DEFINE_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 - # Tell flag_values who's defining the flag. - if isinstance(flag_values, FlagValues): - # Regarding the above isinstance test: some users pass funny - # values of flag_values (e.g., {}) in order to avoid the flag - # registration (in the past, there used to be a flag_values == - # FLAGS test here) and redefine flags with the same name (e.g., - # debug). To avoid breaking their code, we perform the - # registration only if flag_values is a real FlagValues object. - flag_values._RegisterFlagByModule(_GetCallingModule(), flag) - - -def _InternalDeclareKeyFlags(flag_names, flag_values=FLAGS): - """Declares a flag as key for the calling module. - - Internal function. User code should call DECLARE_key_flag or - ADOPT_module_key_flags instead. - - Args: - flag_names: A list of strings that are names of already-registered - Flag objects. - flag_values: A FlagValues object. This should almost never need - to be overridden. - - Raises: - UnrecognizedFlagError: when we refer to a flag that was not - defined yet. - """ - module = _GetCallingModule() - - for flag_name in flag_names: - if flag_name not in flag_values: - raise UnrecognizedFlagError(flag_name) - flag = flag_values.FlagDict()[flag_name] - flag_values._RegisterKeyFlagForModule(module, flag) - - -def DECLARE_key_flag(flag_name, flag_values=FLAGS): - """Declares one flag as key to the current module. - - Key flags are flags that are deemed really important for a module. - They are important when listing help messages; e.g., if the - --helpshort command-line flag is used, then only the key flags of the - main module are listed (instead of all flags, as in the case of - --help). - - Sample usage: - - flags.DECLARED_key_flag('flag_1') - - Args: - flag_name: A string, the name of an already declared flag. - (Redeclaring flags as key, including flags implicitly key - because they were declared in this module, is a no-op.) - flag_values: A FlagValues object. This should almost never - need to be overridden. - """ - _InternalDeclareKeyFlags([flag_name], flag_values=flag_values) - - -def ADOPT_module_key_flags(module, flag_values=FLAGS): - """Declares that all flags key to a module are key to the current module. - - Args: - module: A module object. - flag_values: A FlagValues object. This should almost never need - to be overridden. - - Raises: - FlagsError: When given an argument that is a module name (a - string), instead of a module object. - """ - # NOTE(salcianu): an even better test would be if not - # isinstance(module, types.ModuleType) but I didn't want to import - # types for such a tiny use. - if isinstance(module, str): - raise FlagsError('Received module name %s; expected a module object.' - % module) - _InternalDeclareKeyFlags( - [f.name for f in flag_values._GetKeyFlagsForModule(module.__name__)], - flag_values=flag_values) - - -# -# STRING FLAGS -# - - -def DEFINE_string(name, default, help, flag_values=FLAGS, **args): - """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 flags. - -class BooleanParser(ArgumentParser): - """Parser of boolean values.""" - - def Convert(self, argument): - """Converts the argument to a boolean; raise ValueError on errors.""" - if type(argument) == str: - if argument.lower() in ['true', 't', '1']: - return True - elif argument.lower() in ['false', 'f', '0']: - return False - - bool_argument = bool(argument) - if argument == bool_argument: - # The argument is a valid boolean (True, False, 0, or 1), and not just - # something that always converts to bool (list, string, int, etc.). - return bool_argument - - raise ValueError('Non-boolean argument to boolean flag', argument) - - def Parse(self, argument): - val = self.Convert(argument) - return val - - def Type(self): - return 'bool' - - -class BooleanFlag(Flag): - """Basic boolean flag. - - Boolean flags do not take any arguments, and their value is either - True (1) or False (0). The false value is specified on the command - line by prepending the word 'no' to either the long or the 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() - Flag.__init__(self, p, None, 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): - """Registers a boolean flag. - - Such a boolean flag 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, True or False. 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) - -# Match C++ API to unconfuse C++ people. -DEFINE_bool = DEFINE_boolean - -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 HelpXMLFlag(BooleanFlag): - """Similar to HelpFlag, but generates output in XML format.""" - - def __init__(self): - BooleanFlag.__init__(self, 'helpxml', False, - 'like --help, but generates XML output', - allow_override=1) - - def Parse(self, arg): - if arg: - FLAGS.WriteHelpInXMLFormat(sys.stdout) - 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): - """Parser of floating point values. - - Parsed value may be 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): - """Converts argument to a float; raises 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 Type(self): - return 'float' - - def WriteCustomInfoInXMLFormat(self, outfile, indent): - if self.lower_bound is not None: - _WriteSimpleXMLElement(outfile, 'lower_bound', self.lower_bound, indent) - if self.upper_bound is not None: - _WriteSimpleXMLElement(outfile, 'upper_bound', self.upper_bound, indent) -# End of FloatParser - - -def DEFINE_float(name, default, help, lower_bound=None, upper_bound=None, - flag_values=FLAGS, **args): - """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): - """Parser of an integer value. - - Parsed value may be bounded to a given upper and 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 Type(self): - return 'int' - - -def DEFINE_integer(name, default, help, lower_bound=None, upper_bound=None, - flag_values=FLAGS, **args): - """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): - """Parser of a string enum value (a string value from a given set). - - If enum_values (see below) is not specified, any string is allowed. - """ - - def __init__(self, enum_values=None): - self.enum_values = enum_values - - def Parse(self, argument): - 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 - - def Type(self): - return 'string enum' - - -class EnumFlag(Flag): - """Basic enum flag; its value can be any string from list of enum_values.""" - - def __init__(self, name, default, help, enum_values=None, - short_name=None, **args): - enum_values = enum_values or [] - 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 _WriteCustomInfoInXMLFormat(self, outfile, indent): - for enum_value in self.parser.enum_values: - _WriteSimpleXMLElement(outfile, 'enum_value', enum_value, indent) - - -def DEFINE_enum(name, default, enum_values, help, flag_values=FLAGS, - **args): - """Registers a flag whose value can be any string from enum_values.""" - DEFINE_flag(EnumFlag(name, default, help, enum_values, ** args), - flag_values) - - -# -# LIST FLAGS -# - - -class BaseListParser(ArgumentParser): - """Base class for a parser of lists of strings. - - To extend, inherit from this class; from the subclass __init__, 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 isinstance(argument, list): - return argument - elif argument == '': - return [] - else: - return [s.strip() for s in argument.split(self._token)] - - def Type(self): - return '%s separated list of strings' % self._name - - -class ListParser(BaseListParser): - """Parser for a comma-separated list of strings.""" - - def __init__(self): - BaseListParser.__init__(self, ',', 'comma') - - def WriteCustomInfoInXMLFormat(self, outfile, indent): - BaseListParser.WriteCustomInfoInXMLFormat(self, outfile, indent) - _WriteSimpleXMLElement(outfile, 'list_separator', repr(','), indent) - - -class WhitespaceSeparatedListParser(BaseListParser): - """Parser for a whitespace-separated list of strings.""" - - def __init__(self): - BaseListParser.__init__(self, None, 'whitespace') - - def WriteCustomInfoInXMLFormat(self, outfile, indent): - BaseListParser.WriteCustomInfoInXMLFormat(self, outfile, indent) - separators = list(string.whitespace) - separators.sort() - for ws_char in string.whitespace: - _WriteSimpleXMLElement(outfile, 'list_separator', repr(ws_char), indent) - - -def DEFINE_list(name, default, help, flag_values=FLAGS, **args): - """Registers a flag whose value is a comma-separated list of strings.""" - parser = ListParser() - serializer = ListSerializer(',') - DEFINE(parser, name, default, help, flag_values, serializer, **args) - - -def DEFINE_spaceseplist(name, default, help, flag_values=FLAGS, **args): - """Registers a flag whose value is a whitespace-separated list of strings. - - Any whitespace can be used as a separator. - """ - parser = WhitespaceSeparatedListParser() - serializer = ListSerializer(' ') - DEFINE(parser, name, default, help, flag_values, serializer, **args) - - -# -# MULTI FLAGS -# - - -class MultiFlag(Flag): - """A flag that can appear multiple time on the command-line. - - The value of such a flag is a list that contains the individual values - from all the appearances of that flag on the command-line. - - See the __doc__ for Flag for most behavior of this class. Only - differences in behavior are described here: - - * The default value may be either a single value or a list of values. - A single value is interpreted as the [value] singleton list. - - * 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 += ';\n repeat this option to specify a list of values' - - def Parse(self, arguments): - """Parses one or more arguments with the installed parser. - - Args: - arguments: a single argument or a list of arguments (typically a - list of default values); a single argument is 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 the 'value' attribute - 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 Type(self): - return 'multi ' + self.parser.Type() - - -def DEFINE_multi(parser, serializer, name, default, help, flag_values=FLAGS, - **args): - """Registers a generic MultiFlag that parses its args with a given parser. - - Auxiliary function. Normal users should NOT use it directly. - - 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): - """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): - """Registers a flag whose value can be a list of arbitrary 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()) -DEFINE_flag(HelpXMLFlag()) - -# 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) diff --git a/python/gflags2man.py b/python/gflags2man.py deleted file mode 100755 index f346564..0000000 --- a/python/gflags2man.py +++ /dev/null @@ -1,536 +0,0 @@ -#!/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. - -"""gflags2man runs a Google flags base program and generates a man page. - -Run the program, parse the output, and then format that into a man -page. - -Usage: - gflags2man [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__ = 'Dan Christian' - -import os -import re -import sys -import stat -import time - -import gflags - -_VERSION = '0.1' - - -def _GetDefaultDestDir(): - home = os.environ.get('HOME', '') - homeman = os.path.join(home, 'man', 'man1') - if home and os.path.exists(homeman): - return homeman - else: - return os.environ.get('TMPDIR', '/tmp') - -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 # 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. - Args: - filename An executable filename (string) - Returns: - Absolute version of filename. - None if filename could not be found locally, absolutely, or in PATH - """ - if os.path.isabs(filename): # already absolute - return filename - - if filename.startswith('./') or filename.startswith('../'): # relative - return os.path.abspath(filename) - - path = os.getenv('PATH', '') - for directory in path.split(':'): - tryname = os.path.join(directory, filename) - if os.path.exists(tryname): - if not os.path.isabs(directory): # relative directory - return os.path.abspath(tryname) - return tryname - if os.path.exists(filename): - return os.path.abspath(filename) - return None # could not determine - -class Flag(object): - """The information about a single flag.""" - - def __init__(self, flag_desc, help): - """Create the flag object. - Args: - flag_desc The command line forms this could take. (string) - help The help text (string) - """ - self.desc = flag_desc # the command line forms - self.help = help # the help text - self.default = '' # default value - self.tips = '' # parsing/syntax tips - - -class ProgramInfo(object): - """All the information gleaned from running a program with --help.""" - - # 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" - flag_py_re = re.compile(r'\s+(-\S+):\s+(.*)$') - # " (default: '0')" - flag_default_py_re = re.compile(r'\s+\(default:\s+\'(.*)\'\)$') - # " (an integer)" - flag_tips_py_re = re.compile(r'\s+\((.*)\)$') - - # 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" - flag_c_re = re.compile(r'\s+(-\S+)\s+(.*)$') - - # 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" - flag_java_re = re.compile(r'\s+(-\S+)\s+(.*)$') - - def __init__(self, executable): - """Create object with executable. - Args: - executable Program to execute (string) - """ - self.long_name = executable - 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 = time.localtime(time.time()) # default date info - - def Run(self): - """Run it and collect output. - - Returns: - 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 0 - - finfo = os.stat(self.executable) - self.date = time.localtime(finfo[stat.ST_MTIME]) - - logging.info('Running: %s %s &1' - % (self.executable, FLAGS.help_flag)) - # --help output is often routed to stderr, so we combine with stdout. - # Re-direct stdin to /dev/null to encourage programs that - # don't understand --help to exit. - (child_stdin, child_stdout_and_stderr) = os.popen4( - [self.executable, FLAGS.help_flag]) - child_stdin.close() # ' start_line+1 - and '' == self.output[start_line+1].rstrip()): - start_line += 2 - logging.debug('Flags start (python): %s' % line) - 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 (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 (start_line, 'c') - # java flags begin with a constant string - if line == 'where flags are': - logging.debug('Flags start (java): %s' % line) - start_line += 2 # skip "Standard flags:" - return (start_line, 'java') - - logging.debug('Desc: %s' % line) - self.desc.append(line) - after_blank = (line == '') - else: - logging.warn('Never found the start of the flags section for "%s"!' - % self.long_name) - return (-1, '') - - def ParsePythonFlags(self, start_line=0): - """Parse python/swig style flags.""" - modname = None # name of current module - modlist = [] - flag = None - for line_num in range(start_line, len(self.output)): # collect flags - line = self.output[line_num].rstrip() - if not line: # blank - continue - - mobj = self.module_py_re.match(line) - if mobj: # start of a new module - modname = mobj.group(1) - logging.debug('Module: %s' % line) - if flag: - modlist.append(flag) - self.module_list.append(modname) - self.modules.setdefault(modname, []) - modlist = self.modules[modname] - flag = None - continue - - mobj = self.flag_py_re.match(line) - if mobj: # start of a new flag - if flag: - modlist.append(flag) - logging.debug('Flag: %s' % line) - flag = Flag(mobj.group(1), mobj.group(2)) - continue - - if not flag: # continuation of a flag - logging.error('Flag info, but no current flag "%s"' % line) - mobj = self.flag_default_py_re.match(line) - if mobj: # (default: '...') - flag.default = mobj.group(1) - logging.debug('Fdef: %s' % line) - continue - mobj = self.flag_tips_py_re.match(line) - if mobj: # (tips) - flag.tips = mobj.group(1) - logging.debug('Ftip: %s' % line) - continue - if flag and flag.help: - flag.help += line # multiflags tack on an extra line - else: - logging.info('Extra: %s' % line) - if flag: - modlist.append(flag) - - def ParseCFlags(self, start_line=0): - """Parse C style flags.""" - modname = None # name of current module - modlist = [] - flag = None - 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) - flag = None - continue - - mobj = self.module_c_re.match(line) - if mobj: # start of a new module - modname = mobj.group(1) - logging.debug('Module: %s' % line) - if flag: - modlist.append(flag) - self.module_list.append(modname) - self.modules.setdefault(modname, []) - modlist = self.modules[modname] - flag = None - continue - - mobj = self.flag_c_re.match(line) - if mobj: # start of a new flag - if flag: # save last flag - modlist.append(flag) - logging.debug('Flag: %s' % line) - flag = Flag(mobj.group(1), mobj.group(2)) - continue - - # append to flag help. type and default are part of the main text - if flag: - flag.help += ' ' + line.strip() - else: - logging.info('Extra: %s' % line) - if flag: - modlist.append(flag) - - 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. - modname = 'Standard flags' # name of current module - self.module_list.append(modname) - self.modules.setdefault(modname, []) - modlist = self.modules[modname] - flag = None - - 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 - modlist.append(flag) - flag = None - continue - - mobj = self.module_java_re.match(line) - if mobj: # start of a new module - modname = mobj.group(1) - logging.debug('Module: %s' % line) - if flag: - modlist.append(flag) - self.module_list.append(modname) - self.modules.setdefault(modname, []) - modlist = self.modules[modname] - flag = None - continue - - mobj = self.flag_java_re.match(line) - if mobj: # start of a new flag - if flag: # save last flag - modlist.append(flag) - logging.debug('Flag: %s' % line) - flag = Flag(mobj.group(1), mobj.group(2)) - continue - - # append to flag help. type and default are part of the main text - if flag: - flag.help += ' ' + line.strip() - else: - logging.info('Extra: %s' % line) - if flag: - modlist.append(flag) - - def Filter(self): - """Filter parsed data to create derived fields.""" - if not self.desc: - self.short_desc = '' - return - - 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(' ') - all_names = [ self.name, self.short_name, ] - # Since the short_desc is always listed right after the name, - # trim it from the short_desc - while word_list and (word_list[0] in all_names - or word_list[0].lower() in all_names): - del word_list[0] - self.short_desc = '' # signal need to reconstruct - if not self.short_desc and word_list: - self.short_desc = ' '.join(word_list) - - -class GenerateDoc(object): - """Base class to output flags information.""" - - def __init__(self, proginfo, directory='.'): - """Create base object. - Args: - proginfo A ProgramInfo object - directory Directory to write output into - """ - self.info = proginfo - self.dirname = directory - - def Output(self): - """Output all sections of the page.""" - self.Open() - self.Header() - 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.""" - - def __init__(self, proginfo, directory='.'): - """Create base object. - Args: - proginfo A ProgramInfo object - directory Directory to write output into - """ - GenerateDoc.__init__(self, proginfo, directory) - - def Open(self): - if self.dirname == '-': - logging.info('Writing to stdout') - self.fp = sys.stdout - else: - self.file_path = '%s.1' % os.path.join(self.dirname, self.info.name) - logging.info('Writing: %s' % self.file_path) - self.fp = open(self.file_path, 'w') - - def Header(self): - self.fp.write( - '.\\" DO NOT MODIFY THIS FILE! It was generated by gflags2man %s\n' - % _VERSION) - self.fp.write( - '.TH %s "1" "%s" "%s" "User Commands"\n' - % (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( - '.SH SYNOPSIS\n.B %s\n[\\fIFLAGS\\fR]...\n' % self.info.name) - - def Body(self): - self.fp.write( - '.SH DESCRIPTION\n.\\" Add any additional description here\n.PP\n') - for ln in self.info.desc: - self.fp.write('%s\n' % ln) - self.fp.write( - '.SH OPTIONS\n') - # This shows flags in the original order - for modname in self.info.module_list: - if modname.find(self.info.executable) >= 0: - mod = modname.replace(self.info.executable, self.info.name) - else: - mod = modname - self.fp.write('\n.P\n.I %s\n' % mod) - for flag in self.info.modules[modname]: - help_string = flag.help - if flag.default or flag.tips: - help_string += '\n.br\n' - if flag.default: - help_string += ' (default: \'%s\')' % flag.default - if flag.tips: - help_string += ' (%s)' % flag.tips - self.fp.write( - '.TP\n%s\n%s\n' % (flag.desc, help_string)) - - def Footer(self): - self.fp.write( - '.SH COPYRIGHT\nCopyright \(co %s Google.\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 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: - print >>sys.stderr, __doc__ - print >>sys.stderr, "flags:" - print >>sys.stderr, str(FLAGS) - return 1 - - for arg in argv[1:]: - prog = ProgramInfo(arg) - if not prog.Run(): - continue - prog.Parse() - prog.Filter() - doc = GenerateMan(prog, FLAGS.dest_dir) - doc.Output() - return 0 - -if __name__ == '__main__': - main(sys.argv) diff --git a/python/gflags_helpxml_test.py b/python/gflags_helpxml_test.py deleted file mode 100755 index aea2ffb..0000000 --- a/python/gflags_helpxml_test.py +++ /dev/null @@ -1,563 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, 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. - -"""Unit tests for the XML-format help generated by the gflags.py module.""" - -__author__ = 'Alex Salcianu' - - -import string -import StringIO -import sys -import unittest -import xml.dom.minidom -import xml.sax.saxutils - -# 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 - -# For historic reasons, we use the name module_bar instead of test_module_bar -import test_module_bar as module_bar - -def MultiLineEqual(expected_help, help): - """Returns True if expected_help == help. Otherwise returns False - and logs the difference in a human-readable way. - """ - if help == expected_help: - return True - - 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." - - return False - - -class _MakeXMLSafeTest(unittest.TestCase): - - def _Check(self, s, expected_output): - self.assertEqual(flags._MakeXMLSafe(s), expected_output) - - def testMakeXMLSafe(self): - self._Check('plain text', 'plain text') - self._Check('(x < y) && (a >= b)', - '(x < y) && (a >= b)') - # Some characters with ASCII code < 32 are illegal in XML 1.0 and - # are removed by us. However, '\n', '\t', and '\r' are legal. - self._Check('\x09\x0btext \x02 with\x0dsome \x08 good & bad chars', - '\ttext with\rsome good & bad chars') - - -def _ListSeparatorsInXMLFormat(separators, indent=''): - """Generates XML encoding of a list of list separators. - - Args: - separators: A list of list separators. Usually, this should be a - string whose characters are the valid list separators, e.g., ',' - means that both comma (',') and space (' ') are valid list - separators. - indent: A string that is added at the beginning of each generated - XML element. - - Returns: - A string. - """ - result = '' - separators = list(separators) - separators.sort() - for sep_char in separators: - result += ('%s%s\n' % - (indent, repr(sep_char))) - return result - - -class WriteFlagHelpInXMLFormatTest(unittest.TestCase): - """Test the XML-format help for a single flag at a time. - - There is one test* method for each kind of DEFINE_* declaration. - """ - - def setUp(self): - # self.fv is a FlagValues object, just like flags.FLAGS. Each - # test registers one flag with this FlagValues. - self.fv = flags.FlagValues() - - def assertMultiLineEqual(self, expected, actual): - self.assert_(MultiLineEqual(expected, actual)) - - def _CheckFlagHelpInXML(self, flag_name, module_name, - expected_output, is_key=False): - # StringIO.StringIO is a file object that writes into a memory string. - sio = StringIO.StringIO() - flag_obj = self.fv[flag_name] - flag_obj.WriteInfoInXMLFormat(sio, module_name, is_key=is_key, indent=' ') - self.assertMultiLineEqual(sio.getvalue(), expected_output) - sio.close() - - def testFlagHelpInXML_Int(self): - flags.DEFINE_integer('index', 17, 'An integer flag', flag_values=self.fv) - expected_output_pattern = ( - ' \n' - ' module.name\n' - ' index\n' - ' An integer flag\n' - ' 17\n' - ' %d\n' - ' int\n' - ' \n') - self._CheckFlagHelpInXML('index', 'module.name', - expected_output_pattern % 17) - # Check that the output is correct even when the current value of - # a flag is different from the default one. - self.fv['index'].value = 20 - self._CheckFlagHelpInXML('index', 'module.name', - expected_output_pattern % 20) - - def testFlagHelpInXML_IntWithBounds(self): - flags.DEFINE_integer('nb_iters', 17, 'An integer flag', - lower_bound=5, upper_bound=27, - flag_values=self.fv) - expected_output = ( - ' \n' - ' yes\n' - ' module.name\n' - ' nb_iters\n' - ' An integer flag\n' - ' 17\n' - ' 17\n' - ' int\n' - ' 5\n' - ' 27\n' - ' \n') - self._CheckFlagHelpInXML('nb_iters', 'module.name', - expected_output, is_key=True) - - def testFlagHelpInXML_String(self): - flags.DEFINE_string('file_path', '/path/to/my/dir', 'A test string flag.', - flag_values=self.fv) - expected_output = ( - ' \n' - ' simple_module\n' - ' file_path\n' - ' A test string flag.\n' - ' /path/to/my/dir\n' - ' /path/to/my/dir\n' - ' string\n' - ' \n') - self._CheckFlagHelpInXML('file_path', 'simple_module', - expected_output) - - def testFlagHelpInXML_StringWithXMLIllegalChars(self): - flags.DEFINE_string('file_path', '/path/to/\x08my/dir', - 'A test string flag.', flag_values=self.fv) - # '\x08' is not a legal character in XML 1.0 documents. Our - # current code purges such characters from the generated XML. - expected_output = ( - ' \n' - ' simple_module\n' - ' file_path\n' - ' A test string flag.\n' - ' /path/to/my/dir\n' - ' /path/to/my/dir\n' - ' string\n' - ' \n') - self._CheckFlagHelpInXML('file_path', 'simple_module', - expected_output) - - def testFlagHelpInXML_Boolean(self): - flags.DEFINE_boolean('use_hack', False, 'Use performance hack', - flag_values=self.fv) - expected_output = ( - ' \n' - ' yes\n' - ' a_module\n' - ' use_hack\n' - ' Use performance hack\n' - ' false\n' - ' false\n' - ' bool\n' - ' \n') - self._CheckFlagHelpInXML('use_hack', 'a_module', - expected_output, is_key=True) - - def testFlagHelpInXML_Enum(self): - flags.DEFINE_enum('cc_version', 'stable', ['stable', 'experimental'], - 'Compiler version to use.', flag_values=self.fv) - expected_output = ( - ' \n' - ' tool\n' - ' cc_version\n' - ' <stable|experimental>: ' - 'Compiler version to use.\n' - ' stable\n' - ' stable\n' - ' string enum\n' - ' stable\n' - ' experimental\n' - ' \n') - self._CheckFlagHelpInXML('cc_version', 'tool', expected_output) - - def testFlagHelpInXML_CommaSeparatedList(self): - flags.DEFINE_list('files', 'a.cc,a.h,archive/old.zip', - 'Files to process.', flag_values=self.fv) - expected_output = ( - ' \n' - ' tool\n' - ' files\n' - ' Files to process.\n' - ' a.cc,a.h,archive/old.zip\n' - ' [\'a.cc\', \'a.h\', \'archive/old.zip\']\n' - ' comma separated list of strings\n' - ' \',\'\n' - ' \n') - self._CheckFlagHelpInXML('files', 'tool', expected_output) - - def testFlagHelpInXML_SpaceSeparatedList(self): - flags.DEFINE_spaceseplist('dirs', 'src libs bin', - 'Directories to search.', flag_values=self.fv) - expected_output = ( - ' \n' - ' tool\n' - ' dirs\n' - ' Directories to search.\n' - ' src libs bin\n' - ' [\'src\', \'libs\', \'bin\']\n' - ' whitespace separated list of strings\n' - 'LIST_SEPARATORS' - ' \n').replace('LIST_SEPARATORS', - _ListSeparatorsInXMLFormat(string.whitespace, - indent=' ')) - self._CheckFlagHelpInXML('dirs', 'tool', expected_output) - - def testFlagHelpInXML_MultiString(self): - flags.DEFINE_multistring('to_delete', ['a.cc', 'b.h'], - 'Files to delete', flag_values=self.fv) - expected_output = ( - ' \n' - ' tool\n' - ' to_delete\n' - ' Files to delete;\n ' - 'repeat this option to specify a list of values\n' - ' [\'a.cc\', \'b.h\']\n' - ' [\'a.cc\', \'b.h\']\n' - ' multi string\n' - ' \n') - self._CheckFlagHelpInXML('to_delete', 'tool', expected_output) - - def testFlagHelpInXML_MultiInt(self): - flags.DEFINE_multi_int('cols', [5, 7, 23], - 'Columns to select', flag_values=self.fv) - expected_output = ( - ' \n' - ' tool\n' - ' cols\n' - ' Columns to select;\n ' - 'repeat this option to specify a list of values\n' - ' [5, 7, 23]\n' - ' [5, 7, 23]\n' - ' multi int\n' - ' \n') - self._CheckFlagHelpInXML('cols', 'tool', expected_output) - - -# The next EXPECTED_HELP_XML_* constants are parts of a template for -# the expected XML output from WriteHelpInXMLFormatTest below. When -# we assemble these parts into a single big string, we'll take into -# account the ordering between the name of the main module and the -# name of module_bar. Next, we'll fill in the docstring for this -# module (%(usage_doc)s), the name of the main module -# (%(main_module_name)s) and the name of the module module_bar -# (%(module_bar_name)s). See WriteHelpInXMLFormatTest below. -# -# NOTE: given the current implementation of _GetMainModule(), we -# already know the ordering between the main module and module_bar. -# However, there is no guarantee that _GetMainModule will never be -# changed in the future (especially since it's far from perfect). -EXPECTED_HELP_XML_START = """\ - - - gflags_helpxml_test.py - %(usage_doc)s -""" - -EXPECTED_HELP_XML_FOR_FLAGS_FROM_MAIN_MODULE = """\ - - yes - %(main_module_name)s - cc_version - <stable|experimental>: Compiler version to use. - stable - stable - string enum - stable - experimental - - - yes - %(main_module_name)s - cols - Columns to select; - repeat this option to specify a list of values - [5, 7, 23] - [5, 7, 23] - multi int - - - yes - %(main_module_name)s - dirs - Directories to create. - src libs bins - ['src', 'libs', 'bins'] - whitespace separated list of strings -%(whitespace_separators)s - - yes - %(main_module_name)s - file_path - A test string flag. - /path/to/my/dir - /path/to/my/dir - string - - - yes - %(main_module_name)s - files - Files to process. - a.cc,a.h,archive/old.zip - ['a.cc', 'a.h', 'archive/old.zip'] - comma separated list of strings - \',\' - - - yes - %(main_module_name)s - index - An integer flag - 17 - 17 - int - - - yes - %(main_module_name)s - nb_iters - An integer flag - 17 - 17 - int - 5 - 27 - - - yes - %(main_module_name)s - to_delete - Files to delete; - repeat this option to specify a list of values - ['a.cc', 'b.h'] - ['a.cc', 'b.h'] - multi string - - - yes - %(main_module_name)s - use_hack - Use performance hack - false - false - bool - -""" - -EXPECTED_HELP_XML_FOR_FLAGS_FROM_MODULE_BAR = """\ - - %(module_bar_name)s - tmod_bar_t - Sample int flag. - 4 - 4 - int - - - yes - %(module_bar_name)s - tmod_bar_u - Sample int flag. - 5 - 5 - int - - - %(module_bar_name)s - tmod_bar_v - Sample int flag. - 6 - 6 - int - - - %(module_bar_name)s - tmod_bar_x - Boolean flag. - true - true - bool - - - %(module_bar_name)s - tmod_bar_y - String flag. - default - default - string - - - yes - %(module_bar_name)s - tmod_bar_z - Another boolean flag from module bar. - false - false - bool - -""" - -EXPECTED_HELP_XML_END = """\ - -""" - - -class WriteHelpInXMLFormatTest(unittest.TestCase): - """Big test of FlagValues.WriteHelpInXMLFormat, with several flags.""" - - def assertMultiLineEqual(self, expected, actual): - self.assert_(MultiLineEqual(expected, actual)) - - def testWriteHelpInXMLFormat(self): - fv = flags.FlagValues() - # Since these flags are defined by the top module, they are all key. - flags.DEFINE_integer('index', 17, 'An integer flag', flag_values=fv) - flags.DEFINE_integer('nb_iters', 17, 'An integer flag', - lower_bound=5, upper_bound=27, flag_values=fv) - flags.DEFINE_string('file_path', '/path/to/my/dir', 'A test string flag.', - flag_values=fv) - flags.DEFINE_boolean('use_hack', False, 'Use performance hack', - flag_values=fv) - flags.DEFINE_enum('cc_version', 'stable', ['stable', 'experimental'], - 'Compiler version to use.', flag_values=fv) - flags.DEFINE_list('files', 'a.cc,a.h,archive/old.zip', - 'Files to process.', flag_values=fv) - flags.DEFINE_spaceseplist('dirs', 'src libs bins', - 'Directories to create.', flag_values=fv) - flags.DEFINE_multistring('to_delete', ['a.cc', 'b.h'], - 'Files to delete', flag_values=fv) - flags.DEFINE_multi_int('cols', [5, 7, 23], - 'Columns to select', flag_values=fv) - # Define a few flags in a different module. - module_bar.DefineFlags(flag_values=fv) - # And declare only a few of them to be key. This way, we have - # different kinds of flags, defined in different modules, and not - # all of them are key flags. - flags.DECLARE_key_flag('tmod_bar_z', flag_values=fv) - flags.DECLARE_key_flag('tmod_bar_u', flag_values=fv) - - # Generate flag help in XML format in the StringIO sio. - sio = StringIO.StringIO() - fv.WriteHelpInXMLFormat(sio) - - # Check that we got the expected result. - expected_output_template = EXPECTED_HELP_XML_START - main_module_name = flags._GetMainModule() - module_bar_name = module_bar.__name__ - - if main_module_name < module_bar_name: - expected_output_template += EXPECTED_HELP_XML_FOR_FLAGS_FROM_MAIN_MODULE - expected_output_template += EXPECTED_HELP_XML_FOR_FLAGS_FROM_MODULE_BAR - else: - expected_output_template += EXPECTED_HELP_XML_FOR_FLAGS_FROM_MODULE_BAR - expected_output_template += EXPECTED_HELP_XML_FOR_FLAGS_FROM_MAIN_MODULE - - expected_output_template += EXPECTED_HELP_XML_END - - # XML representation of the whitespace list separators. - whitespace_separators = _ListSeparatorsInXMLFormat(string.whitespace, - indent=' ') - expected_output = ( - expected_output_template % - {'usage_doc': sys.modules['__main__'].__doc__, - 'main_module_name': main_module_name, - 'module_bar_name': module_bar_name, - 'whitespace_separators': whitespace_separators}) - - actual_output = sio.getvalue() - self.assertMultiLineEqual(actual_output, expected_output) - - # Also check that our result is valid XML. minidom.parseString - # throws an xml.parsers.expat.ExpatError in case of an error. - xml.dom.minidom.parseString(actual_output) - - -if __name__ == '__main__': - unittest.main() diff --git a/python/gflags_unittest.py b/python/gflags_unittest.py deleted file mode 100755 index 19cd286..0000000 --- a/python/gflags_unittest.py +++ /dev/null @@ -1,1573 +0,0 @@ -#!/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 gflags.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 - -# For historic reasons, we use the name module_foo instead of -# test_module_foo, and module_bar instead of test_module_bar. -import test_module_foo as module_foo -import test_module_bar as module_bar - -def MultiLineEqual(expected_help, help): - """Returns True if expected_help == help. Otherwise returns False - and logs the difference in a human-readable way. - """ - if help == expected_help: - return True - - 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." - - return False - - -class FlagsUnitTest(unittest.TestCase): - "Flags Unit Test" - - def setUp(self): - # make sure we are using the old, stupid way of parsing flags. - FLAGS.UseGnuGetOpt(False) - - def assertListEqual(self, list1, list2): - """Asserts that, when sorted, list1 and list2 are identical.""" - sorted_list1 = list1[:] - sorted_list2 = list2[:] - sorted_list1.sort() - sorted_list2.sort() - self.assertEqual(sorted_list1, sorted_list2) - - def assertMultiLineEqual(self, expected, actual): - self.assert_(MultiLineEqual(expected, actual)) - - - 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") - flags.DEFINE_list('letters', 'a,b,c', "a list of letters") - flags.DEFINE_list('numbers', [1, 2, 3], "a list of numbers") - flags.DEFINE_enum("kwery", None, ['who', 'what', 'why', 'where', 'when'], - "?") - - # Specify number of flags defined above. The short_name defined - # for 'repeat' counts as an extra flag. - number_defined_flags = 11 + 1 - self.assertEqual(len(FLAGS.RegisteredFlags()), - number_defined_flags + number_test_framework_flags) - - 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) - assert FLAGS.letters == ['a', 'b', 'c'], ("list default values not set:" - + FLAGS.letters) - assert FLAGS.numbers == [1, 2, 3], ("list default values not set:" - + FLAGS.numbers) - assert FLAGS.kwery is None, ("enum default None value not set:" - + FLAGS.kwery) - - 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 - assert flag_values['letters'] == ['a', 'b', 'c'] - assert flag_values['numbers'] == [1, 2, 3] - assert flag_values['kwery'] is None - - # 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'" - assert FLAGS['letters'].default_as_str == "'a,b,c'" - assert FLAGS['numbers'].default_as_str == "'1,2,3'" - - # 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 - self.assertEqual(len(FLAGS.RegisteredFlags()), - number_defined_flags + 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() - assert 'letters' in FLAGS.RegisteredFlags() - assert 'numbers' 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 - self.assertEqual(len(FLAGS.RegisteredFlags()), - number_defined_flags - 1 + 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 - FLAGS.Reset() - assert FLAGS['debug'].present == 0 - assert not FLAGS['debug'].value - - # Test that reset restores default value when default value is None. - argv = ('./program', '--kwery=who') - argv = FLAGS(argv) - assert len(argv) == 1, "wrong number of arguments pulled" - assert argv[0] == './program', "program name not preserved" - assert FLAGS['kwery'].present == 1 - assert FLAGS['kwery'].value == 'who' - FLAGS.Reset() - assert FLAGS['kwery'].present == 0 - assert FLAGS['kwery'].value == None - - # Test integer argument passing - argv = ('./program', '--x', '0x12345') - argv = FLAGS(argv) - self.assertEquals(FLAGS.x, 0x12345) - self.assertEquals(type(FLAGS.x), int) - - argv = ('./program', '--x', '0x1234567890ABCDEF1234567890ABCDEF') - argv = FLAGS(argv) - self.assertEquals(FLAGS.x, 0x1234567890ABCDEF1234567890ABCDEF) - 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(), - "--kwery None " - "--l 9223372032559808512 " - "--letters ['a', 'b', 'c'] " - "--m ['str1', 'str2'] --m_str ['str1', 'str2'] " - "--name giants " - "--numbers [1, 2, 3] " - "--repeat 3 " - "--s ['sing1'] --s_str ['sing1'] " - "--testget4 None --testlist [] " - "--testspacelist [] --x 10 " - "--noexec --quack " - "--test1 " - "--testget1 --no? --nodebug --nohelp --nohelpshort --nohelpxml " - "--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(), - "--kwery None " - "--l 9223372032559808512 " - "--letters ['a', 'b', 'c'] " - "--m ['str1', 'str2', 'upd1'] " - "--m_str ['str1', 'str2', 'upd1'] " - "--name giants " - "--numbers [1, 2, 3] " - "--repeat 3 " - "--s ['upd2'] --s_str ['upd2'] " - "--testget4 None --testlist [] " - "--testspacelist [] --x 10 " - "--debug --noexec --quack " - "--test1 " - "--testget1 --no? --nohelp --nohelpshort --nohelpxml " - "--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 - - # Duplicate short flag detection - try: - flags.DEFINE_boolean("zoom1", 0, "runhelp z1", short_name='z') - flags.DEFINE_boolean("zoom2", 0, "runhelp z2", short_name='z') - raise AssertionError("duplicate short flag detection failed") - except flags.DuplicateFlag, e: - self.assertTrue("The flag 'z' is defined twice. " in e.args[0]) - self.assertTrue("First from" in e.args[0]) - self.assertTrue(", Second from" in e.args[0]) - - # Duplicate mixed flag detection - try: - flags.DEFINE_boolean("short1", 0, "runhelp s1", short_name='s') - flags.DEFINE_boolean("s", 0, "runhelp s2") - raise AssertionError("duplicate mixed flag detection failed") - except flags.DuplicateFlag, e: - self.assertTrue("The flag 's' is defined twice. " in e.args[0]) - self.assertTrue("First from" in e.args[0]) - self.assertTrue(", Second from" in e.args[0]) - - # 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) - - # 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 works with flags with shortnames. - new_flags = flags.FlagValues() - flags.DEFINE_boolean("new3", 0, "runhelp n3", flag_values=new_flags) - flags.DEFINE_boolean("new4", 0, "runhelp n4", flag_values=new_flags, - short_name="n4") - self.assertEqual(len(new_flags.FlagDict()), 3) - old_len = len(FLAGS.FlagDict()) - FLAGS.AppendFlagValues(new_flags) - self.assertEqual(len(FLAGS.FlagDict())-old_len, 3) - self.assertTrue("new3" in FLAGS.FlagDict()) - self.assertTrue("new4" in FLAGS.FlagDict()) - self.assertTrue("n4" in FLAGS.FlagDict()) - self.assertEqual(FLAGS.FlagDict()['n4'], FLAGS.FlagDict()['new4']) - - # 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 raised:' - + str(FLAGS.repeat)) - except flags.IllegalFlagValue: - pass - - # Non-integer - try: - argv = ('./program', '--repeat=2.5') - FLAGS(argv) - raise AssertionError("malformed integer value exception not raised") - except flags.IllegalFlagValue: - pass - - # Missing required arugment - try: - argv = ('./program', '--name') - FLAGS(argv) - raise AssertionError("Flag argument required exception not raised") - except flags.FlagsError: - pass - - # Non-boolean arguments for boolean - try: - argv = ('./program', '--debug=goofup') - FLAGS(argv) - raise AssertionError("Illegal flag value exception not raised") - except flags.IllegalFlagValue: - pass - - try: - argv = ('./program', '--debug=42') - FLAGS(argv) - raise AssertionError("Illegal flag value exception not raised") - except flags.IllegalFlagValue: - pass - - - # Non-numeric argument for integer flag --repeat - try: - argv = ('./program', '--repeat', 'Bob', 'extra') - FLAGS(argv) - raise AssertionError("Illegal flag value exception not raised") - 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) - flags.DEFINE_list('UnitTestList', "1,2,3", 'Some list') - - def _UndeclareSomeFlags(self): - FLAGS.__delattr__('UnitTestMessage1') - FLAGS.__delattr__('UnitTestMessage2') - FLAGS.__delattr__('UnitTestBoolFlag') - FLAGS.__delattr__('UnitTestNumber') - FLAGS.__delattr__('UnitTestList') - - #### 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-referential 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_parse_flags_after_args_if_using_gnu_getopt(self): - """ - Test that flags given after arguments are parsed if using gnu_getopt. - """ - self.__DeclareSomeFlags() - FLAGS.UseGnuGetOpt() - fake_argv = ['fooScript', '--UnitTestBoolFlag', - 'command', '--UnitTestB'] - argv = FLAGS(fake_argv) - self.assertEqual(argv, ['fooScript', 'command']) - 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 the default to zero works correctly. - FLAGS['UnitTestNumber'].SetDefault(0) - self.assertEqual(FLAGS.UnitTestNumber, 0) - self.assertEqual(FLAGS['UnitTestNumber'].default_as_str, "'0'") - FLAGS([ 'dummyscript', '--UnitTestNumber=56' ]) - self.assertEqual(FLAGS.UnitTestNumber, 56) - - # Test that setting the default to "" works correctly. - FLAGS['UnitTestMessage1'].SetDefault("") - self.assertEqual(FLAGS.UnitTestMessage1, "") - self.assertEqual(FLAGS['UnitTestMessage1'].default_as_str, "''") - FLAGS([ 'dummyscript', '--UnitTestMessage1=fifty-six' ]) - self.assertEqual(FLAGS.UnitTestMessage1, "fifty-six") - - # Test that setting the default to false works correctly. - FLAGS['UnitTestBoolFlag'].SetDefault(False) - self.assertEqual(FLAGS.UnitTestBoolFlag, False) - self.assertEqual(FLAGS['UnitTestBoolFlag'].default_as_str, "'false'") - FLAGS([ 'dummyscript', '--UnitTestBoolFlag=true' ]) - self.assertEqual(FLAGS.UnitTestBoolFlag, True) - - # Test that setting a list default works correctly. - FLAGS['UnitTestList'].SetDefault('4,5,6') - self.assertEqual(FLAGS.UnitTestList, ['4', '5', '6']) - self.assertEqual(FLAGS['UnitTestList'].default_as_str, "'4,5,6'") - FLAGS([ 'dummyscript', '--UnitTestList=7,8,9' ]) - self.assertEqual(FLAGS.UnitTestList, ['7', '8', '9']) - - # 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') - - 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). - # - This requires gnu_getopt from Python 2.3+ see FLAGS.UseGnuGetOpt() - - 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" - - # Allow unknown flag --noboolflag if undefok=boolflag is specified - argv = ('./program', '--noboolflag', '--name=Bob', - '--undefok=boolflag', '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 - 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 - --[no]helpxml: like --help, but generates XML output - --kwery: : ? - --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') - --numbers: a list of numbers - (default: '1,2,3') - (a comma separated list) - --[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 not MultiLineEqual(expected_help, help): - 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 testFlagValuesDelAttr(self): - """Checks that del FLAGS.flag_id works.""" - default_value = 'default value for testFlagValuesDelAttr' - # 1. Declare and delete a flag with no short name. - flags.DEFINE_string('delattr_foo', default_value, 'A simple flag.') - self.assertEquals(FLAGS.delattr_foo, default_value) - flag_obj = FLAGS['delattr_foo'] - # We also check that _FlagIsRegistered works as expected :) - self.assertTrue(FLAGS._FlagIsRegistered(flag_obj)) - del FLAGS.delattr_foo - self.assertFalse('delattr_foo' in FLAGS.FlagDict()) - self.assertFalse(FLAGS._FlagIsRegistered(flag_obj)) - # If the previous del FLAGS.delattr_foo did not work properly, the - # next definition will trigger a redefinition error. - flags.DEFINE_integer('delattr_foo', 3, 'A simple flag.') - del FLAGS.delattr_foo - - self.assertFalse('delattr_foo' in FLAGS.RegisteredFlags()) - - # 2. Declare and delete a flag with a short name. - flags.DEFINE_string('delattr_bar', default_value, 'flag with short name', - short_name='x5') - flag_obj = FLAGS['delattr_bar'] - self.assertTrue(FLAGS._FlagIsRegistered(flag_obj)) - del FLAGS.x5 - self.assertTrue(FLAGS._FlagIsRegistered(flag_obj)) - del FLAGS.delattr_bar - self.assertFalse(FLAGS._FlagIsRegistered(flag_obj)) - - # 3. Just like 2, but del FLAGS.name last - flags.DEFINE_string('delattr_bar', default_value, 'flag with short name', - short_name='x5') - flag_obj = FLAGS['delattr_bar'] - self.assertTrue(FLAGS._FlagIsRegistered(flag_obj)) - del FLAGS.delattr_bar - self.assertTrue(FLAGS._FlagIsRegistered(flag_obj)) - del FLAGS.x5 - self.assertFalse(FLAGS._FlagIsRegistered(flag_obj)) - - self.assertFalse('delattr_bar' in FLAGS.RegisteredFlags()) - self.assertFalse('x5' in FLAGS.RegisteredFlags()) - - def _GetNamesOfDefinedFlags(self, module, flag_values=FLAGS): - """Returns the list of names of flags defined by a module. - - Auxiliary for the testKeyFlags* methods. - - Args: - module: A module object or a string module name. - flag_values: A FlagValues object. - - Returns: - A list of strings. - """ - return [f.name for f in flag_values._GetFlagsDefinedByModule(module)] - - def _GetNamesOfKeyFlags(self, module, flag_values=FLAGS): - """Returns the list of names of key flags for a module. - - Auxiliary for the testKeyFlags* methods. - - Args: - module: A module object or a string module name. - flag_values: A FlagValues object. - - Returns: - A list of strings. - """ - return [f.name for f in flag_values._GetKeyFlagsForModule(module)] - - def testKeyFlags(self): - # Before starting any testing, make sure no flags are already - # defined for module_foo and module_bar. - self.assertListEqual(self._GetNamesOfKeyFlags(module_foo), []) - self.assertListEqual(self._GetNamesOfKeyFlags(module_bar), []) - self.assertListEqual(self._GetNamesOfDefinedFlags(module_foo), []) - self.assertListEqual(self._GetNamesOfDefinedFlags(module_bar), []) - - try: - # Defines a few flags in module_foo and module_bar. - module_foo.DefineFlags() - - # Part 1. Check that all flags defined by module_foo are key for - # that module, and similarly for module_bar. - for module in [module_foo, module_bar]: - self.assertListEqual(FLAGS._GetFlagsDefinedByModule(module), - FLAGS._GetKeyFlagsForModule(module)) - # Also check that each module defined the expected flags. - self.assertListEqual(self._GetNamesOfDefinedFlags(module), - module.NamesOfDefinedFlags()) - - # Part 2. Check that flags.DECLARE_key_flag works fine. - # Declare that some flags from module_bar are key for - # module_foo. - module_foo.DeclareKeyFlags() - - # Check that module_foo has the expected list of defined flags. - self.assertListEqual(self._GetNamesOfDefinedFlags(module_foo), - module_foo.NamesOfDefinedFlags()) - - # Check that module_foo has the expected list of key flags. - self.assertListEqual(self._GetNamesOfKeyFlags(module_foo), - module_foo.NamesOfDeclaredKeyFlags()) - - # Part 3. Check that flags.ADOPT_module_key_flags works fine. - # Trigger a call to flags.ADOPT_module_key_flags(module_bar) - # inside module_foo. This should declare a few more key - # flags in module_foo. - module_foo.DeclareExtraKeyFlags() - - # Check that module_foo has the expected list of key flags. - self.assertListEqual(self._GetNamesOfKeyFlags(module_foo), - module_foo.NamesOfDeclaredKeyFlags() + - module_foo.NamesOfDeclaredExtraKeyFlags()) - finally: - module_foo.RemoveFlags() - - def testKeyFlagsWithNonDefaultFlagValuesObject(self): - # Check that key flags work even when we use a FlagValues object - # that is not the default flags.FLAGS object. Otherwise, this - # test is similar to testKeyFlags, but it uses only module_bar. - # The other test module (module_foo) uses only the default values - # for the flag_values keyword arguments. This way, testKeyFlags - # and this method test both the default FlagValues, the explicitly - # specified one, and a mixed usage of the two. - - # A brand-new FlagValues object, to use instead of flags.FLAGS. - fv = flags.FlagValues() - - # Before starting any testing, make sure no flags are already - # defined for module_foo and module_bar. - self.assertListEqual( - self._GetNamesOfKeyFlags(module_bar, flag_values=fv), - []) - self.assertListEqual( - self._GetNamesOfDefinedFlags(module_bar, flag_values=fv), - []) - - module_bar.DefineFlags(flag_values=fv) - - # Check that all flags defined by module_bar are key for that - # module, and that module_bar defined the expected flags. - self.assertListEqual(fv._GetFlagsDefinedByModule(module_bar), - fv._GetKeyFlagsForModule(module_bar)) - self.assertListEqual( - self._GetNamesOfDefinedFlags(module_bar, flag_values=fv), - module_bar.NamesOfDefinedFlags()) - - # Pick two flags from module_bar, declare them as key for the - # current (i.e., main) module (via flags.DECLARE_key_flag), and - # check that we get the expected effect. The important thing is - # that we always use flags_values=fv (instead of the default - # FLAGS). - main_module = flags._GetMainModule() - names_of_flags_defined_by_bar = module_bar.NamesOfDefinedFlags() - flag_name_0 = names_of_flags_defined_by_bar[0] - flag_name_2 = names_of_flags_defined_by_bar[2] - - flags.DECLARE_key_flag(flag_name_0, flag_values=fv) - self.assertListEqual( - self._GetNamesOfKeyFlags(main_module, flag_values=fv), - [flag_name_0]) - - flags.DECLARE_key_flag(flag_name_2, flag_values=fv) - self.assertListEqual( - self._GetNamesOfKeyFlags(main_module, flag_values=fv), - [flag_name_0, flag_name_2]) - - flags.ADOPT_module_key_flags(module_bar, flag_values=fv) - key_flags = self._GetNamesOfKeyFlags(main_module, flag_values=fv) - # Order is irrelevant; hence, we sort both lists before comparison. - key_flags.sort() - names_of_flags_defined_by_bar.sort() - self.assertListEqual(key_flags, names_of_flags_defined_by_bar) - - def testMainModuleHelpWithKeyFlags(self): - # Similar to test_main_module_help, but this time we make sure to - # declare some key flags. - try: - help_flag_help = ( - " -?,--[no]help: show this help\n" - " --[no]helpshort: show usage only for this module\n" - " --[no]helpxml: like --help, but generates XML output" - ) - - expected_help = "\n%s:\n%s" % (sys.argv[0], help_flag_help) - - # Safety check that the main module does not declare any flags - # at the beginning of this test. - self.assertMultiLineEqual(expected_help, FLAGS.MainModuleHelp()) - - # Define one flag in this main module and some flags in modules - # a and b. Also declare one flag from module a and one flag - # from module b as key flags for the main module. - flags.DEFINE_integer('main_module_int_fg', 1, - 'Integer flag in the main module.') - - main_module_int_fg_help = ( - " --main_module_int_fg: Integer flag in the main module.\n" - " (default: '1')\n" - " (an integer)") - - expected_help += "\n" + main_module_int_fg_help - self.assertMultiLineEqual(expected_help, FLAGS.MainModuleHelp()) - - # The following call should be a no-op: any flag declared by a - # module is automatically key for that module. - flags.DECLARE_key_flag('main_module_int_fg') - self.assertMultiLineEqual(expected_help, FLAGS.MainModuleHelp()) - - # The definition of a few flags in an imported module should not - # change the main module help. - module_foo.DefineFlags() - self.assertMultiLineEqual(expected_help, FLAGS.MainModuleHelp()) - - flags.DECLARE_key_flag('tmod_foo_bool') - tmod_foo_bool_help = ( - " --[no]tmod_foo_bool: Boolean flag from module foo.\n" - " (default: 'true')") - expected_help += "\n" + tmod_foo_bool_help - self.assertMultiLineEqual(expected_help, FLAGS.MainModuleHelp()) - - flags.DECLARE_key_flag('tmod_bar_z') - tmod_bar_z_help = ( - " --[no]tmod_bar_z: Another boolean flag from module bar.\n" - " (default: 'false')") - # Unfortunately, there is some flag sorting inside - # MainModuleHelp, so we can't keep incrementally extending - # the expected_help string ... - expected_help = ("\n%s:\n%s\n%s\n%s\n%s" % - (sys.argv[0], - help_flag_help, - main_module_int_fg_help, - tmod_bar_z_help, - tmod_foo_bool_help)) - self.assertMultiLineEqual(FLAGS.MainModuleHelp(), expected_help) - - finally: - # At the end, delete all the flag information we created. - FLAGS.__delattr__('main_module_int_fg') - module_foo.RemoveFlags() - - def test_ADOPT_module_key_flags(self): - # Check that ADOPT_module_key_flags raises an exception when - # called with a module name (as opposed to a module object). - self.assertRaises(flags.FlagsError, - flags.ADOPT_module_key_flags, - 'google3.pyglib.app') - - def test_GetCallingModule(self): - self.assertEqual(flags._GetCallingModule(), sys.argv[0]) - self.assertEqual( - module_foo.GetModuleName(), - 'test_module_foo') - self.assertEqual( - module_bar.GetModuleName(), - 'test_module_bar') - - # We execute the following exec statements for their side-effect - # (i.e., not raising an error). They emphasize the case that not - # all code resides in one of the imported modules: Python is a - # really dynamic language, where we can dynamically construct some - # code and execute it. - code = ("import gflags\n" - "module_name = gflags._GetCallingModule()") - exec code - - # Next two exec statements executes code with a global environment - # that is different from the global environment of any imported - # module. - exec code in {} - # vars(self) returns a dictionary corresponding to the symbol - # table of the self object. dict(...) makes a distinct copy of - # this dictionary, such that any new symbol definition by the - # exec-ed code (e.g., import flags, module_name = ...) does not - # affect the symbol table of self. - exec code in dict(vars(self)) - - # Next test is actually more involved: it checks not only that - # _GetCallingModule does not crash inside exec code, it also checks - # that it returns the expected value: the code executed via exec - # code is treated as being executed by the current module. We - # check it twice: first time by executing exec from the main - # module, second time by executing it from module_bar. - global_dict = {} - exec code in global_dict - self.assertEqual(global_dict['module_name'], - sys.argv[0]) - - global_dict = {} - module_bar.ExecuteCode(code, global_dict) - self.assertEqual( - global_dict['module_name'], - 'test_module_bar') - - -def main(): - unittest.main() - - -if __name__ == '__main__': - main() diff --git a/python/setup.py b/python/setup.py deleted file mode 100755 index f82c4fb..0000000 --- a/python/setup.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/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. - -from distutils.core import setup - -setup(name='gflags', - version='0.8', - 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=[("bin", ["gflags2man.py"])]) diff --git a/python/test_module_bar.py b/python/test_module_bar.py deleted file mode 100755 index 55541ff..0000000 --- a/python/test_module_bar.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, 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. - -"""Auxiliary module for testing flags.py. - -The purpose of this module is to define a few flags. We want to make -sure the unit tests for flags.py involve more than one module. -""" - -__author__ = 'Alex Salcianu' - -__pychecker__ = "no-local" # for 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 - - -def DefineFlags(flag_values=FLAGS): - """Defines some flags. - - Args: - flag_values: The FlagValues object we want to register the flags - with. - """ - # The 'tmod_bar_' prefix (short for 'test_module_bar') ensures there - # is no name clash with the existing flags. - flags.DEFINE_boolean('tmod_bar_x', True, 'Boolean flag.', - flag_values=flag_values) - flags.DEFINE_string('tmod_bar_y', 'default', 'String flag.', - flag_values=flag_values) - flags.DEFINE_boolean('tmod_bar_z', False, - 'Another boolean flag from module bar.', - flag_values=flag_values) - flags.DEFINE_integer('tmod_bar_t', 4, 'Sample int flag.', - flag_values=flag_values) - flags.DEFINE_integer('tmod_bar_u', 5, 'Sample int flag.', - flag_values=flag_values) - flags.DEFINE_integer('tmod_bar_v', 6, 'Sample int flag.', - flag_values=flag_values) - - -def RemoveOneFlag(flag_name, flag_values=FLAGS): - """Removes the definition of one flag from flags.FLAGS. - - Note: if the flag is not defined in flags.FLAGS, this function does - not do anything (in particular, it does not raise any exception). - - Motivation: We use this function for cleanup *after* a test: if - there was a failure during a test and not all flags were declared, - we do not want the cleanup code to crash. - - Args: - flag_name: A string, the name of the flag to delete. - flag_values: The FlagValues object we remove the flag from. - """ - if flag_name in flag_values.FlagDict(): - flag_values.__delattr__(flag_name) - - -def NamesOfDefinedFlags(): - """Returns: List of names of the flags declared in this module.""" - return ['tmod_bar_x', - 'tmod_bar_y', - 'tmod_bar_z', - 'tmod_bar_t', - 'tmod_bar_u', - 'tmod_bar_v'] - - -def RemoveFlags(flag_values=FLAGS): - """Deletes the flag definitions done by the above DefineFlags(). - - Args: - flag_values: The FlagValues object we remove the flags from. - """ - for flag_name in NamesOfDefinedFlags(): - RemoveOneFlag(flag_name, flag_values=flag_values) - - -def GetModuleName(): - """Uses flags._GetCallingModule() to return the name of this module. - - For checking that _GetCallingModule works as expected. - - Returns: - A string, the name of this module. - """ - # Calling the protected _GetCallingModule generates a lint warning, - # but we do not have any other alternative to test that function. - return flags._GetCallingModule() - - -def ExecuteCode(code, global_dict): - """Executes some code in a given global environment. - - For testing of _GetCallingModule. - - Args: - code: A string, the code to be executed. - global_dict: A dictionary, the global environment that code should - be executed in. - """ - # Indeed, using exec generates a lint warning. But some user code - # actually uses exec, and we have to test for it ... - exec code in global_dict diff --git a/python/test_module_foo.py b/python/test_module_foo.py deleted file mode 100755 index 9f2ab49..0000000 --- a/python/test_module_foo.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, 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. - -"""Auxiliary module for testing flags.py. - -The purpose of this module is to define a few flags, and declare some -other flags as being important. We want to make sure the unit tests -for flags.py involve more than one module. -""" - -__author__ = 'Alex Salcianu' - -__pychecker__ = "no-local" # for 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 - -# For historical reasons we use the name module_bar instead of test_module_bar. -import test_module_bar as module_bar - -DECLARED_KEY_FLAGS = ['tmod_bar_x', 'tmod_bar_z', 'tmod_bar_t'] - - -def DefineFlags(): - """Defines a few flags.""" - module_bar.DefineFlags() - # The 'tmod_foo_' prefix (short for 'test_module_foo') ensures that we - # have no name clash with existing flags. - flags.DEFINE_boolean('tmod_foo_bool', True, 'Boolean flag from module foo.') - flags.DEFINE_string('tmod_foo_str', 'default', 'String flag.') - flags.DEFINE_integer('tmod_foo_int', 3, 'Sample int flag.') - - -def DeclareKeyFlags(): - """Declares a few key flags.""" - for flag_name in DECLARED_KEY_FLAGS: - flags.DECLARE_key_flag(flag_name) - - -def DeclareExtraKeyFlags(): - """Declares some extra key flags.""" - flags.ADOPT_module_key_flags(module_bar) - - -def NamesOfDefinedFlags(): - """Returns: list of names of flags defined by this module.""" - return ['tmod_foo_bool', 'tmod_foo_str', 'tmod_foo_int'] - - -def NamesOfDeclaredKeyFlags(): - """Returns: list of names of key flags for this module.""" - return NamesOfDefinedFlags() + DECLARED_KEY_FLAGS - - -def NamesOfDeclaredExtraKeyFlags(): - """Returns the list of names of additional key flags for this module. - - These are the flags that became key for this module only as a result - of a call to DeclareExtraKeyFlags() above. I.e., the flags declared - by module_bar, that were not already declared as key for this - module. - - Returns: - The list of names of additional key flags for this module. - """ - names_of_extra_key_flags = list(module_bar.NamesOfDefinedFlags()) - for flag_name in NamesOfDeclaredKeyFlags(): - while flag_name in names_of_extra_key_flags: - names_of_extra_key_flags.remove(flag_name) - return names_of_extra_key_flags - - -def RemoveFlags(): - """Deletes the flag definitions done by the above DefineFlags().""" - for flag_name in NamesOfDefinedFlags(): - module_bar.RemoveOneFlag(flag_name) - module_bar.RemoveFlags() - - -def GetModuleName(): - """Uses flags._GetCallingModule() to return the name of this module. - - For checking that _GetCallingModule works as expected. - - Returns: - A string, the name of this module. - """ - # Calling the protected _GetCallingModule generates a lint warning, - # but we do not have any other alternative to test that function. - return flags._GetCallingModule() diff --git a/src/gflags.cc b/src/gflags.cc index 7c251b0..e1d5294 100644 --- a/src/gflags.cc +++ b/src/gflags.cc @@ -144,13 +144,6 @@ # define PRIu64 "llu" #endif -using std::string; -using std::map; -using std::vector; -using std::pair; -using std::cerr; -using std::sort; - // Special flags, type 1: the 'recursive' flags. They set another flag's val. DEFINE_string(flagfile, "", "load flags from file"); @@ -169,6 +162,13 @@ DEFINE_string(undefok, "", _START_GOOGLE_NAMESPACE_ +using std::cerr; +using std::map; +using std::pair; +using std::sort; +using std::string; +using std::vector; + // 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 diff --git a/src/gflags_completions.cc b/src/gflags_completions.cc index 31f5f32..92ab4f3 100644 --- a/src/gflags_completions.cc +++ b/src/gflags_completions.cc @@ -60,10 +60,6 @@ #include -using std::set; -using std::string; -using std::vector; - #ifndef PATH_SEPARATOR #define PATH_SEPARATOR '/' #endif @@ -79,6 +75,10 @@ _START_GOOGLE_NAMESPACE_ namespace { +using std::set; +using std::string; +using std::vector; + // Function prototypes and Type forward declarations. Code may be // more easily understood if it is roughly ordered according to // control flow, rather than by C's "declare before use" ordering diff --git a/src/gflags_reporting.cc b/src/gflags_reporting.cc index 0185f9f..dd98dbc 100644 --- a/src/gflags_reporting.cc +++ b/src/gflags_reporting.cc @@ -62,9 +62,6 @@ #define PATH_SEPARATOR '/' #endif -using std::string; -using std::vector; - // The 'reporting' flags. They all call exit(). DEFINE_bool(help, false, "show help on all flags [tip: all flags can have two dashes]"); @@ -85,6 +82,9 @@ DEFINE_bool(version, false, _START_GOOGLE_NAMESPACE_ +using std::string; +using std::vector; + // -------------------------------------------------------------------- // DescribeOneFlag() // DescribeOneFlagInXML() diff --git a/src/gflags_unittest.cc b/src/gflags_unittest.cc index 32ae9b3..d547c37 100644 --- a/src/gflags_unittest.cc +++ b/src/gflags_unittest.cc @@ -47,18 +47,17 @@ #include // for isinf() and isnan() #include #include + #include // I don't actually use this header file, but #include it under the // old location to make sure that the include-header-forwarding // works. But don't bother on windows; the windows port is so new // it never had the old location-names. -#ifndef _WIN32 +#ifndef _MSC_VER #include void (*unused_fn)() = &GOOGLE_NAMESPACE::HandleCommandLineCompletions; #endif -using std::vector; -using std::string; using GOOGLE_NAMESPACE::int32; using GOOGLE_NAMESPACE::FlagRegisterer; using GOOGLE_NAMESPACE::StringFromEnv; @@ -94,9 +93,13 @@ void setenv(const char* name, const char* value, int) { DECLARE_string(tryfromenv); // in gflags.cc DEFINE_string(test_tmpdir, "/tmp/gflags_unittest", "Dir we use for temp files"); +#ifdef _MSC_VER // in MSVC, we run from the vsprojects directory +DEFINE_string(srcdir, "..\\..", + "Source-dir root, needed to find gflags_unittest_flagfile"); +#else DEFINE_string(srcdir, StringFromEnv("SRCDIR", "."), "Source-dir root, needed to find gflags_unittest_flagfile"); - +#endif DEFINE_bool(test_bool, false, "tests bool-ness"); DEFINE_int32(test_int32, -1, ""); @@ -128,8 +131,8 @@ static int changeable_bool_var = 8008; DEFINE_bool(changeable_bool_var, ++changeable_bool_var == 8009, ""); static int changeable_string_var = 0; -static string ChangeableString() { - char r[] = {'0' + ++changeable_string_var, '\0'}; +static std::string ChangeableString() { + char r[] = {static_cast('0' + ++changeable_string_var), '\0'}; return r; } DEFINE_string(changeable_string_var, ChangeableString(), ""); @@ -151,14 +154,14 @@ DEFINE_bool(changed_bool2, false, "changed"); static bool AlwaysFail(const char* flag, bool value) { return value == false; } DEFINE_bool(always_fail, false, "will fail to validate when you set it"); -static const bool dummy = RegisterFlagValidator(&FLAGS_always_fail, AlwaysFail); +static bool dummy = RegisterFlagValidator(&FLAGS_always_fail, AlwaysFail); // See the comment by GetAllFlags in commandlineflags.h static bool DeadlockIfCantLockInValidators(const char* flag, bool value) { if (!value) { return true; } - vector dummy; + std::vector dummy; GetAllFlags(&dummy); return true; } @@ -166,8 +169,8 @@ DEFINE_bool(deadlock_if_cant_lock, false, "will deadlock if set to true and " "if locking of registry in validators fails."); -static const bool dummy1 = RegisterFlagValidator(&FLAGS_deadlock_if_cant_lock, - DeadlockIfCantLockInValidators); +static bool dummy1 = RegisterFlagValidator(&FLAGS_deadlock_if_cant_lock, + DeadlockIfCantLockInValidators); // This is a pseudo-flag -- we want to register a flag with a filename // at the top level, but there is no way to do this except by faking @@ -196,6 +199,9 @@ using fLI::FLAGS_tldflag2; _START_GOOGLE_NAMESPACE_ +using std::string; +using std::vector; + // The following is some bare-bones testing infrastructure #define EXPECT_TRUE(cond) \ @@ -308,6 +314,26 @@ static int RUN_ALL_TESTS() { } +static string TmpFile(const string& basename) { +#ifdef _MSC_VER + return FLAGS_test_tmpdir + "\\" + basename; +#else + return FLAGS_test_tmpdir + "/" + basename; +#endif +} + +// Returns the definition of the --flagfile flag to be used in the tests. +static const char* GetFlagFileFlag() { +#ifdef _MSC_VER + static const string flagfile = FLAGS_srcdir + "\\src\\gflags_unittest_flagfile"; +#else + static const string flagfile = FLAGS_srcdir + "/src/gflags_unittest_flagfile"; +#endif + static const string flagfile_flag = string("--flagfile=") + flagfile; + return flagfile_flag.c_str(); +} + + // Defining a variable of type CompileAssertTypesEqual will cause a // compiler error iff T1 and T2 are different types. template @@ -665,7 +691,7 @@ TEST(SetFlagValueTest, IllegalValues) { EXPECT_EQ("", SetCommandLineOption("test_double", "")); EXPECT_EQ("test_string set to \n", SetCommandLineOption("test_string", "")); - EXPECT_EQ(true, FLAGS_test_bool); + EXPECT_TRUE(FLAGS_test_bool); EXPECT_EQ(119, FLAGS_test_int32); EXPECT_EQ(1191, FLAGS_test_int64); EXPECT_EQ(11911, FLAGS_test_uint64); @@ -685,12 +711,12 @@ TEST(MacroArgs, EvaluateOnce) { } TEST(MacroArgs, EvaluateOnceBool) { - EXPECT_EQ(true, FLAGS_changeable_bool_var); - EXPECT_EQ(true, FLAGS_changeable_bool_var); + EXPECT_TRUE(FLAGS_changeable_bool_var); + EXPECT_TRUE(FLAGS_changeable_bool_var); EXPECT_EQ(8009, changeable_bool_var); SetCommandLineOptionWithMode("changeable_bool_var", "false", SET_FLAG_IF_DEFAULT); - EXPECT_EQ(false, FLAGS_changeable_bool_var); + EXPECT_FALSE(FLAGS_changeable_bool_var); } TEST(MacroArgs, EvaluateOnceStrings) { @@ -708,12 +734,12 @@ TEST(FromEnvTest, LegalValues) { setenv("BOOL_VAL2", "false", 1); setenv("BOOL_VAL3", "1", 1); setenv("BOOL_VAL4", "F", 1); - EXPECT_EQ(true, BoolFromEnv("BOOL_VAL1", false)); - EXPECT_EQ(false, BoolFromEnv("BOOL_VAL2", true)); - EXPECT_EQ(true, BoolFromEnv("BOOL_VAL3", false)); - EXPECT_EQ(false, BoolFromEnv("BOOL_VAL4", true)); - EXPECT_EQ(true, BoolFromEnv("BOOL_VAL_UNKNOWN", true)); - EXPECT_EQ(false, BoolFromEnv("BOOL_VAL_UNKNOWN", false)); + EXPECT_TRUE(BoolFromEnv("BOOL_VAL1", false)); + EXPECT_FALSE(BoolFromEnv("BOOL_VAL2", true)); + EXPECT_TRUE(BoolFromEnv("BOOL_VAL3", false)); + EXPECT_FALSE(BoolFromEnv("BOOL_VAL4", true)); + EXPECT_TRUE(BoolFromEnv("BOOL_VAL_UNKNOWN", true)); + EXPECT_FALSE(BoolFromEnv("BOOL_VAL_UNKNOWN", false)); setenv("INT_VAL1", "1", 1); setenv("INT_VAL2", "-1", 1); @@ -749,7 +775,7 @@ TEST(FromEnvTest, LegalValues) { // Tests that the FooFromEnv dies on parse-error TEST(FromEnvDeathTest, IllegalValues) { - setenv("BOOL_BAD1", "so true!",1 ); + setenv("BOOL_BAD1", "so true!", 1); setenv("BOOL_BAD2", "", 1); EXPECT_DEATH(BoolFromEnv("BOOL_BAD1", false), "error parsing env variable"); EXPECT_DEATH(BoolFromEnv("BOOL_BAD2", true), "error parsing env variable"); @@ -906,7 +932,7 @@ TEST(GetAllFlagsTest, BaseTest) { break; } } - EXPECT_EQ(true, found_test_bool); + EXPECT_TRUE(found_test_bool); } TEST(ShowUsageWithFlagsTest, BaseTest) { @@ -956,7 +982,7 @@ TEST(ProgramInvocationShortNameTest, BaseTest) { EXPECT_STREQ("gflags_unittest", ProgramInvocationShortName()); } -TEST(ProgramUsageTest, BaseTest) { // Depends on 1st arg to InitGoogle in main() +TEST(ProgramUsageTest, BaseTest) { // Depends on 1st arg to InitGoogle in main EXPECT_STREQ("/test/argv/for/gflags_unittest: " " [...]\nDoes something useless.\n", ProgramUsage()); @@ -965,11 +991,11 @@ TEST(ProgramUsageTest, BaseTest) { // Depends on 1st arg to InitGoogle in main() TEST(GetCommandLineOptionTest, NameExistsAndIsDefault) { string value("will be changed"); bool r = GetCommandLineOption("test_bool", &value); - EXPECT_EQ(true, r); + EXPECT_TRUE(r); EXPECT_EQ("false", value); r = GetCommandLineOption("test_int32", &value); - EXPECT_EQ(true, r); + EXPECT_TRUE(r); EXPECT_EQ("-1", value); } @@ -977,7 +1003,7 @@ TEST(GetCommandLineOptionTest, NameExistsAndWasAssigned) { FLAGS_test_int32 = 400; string value("will be changed"); const bool r = GetCommandLineOption("test_int32", &value); - EXPECT_EQ(true, r); + EXPECT_TRUE(r); EXPECT_EQ("400", value); } @@ -985,7 +1011,7 @@ TEST(GetCommandLineOptionTest, NameExistsAndWasSet) { SetCommandLineOption("test_int32", "700"); string value("will be changed"); const bool r = GetCommandLineOption("test_int32", &value); - EXPECT_EQ(true, r); + EXPECT_TRUE(r); EXPECT_EQ("700", value); } @@ -995,60 +1021,59 @@ TEST(GetCommandLineOptionTest, NameExistsAndWasNotSet) { SetCommandLineOptionWithMode("test_int32", "800", SET_FLAGS_DEFAULT); string value("will be changed"); const bool r = GetCommandLineOption("test_int32", &value); - EXPECT_EQ(true, r); + EXPECT_TRUE(r); EXPECT_EQ("800", value); - EXPECT_EQ(true, GetCommandLineFlagInfoOrDie("test_int32").is_default); - + EXPECT_TRUE(GetCommandLineFlagInfoOrDie("test_int32").is_default); } TEST(GetCommandLineOptionTest, NameExistsAndWasConditionallySet) { SetCommandLineOptionWithMode("test_int32", "900", SET_FLAG_IF_DEFAULT); string value("will be changed"); const bool r = GetCommandLineOption("test_int32", &value); - EXPECT_EQ(true, r); + EXPECT_TRUE(r); EXPECT_EQ("900", value); } TEST(GetCommandLineOptionTest, NameDoesNotExist) { string value("will not be changed"); const bool r = GetCommandLineOption("test_int3210", &value); - EXPECT_EQ(false, r); + EXPECT_FALSE(r); EXPECT_EQ("will not be changed", value); } TEST(GetCommandLineFlagInfoTest, FlagExists) { CommandLineFlagInfo info; bool r = GetCommandLineFlagInfo("test_int32", &info); - EXPECT_EQ(true, r); + EXPECT_TRUE(r); EXPECT_EQ("test_int32", info.name); EXPECT_EQ("int32", info.type); EXPECT_EQ("", info.description); EXPECT_EQ("-1", info.current_value); EXPECT_EQ("-1", info.default_value); - EXPECT_EQ(true, info.is_default); - EXPECT_EQ(false, info.has_validator_fn); + EXPECT_TRUE(info.is_default); + EXPECT_FALSE(info.has_validator_fn); FLAGS_test_bool = true; r = GetCommandLineFlagInfo("test_bool", &info); - EXPECT_EQ(true, r); + EXPECT_TRUE(r); EXPECT_EQ("test_bool", info.name); EXPECT_EQ("bool", info.type); EXPECT_EQ("tests bool-ness", info.description); EXPECT_EQ("true", info.current_value); EXPECT_EQ("false", info.default_value); - EXPECT_EQ(false, info.is_default); - EXPECT_EQ(false, info.has_validator_fn); + EXPECT_FALSE(info.is_default); + EXPECT_FALSE(info.has_validator_fn); FLAGS_test_bool = false; r = GetCommandLineFlagInfo("test_bool", &info); - EXPECT_EQ(true, r); + EXPECT_TRUE(r); EXPECT_EQ("test_bool", info.name); EXPECT_EQ("bool", info.type); EXPECT_EQ("tests bool-ness", info.description); EXPECT_EQ("false", info.current_value); EXPECT_EQ("false", info.default_value); - EXPECT_EQ(false, info.is_default); // value is same, but flag *was* modified - EXPECT_EQ(false, info.has_validator_fn); + EXPECT_FALSE(info.is_default); // value is same, but flag *was* modified + EXPECT_FALSE(info.has_validator_fn); } TEST(GetCommandLineFlagInfoTest, FlagDoesNotExist) { @@ -1062,15 +1087,15 @@ TEST(GetCommandLineFlagInfoTest, FlagDoesNotExist) { info.is_default = false; info.has_validator_fn = true; bool r = GetCommandLineFlagInfo("test_int3210", &info); - EXPECT_EQ(false, r); + EXPECT_FALSE(r); EXPECT_EQ("name", info.name); EXPECT_EQ("type", info.type); EXPECT_EQ("", info.description); EXPECT_EQ("curr", info.current_value); EXPECT_EQ("def", info.default_value); EXPECT_EQ("/", info.filename); - EXPECT_EQ(false, info.is_default); - EXPECT_EQ(true, info.has_validator_fn); + EXPECT_FALSE(info.is_default); + EXPECT_TRUE(info.has_validator_fn); } TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndIsDefault) { @@ -1081,15 +1106,15 @@ TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndIsDefault) { EXPECT_EQ("", info.description); EXPECT_EQ("-1", info.current_value); EXPECT_EQ("-1", info.default_value); - EXPECT_EQ(true, info.is_default); + EXPECT_TRUE(info.is_default); info = GetCommandLineFlagInfoOrDie("test_bool"); EXPECT_EQ("test_bool", info.name); EXPECT_EQ("bool", info.type); EXPECT_EQ("tests bool-ness", info.description); EXPECT_EQ("false", info.current_value); EXPECT_EQ("false", info.default_value); - EXPECT_EQ(true, info.is_default); - EXPECT_EQ(false, info.has_validator_fn); + EXPECT_TRUE(info.is_default); + EXPECT_FALSE(info.has_validator_fn); } TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndWasAssigned) { @@ -1101,7 +1126,7 @@ TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndWasAssigned) { EXPECT_EQ("", info.description); EXPECT_EQ("400", info.current_value); EXPECT_EQ("-1", info.default_value); - EXPECT_EQ(false, info.is_default); + EXPECT_FALSE(info.is_default); FLAGS_test_bool = true; info = GetCommandLineFlagInfoOrDie("test_bool"); EXPECT_EQ("test_bool", info.name); @@ -1109,8 +1134,8 @@ TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndWasAssigned) { EXPECT_EQ("tests bool-ness", info.description); EXPECT_EQ("true", info.current_value); EXPECT_EQ("false", info.default_value); - EXPECT_EQ(false, info.is_default); - EXPECT_EQ(false, info.has_validator_fn); + EXPECT_FALSE(info.is_default); + EXPECT_FALSE(info.has_validator_fn); } TEST(GetCommandLineFlagInfoOrDieDeathTest, FlagDoesNotExist) { @@ -1129,10 +1154,10 @@ TEST(DeprecatedFunctionsTest, CommandlineFlagsIntoString) { TEST(DeprecatedFunctionsTest, AppendFlagsIntoFile) { FLAGS_test_int32 = 10; // just to make the test more interesting - string filename(FLAGS_test_tmpdir + "/flagfile"); + string filename(TmpFile("flagfile")); unlink(filename.c_str()); // just to be safe const bool r = AppendFlagsIntoFile(filename, "not the real argv0"); - EXPECT_EQ(true, r); + EXPECT_TRUE(r); FILE* fp = fopen(filename.c_str(), "r"); EXPECT_TRUE(fp != NULL); @@ -1148,27 +1173,27 @@ TEST(DeprecatedFunctionsTest, AppendFlagsIntoFile) { if (strcmp(line, "--test_int32=10\n") == 0) found_int32 = true; } - EXPECT_EQ(true, found_int32); - EXPECT_EQ(true, found_bool); + EXPECT_TRUE(found_int32); + EXPECT_TRUE(found_bool); fclose(fp); } TEST(DeprecatedFunctionsTest, ReadFromFlagsFile) { FLAGS_test_int32 = -10; // just to make the test more interesting - string filename(FLAGS_test_tmpdir + "/flagfile2"); + string filename(TmpFile("flagfile2")); unlink(filename.c_str()); // just to be safe bool r = AppendFlagsIntoFile(filename, GetArgv0()); - EXPECT_EQ(true, r); + EXPECT_TRUE(r); FLAGS_test_int32 = -11; r = ReadFromFlagsFile(filename, GetArgv0(), true); - EXPECT_EQ(true, r); + EXPECT_TRUE(r); EXPECT_EQ(-10, FLAGS_test_int32); } TEST(DeprecatedFunctionsTest, ReadFromFlagsFileFailure) { FLAGS_test_int32 = -20; - string filename(FLAGS_test_tmpdir + "/flagfile3"); + string filename(TmpFile("flagfile3")); FILE* fp = fopen(filename.c_str(), "w"); EXPECT_TRUE(fp != NULL); // Note the error in the bool assignment below... @@ -1177,7 +1202,7 @@ TEST(DeprecatedFunctionsTest, ReadFromFlagsFileFailure) { FLAGS_test_int32 = -22; const bool r = ReadFromFlagsFile(filename, GetArgv0(), false); - EXPECT_EQ(false, r); + EXPECT_FALSE(r); EXPECT_EQ(-22, FLAGS_test_int32); // the -21 from the flagsfile didn't take } @@ -1191,14 +1216,6 @@ TEST(FlagsSetBeforeInitGoogleTest, TryFromEnv) { DEFINE_int32(test_flag, -1, "used for testing commandlineflags.cc"); -// Returns the definition of the --flagfile flag to be used in the tests. -const char* GetFlagFileFlag() { - static const string flagfile_flag = string("--flagfile=") - + FLAGS_srcdir + "/src/gflags_unittest_flagfile"; - - return flagfile_flag.c_str(); -} - // Parses and returns the --test_flag flag. // If with_help is true, calls ParseCommandLineFlags; otherwise calls // ParseCommandLineNonHelpFlags. @@ -1506,7 +1523,7 @@ TEST(FlagsValidator, FlagSaver) { { FlagSaver fs; EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5)); - EXPECT_EQ("", SetCommandLineOption("test_flag", "50")); // fails validation + EXPECT_EQ("", SetCommandLineOption("test_flag", "50")); // fails validation } EXPECT_NE("", SetCommandLineOption("test_flag", "50")); // validator is gone @@ -1550,7 +1567,7 @@ static int Main(int argc, char **argv) { // I had trouble creating a directory in /tmp from mingw FLAGS_test_tmpdir = "./gflags_unittest_testdir"; mkdir(FLAGS_test_tmpdir.c_str()); // mingw has a weird one-arg mkdir -#elif defined(_WIN32) +#elif defined(_MSC_VER) char tmppath_buffer[1024]; int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer); assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer)); -- 2.7.4