diff --git a/src/BUILD b/src/BUILD index 0d46818463b214..1d4d71cfa6c032 100644 --- a/src/BUILD +++ b/src/BUILD @@ -117,9 +117,6 @@ JAVA_TOOLS = [ "//third_party/java/j2objc:embedded_tools_srcs", "//third_party/py/abseil:srcs", "//third_party/py/concurrent:srcs", - # TODO(laszlocsomor): delete "//third_party/py/gflags:srcs" after - # every script in @bazel_tools was migrated to use Abseil. - "//third_party/py/gflags:srcs", "//third_party/py/six:srcs", "//src/conditions:embedded_tools", "//src/tools/android/java/com/google/devtools/build/android:embedded_tools", diff --git a/src/test/java/com/google/devtools/build/lib/blackbox/bazel/PythonToolsSetup.java b/src/test/java/com/google/devtools/build/lib/blackbox/bazel/PythonToolsSetup.java index 8a61c70561b277..d88aca8dbe1b9f 100644 --- a/src/test/java/com/google/devtools/build/lib/blackbox/bazel/PythonToolsSetup.java +++ b/src/test/java/com/google/devtools/build/lib/blackbox/bazel/PythonToolsSetup.java @@ -16,18 +16,11 @@ import com.google.devtools.build.lib.blackbox.framework.BlackBoxTestContext; import com.google.devtools.build.lib.blackbox.framework.ToolsSetup; -import java.io.IOException; /** Setup for Bazel Python tools */ public class PythonToolsSetup implements ToolsSetup { @Override - public void setup(BlackBoxTestContext context) throws IOException { - context.write( - "third_party/py/gflags/build", - "licenses([\"notice\"])" - + "package(default_visibility = [\"//visibility:public\"])" - + "py_library(" - + " name = \"gflags\"," - + ")"); + public void setup(BlackBoxTestContext context) { + // nothing needed to be done } } diff --git a/src/test/shell/testenv.sh b/src/test/shell/testenv.sh index cd447779bd4f26..04be813680e007 100755 --- a/src/test/shell/testenv.sh +++ b/src/test/shell/testenv.sh @@ -139,16 +139,6 @@ EOF cp -R ${langtools_dir}/* third_party/java/jdk/langtools chmod -R +w . - - mkdir -p third_party/py/gflags - cat > third_party/py/gflags/BUILD < - * python-gflags: version 3.1.1. - * Added PEP8 style method/function aliases. - -Tue Nov 01 00:00:01 2016 Google Inc. - * python-gflags: version 3.1.0. - * Python3 compatibility - * Removed UnrecognizedFlag exception. - * Replaced flags.DuplicateFlag with flags.DuplicateFlagError. - * Moved the validators.Error class to exceptions.ValidationError. - * Renamed IllegalFlagValue to IllegalFlagValueError. - * Removed MutualExclusionValidator class, in favor of flags.MarkFlagsAsMutualExclusive. - * Removed FlagValues.AddValidator method. - * Removed _helpers.GetMainModule. - * Use xml.dom.minidom to create XML strings, instead of manual crafting. - * Declared PEP8-style names. - * Added examples. - - - - * python-gflags: version 3.0.7. - * Removed the unused method ShortestUniquePrefixes. - * Removed _GetCallingModule function alias. - -Fri Aug 05 00:00:01 2016 Google Inc. - - * python-gflags: version 3.0.6 - * Declared pypi package classifiers. - * Added support for CLIF flag processing (not included in python-gflags repo - yet). - -Thu May 12 00:00:01 2016 Google Inc. - - * python-gflags: version 3.0.5 - * Added a warning when FLAGS.SetDefault is used after flags were parsed. - * Added new function: MarkFlagsAsRequired. - -Fri Apr 15 00:00:01 2016 Google Inc. - - * python-gflags: version 3.0.4 - * One more fix for setup.py - this time about third_party package. - -Mon Apr 11 00:00:01 2016 Google Inc. - - * python-gflags: version 3.0.3 - * Fixed setup.py. - * --noflag if argument is given is no longer allowed. - * Python3 compatibility: removed need for cgi import. - * Disallowed unparsed flag usage after FLAGS.Reset() - -Thu Feb 09 11:55:00 2016 Google Inc. - - * python-gflags: version 3.0.2 - * Fix MANIFEST.in to include all relevant files. - -Thu Feb 04 22:23:00 2016 Google Inc. - - * python-gflags: version 3.0.1 - * Some changes for python3 compatibility. - * Automatically generate ordering operations for Flag. - * Add optional comma compatibility to whitespace-separated list flags. - -Tue Jan 12 16:39:00 2016 Google Inc. - - * python-gflags: version 3.0.0. - * A lot of potentially backwards incompatible changes since 2.0. - * This version is NOT recommended to use in production. Some of the files and - documentation has been lost during export; this will be fixed in next - versions. - -Wed Jan 18 13:57:39 2012 Google Inc. - - * python-gflags: version 2.0 - * No changes from version 1.8. - -Wed Jan 18 11:54:03 2012 Google Inc. - - * python-gflags: version 1.8 - * Don't raise DuplicateFlag when re-importing a module (mmcdonald) - * Changed the 'official' python-gflags email in setup.py/etc - * Changed copyright text to reflect Google's relinquished ownership - -Tue Dec 20 17:10:41 2011 Google Inc. - - * python-gflags: version 1.7 - * Prepare gflags for python 3.x, keeping 2.4 compatibility (twouters) - * If output is a tty, use terminal's width to wrap help-text (wiesmann) - * PORTING: Fix ImportError for non-Unix platforms (kdeus) - * PORTING: Run correctly when termios isn't available (shines) - * Add unicode support to flags (csilvers) - -Fri Jul 29 12:24:08 2011 Google Inc. - - * python-gflags: version 1.6 - * Document FlagValues.UseGnuGetOpt (garymm) - * replace fchmod with chmod to work on python 2.4 (mshields) - * Fix bug in flag decl reporting for dup flags (craigcitro) - * Add multi_float, and tests for multi_float/int (simonf) - * Make flagfiles expand in place, to follow docs (dmlynch) - * Raise exception if --flagfile can't be read (tlim) - -Wed Jan 26 13:50:46 2011 Google Inc. - - * python-gflags: version 1.5.1 - * Fix manifest and setup.py to include new files - -Mon Jan 24 16:58:10 2011 Google Inc. - - * python-gflags: version 1.5 - * Add support for flag validators (olexiy) - * Better reporting on UnrecognizedFlagError (sorenj) - * Cache ArgumentParser, to save space (tmarek) - -Wed Oct 13 17:40:12 2010 Google Inc. - - * python-gflags: version 1.4 - * Unregister per-command flags after running the command (dnr) - * Allow key-flags to work with special flags (salcianu) - * Allow printing flags of a specific module (mikecurtis) - * BUGFIX: Fix an error message for float flags (olexiy) - * BUGFIX: Can now import while defining flags (salcianu) - * BUGFIX: Fix flagfile parsing in python (chronos) - * DOC: Better explain the format of --helpxml output (salcianu) - * DOC: Better error message on parse failure (tstromberg) - * Better test coverage under python 2.2 (mshields) - * Added a Makefile for building the packages. - -Mon Jan 4 18:46:29 2010 Tim 'mithro' Ansell - - * python-gflags: version 1.3 - * Fork from the C++ package (google-gflags 1.3) - * Add debian packaging diff --git a/third_party/py/gflags/MANIFEST.in b/third_party/py/gflags/MANIFEST.in deleted file mode 100644 index 59c4c5e0777d59..00000000000000 --- a/third_party/py/gflags/MANIFEST.in +++ /dev/null @@ -1,16 +0,0 @@ -include AUTHORS -include COPYING -include ChangeLog -include MANIFEST.in -include Makefile -include README -include *.md -include debian/README -include debian/changelog -include debian/compat -include debian/control -include debian/copyright -include debian/docs -include debian/rules -include *.py -recursive-include gflags * diff --git a/third_party/py/gflags/Makefile b/third_party/py/gflags/Makefile deleted file mode 100644 index 6627c32a5e8cb7..00000000000000 --- a/third_party/py/gflags/Makefile +++ /dev/null @@ -1,69 +0,0 @@ - -prep: - @echo - # Install needed packages - sudo apt-get install subversion fakeroot python-setuptools python-subversion - # - @echo - # Check that the person has .pypirc - @if [ ! -e ~/.pypirc ]; then \ - echo "Please create a ~/.pypirc with the following contents:"; \ - echo "[server-login]"; \ - echo "username:google_opensource"; \ - echo "password:"; \ - fi - # - @echo - # FIXME(tansell): Check that the person has .dputrc for PPA - -clean: - # Clean up any build files. - python setup.py clean --all - # - # Clean up the debian stuff - fakeroot ./debian/rules clean - # - # Clean up everything else - rm MANIFEST || true - rm -rf build-* - # - # Clean up the egg files - rm -rf *egg* - # - # Remove dist - rm -rf dist - -dist: - # Generate the tarball based on MANIFEST.in - python setup.py sdist - # - # Build the debian packages - fakeroot ./debian/rules binary - mv ../python-gflags*.deb ./dist/ - # - # Build the python Egg - python setup.py bdist_egg - # - @echo - @echo "Files to upload:" - @echo "--------------------------" - @ls -l ./dist/ - -push: - # Send the updates to svn - # Upload the source package to code.google.com - - /home/build/opensource/tools/googlecode_upload.py \ - -p python-gflags ./dist/* - # - # Upload the package to PyPi - - python setup.py sdist upload - - python setup.py bdist_egg upload - # - # Upload the package to the ppa - # FIXME(tansell): dput should run here - -check: - # Run all the tests. - for test in tests/*.py; do PYTHONPATH=. python $$test || exit 1; done - -.PHONY: prep dist clean push check diff --git a/third_party/py/gflags/PKG-INFO b/third_party/py/gflags/PKG-INFO deleted file mode 100644 index 77adc5c79ae640..00000000000000 --- a/third_party/py/gflags/PKG-INFO +++ /dev/null @@ -1,18 +0,0 @@ -Metadata-Version: 1.1 -Name: python-gflags -Version: 3.1.1 -Summary: Google Commandline Flags Module -Home-page: https://github.com/google/python-gflags -Author: Google Inc. and others -Author-email: google-gflags@googlegroups.com -License: BSD -Description: UNKNOWN -Platform: UNKNOWN -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Intended Audience :: Developers -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Requires: six diff --git a/third_party/py/gflags/README b/third_party/py/gflags/README deleted file mode 100644 index 81daa7ab49aaf6..00000000000000 --- a/third_party/py/gflags/README +++ /dev/null @@ -1,23 +0,0 @@ -This repository contains a python implementation of the Google commandline -flags module. - - GFlags defines a *distributed* command line system, replacing systems like - getopt(), optparse and manual argument processing. 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. - - It includes the ability to define flag types (boolean, float, interger, list), - autogeneration of help (in both human and machine readable format) and reading - arguments from a file. It also includes the ability to automatically generate - man pages from the help flags. - -Documentation for implementation is at the top of gflags.py file. - -To install the python module, run - python ./setup.py install - -When you install this 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/third_party/py/gflags/README.md b/third_party/py/gflags/README.md deleted file mode 100644 index 786d817c679db2..00000000000000 --- a/third_party/py/gflags/README.md +++ /dev/null @@ -1,6 +0,0 @@ -[gflags](https://github.com/google/python-gflags) --------- - -* Version: 3.1.0 -* License: New BSD License -* From: [https://pypi.python.org/packages/82/9c/7ed91459f01422d90a734afcf30de7df6b701b90a2e7c7a7d01fd580242d/python-gflags-3.1.0.tar.gz](https://pypi.python.org/packages/82/9c/7ed91459f01422d90a734afcf30de7df6b701b90a2e7c7a7d01fd580242d/python-gflags-3.1.0.tar.gz) diff --git a/third_party/py/gflags/__init__.py b/third_party/py/gflags/__init__.py deleted file mode 100644 index 16a24afda27d23..00000000000000 --- a/third_party/py/gflags/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from __future__ import absolute_import -from gflags import * diff --git a/third_party/py/gflags/debian/README b/third_party/py/gflags/debian/README deleted file mode 100644 index 57becfda757e1c..00000000000000 --- a/third_party/py/gflags/debian/README +++ /dev/null @@ -1,7 +0,0 @@ -The list of files here isn't complete. For a step-by-step guide on -how to set this package up correctly, check out - http://www.debian.org/doc/maint-guide/ - -Most of the files that are in this directory are boilerplate. -However, you may need to change the list of binary-arch dependencies -in 'rules'. diff --git a/third_party/py/gflags/debian/changelog b/third_party/py/gflags/debian/changelog deleted file mode 100644 index 5e6457e2d7a7b4..00000000000000 --- a/third_party/py/gflags/debian/changelog +++ /dev/null @@ -1,54 +0,0 @@ -python-gflags (2.0-1) unstable; urgency=low - - * New upstream release. - - -- Google Inc. Wed, 18 Jan 2012 13:57:39 -0800 - -python-gflags (1.8-1) unstable; urgency=low - - * New upstream release. - - -- Google Inc. Wed, 18 Jan 2012 11:54:03 -0800 - -python-gflags (1.7-1) unstable; urgency=low - - * New upstream release. - - -- Google Inc. Tue, 20 Dec 2011 17:10:41 -0800 - -python-gflags (1.6-1) unstable; urgency=low - - * New upstream release. - - -- Google Inc. Fri, 29 Jul 2011 12:24:08 -0700 - -python-gflags (1.5.1-1) unstable; urgency=low - - * New upstream release (fixes manifest and setup.py files) - - -- Google Inc. Wed, 26 Jan 2011 13:50:46 -0800 - -python-gflags (1.5-1) unstable; urgency=low - - * New upstream release. - - -- Google Inc. Mon, 24 Jan 2011 16:58:10 -0800 - -python-gflags (1.4-1) unstable; urgency=low - - * New upstream release. - - -- Google Inc. Wed, 13 Oct 2010 17:40:12 -0700 - -python-gflags (1.3-2) unstable; urgency=low - - * Fixed man-page generation. - - -- Tim 'mithro' Ansell Mon, 07 Jan 2010 13:46:10 +1100 - -python-gflags (1.3-1) unstable; urgency=low - - * Initial release. - * Packaging based on gflags 1.3 - - -- Tim 'mithro' Ansell Mon, 04 Jan 2010 18:46:10 -0800 diff --git a/third_party/py/gflags/debian/compat b/third_party/py/gflags/debian/compat deleted file mode 100644 index 7ed6ff82de6bcc..00000000000000 --- a/third_party/py/gflags/debian/compat +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/third_party/py/gflags/debian/control b/third_party/py/gflags/debian/control deleted file mode 100644 index 4a9b15942ae685..00000000000000 --- a/third_party/py/gflags/debian/control +++ /dev/null @@ -1,26 +0,0 @@ -Source: python-gflags -Section: python -XS-Python-Version: all -Priority: optional -Maintainer: Craig Silverstein -Build-Depends-Indep: python-central (>= 0.5.6), python-setuptools (>= 0.6b3-1), python-all -Build-Depends: debhelper (>= 5.0.38) -Standards-Version: 3.7.2 - -Package: python-gflags -Architecture: all -Depends: ${python:Depends} -XB-Python-Version: ${python:Versions} -Description: A Python implementation of the Google commandline flags module - . - GFlags defines a *distributed* command line system, replacing systems like - getopt(), optparse and manual argument processing. 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. - . - It includes the ability to define flag types (boolean, float, interger, list), - autogeneration of help (in both human and machine readable format) and reading - arguments from a file. It also includes the ability to automatically generate - man pages from the help flags. - diff --git a/third_party/py/gflags/debian/copyright b/third_party/py/gflags/debian/copyright deleted file mode 100644 index 7d27d62fb4117c..00000000000000 --- a/third_party/py/gflags/debian/copyright +++ /dev/null @@ -1,41 +0,0 @@ -This package was debianized by Craig Silverstein on -Wed, 18 Jan 2012 13:57:39 -0800. - -It was downloaded from http://code.google.com/p/python-gflags/downloads/list - -Upstream Author: Google Inc. and others -Copyright: Google Inc. and others - -License: - -Copyright (c) 2006, 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. - -The Debian packaging is (C) 2011, Tim 'mithro' Ansell and -is licensed under the above. diff --git a/third_party/py/gflags/debian/docs b/third_party/py/gflags/debian/docs deleted file mode 100644 index 6f12db50845a5d..00000000000000 --- a/third_party/py/gflags/debian/docs +++ /dev/null @@ -1,2 +0,0 @@ -AUTHORS -README diff --git a/third_party/py/gflags/debian/rules b/third_party/py/gflags/debian/rules deleted file mode 100644 index 0840b5ef8c89b8..00000000000000 --- a/third_party/py/gflags/debian/rules +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/make -f -# -*- makefile -*- -# Sample debian/rules that uses debhelper. -# GNU copyright 1997 to 1999 by Joey Hess. - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -PYTHON := /usr/bin/python -#PYVER := $(shell $(PYTHON) -c 'import sys; print sys.version[:3]') -PYVERS = $(shell pyversions -vr) - -build: $(PYVERS:%=build-python%) - touch $@ - -build-python%: - dh_testdir - python$* setup.py build - touch $@ - -clean: - dh_testdir - dh_testroot - rm -f build-python* - rm -rf build - -find . -name '*.py[co]' | xargs rm -f - dh_clean - -install: build $(PYVERS:%=install-python%) - -install-python%: - dh_testdir - dh_testroot - dh_clean -k - dh_installdirs - python$* setup.py install --root=$(CURDIR)/debian/python-gflags --prefix=/usr - # Scripts should not have a .py on the end of them - mv $(CURDIR)/debian/python-gflags/usr/bin/gflags2man.py $(CURDIR)/debian/python-gflags/usr/bin/gflags2man - # Generate a man file for gflags2man - mkdir -p $(CURDIR)/debian/python-gflags/usr/share/man/man1 - PYTHONPATH=$(CURDIR)/debian/.. python$* gflags2man.py --dest_dir $(CURDIR)/debian/python-gflags/usr/share/man/man1 $(CURDIR)/debian/python-gflags/usr/bin/gflags2man - -# Build architecture-independent files here. -binary-indep: build install - dh_testdir - dh_testroot - dh_installchangelogs -k ChangeLog - dh_installdocs - dh_pycentral - dh_compress -X.py - dh_fixperms - dh_installdeb - dh_gencontrol - dh_md5sums - dh_builddeb - -# Build architecture-dependent files here. -binary-arch: build install -# We have nothing to do by default. - -binary: binary-indep binary-arch -.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/third_party/py/gflags/gflags/__init__.py b/third_party/py/gflags/gflags/__init__.py deleted file mode 100644 index 263bd3602b1def..00000000000000 --- a/third_party/py/gflags/gflags/__init__.py +++ /dev/null @@ -1,900 +0,0 @@ -#!/usr/bin/env python -# Copyright 2002 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 -# Contributions by: -# Amit Patel, Bogdan Cocosel, Daniel Dulitz, Eric Tiedemann, -# Eric Veach, Laurence Gonsalves, Matthew Springer, Craig Silverstein, -# Vladimir Rusinov - -"""This package is used to define and parse command line flags. - -This package 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. -""" - -import getopt -import os -import re -import sys -import types -import warnings - -import six - -from gflags import _helpers -from gflags import argument_parser -from gflags import exceptions -# _flag alias is to avoid 'redefined outer name' warnings. -from gflags import flag as _flag -from gflags import flagvalues -from gflags import validators as gflags_validators - - -# Add current module to disclaimed module ids. -_helpers.disclaim_module_ids.add(id(sys.modules[__name__])) - -# Function/class aliases. Lint complains about invalid-name for many of them, -# suppress warning for whole block: -# pylint: disable=invalid-name - -# Module exceptions: -# TODO(vrusinov): these should all be renamed to *Error, e.g. IllegalFlagValue -# should be removed in favour of IllegalFlagValueError. -FlagsError = exceptions.Error -Error = exceptions.Error -CantOpenFlagFileError = exceptions.CantOpenFlagFileError -DuplicateFlagError = exceptions.DuplicateFlagError -DuplicateFlagCannotPropagateNoneToSwig = ( - exceptions.DuplicateFlagCannotPropagateNoneToSwig) -IllegalFlagValue = exceptions.IllegalFlagValueError -IllegalFlagValueError = exceptions.IllegalFlagValueError -UnrecognizedFlagError = exceptions.UnrecognizedFlagError -ValidationError = exceptions.ValidationError - -# Public functions: -GetHelpWidth = _helpers.GetHelpWidth -TextWrap = _helpers.TextWrap -FlagDictToArgs = _helpers.FlagDictToArgs -DocToHelp = _helpers.DocToHelp - -# Public classes: -Flag = _flag.Flag -BooleanFlag = _flag.BooleanFlag -EnumFlag = _flag.EnumFlag -MultiFlag = _flag.MultiFlag - -FlagValues = flagvalues.FlagValues -ArgumentParser = argument_parser.ArgumentParser -BooleanParser = argument_parser.BooleanParser -EnumParser = argument_parser.EnumParser -ArgumentSerializer = argument_parser.ArgumentSerializer -FloatParser = argument_parser.FloatParser -IntegerParser = argument_parser.IntegerParser -BaseListParser = argument_parser.BaseListParser -ListParser = argument_parser.ListParser -ListSerializer = argument_parser.ListSerializer -CsvListSerializer = argument_parser.CsvListSerializer -WhitespaceSeparatedListParser = argument_parser.WhitespaceSeparatedListParser - -# pylint: enable=invalid-name - - - - -# The global FlagValues instance -FLAGS = FlagValues() - - -# Flags validators - - -def register_validator(flag_name, - checker, - message='Flag validation failed', - flag_values=FLAGS): - """Adds a constraint, which will be enforced during program execution. - - The constraint is validated when flags are initially parsed, and after each - change of the corresponding flag's value. - Args: - flag_name: str, Name of the flag to be checked. - checker: callable, A function to validate the flag. - input - A single positional argument: The value of the corresponding - flag (string, boolean, etc. This value will be passed to checker - by the library). - output - Boolean. - Must return True if validator constraint is satisfied. - If constraint is not satisfied, it should either return False or - raise gflags.ValidationError(desired_error_message). - message: Error text to be shown to the user if checker returns False. - If checker raises gflags.ValidationError, message from the raised - Error will be shown. - flag_values: An optional FlagValues instance to validate against. - Raises: - AttributeError: If flag_name is not registered as a valid flag name. - """ - v = gflags_validators.SingleFlagValidator(flag_name, checker, message) - _add_validator(flag_values, v) - - -def validator(flag_name, message='Flag validation failed', flag_values=FLAGS): - """A function decorator for defining a flag validator. - - Registers the decorated function as a validator for flag_name, e.g. - - @gflags.validator('foo') - def _CheckFoo(foo): - ... - - See register_validator() for the specification of checker function. - - Args: - flag_name: string, name of the flag to be checked. - message: error text to be shown to the user if checker returns False. - If checker raises gflags.ValidationError, message from the raised - Error will be shown. - flag_values: FlagValues - Returns: - A function decorator that registers its function argument as a validator. - Raises: - AttributeError: if flag_name is not registered as a valid flag name. - """ - - def decorate(function): - register_validator(flag_name, function, - message=message, - flag_values=flag_values) - return function - return decorate - - -def register_multi_flags_validator(flag_names, - multi_flags_checker, - message='Flags validation failed', - flag_values=FLAGS): - """Adds a constraint to multiple flags. - - The constraint is validated when flags are initially parsed, and after each - change of the corresponding flag's value. - - Args: - flag_names: [str], a list of the flag names to be checked. - multi_flags_checker: callable, a function to validate the flag. - input - dictionary, with keys() being flag_names, and value for each key - being the value of the corresponding flag (string, boolean, etc). - output - Boolean. Must return True if validator constraint is satisfied. - If constraint is not satisfied, it should either return False or - raise gflags.ValidationError. - message: Error text to be shown to the user if checker returns False. - If checker raises gflags.ValidationError, message from the raised error - will be shown. - flag_values: An optional FlagValues instance to validate against. - - Raises: - AttributeError: If a flag is not registered as a valid flag name. - """ - v = gflags_validators.MultiFlagsValidator( - flag_names, multi_flags_checker, message) - _add_validator(flag_values, v) - - -def multi_flags_validator(flag_names, - message='Flag validation failed', - flag_values=FLAGS): - """A function decorator for defining a multi-flag validator. - - Registers the decorated function as a validator for flag_names, e.g. - - @gflags.multi_flags_validator(['foo', 'bar']) - def _CheckFooBar(flags_dict): - ... - - See register_multi_flags_validator() for the specification of checker - function. - - Args: - flag_names: [str], a list of the flag names to be checked. - message: error text to be shown to the user if checker returns False. - If checker raises ValidationError, message from the raised - error will be shown. - flag_values: An optional FlagValues instance to validate against. - - Returns: - A function decorator that registers its function argument as a validator. - - Raises: - AttributeError: If a flag is not registered as a valid flag name. - """ - - def decorate(function): - register_multi_flags_validator(flag_names, - function, - message=message, - flag_values=flag_values) - return function - - return decorate - - -def mark_flag_as_required(flag_name, flag_values=FLAGS): - """Ensures that flag is not None during program execution. - - Registers a flag validator, which will follow usual validator rules. - Important note: validator will pass for any non-None value, such as False, - 0 (zero), '' (empty string) and so on. - - It is recommended to call this method like this: - - if __name__ == '__main__': - gflags.mark_flag_as_required('your_flag_name') - app.run() - - Because validation happens at app.run() we want to ensure required-ness - is enforced at that time. However, you generally do not want to force - users who import your code to have additional required flags for their - own binaries or tests. - - Args: - flag_name: string, name of the flag - flag_values: FlagValues - Raises: - AttributeError: if flag_name is not registered as a valid flag name. - """ - if flag_values[flag_name].default is not None: - # TODO(vrusinov): Turn this warning into an exception. - warnings.warn( - 'Flag %s has a non-None default value; therefore, ' - 'mark_flag_as_required will pass even if flag is not specified in the ' - 'command line!' % flag_name) - register_validator(flag_name, - lambda value: value is not None, - message='Flag --%s must be specified.' % flag_name, - flag_values=flag_values) - - -def mark_flags_as_required(flag_names, flag_values=FLAGS): - """Ensures that flags are not None during program execution. - - Recommended usage: - - if __name__ == '__main__': - gflags.mark_flags_as_required(['flag1', 'flag2', 'flag3']) - app.run() - - Args: - flag_names: list/tuple, names of the flags. - flag_values: FlagValues - Raises: - AttributeError: If any of flag name has not already been defined as a flag. - """ - for flag_name in flag_names: - mark_flag_as_required(flag_name, flag_values) - - -def mark_flags_as_mutual_exclusive(flag_names, required=False, - flag_values=FLAGS): - """Ensures that only one flag among flag_names is set. - - Args: - flag_names: [str], a list of the flag names to be checked. - required: Boolean, if set, exactly one of the flags must be set. - Otherwise, it is also valid for none of the flags to be set. - flag_values: An optional FlagValues instance to validate against. - """ - - def validate_mutual_exclusion(flags_dict): - flag_count = sum(1 for val in flags_dict.values() if val is not None) - if flag_count == 1 or (not required and flag_count == 0): - return True - message = ('%s one of (%s) must be specified.' % - ('Exactly' if required else 'At most', ', '.join(flag_names))) - raise ValidationError(message) - - register_multi_flags_validator( - flag_names, validate_mutual_exclusion, flag_values=flag_values) - - -def _add_validator(fv, validator_instance): - """Register new flags validator to be checked. - - Args: - fv: flagvalues.FlagValues - validator_instance: validators.Validator - Raises: - KeyError: if validators work with a non-existing flag. - """ - for flag_name in validator_instance.get_flags_names(): - fv[flag_name].validators.append(validator_instance) - - -def _register_bounds_validator_if_needed(parser, name, flag_values): - """Enforces lower and upper bounds for numeric flags. - - Args: - parser: NumericParser (either FloatParser or IntegerParser). Provides lower - and upper bounds, and help text to display. - name: string, name of the flag - flag_values: FlagValues - """ - if parser.lower_bound is not None or parser.upper_bound is not None: - - def checker(value): - if value is not None and parser.is_outside_bounds(value): - message = '%s is not %s' % (value, parser.syntactic_help) - raise ValidationError(message) - return True - - register_validator(name, checker, flag_values=flag_values) - - -# The DEFINE functions are explained in more details in the module doc string. - - -def DEFINE(parser, name, default, help, flag_values=FLAGS, serializer=None, # pylint: disable=redefined-builtin,invalid-name - module_name=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 with which the flag will be registered. - serializer: ArgumentSerializer that serializes the flag value. - module_name: A string, the name of the Python module declaring this flag. - If not provided, it will be computed using the stack trace of this call. - **args: Dictionary with extra keyword args that are passed to the - Flag __init__. - """ - DEFINE_flag(Flag(parser, serializer, name, default, help, **args), - flag_values, module_name) - - -def DEFINE_flag(flag, flag_values=FLAGS, module_name=None): # pylint: disable=g-bad-name - """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. - - Args: - flag: A Flag object, a flag that is key to the module. - flag_values: FlagValues object with which the flag will be registered. - module_name: A string, the name of the Python module declaring this flag. - If not provided, it will be computed using the stack trace of this call. - """ - # 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. - if module_name: - module = sys.modules.get(module_name) - else: - module, module_name = _helpers.GetCallingModuleObjectAndName() - # TODO(vrusinov): _RegisterFlagByModule* should be public. - # pylint: disable=protected-access - flag_values._RegisterFlagByModule(module_name, flag) - flag_values._RegisterFlagByModuleId(id(module), flag) - # pylint: enable=protected-access - - -def _internal_declare_key_flags(flag_names, - flag_values=FLAGS, key_flag_values=None): - """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 that the flags listed in - flag_names have registered with (the value of the flag_values - argument from the DEFINE_* calls that defined those flags). - This should almost never need to be overridden. - key_flag_values: A FlagValues object that (among possibly many - other things) keeps track of the key flags for each module. - Default None means "same as flag_values". This should almost - never need to be overridden. - - Raises: - UnrecognizedFlagError: when we refer to a flag that was not - defined yet. - """ - key_flag_values = key_flag_values or flag_values - - module = _helpers.GetCallingModule() - - for flag_name in flag_names: - flag = flag_values.GetFlag(flag_name) - # TODO(vrusinov): _RegisterKeyFlagForModule should be public. - key_flag_values._RegisterKeyFlagForModule(module, flag) # pylint: disable=protected-access - - -def DECLARE_key_flag( # pylint: disable=g-bad-name - 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 - --helpfull). - - Sample usage: - - gflags.DECLARE_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. - """ - if flag_name in _helpers.SPECIAL_FLAGS: - # Take care of the special flags, e.g., --flagfile, --undefok. - # These flags are defined in _SPECIAL_FLAGS, and are treated - # specially during flag parsing, taking precedence over the - # user-defined flags. - _internal_declare_key_flags([flag_name], - flag_values=_helpers.SPECIAL_FLAGS, - key_flag_values=flag_values) - return - _internal_declare_key_flags([flag_name], flag_values=flag_values) - - -def ADOPT_module_key_flags( # pylint: disable=g-bad-name - 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: - Error: When given an argument that is a module name (a - string), instead of a module object. - """ - if not isinstance(module, types.ModuleType): - raise Error('Expected a module object, not %r.' % (module,)) - # TODO(vrusinov): _GetKeyFlagsForModule should be public. - _internal_declare_key_flags( - [f.name for f in flag_values._GetKeyFlagsForModule(module.__name__)], # pylint: disable=protected-access - flag_values=flag_values) - # If module is this flag module, take _helpers._SPECIAL_FLAGS into account. - if module == _helpers.GetModuleObjectAndName(globals())[0]: - _internal_declare_key_flags( - # As we associate flags with _GetCallingModuleObjectAndName(), the - # special flags defined in this module are incorrectly registered with - # a different module. So, we can't use _GetKeyFlagsForModule. - # Instead, we take all flags from _helpers._SPECIAL_FLAGS (a private - # FlagValues, where no other module should register flags). - [f.name for f in six.itervalues(_helpers.SPECIAL_FLAGS.FlagDict())], - flag_values=_helpers.SPECIAL_FLAGS, - key_flag_values=flag_values) - - -def DISCLAIM_key_flags(): # pylint: disable=g-bad-name - """Declares that the current module will not define any more key flags. - - Normally, the module that calls the DEFINE_xxx functions claims the - flag to be its key flag. This is undesirable for modules that - define additional DEFINE_yyy functions with its own flag parsers and - serializers, since that module will accidentally claim flags defined - by DEFINE_yyy as its key flags. After calling this function, the - module disclaims flag definitions thereafter, so the key flags will - be correctly attributed to the caller of DEFINE_yyy. - - After calling this function, the module will not be able to define - any more flags. This function will affect all FlagValues objects. - """ - globals_for_caller = sys._getframe(1).f_globals # pylint: disable=protected-access - module, _ = _helpers.GetModuleObjectAndName(globals_for_caller) - _helpers.disclaim_module_ids.add(id(module)) - - -# -# STRING FLAGS -# - - -def DEFINE_string( # pylint: disable=g-bad-name,redefined-builtin - 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) - - -def DEFINE_boolean( # pylint: disable=g-bad-name,redefined-builtin - name, default, help, flag_values=FLAGS, module_name=None, **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. - - Args: - name: A string, the flag name. - default: The default value of the flag. - help: A help string. - flag_values: FlagValues object with which the flag will be registered. - module_name: A string, the name of the Python module declaring this flag. - If not provided, it will be computed using the stack trace of this call. - **args: Dictionary with extra keyword args that are passed to the - Flag __init__. - """ - DEFINE_flag(BooleanFlag(name, default, help, **args), - flag_values, module_name) - - -# Match C++ API to unconfuse C++ people. -DEFINE_bool = DEFINE_boolean # pylint: disable=g-bad-name - - -def DEFINE_float( # pylint: disable=g-bad-name,redefined-builtin - name, default, help, lower_bound=None, upper_bound=None, - flag_values=FLAGS, **args): # pylint: disable=g-bad-name - """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. - - Args: - name: str, flag name. - default: float, default flag value. - help: str, help message. - lower_bound: float, min value of the flag. - upper_bound: float, max value of the flag. - flag_values: FlagValues object with which the flag will be registered. - **args: additional arguments to pass to DEFINE. - """ - parser = FloatParser(lower_bound, upper_bound) - serializer = ArgumentSerializer() - DEFINE(parser, name, default, help, flag_values, serializer, **args) - _register_bounds_validator_if_needed(parser, name, flag_values=flag_values) - - -def DEFINE_integer( # pylint: disable=g-bad-name,redefined-builtin - 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. - - Args: - name: str, flag name. - default: int, default flag value. - help: str, help message. - lower_bound: int, min value of the flag. - upper_bound: int, max value of the flag. - flag_values: FlagValues object with which the flag will be registered. - **args: additional arguments to pass to DEFINE. - """ - parser = IntegerParser(lower_bound, upper_bound) - serializer = ArgumentSerializer() - DEFINE(parser, name, default, help, flag_values, serializer, **args) - _register_bounds_validator_if_needed(parser, name, flag_values=flag_values) - - -def DEFINE_enum( # pylint: disable=g-bad-name,redefined-builtin - name, default, enum_values, help, flag_values=FLAGS, module_name=None, - **args): - """Registers a flag whose value can be any string from enum_values. - - Args: - name: A string, the flag name. - default: The default value of the flag. - enum_values: A list of strings with the possible values for the flag. - help: A help string. - flag_values: FlagValues object with which the flag will be registered. - module_name: A string, the name of the Python module declaring this flag. - If not provided, it will be computed using the stack trace of this call. - **args: Dictionary with extra keyword args that are passed to the - Flag __init__. - """ - DEFINE_flag(EnumFlag(name, default, help, enum_values, ** args), - flag_values, module_name) - - -def DEFINE_list( # pylint: disable=g-bad-name,redefined-builtin - name, default, help, flag_values=FLAGS, **args): - """Registers a flag whose value is a comma-separated list of strings. - - The flag value is parsed with a CSV parser. - - Args: - name: A string, the flag name. - default: The default value of the flag. - help: A help string. - flag_values: FlagValues object with which the flag will be registered. - **args: Dictionary with extra keyword args that are passed to the - Flag __init__. - """ - parser = ListParser() - serializer = CsvListSerializer(',') - DEFINE(parser, name, default, help, flag_values, serializer, **args) - - -def DEFINE_spaceseplist( # pylint: disable=g-bad-name,redefined-builtin - name, default, help, comma_compat=False, flag_values=FLAGS, **args): - """Registers a flag whose value is a whitespace-separated list of strings. - - Any whitespace can be used as a separator. - - Args: - name: A string, the flag name. - default: The default value of the flag. - help: A help string. - comma_compat: bool - Whether to support comma as an additional separator. - If false then only whitespace is supported. This is intended only for - backwards compatibility with flags that used to be comma-separated. - flag_values: FlagValues object with which the flag will be registered. - **args: Dictionary with extra keyword args that are passed to the - Flag __init__. - """ - parser = WhitespaceSeparatedListParser(comma_compat=comma_compat) - serializer = ListSerializer(' ') - DEFINE(parser, name, default, help, flag_values, serializer, **args) - - -def DEFINE_multi( # pylint: disable=g-bad-name,redefined-builtin - parser, serializer, name, default, help, flag_values=FLAGS, - module_name=None, **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. - - Args: - parser: ArgumentParser that is used to parse the flag arguments. - serializer: ArgumentSerializer that serializes the flag value. - name: A string, the flag name. - default: The default value of the flag. - help: A help string. - flag_values: FlagValues object with which the flag will be registered. - module_name: A string, the name of the Python module declaring this flag. - If not provided, it will be computed using the stack trace of this call. - **args: Dictionary with extra keyword args that are passed to the - Flag __init__. - """ - DEFINE_flag(MultiFlag(parser, serializer, name, default, help, **args), - flag_values, module_name) - - -def DEFINE_multistring( # pylint: disable=g-bad-name,redefined-builtin - 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. - - - Args: - name: A string, the flag name. - default: The default value of the flag. - help: A help string. - flag_values: FlagValues object with which the flag will be registered. - **args: Dictionary with extra keyword args that are passed to the - Flag __init__. - """ - parser = ArgumentParser() - serializer = ArgumentSerializer() - DEFINE_multi(parser, serializer, name, default, help, flag_values, **args) - - -def DEFINE_multi_int( # pylint: disable=g-bad-name,redefined-builtin - 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. - - Args: - name: A string, the flag name. - default: The default value of the flag. - help: A help string. - lower_bound: int, min values of the flag. - upper_bound: int, max values of the flag. - flag_values: FlagValues object with which the flag will be registered. - **args: Dictionary with extra keyword args that are passed to the - Flag __init__. - """ - parser = IntegerParser(lower_bound, upper_bound) - serializer = ArgumentSerializer() - DEFINE_multi(parser, serializer, name, default, help, flag_values, **args) - - -def DEFINE_multi_float( # pylint: disable=g-bad-name,redefined-builtin - name, default, help, lower_bound=None, upper_bound=None, - flag_values=FLAGS, **args): - """Registers a flag whose value can be a list of arbitrary floats. - - Use the flag on the command line multiple times to place multiple - float values into the list. The 'default' may be a single float - (which will be converted into a single-element list) or a list of - floats. - - Args: - name: A string, the flag name. - default: The default value of the flag. - help: A help string. - lower_bound: float, min values of the flag. - upper_bound: float, max values of the flag. - flag_values: FlagValues object with which the flag will be registered. - **args: Dictionary with extra keyword args that are passed to the - Flag __init__. - """ - parser = FloatParser(lower_bound, upper_bound) - serializer = ArgumentSerializer() - DEFINE_multi(parser, serializer, name, default, help, flag_values, **args) - - -def DEFINE_multi_enum( # pylint: disable=g-bad-name,redefined-builtin - name, default, enum_values, help, flag_values=FLAGS, case_sensitive=True, - **args): - """Registers a flag whose value can be a list strings from enum_values. - - Use the flag on the command line multiple times to place multiple - enum 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. - - Args: - name: A string, the flag name. - default: The default value of the flag. - enum_values: A list of strings with the possible values for the flag. - help: A help string. - flag_values: FlagValues object with which the flag will be registered. - case_sensitive: Whether or not the enum is to be case-sensitive. - **args: Dictionary with extra keyword args that are passed to the - Flag __init__. - """ - parser = EnumParser(enum_values, case_sensitive) - serializer = ArgumentSerializer() - DEFINE_multi(parser, serializer, name, default, help, flag_values, **args) - - -def DEFINE_alias(name, original_name, flag_values=FLAGS, module_name=None): # pylint: disable=g-bad-name - """Defines an alias flag for an existing one. - - Args: - name: A string, name of the alias flag. - original_name: A string, name of the original flag. - flag_values: FlagValues object with which the flag will be registered. - module_name: A string, the name of the module that defines this flag. - - Raises: - gflags.FlagError: - UnrecognizedFlagError: if the referenced flag doesn't exist. - DuplicateFlagError: if the alias name has been used by some existing flag. - """ - if original_name not in flag_values: - raise UnrecognizedFlagError(original_name) - flag = flag_values[original_name] - - class _Parser(ArgumentParser): - """The parser for the alias flag calls the original flag parser.""" - - def parse(self, argument): - flag.parse(argument) - return flag.value - - class _FlagAlias(Flag): - """Overrides Flag class so alias value is copy of original flag value.""" - - @property - def value(self): - return flag.value - - @value.setter - def value(self, value): - flag.value = value - - help_msg = 'Alias for --%s.' % flag.name - # If alias_name has been used, gflags.DuplicatedFlag will be raised. - DEFINE_flag(_FlagAlias(_Parser(), flag.serializer, name, flag.default, - help_msg, boolean=flag.boolean), - flag_values, module_name) - - -DEFINE_string( - 'flagfile', '', - 'Insert flag definitions from the given file into the command line.', - _helpers.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.', _helpers.SPECIAL_FLAGS) - - -# Old CamelCase functions. It's OK to use them, but those use cases will be -# migrated to PEP8 style functions in the future. -# pylint: disable=invalid-name -RegisterValidator = register_validator -Validator = validator -RegisterMultiFlagsValidator = register_multi_flags_validator -MultiFlagsValidator = multi_flags_validator -MarkFlagAsRequired = mark_flag_as_required -MarkFlagsAsRequired = mark_flags_as_required -MarkFlagsAsMutualExclusive = mark_flags_as_mutual_exclusive -# pylint: enable=invalid-name - -# New PEP8 style functions. -get_help_width = GetHelpWidth -text_wrap = TextWrap -flag_dict_to_args = FlagDictToArgs -doc_to_help = DocToHelp -declare_key_flag = DECLARE_key_flag -adopt_module_key_flags = ADOPT_module_key_flags -disclaim_key_flags = DISCLAIM_key_flags diff --git a/third_party/py/gflags/gflags/_helpers.py b/third_party/py/gflags/gflags/_helpers.py deleted file mode 100644 index d46c4e6e63c5aa..00000000000000 --- a/third_party/py/gflags/gflags/_helpers.py +++ /dev/null @@ -1,430 +0,0 @@ -#!/usr/bin/env python -# Copyright 2002 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. - - -"""Helper functions for //gflags.""" - -import collections -import os -import re -import struct -import sys -import textwrap -try: - import fcntl # pylint: disable=g-import-not-at-top -except ImportError: - fcntl = None -try: - # Importing termios will fail on non-unix platforms. - import termios # pylint: disable=g-import-not-at-top -except ImportError: - termios = None - -# pylint: disable=g-import-not-at-top -import gflags.third_party.pep257 as pep257 -import six - - -_DEFAULT_HELP_WIDTH = 80 # Default width of help output. -_MIN_HELP_WIDTH = 40 # Minimal "sane" width of help output. We assume that any - # value below 40 is unreasonable. - -# Define the allowed error rate in an input string to get suggestions. -# -# We lean towards a high threshold because we tend to be matching a phrase, -# and the simple algorithm used here is geared towards correcting word -# spellings. -# -# For manual testing, consider " --list" which produced a large number -# of spurious suggestions when we used "least_errors > 0.5" instead of -# "least_erros >= 0.5". -_SUGGESTION_ERROR_RATE_THRESHOLD = 0.50 - -# Characters that cannot appear or are highly discouraged in an XML 1.0 -# document. (See http://www.w3.org/TR/REC-xml/#charsets or -# https://en.wikipedia.org/wiki/Valid_characters_in_XML#XML_1.0) -_ILLEGAL_XML_CHARS_REGEX = re.compile( - u'[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]') - -# This is a set of module ids for the modules that disclaim key flags. -# This module is explicitly added to this set so that we never consider it to -# define key flag. -disclaim_module_ids = set([id(sys.modules[__name__])]) - - - -# Define special flags here so that help may be generated for them. -# NOTE: Please do NOT use SPECIAL_FLAGS from outside flags module. -# Initialized inside flagvalues.py. -SPECIAL_FLAGS = None - - -class _ModuleObjectAndName( - collections.namedtuple('_ModuleObjectAndName', 'module module_name')): - """Module object and name. - - Fields: - - module: object, module object. - - module_name: str, module name. - """ - - -def GetModuleObjectAndName(globals_dict): - """Returns the module that defines a global environment, and its name. - - Args: - globals_dict: A dictionary that should correspond to an environment - providing the values of the globals. - - Returns: - _ModuleObjectAndName - pair of module object & module name. - Returns (None, None) if the module could not be identified. - """ - name = globals_dict.get('__name__', None) - module = sys.modules.get(name, None) - # Pick a more informative name for the main module. - return _ModuleObjectAndName(module, - (sys.argv[0] if name == '__main__' else name)) - - -def GetCallingModuleObjectAndName(): - """Returns 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. - - Returns: - The module object that called into this one. - - Raises: - AssertionError: if no calling module could be identified. - """ - range_func = range if sys.version_info[0] >= 3 else xrange - for depth in range_func(1, sys.getrecursionlimit()): - # sys._getframe is the right thing to use here, as it's the best - # way to walk up the call stack. - globals_for_frame = sys._getframe(depth).f_globals # pylint: disable=protected-access - module, module_name = GetModuleObjectAndName(globals_for_frame) - if id(module) not in disclaim_module_ids and module_name is not None: - return _ModuleObjectAndName(module, module_name) - raise AssertionError('No module was found') - - -def GetCallingModule(): - """Returns the name of the module that's calling into this module.""" - return GetCallingModuleObjectAndName().module_name - - -def StrOrUnicode(value): - """Converts a value to a python string. - - Behavior of this function is intentionally different in Python2/3. - - In Python2, the given value is attempted to convert to a str (byte string). - If it contains non-ASCII characters, it is converted to a unicode instead. - - In Python3, the given value is always converted to a str (unicode string). - - This behavior reflects the (bad) practice in Python2 to try to represent - a string as str as long as it contains ASCII characters only. - - Args: - value: An object to be converted to a string. - - Returns: - A string representation of the given value. See the description above - for its type. - """ - try: - return str(value) - except UnicodeEncodeError: - return unicode(value) # Python3 should never come here - - -def CreateXMLDOMElement(doc, name, value): - """Returns an XML DOM element with name and text value. - - Args: - doc: A minidom.Document, the DOM document it should create nodes from. - name: A string, the tag of XML element. - value: A Python object, whose string representation will be used - as the value of the XML element. Illegal or highly discouraged xml 1.0 - characters are stripped. - - Returns: - An instance of minidom.Element. - """ - s = StrOrUnicode(value) - if six.PY2 and not isinstance(s, unicode): - # Get a valid unicode string. - s = s.decode('utf-8', 'ignore') - if isinstance(value, bool): - # Display boolean values as the C++ flag library does: no caps. - s = s.lower() - # Remove illegal xml characters. - s = _ILLEGAL_XML_CHARS_REGEX.sub(u'', s) - - e = doc.createElement(name) - e.appendChild(doc.createTextNode(s)) - return e - - -def GetHelpWidth(): - """Returns: an integer, the width of help lines that is used in TextWrap.""" - if not sys.stdout.isatty() or termios is None or fcntl is None: - return _DEFAULT_HELP_WIDTH - try: - data = fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ, '1234') - columns = struct.unpack('hh', data)[1] - # Emacs mode returns 0. - # Here we assume that any value below 40 is unreasonable. - if columns >= _MIN_HELP_WIDTH: - return columns - # Returning an int as default is fine, int(int) just return the int. - return int(os.getenv('COLUMNS', _DEFAULT_HELP_WIDTH)) - - except (TypeError, IOError, struct.error): - return _DEFAULT_HELP_WIDTH - - -def GetFlagSuggestions(attempt, longopt_list): - """Get helpful similar matches for an invalid flag.""" - # Don't suggest on very short strings, or if no longopts are specified. - if len(attempt) <= 2 or not longopt_list: - return [] - - option_names = [v.split('=')[0] for v in longopt_list] - - # Find close approximations in flag prefixes. - # This also handles the case where the flag is spelled right but ambiguous. - distances = [(_DamerauLevenshtein(attempt, option[0:len(attempt)]), option) - for option in option_names] - distances.sort(key=lambda t: t[0]) - - least_errors, _ = distances[0] - # Don't suggest excessively bad matches. - if least_errors >= _SUGGESTION_ERROR_RATE_THRESHOLD * len(attempt): - return [] - - suggestions = [] - for errors, name in distances: - if errors == least_errors: - suggestions.append(name) - else: - break - return suggestions - - -def _DamerauLevenshtein(a, b): - """Damerau-Levenshtein edit distance from a to b.""" - memo = {} - - def Distance(x, y): - """Recursively defined string distance with memoization.""" - if (x, y) in memo: - return memo[x, y] - if not x: - d = len(y) - elif not y: - d = len(x) - else: - d = min( - Distance(x[1:], y) + 1, # correct an insertion error - Distance(x, y[1:]) + 1, # correct a deletion error - Distance(x[1:], y[1:]) + (x[0] != y[0])) # correct a wrong character - if len(x) >= 2 and len(y) >= 2 and x[0] == y[1] and x[1] == y[0]: - # Correct a transposition. - t = Distance(x[2:], y[2:]) + 1 - if d > t: - d = t - - memo[x, y] = d - return d - return Distance(a, b) - - -def TextWrap(text, length=None, indent='', firstline_indent=None): - """Wraps a given text to a maximum line length and returns it. - - It turns lines that only contain whitespace into empty lines, keeps new lines, - and expands tabs using 4 spaces. - - Args: - text: str, Text to wrap. - length: int, Maximum length of a line, includes indentation. - If this is None then use GetHelpWidth() - indent: str, Indent for all but first line. - firstline_indent: str, Indent for first line; if None, fall back to indent. - - Returns: - Wrapped text. - - Raises: - ValueError: if indent or firstline_indent not shorter than length. - """ - # Get defaults where callee used None - if length is None: - length = GetHelpWidth() - if indent is None: - indent = '' - if firstline_indent is None: - firstline_indent = indent - - if len(indent) >= length: - raise ValueError('Length of indent exceeds length') - if len(firstline_indent) >= length: - raise ValueError('Length of first line indent exceeds length') - - text = text.expandtabs(4) - - result = [] - # Create one wrapper for the first paragraph and one for subsequent - # paragraphs that does not have the initial wrapping. - wrapper = textwrap.TextWrapper( - width=length, initial_indent=firstline_indent, subsequent_indent=indent) - subsequent_wrapper = textwrap.TextWrapper( - width=length, initial_indent=indent, subsequent_indent=indent) - - # textwrap does not have any special treatment for newlines. From the docs: - # "...newlines may appear in the middle of a line and cause strange output. - # For this reason, text should be split into paragraphs (using - # str.splitlines() or similar) which are wrapped separately." - for paragraph in (p.strip() for p in text.splitlines()): - if paragraph: - result.extend(wrapper.wrap(paragraph)) - else: - result.append('') # Keep empty lines. - # Replace initial wrapper with wrapper for subsequent paragraphs. - wrapper = subsequent_wrapper - - return '\n'.join(result) - - -def FlagDictToArgs(flag_map): - """Convert a dict of values into process call parameters. - - This method is used to convert a dictionary into a sequence of parameters - for a binary that parses arguments using this module. - - Args: - flag_map: a mapping where the keys are flag names (strings). - values are treated according to their type: - * If value is None, then only the name is emitted. - * If value is True, then only the name is emitted. - * If value is False, then only the name prepended with 'no' is emitted. - * If value is a string then --name=value is emitted. - * If value is a collection, this will emit --name=value1,value2,value3. - * Everything else is converted to string an passed as such. - Yields: - sequence of string suitable for a subprocess execution. - """ - for key, value in six.iteritems(flag_map): - if value is None: - yield '--%s' % key - elif isinstance(value, bool): - if value: - yield '--%s' % key - else: - yield '--no%s' % key - elif isinstance(value, (bytes, type(u''))): - # We don't want strings to be handled like python collections. - yield '--%s=%s' % (key, value) - else: - # Now we attempt to deal with collections. - try: - yield '--%s=%s' % (key, ','.join(str(item) for item in value)) - except TypeError: - # Default case. - yield '--%s=%s' % (key, value) - - -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 = pep257.trim(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(r'(?<=\S)\n(?=\S)', ' ', doc, flags=re.M) - - return doc - - -def IsRunningTest(): - """Tries to detect whether we are inside of the test.""" - modules = set(sys.modules) - test_modules = { - 'unittest', - 'unittest2', - 'pytest', - } - return bool(test_modules & modules) - - -# TODO(b/31830082): Migrate all users to PEP8-style methods and remove this. -def define_both_methods(class_name, class_dict, old_name, new_name): # pylint: disable=invalid-name - """Function to help CamelCase to PEP8 style class methods migration. - - For any class definition: - 1. Assert it does not define both old and new methods, - otherwise it does not work. - 2. If it defines the old method, create the same new method. - 3. If it defines the new method, create the same old method. - - Args: - class_name: the class name. - class_dict: the class dictionary. - old_name: old method's name. - new_name: new method's name. - - Raises: - AssertionError: raised when the class defines both the old_name and - new_name. - """ - assert old_name not in class_dict or new_name not in class_dict, ( - 'Class "{}" cannot define both "{}" and "{}" methods.'.format( - class_name, old_name, new_name)) - if old_name in class_dict: - class_dict[new_name] = class_dict[old_name] - elif new_name in class_dict: - class_dict[old_name] = class_dict[new_name] diff --git a/third_party/py/gflags/gflags/_helpers_test.py b/third_party/py/gflags/gflags/_helpers_test.py deleted file mode 100644 index 0f2870a1138dc4..00000000000000 --- a/third_party/py/gflags/gflags/_helpers_test.py +++ /dev/null @@ -1,177 +0,0 @@ -#!/usr/bin/env python -# Copyright 2014 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 helpers module.""" - -import sys - -import unittest - -from gflags import _helpers -from gflags.flags_modules_for_testing import module_bar -from gflags.flags_modules_for_testing import module_foo - - -class FlagSuggestionTest(unittest.TestCase): - - def setUp(self): - self.longopts = [ - 'fsplit-ivs-in-unroller=', - 'fsplit-wide-types=', - 'fstack-protector=', - 'fstack-protector-all=', - 'fstrict-aliasing=', - 'fstrict-overflow=', - 'fthread-jumps=', - 'ftracer', - 'ftree-bit-ccp', - 'ftree-builtin-call-dce', - 'ftree-ccp', - 'ftree-ch'] - - def testDamerauLevenshteinId(self): - self.assertEqual(0, _helpers._DamerauLevenshtein('asdf', 'asdf')) - - def testDamerauLevenshteinEmpty(self): - self.assertEqual(5, _helpers._DamerauLevenshtein('', 'kites')) - self.assertEqual(6, _helpers._DamerauLevenshtein('kitten', '')) - - def testDamerauLevenshteinCommutative(self): - self.assertEqual(2, _helpers._DamerauLevenshtein('kitten', 'kites')) - self.assertEqual(2, _helpers._DamerauLevenshtein('kites', 'kitten')) - - def testDamerauLevenshteinTransposition(self): - self.assertEqual(1, _helpers._DamerauLevenshtein('kitten', 'ktiten')) - - def testMispelledSuggestions(self): - suggestions = _helpers.GetFlagSuggestions('fstack_protector_all', - self.longopts) - self.assertEqual(['fstack-protector-all'], suggestions) - - def testAmbiguousPrefixSuggestion(self): - suggestions = _helpers.GetFlagSuggestions('fstack', self.longopts) - self.assertEqual(['fstack-protector', 'fstack-protector-all'], suggestions) - - def testMisspelledAmbiguousPrefixSuggestion(self): - suggestions = _helpers.GetFlagSuggestions('stack', self.longopts) - self.assertEqual(['fstack-protector', 'fstack-protector-all'], suggestions) - - def testCrazySuggestion(self): - suggestions = _helpers.GetFlagSuggestions('asdfasdgasdfa', self.longopts) - self.assertEqual([], suggestions) - - -class GetCallingModuleTest(unittest.TestCase): - """Test whether we correctly determine the module which defines the flag.""" - - def testGetCallingModule(self): - self.assertEqual(_helpers.GetCallingModule(), sys.argv[0]) - self.assertEqual( - module_foo.GetModuleName(), - 'gflags.flags_modules_for_testing.module_foo') - self.assertEqual( - module_bar.GetModuleName(), - 'gflags.flags_modules_for_testing.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 = ('from gflags import _helpers\n' - 'module_name = _helpers.GetCallingModule()') - exec(code) # pylint: disable=exec-used - - # Next two exec statements executes code with a global environment - # that is different from the global environment of any imported - # module. - exec(code, {}) # pylint: disable=exec-used - # 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, dict(vars(self))) # pylint: disable=exec-used - - # 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, global_dict) # pylint: disable=exec-used - self.assertEqual(global_dict['module_name'], - sys.argv[0]) - - global_dict = {} - module_bar.ExecuteCode(code, global_dict) - self.assertEqual( - global_dict['module_name'], - 'gflags.flags_modules_for_testing.module_bar') - - def testGetCallingModuleWithIteritemsError(self): - # This test checks that GetCallingModule is using - # sys.modules.items(), instead of .iteritems(). - orig_sys_modules = sys.modules - - # Mock sys.modules: simulates error produced by importing a module - # in paralel with our iteration over sys.modules.iteritems(). - class SysModulesMock(dict): - - def __init__(self, original_content): - dict.__init__(self, original_content) - - def iteritems(self): - # Any dictionary method is fine, but not .iteritems(). - raise RuntimeError('dictionary changed size during iteration') - - sys.modules = SysModulesMock(orig_sys_modules) - try: - # _GetCallingModule should still work as expected: - self.assertEqual(_helpers.GetCallingModule(), sys.argv[0]) - self.assertEqual( - module_foo.GetModuleName(), - 'gflags.flags_modules_for_testing.module_foo') - finally: - sys.modules = orig_sys_modules - - -class IsRunningTestTest(unittest.TestCase): - - def testUnderTest(self): - self.assertTrue(_helpers.IsRunningTest()) - - -def main(): - unittest.main() - - -if __name__ == '__main__': - main() diff --git a/third_party/py/gflags/gflags/argument_parser.py b/third_party/py/gflags/gflags/argument_parser.py deleted file mode 100644 index 8e3edaf4941d36..00000000000000 --- a/third_party/py/gflags/gflags/argument_parser.py +++ /dev/null @@ -1,480 +0,0 @@ -#!/usr/bin/env python -# Copyright 2002 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. - - -"""Contains base classes used to parse and convert arguments. - -Instead of importing this module directly, it's preferable to import the -flags package and use the aliases defined at the package level. -""" - -import csv -import io -import string - -import six - -from gflags import _helpers - - -class _ArgumentParserCache(type): - """Metaclass used to cache and share argument parsers among flags.""" - - _instances = {} - - def __new__(mcs, name, bases, dct): - _helpers.define_both_methods(name, dct, 'Parse', 'parse') - _helpers.define_both_methods(name, dct, 'Type', 'flag_type') - _helpers.define_both_methods(name, dct, 'Convert', 'convert') - return type.__new__(mcs, name, bases, dct) - - def __call__(cls, *args, **kwargs): - """Returns an instance of the argument parser cls. - - This method overrides behavior of the __new__ methods in - all subclasses of ArgumentParser (inclusive). If an instance - for cls with the same set of arguments exists, this instance is - returned, otherwise a new instance is created. - - If any keyword arguments are defined, or the values in args - are not hashable, this method always returns a new instance of - cls. - - Args: - *args: Positional initializer arguments. - **kwargs: Initializer keyword arguments. - - Returns: - An instance of cls, shared or new. - """ - if kwargs: - return type.__call__(cls, *args, **kwargs) - else: - instances = cls._instances - key = (cls,) + tuple(args) - try: - return instances[key] - except KeyError: - # No cache entry for key exists, create a new one. - return instances.setdefault(key, type.__call__(cls, *args)) - except TypeError: - # An object in args cannot be hashed, always return - # a new instance. - return type.__call__(cls, *args) - - -class ArgumentParser(six.with_metaclass(_ArgumentParserCache, object)): - """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. - - Argument parser classes must be stateless, since instances are cached - and shared between flags. Initializer arguments are allowed, but all - member variables must be derived from initializer arguments only. - """ - - syntactic_help = '' - - def parse(self, argument): - """Parses the string argument and returns the native value. - - By default it returns its argument unmodified. - - Args: - argument: string argument passed in the commandline. - - Raises: - ValueError: Raised when it fails to parse the argument. - - Returns: - The parsed value in native type. - """ - return argument - - def flag_type(self): - """Returns a string representing the type of the flag.""" - return 'string' - - def _custom_xml_dom_elements(self, doc): # pylint: disable=unused-argument - """Returns a list of XML DOM elements to add additional flag information. - - Args: - doc: A minidom.Document, the DOM document it should create nodes from. - - Returns: - A list of minidom.Element. - """ - return [] - - -class _ArgumentSerializerMeta(type): - - def __new__(mcs, name, bases, dct): - _helpers.define_both_methods(name, dct, 'Serialize', 'serialize') - return type.__new__(mcs, name, bases, dct) - - -class ArgumentSerializer(six.with_metaclass(_ArgumentSerializerMeta, object)): - """Base class for generating string representations of a flag value.""" - - def serialize(self, value): - return _helpers.StrOrUnicode(value) - - -class NumericParser(ArgumentParser): - """Parser of numeric values. - - Parsed value may be bounded to a given upper and lower bound. - """ - - def is_outside_bounds(self, val): - return ((self.lower_bound is not None and val < self.lower_bound) or - (self.upper_bound is not None and val > self.upper_bound)) - - def parse(self, argument): - val = self.convert(argument) - if self.is_outside_bounds(val): - raise ValueError('%s is not %s' % (val, self.syntactic_help)) - return val - - def _custom_xml_dom_elements(self, doc): - elements = [] - if self.lower_bound is not None: - elements.append(_helpers.CreateXMLDOMElement( - doc, 'lower_bound', self.lower_bound)) - if self.upper_bound is not None: - elements.append(_helpers.CreateXMLDOMElement( - doc, 'upper_bound', self.upper_bound)) - return elements - - def convert(self, argument): - """Default implementation: always returns its argument unmodified.""" - return argument - - -class FloatParser(NumericParser): - """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): - super(FloatParser, self).__init__() - self.lower_bound = lower_bound - self.upper_bound = upper_bound - sh = self.syntactic_help - if lower_bound is not None and upper_bound is not None: - sh = ('%s in the range [%s, %s]' % (sh, lower_bound, upper_bound)) - elif lower_bound == 0: - sh = 'a non-negative %s' % self.number_name - elif upper_bound == 0: - sh = 'a non-positive %s' % self.number_name - elif upper_bound is not None: - sh = '%s <= %s' % (self.number_name, upper_bound) - elif lower_bound is not 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 flag_type(self): - return 'float' - - -class IntegerParser(NumericParser): - """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 __init__(self, lower_bound=None, upper_bound=None): - super(IntegerParser, self).__init__() - self.lower_bound = lower_bound - self.upper_bound = upper_bound - sh = self.syntactic_help - if lower_bound is not None and upper_bound is not 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 == 0: - sh = 'a non-positive %s' % self.number_name - elif upper_bound is not None: - sh = '%s <= %s' % (self.number_name, upper_bound) - elif lower_bound is not None: - sh = '%s >= %s' % (self.number_name, lower_bound) - self.syntactic_help = sh - - def convert(self, argument): - if isinstance(argument, str): - base = 10 - if len(argument) > 2 and argument[0] == '0': - if argument[1] == 'o': - base = 8 - elif argument[1] == 'x': - base = 16 - return int(argument, base) - else: - return int(argument) - - def flag_type(self): - return 'int' - - -class BooleanParser(ArgumentParser): - """Parser of boolean values.""" - - def convert(self, argument): - """Converts the argument to a boolean; raise ValueError on errors.""" - if isinstance(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 flag_type(self): - return 'bool' - - -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, case_sensitive=True): - """Initialize EnumParser. - - Args: - enum_values: Array of values in the enum. - case_sensitive: Whether or not the enum is to be case-sensitive. - """ - super(EnumParser, self).__init__() - self.enum_values = enum_values - self.case_sensitive = case_sensitive - - def parse(self, argument): - """Determine validity of argument and return the correct element of enum. - - If self.enum_values is empty, then all arguments are valid and argument - will be returned. - - Otherwise, if argument matches an element in enum, then the first - matching element will be returned. - - Args: - argument: The supplied flag value. - - Returns: - The matching element from enum_values, or argument if enum_values is - empty. - - Raises: - ValueError: enum_values was non-empty, but argument didn't match - anything in enum. - """ - if not self.enum_values: - return argument - elif self.case_sensitive: - if argument not in self.enum_values: - raise ValueError('value should be one of <%s>' % - '|'.join(self.enum_values)) - else: - return argument - else: - if argument.upper() not in [value.upper() for value in self.enum_values]: - raise ValueError('value should be one of <%s>' % - '|'.join(self.enum_values)) - else: - return [value for value in self.enum_values - if value.upper() == argument.upper()][0] - - def flag_type(self): - return 'string enum' - - -class ListSerializer(ArgumentSerializer): - - def __init__(self, list_sep): - self.list_sep = list_sep - - def serialize(self, value): - return self.list_sep.join([_helpers.StrOrUnicode(x) for x in value]) - - -class CsvListSerializer(ArgumentSerializer): - - def __init__(self, list_sep): - self.list_sep = list_sep - - def serialize(self, value): - """Serialize a list as a string, if possible, or as a unicode string.""" - if six.PY2: - # In Python2 csv.writer doesn't accept unicode, so we convert to UTF-8. - output = io.BytesIO() - csv.writer(output).writerow([unicode(x).encode('utf-8') for x in value]) - serialized_value = output.getvalue().decode('utf-8').strip() - else: - # In Python3 csv.writer expects a text stream. - output = io.StringIO() - csv.writer(output).writerow([str(x) for x in value]) - serialized_value = output.getvalue().strip() - - # We need the returned value to be pure ascii or Unicodes so that - # when the xml help is generated they are usefully encodable. - return _helpers.StrOrUnicode(serialized_value) - - -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 - super(BaseListParser, self).__init__() - 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 not argument: - return [] - else: - return [s.strip() for s in argument.split(self._token)] - - def flag_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 parse(self, argument): - """Override to support full CSV syntax.""" - if isinstance(argument, list): - return argument - elif not argument: - return [] - else: - try: - return [s.strip() for s in list(csv.reader([argument], strict=True))[0]] - except csv.Error as e: - # Provide a helpful report for case like - # --listflag="$(printf 'hello,\nworld')" - # IOW, list flag values containing naked newlines. This error - # was previously "reported" by allowing csv.Error to - # propagate. - raise ValueError('Unable to parse the value %r as a %s: %s' - % (argument, self.flag_type(), e)) - - def _custom_xml_dom_elements(self, doc): - elements = super(ListParser, self)._custom_xml_dom_elements(doc) - elements.append(_helpers.CreateXMLDOMElement( - doc, 'list_separator', repr(','))) - return elements - - -class WhitespaceSeparatedListParser(BaseListParser): - """Parser for a whitespace-separated list of strings.""" - - def __init__(self, comma_compat=False): - """Initializer. - - Args: - comma_compat: bool - Whether to support comma as an additional separator. - If false then only whitespace is supported. This is intended only for - backwards compatibility with flags that used to be comma-separated. - """ - self._comma_compat = comma_compat - name = 'whitespace or comma' if self._comma_compat else 'whitespace' - BaseListParser.__init__(self, None, name) - - def parse(self, argument): - """Override to support comma compatibility.""" - if isinstance(argument, list): - return argument - elif not argument: - return [] - else: - if self._comma_compat: - argument = argument.replace(',', ' ') - return argument.split() - - def _custom_xml_dom_elements(self, doc): - elements = super(WhitespaceSeparatedListParser, self - )._custom_xml_dom_elements(doc) - separators = list(string.whitespace) - if self._comma_compat: - separators.append(',') - separators.sort() - for sep_char in separators: - elements.append(_helpers.CreateXMLDOMElement( - doc, 'list_separator', repr(sep_char))) - return elements diff --git a/third_party/py/gflags/gflags/exceptions.py b/third_party/py/gflags/gflags/exceptions.py deleted file mode 100644 index 86ca1587df5fbc..00000000000000 --- a/third_party/py/gflags/gflags/exceptions.py +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/env python -# Copyright 2002 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. - - -"""//gflags exceptions. - -Instead of importing this module directly, it's preferable to import the -flags package and use the aliases defined at the package level. -""" - -import sys - -from gflags import _helpers - - -# TODO(vrusinov): use DISCLAIM_key_flags when it's moved out of __init__. -_helpers.disclaim_module_ids.add(id(sys.modules[__name__])) - - -class Error(Exception): - """The base class for all flags errors.""" - - -# TODO(b/31596146): Remove FlagsError. -FlagsError = Error - - -class CantOpenFlagFileError(Error): - """Raised if flagfile fails to open: doesn't exist, wrong permissions, etc.""" - - -class DuplicateFlagCannotPropagateNoneToSwig(Error): - """Raised when redefining a SWIG flag and the default value is None. - - It's raised when redefining a SWIG flag with allow_override=True and the - default value is None. Because it's currently impossible to pass None default - value back to SWIG. See FlagValues.SetDefault for details. - """ - - -class DuplicateFlagError(Error): - """Raised if there is a flag naming conflict.""" - - @classmethod - def from_flag(cls, flagname, flag_values, other_flag_values=None): - """Create a DuplicateFlagError by providing flag name and values. - - Args: - flagname: Name of the flag being redefined. - flag_values: FlagValues object containing the first definition of - flagname. - other_flag_values: If this argument is not None, it should be the - FlagValues object where the second definition of flagname occurs. - If it is None, we assume that we're being called when attempting - to create the flag a second time, and we use the module calling - this one as the source of the second definition. - - Returns: - An instance of DuplicateFlagError. - """ - first_module = flag_values.FindModuleDefiningFlag( - flagname, default='') - if other_flag_values is None: - second_module = _helpers.GetCallingModule() - else: - second_module = other_flag_values.FindModuleDefiningFlag( - flagname, default='') - flag_summary = flag_values[flagname].help - msg = ("The flag '%s' is defined twice. First from %s, Second from %s. " - "Description from first occurrence: %s") % ( - flagname, first_module, second_module, flag_summary) - return cls(msg) - - -class IllegalFlagValueError(Error): - """Raised if the flag command line argument is illegal.""" - - -# TODO(yileiyang): Remove IllegalFlagValue. -IllegalFlagValue = IllegalFlagValueError - - -class UnrecognizedFlagError(Error): - """Raised if a flag is unrecognized. - - Attributes: - flagname: Name of the unrecognized flag. - flagvalue: Value of the flag, empty if the flag is not defined. - """ - - def __init__(self, flagname, flagvalue='', suggestions=None): - self.flagname = flagname - self.flagvalue = flagvalue - if suggestions: - tip = '. Did you mean: %s?' % ', '.join(suggestions) - else: - tip = '' - Error.__init__( - self, 'Unknown command line flag \'%s\'%s' % (flagname, tip)) - - -class UnparsedFlagAccessError(Error): - """Attempt to use flag from unparsed FlagValues.""" - - -class ValidationError(Error): - """Raised if flag validator constraint is not satisfied.""" diff --git a/third_party/py/gflags/gflags/flag.py b/third_party/py/gflags/gflags/flag.py deleted file mode 100644 index b0b2dd998ca3cd..00000000000000 --- a/third_party/py/gflags/gflags/flag.py +++ /dev/null @@ -1,416 +0,0 @@ -#!/usr/bin/env python -# Copyright 2002 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. - -"""Contains Flag class - information about single command-line flag. - -Instead of importing this module directly, it's preferable to import the -flags package and use the aliases defined at the package level. -""" - -from functools import total_ordering - -import six - -from gflags import _helpers -from gflags import argument_parser -from gflags import exceptions - - -class _FlagMetaClass(type): - - def __new__(mcs, name, bases, dct): - _helpers.define_both_methods(name, dct, 'Parse', 'parse') - _helpers.define_both_methods(name, dct, 'Unparse', 'unparse') - _helpers.define_both_methods(name, dct, 'Serialize', 'serialize') - - # TODO(b/32385202): Migrate all users to use FlagValues.SetDefault and - # remove the public Flag.SetDefault method. - _helpers.define_both_methods(name, dct, 'SetDefault', '_set_default') - - _helpers.define_both_methods(name, dct, 'Type', 'flag_type') - return type.__new__(mcs, name, bases, dct) - - -@total_ordering -class Flag(six.with_metaclass(_FlagMetaClass, object)): - """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, and - newly defined flag overrides the old one. - .allow_cpp_override - the flag may be redefined in C++ without raising an - error, value "transfered" to C++, and the flag is - replaced by the C++ flag after init; - .allow_hide_cpp - the flag may be redefined despite hiding a C++ flag with - the same name; - .using_default_value - the flag value has not been set by user; - .allow_overwrite - the flag may be parsed more than once without raising - an error, the last set value will be used; - - 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, an Error 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=False, allow_override=False, - allow_cpp_override=False, allow_hide_cpp=False, - allow_overwrite=True, parse_default=True): - 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.allow_cpp_override = allow_cpp_override - self.allow_hide_cpp = allow_hide_cpp - self.allow_overwrite = allow_overwrite - - self.using_default_value = True - self._value = None - self.validators = [] - if allow_hide_cpp and allow_cpp_override: - raise exceptions.Error( - "Can't have both allow_hide_cpp (means use Python flag) and " - 'allow_cpp_override (means use C++ flag after InitGoogle)') - - if parse_default: - self._set_default(default) - else: - self.default = default - - @property - def value(self): - return self._value - - @value.setter - def value(self, value): - self._value = value - - def __hash__(self): - return hash(id(self)) - - def __eq__(self, other): - return self is other - - def __lt__(self, other): - if isinstance(other, Flag): - return id(self) < id(other) - return NotImplemented - - def _get_parsed_value_as_string(self, value): - """Get parsed flag value as string.""" - 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(_helpers.StrOrUnicode(value)) - - def parse(self, argument): - """Parse string and set flag value. - - Args: - argument: String, value to be parsed for flag. - """ - if self.present and not self.allow_overwrite: - raise exceptions.IllegalFlagValueError( - 'flag --%s=%s: already defined as %s' % ( - self.name, argument, self.value)) - try: - self.value = self.parser.parse(argument) - except ValueError as e: # Recast ValueError as IllegalFlagValueError. - raise exceptions.IllegalFlagValueError( - 'flag --%s=%s: %s' % (self.name, argument, e)) - self.present += 1 - - def unparse(self): - if self.default is None: - self.value = None - else: - self.present = 0 - self.Parse(self.default) - self.using_default_value = True - 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 exceptions.Error( - 'Serializer not present for flag %s' % self.name) - return '--%s=%s' % (self.name, self.serializer.serialize(self.value)) - - def _set_default(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 exceptions.DuplicateFlagCannotPropagateNoneToSwig(self.name) - - self.default = value - self.unparse() - self.default_as_str = self._get_parsed_value_as_string(self.value) - - def flag_type(self): - """Get type of 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. - - Returns: - a string that describes the type of this Flag. - """ - return self.parser.flag_type() - - def _create_xml_dom_element(self, doc, module_name, is_key=False): - """Returns an XML element that contains this flag's information. - - 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 _ExtraXMLInfo. - - Please do NOT override this method. - - Args: - doc: A minidom.Document, the DOM document it should create nodes from. - 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. - - Returns: - A minidom.Element instance. - """ - element = doc.createElement('flag') - if is_key: - element.appendChild(_helpers.CreateXMLDOMElement(doc, 'key', 'yes')) - element.appendChild(_helpers.CreateXMLDOMElement(doc, 'file', module_name)) - # Adds flag features that are relevant for all flags. - element.appendChild(_helpers.CreateXMLDOMElement(doc, 'name', self.name)) - if self.short_name: - element.appendChild(_helpers.CreateXMLDOMElement( - doc, 'short_name', self.short_name)) - if self.help: - element.appendChild(_helpers.CreateXMLDOMElement( - doc, 'meaning', self.help)) - # The default flag value can either be represented as a string like on the - # command line, or as a Python object. We serialize this value in the - # latter case in order to remain consistent. - if self.serializer and not isinstance(self.default, str): - if self.default is not None: - default_serialized = self.serializer.serialize(self.default) - else: - default_serialized = '' - else: - default_serialized = self.default - element.appendChild(_helpers.CreateXMLDOMElement( - doc, 'default', default_serialized)) - element.appendChild(_helpers.CreateXMLDOMElement( - doc, 'current', self.value)) - element.appendChild(_helpers.CreateXMLDOMElement( - doc, 'type', self.flag_type())) - # Adds extra flag features this flag may have. - for e in self._extra_xml_dom_elements(doc): - element.appendChild(e) - return element - - def _extra_xml_dom_elements(self, doc): - """Returns extra info about this flag in XML. - - "Extra" means "not already included by _create_xml_dom_element above." - - Args: - doc: A minidom.Document, the DOM document it should create nodes from. - - Returns: - A list of minidom.Element. - """ - # Usually, the parser knows the extra details about the flag, so - # we just forward the call to it. - return self.parser._custom_xml_dom_elements(doc) # pylint: disable=protected-access - - -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): # pylint: disable=redefined-builtin - p = argument_parser.BooleanParser() - Flag.__init__(self, p, None, name, default, help, short_name, 1, **args) - - -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, # pylint: disable=redefined-builtin - short_name=None, case_sensitive=True, **args): - enum_values = enum_values or [] - p = argument_parser.EnumParser(enum_values, case_sensitive) - g = argument_parser.ArgumentSerializer() - Flag.__init__(self, p, g, name, default, help, short_name, **args) - self.help = '<%s>: %s' % ('|'.join(enum_values), self.help) - - def _extra_xml_dom_elements(self, doc): - elements = [] - for enum_value in self.parser.enum_values: - elements.append(_helpers.CreateXMLDOMElement( - doc, 'enum_value', enum_value)) - return elements - - -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 exceptions.Error( - '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 flag_type(self): - return 'multi ' + self.parser.flag_type() - - def _extra_xml_dom_elements(self, doc): - elements = [] - if hasattr(self.parser, 'enum_values'): - for enum_value in self.parser.enum_values: - elements.append(_helpers.CreateXMLDOMElement( - doc, 'enum_value', enum_value)) - return elements diff --git a/third_party/py/gflags/gflags/flags_formatting_test.py b/third_party/py/gflags/gflags/flags_formatting_test.py deleted file mode 100644 index a2a925a802801f..00000000000000 --- a/third_party/py/gflags/gflags/flags_formatting_test.py +++ /dev/null @@ -1,201 +0,0 @@ -#!/usr/bin/env python -import unittest - -import gflags -from gflags import _helpers - -FLAGS = gflags.FLAGS - - -class FlagsUnitTest(unittest.TestCase): - """Flags formatting Unit Test.""" - - def testGetHelpWidth(self): - """Verify that GetHelpWidth() reflects _help_width.""" - default_help_width = _helpers._DEFAULT_HELP_WIDTH # Save. - self.assertEqual(80, _helpers._DEFAULT_HELP_WIDTH) - self.assertEqual(_helpers._DEFAULT_HELP_WIDTH, gflags.GetHelpWidth()) - _helpers._DEFAULT_HELP_WIDTH = 10 - self.assertEqual(_helpers._DEFAULT_HELP_WIDTH, gflags.GetHelpWidth()) - _helpers._DEFAULT_HELP_WIDTH = default_help_width # restore - - def testTextWrap(self): - """Test that wrapping works as expected. - - Also tests that it is using global gflags._help_width by default. - """ - default_help_width = _helpers._DEFAULT_HELP_WIDTH - _helpers._DEFAULT_HELP_WIDTH = 10 - - # Generate a string with length 40, no spaces - text = '' - expect = [] - for n in range(4): - line = str(n) - line += '123456789' - text += line - expect.append(line) - - # Verify we still break - wrapped = gflags.TextWrap(text).split('\n') - self.assertEqual(4, len(wrapped)) - self.assertEqual(expect, wrapped) - - wrapped = gflags.TextWrap(text, 80).split('\n') - self.assertEqual(1, len(wrapped)) - self.assertEqual([text], wrapped) - - # Normal case, breaking at word boundaries and rewriting new lines - input_value = 'a b c d e f g h' - expect = {1: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'], - 2: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'], - 3: ['a b', 'c d', 'e f', 'g h'], - 4: ['a b', 'c d', 'e f', 'g h'], - 5: ['a b c', 'd e f', 'g h'], - 6: ['a b c', 'd e f', 'g h'], - 7: ['a b c d', 'e f g h'], - 8: ['a b c d', 'e f g h'], - 9: ['a b c d e', 'f g h'], - 10: ['a b c d e', 'f g h'], - 11: ['a b c d e f', 'g h'], - 12: ['a b c d e f', 'g h'], - 13: ['a b c d e f g', 'h'], - 14: ['a b c d e f g', 'h'], - 15: ['a b c d e f g h']} - for width, exp in expect.items(): - self.assertEqual(exp, gflags.TextWrap(input_value, width).split('\n')) - - # We turn lines with only whitespace into empty lines - # We strip from the right up to the first new line - self.assertEqual('', gflags.TextWrap(' ')) - self.assertEqual('\n', gflags.TextWrap(' \n ')) - self.assertEqual('\n', gflags.TextWrap('\n\n')) - self.assertEqual('\n\n', gflags.TextWrap('\n\n\n')) - self.assertEqual('\n', gflags.TextWrap('\n ')) - self.assertEqual('a\n\nb', gflags.TextWrap('a\n \nb')) - self.assertEqual('a\n\n\nb', gflags.TextWrap('a\n \n \nb')) - self.assertEqual('a\nb', gflags.TextWrap(' a\nb ')) - self.assertEqual('\na\nb', gflags.TextWrap('\na\nb\n')) - self.assertEqual('\na\nb\n', gflags.TextWrap(' \na\nb\n ')) - self.assertEqual('\na\nb\n', gflags.TextWrap(' \na\nb\n\n')) - - # Double newline. - self.assertEqual('a\n\nb', gflags.TextWrap(' a\n\n b')) - - # We respect prefix - self.assertEqual(' a\n b\n c', gflags.TextWrap('a\nb\nc', 80, ' ')) - self.assertEqual('a\n b\n c', gflags.TextWrap('a\nb\nc', 80, ' ', '')) - - # tabs - self.assertEqual('a\n b c', - gflags.TextWrap('a\nb\tc', 80, ' ', '')) - self.assertEqual('a\n bb c', - gflags.TextWrap('a\nbb\tc', 80, ' ', '')) - self.assertEqual('a\n bbb c', - gflags.TextWrap('a\nbbb\tc', 80, ' ', '')) - self.assertEqual('a\n bbbb c', - gflags.TextWrap('a\nbbbb\tc', 80, ' ', '')) - self.assertEqual('a\n b\n c\n d', - gflags.TextWrap('a\nb\tc\td', 3, ' ', '')) - self.assertEqual('a\n b\n c\n d', - gflags.TextWrap('a\nb\tc\td', 4, ' ', '')) - self.assertEqual('a\n b\n c\n d', - gflags.TextWrap('a\nb\tc\td', 5, ' ', '')) - self.assertEqual('a\n b c\n d', - gflags.TextWrap('a\nb\tc\td', 6, ' ', '')) - self.assertEqual('a\n b c\n d', - gflags.TextWrap('a\nb\tc\td', 7, ' ', '')) - self.assertEqual('a\n b c\n d', - gflags.TextWrap('a\nb\tc\td', 8, ' ', '')) - self.assertEqual('a\n b c\n d', - gflags.TextWrap('a\nb\tc\td', 9, ' ', '')) - self.assertEqual('a\n b c d', - gflags.TextWrap('a\nb\tc\td', 10, ' ', '')) - - # multiple tabs - self.assertEqual('a c', - gflags.TextWrap('a\t\tc', 80, ' ', '')) - - _helpers._DEFAULT_HELP_WIDTH = default_help_width # restore - - def testDocToHelp(self): - self.assertEqual('', gflags.DocToHelp(' ')) - self.assertEqual('', gflags.DocToHelp(' \n ')) - self.assertEqual('a\n\nb', gflags.DocToHelp('a\n \nb')) - self.assertEqual('a\n\n\nb', gflags.DocToHelp('a\n \n \nb')) - self.assertEqual('a b', gflags.DocToHelp(' a\nb ')) - self.assertEqual('a b', gflags.DocToHelp('\na\nb\n')) - self.assertEqual('a\n\nb', gflags.DocToHelp('\na\n\nb\n')) - self.assertEqual('a b', gflags.DocToHelp(' \na\nb\n ')) - # Different first line, one line empty - erm double new line. - self.assertEqual('a b c\n\nd', gflags.DocToHelp('a\n b\n c\n\n d')) - self.assertEqual('a b\n c d', gflags.DocToHelp('a\n b\n \tc\n d')) - self.assertEqual('a b\n c\n d', - gflags.DocToHelp('a\n b\n \tc\n \td')) - - def testDocToHelp_FlagValues(self): - # !!!!!!!!!!!!!!!!!!!! - # The following doc string is taken as is directly from gflags.py:FlagValues - # The intention of this test is to verify 'live' performance - # !!!!!!!!!!!!!!!!!!!! - """Used as a registry for 'Flag' objects. - - A 'FlagValues' can then scan command line arguments, passing flag - arguments through to the 'Flag' objects that it owns. It also - provides easy access to the flag values. Typically only one - 'FlagValues' object is needed by an application: gflags.FLAGS - - This class is heavily overloaded: - - 'Flag' objects are registered via __setitem__: - FLAGS['longname'] = x # register a new flag - - The .value member of the registered 'Flag' objects can be accessed as - members of this 'FlagValues' object, through __getattr__. Both the - long and short name of the original 'Flag' objects can be used to - access its value: - FLAGS.longname # parsed flag value - FLAGS.x # parsed flag value (short name) - - Command line arguments are scanned and passed to the registered 'Flag' - objects through the __call__ method. Unparsed arguments, including - argv[0] (e.g. the program name) are returned. - argv = FLAGS(sys.argv) # scan command line arguments - - The original registered Flag objects can be retrieved through the use - """ - doc = gflags.DocToHelp(self.testDocToHelp_FlagValues.__doc__) - # Test the general outline of the converted docs - lines = doc.splitlines() - self.assertEqual(17, len(lines)) - empty_lines = [index for index in range(len(lines)) if not lines[index]] - self.assertEqual([1, 3, 5, 8, 12, 15], empty_lines) - # test that some starting prefix is kept - flags_lines = [index for index in range(len(lines)) - if lines[index].startswith(' FLAGS')] - self.assertEqual([7, 10, 11], flags_lines) - # but other, especially common space has been removed - space_lines = [index for index in range(len(lines)) - if lines[index] and lines[index][0].isspace()] - self.assertEqual([7, 10, 11, 14], space_lines) - # No right space was kept - rspace_lines = [index for index in range(len(lines)) - if lines[index] != lines[index].rstrip()] - self.assertEqual([], rspace_lines) - # test double spaces are kept - self.assertEqual(True, lines[2].endswith('application: gflags.FLAGS')) - - def testTextWrapRaisesOnExcessiveIndent(self): - """Ensure an indent longer than line length raises.""" - self.assertRaises(ValueError, - gflags.TextWrap, 'dummy', length=10, indent=' ' * 10) - - def testTextWrapRaisesOnExcessiveFirstLine(self): - """Ensure a first line indent longer than line length raises.""" - self.assertRaises( - ValueError, - gflags.TextWrap, 'dummy', length=80, firstline_indent=' ' * 80) - - -if __name__ == '__main__': - unittest.main() diff --git a/third_party/py/gflags/gflags/flags_modules_for_testing/__init__.py b/third_party/py/gflags/gflags/flags_modules_for_testing/__init__.py deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/third_party/py/gflags/gflags/flags_modules_for_testing/module_bar.py b/third_party/py/gflags/gflags/flags_modules_for_testing/module_bar.py deleted file mode 100644 index f703be8eb9c4bf..00000000000000 --- a/third_party/py/gflags/gflags/flags_modules_for_testing/module_bar.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python -# Copyright 2014 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 gflags.py. - -The purpose of this module is to define a few flags. We want to make -sure the unit tests for gflags.py involve more than one module. -""" - -__author__ = 'salcianu@google.com (Alex Salcianu)' - -import gflags -from gflags import _helpers - -FLAGS = gflags.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. - gflags.DEFINE_boolean('tmod_bar_x', True, 'Boolean flag.', - flag_values=flag_values) - gflags.DEFINE_string('tmod_bar_y', 'default', 'String flag.', - flag_values=flag_values) - gflags.DEFINE_boolean('tmod_bar_z', False, - 'Another boolean flag from module bar.', - flag_values=flag_values) - gflags.DEFINE_integer('tmod_bar_t', 4, 'Sample int flag.', - flag_values=flag_values) - gflags.DEFINE_integer('tmod_bar_u', 5, 'Sample int flag.', - flag_values=flag_values) - gflags.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 gflags.FLAGS. - - Note: if the flag is not defined in gflags.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 GetCallingModule() to return the name of this module. - - For checking that _GetCallingModule works as expected. - - Returns: - A string, the name of this module. - """ - return _helpers.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, global_dict) # pylint: disable=exec-used - - -def DisclaimKeyFlags(): - """Disclaims flags declared in this module.""" - gflags.DISCLAIM_key_flags() diff --git a/third_party/py/gflags/gflags/flags_modules_for_testing/module_baz.py b/third_party/py/gflags/gflags/flags_modules_for_testing/module_baz.py deleted file mode 100644 index cb47832ba330ba..00000000000000 --- a/third_party/py/gflags/gflags/flags_modules_for_testing/module_baz.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python -# Copyright 2014 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 gflags.py. - -The purpose of this module is to test the behavior of flags that are defined -before main() executes. -""" - - - - -import gflags - -FLAGS = gflags.FLAGS - -gflags.DEFINE_boolean('tmod_baz_x', True, 'Boolean flag.') diff --git a/third_party/py/gflags/gflags/flags_modules_for_testing/module_foo.py b/third_party/py/gflags/gflags/flags_modules_for_testing/module_foo.py deleted file mode 100644 index f5f0998c0692a0..00000000000000 --- a/third_party/py/gflags/gflags/flags_modules_for_testing/module_foo.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env python -# Copyright 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 gflags.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 gflags.py involve more than one module. -""" - -__author__ = 'salcianu@google.com (Alex Salcianu)' - -import gflags -from gflags import _helpers -from gflags.flags_modules_for_testing import module_bar - -FLAGS = gflags.FLAGS - - -DECLARED_KEY_FLAGS = ['tmod_bar_x', 'tmod_bar_z', 'tmod_bar_t', - # Special (not user-defined) flag: - 'flagfile'] - - -def DefineFlags(flag_values=FLAGS): - """Defines a few flags.""" - module_bar.DefineFlags(flag_values=flag_values) - # The 'tmod_foo_' prefix (short for 'test_module_foo') ensures that we - # have no name clash with existing flags. - gflags.DEFINE_boolean('tmod_foo_bool', True, 'Boolean flag from module foo.', - flag_values=flag_values) - gflags.DEFINE_string('tmod_foo_str', 'default', 'String flag.', - flag_values=flag_values) - gflags.DEFINE_integer('tmod_foo_int', 3, 'Sample int flag.', - flag_values=flag_values) - - -def DeclareKeyFlags(flag_values=FLAGS): - """Declares a few key flags.""" - for flag_name in DECLARED_KEY_FLAGS: - gflags.DECLARE_key_flag(flag_name, flag_values=flag_values) - - -def DeclareExtraKeyFlags(flag_values=FLAGS): - """Declares some extra key flags.""" - gflags.ADOPT_module_key_flags(module_bar, flag_values=flag_values) - - -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(flag_values=FLAGS): - """Deletes the flag definitions done by the above DefineFlags().""" - for flag_name in NamesOfDefinedFlags(): - module_bar.RemoveOneFlag(flag_name, flag_values=flag_values) - module_bar.RemoveFlags(flag_values=flag_values) - - -def GetModuleName(): - """Uses GetCallingModule() to return the name of this module. - - For checking that _GetCallingModule works as expected. - - Returns: - A string, the name of this module. - """ - return _helpers.GetCallingModule() - - -def DuplicateFlags(flagnames=None): - """Returns a new FlagValues object with the requested flagnames. - - Used to test DuplicateFlagError detection. - - Args: - flagnames: str, A list of flag names to create. - - Returns: - A FlagValues object with one boolean flag for each name in flagnames. - """ - flag_values = gflags.FlagValues() - for name in flagnames: - gflags.DEFINE_boolean(name, False, 'Flag named %s' % (name,), - flag_values=flag_values) - return flag_values - - -def DefineBarFlags(flag_values=FLAGS): - """Defines flags from module_bar.""" - module_bar.DefineFlags(flag_values) diff --git a/third_party/py/gflags/gflags/flags_unicode_literals_test.py b/third_party/py/gflags/gflags/flags_unicode_literals_test.py deleted file mode 100644 index cb20887c13b1b0..00000000000000 --- a/third_party/py/gflags/gflags/flags_unicode_literals_test.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python -"""Test the use of flags when from __future__ import unicode_literals is on.""" - -from __future__ import unicode_literals - -import unittest -import gflags - - -gflags.DEFINE_string('seen_in_crittenden', 'alleged mountain lion', - 'This tests if unicode input to these functions works.') - - -class FlagsUnicodeLiteralsTest(unittest.TestCase): - - def testUnicodeFlagNameAndValueAreGood(self): - alleged_mountain_lion = gflags.FLAGS.seen_in_crittenden - self.assertTrue( - isinstance(alleged_mountain_lion, type(u'')), - msg='expected flag value to be a {} not {}'.format( - type(u''), type(alleged_mountain_lion))) - self.assertEqual(alleged_mountain_lion, u'alleged mountain lion') - - -if __name__ == '__main__': - unittest.main() diff --git a/third_party/py/gflags/gflags/flagvalues.py b/third_party/py/gflags/gflags/flagvalues.py deleted file mode 100644 index 0e487bbca80719..00000000000000 --- a/third_party/py/gflags/gflags/flagvalues.py +++ /dev/null @@ -1,1287 +0,0 @@ -#!/usr/bin/env python -# Copyright 2002 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. - -"""Flagvalues module - Registry of 'Flag' objects. - -Instead of importing this module directly, it's preferable to import the -flags package and use the aliases defined at the package level. -""" - -import hashlib -import logging -import os -import struct -import sys -import traceback -import warnings -from xml.dom import minidom - -import six - -from gflags import _helpers -from gflags import exceptions -from gflags import flag as _flag - -# Add flagvalues module to disclaimed module ids. -_helpers.disclaim_module_ids.add(id(sys.modules[__name__])) - -# The MOE directives in this file cause the docstring indentation -# linter to go nuts. -# pylint: disable=g-doc-bad-indent - -# Environment variable that controls whether to allow unparsed flag access. -# Do not rely on, it will be removed later. -_UNPARSED_FLAG_ACCESS_ENV_NAME = 'GFLAGS_ALLOW_UNPARSED_FLAG_ACCESS' - -# Percentage of the flag names for which unparsed flag access will fail by -# default. -_UNPARSED_ACCESS_DISABLED_PERCENT = 0 - -# b/32278439 will change flag parsing to use GNU-style scanning by default. -# This environment variable allows users to force setting the default parsing -# style. Do NOT rely on it. It will be removed as part of b/32278439. -_USE_GNU_GET_OPT_ENV_NAME = 'GFLAGS_USE_GNU_GET_OPT' - - - - -class FlagValues(object): - """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'] = {} - - # Set: name of hidden flag (string). - # Holds flags that should not be directly accessible from Python. - self.__dict__['__hiddenflags'] = set() - - # Dictionary: module name (string) -> list of Flag objects that are defined - # by that module. - self.__dict__['__flags_by_module'] = {} - # Dictionary: module id (int) -> list of Flag objects that are defined by - # that module. - self.__dict__['__flags_by_module_id'] = {} - # Dictionary: module name (string) -> list of Flag objects that are - # key for that module. - self.__dict__['__key_flags_by_module'] = {} - - # Bool: True if flags were parsed. - self.__dict__['__flags_parsed'] = False - - # Bool: True if Reset() was called. - self.__dict__['__reset_called'] = False - - # None or Method(name, value) to call from __setattr__ for an unknown flag. - self.__dict__['__set_unknown'] = None - - if _USE_GNU_GET_OPT_ENV_NAME in os.environ: - self.__dict__['__use_gnu_getopt'] = ( - os.environ[_USE_GNU_GET_OPT_ENV_NAME] == '1') - else: - # By default don't use the GNU-style scanning when parsing the args. - self.__dict__['__use_gnu_getopt'] = False - - def UseGnuGetOpt(self, use_gnu_getopt=True): - """Use GNU-style scanning. Allows mixing of flag and non-flag arguments. - - See http://docs.python.org/library/getopt.html#getopt.gnu_getopt - - Args: - use_gnu_getopt: wether or not to use GNU style scanning. - """ - 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 FlagsByModuleIdDict(self): - """Returns the dictionary of module_id -> list of defined flags. - - Returns: - A dictionary. Its keys are module IDs (ints). Its values - are lists of Flag objects. - """ - return self.__dict__['__flags_by_module_id'] - - 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 _RegisterFlagByModuleId(self, module_id, flag): - """Records the module that defines a specific flag. - - Args: - module_id: An int, the ID of the Python module. - flag: A Flag object, a flag that is key to the module. - """ - flags_by_module_id = self.FlagsByModuleIdDict() - flags_by_module_id.setdefault(module_id, []).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 _FlagIsRegistered(self, flag_obj): - """Checks whether a Flag object is registered under long name or short name. - - Args: - flag_obj: A Flag object. - - Returns: - A boolean: True iff flag_obj is registered under long name or short 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 - return False - - def _CleanupUnregisteredFlagFromModuleDicts(self, flag_obj): - """Cleanup unregistered flags from all module -> [flags] dictionaries. - - If flag_obj is registered under either its long name or short name, it - won't be removed from the dictionaries. - - Args: - flag_obj: A flag object. - """ - if self._FlagIsRegistered(flag_obj): - return - for flags_by_module_dict in (self.FlagsByModuleDict(), - self.FlagsByModuleIdDict(), - self.KeyFlagsByModuleDict()): - for flags_in_module in six.itervalues(flags_by_module_dict): - # While (as opposed to if) takes care of multiple occurrences of a - # flag in the list for the same module. - while flag_obj in flags_in_module: - flags_in_module.remove(flag_obj) - - 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 FindModuleDefiningFlag(self, flagname, default=None): - """Return the name of the module defining this flag, or default. - - Args: - flagname: Name of the flag to lookup. - default: Value to return if flagname is not defined. Defaults - to None. - - Returns: - The name of the module which registered the flag with this name. - If no such module exists (i.e. no flag with this name exists), - we return default. - """ - registered_flag = self.FlagDict().get(flagname) - if registered_flag is None: - return default - for module, flags in six.iteritems(self.FlagsByModuleDict()): - for flag in flags: - # It must compare the flag with the one in FlagDict. This is because a - # flag might be overridden only for its long name (or short name), - # and only its short name (or long name) is considered registered. - if (flag.name == registered_flag.name and - flag.short_name == registered_flag.short_name): - return module - return default - - def FindModuleIdDefiningFlag(self, flagname, default=None): - """Return the ID of the module defining this flag, or default. - - Args: - flagname: Name of the flag to lookup. - default: Value to return if flagname is not defined. Defaults - to None. - - Returns: - The ID of the module which registered the flag with this name. - If no such module exists (i.e. no flag with this name exists), - we return default. - """ - registered_flag = self.FlagDict().get(flagname) - if registered_flag is None: - return default - for module_id, flags in six.iteritems(self.FlagsByModuleIdDict()): - for flag in flags: - # It must compare the flag with the one in FlagDict. This is because a - # flag might be overridden only for its long name (or short name), - # and only its short name (or long name) is considered registered. - if (flag.name == registered_flag.name and - flag.short_name == registered_flag.short_name): - return module_id - return default - - def _RegisterUnknownFlagSetter(self, setter): - """Allow set default values for undefined flags. - - Args: - setter: Method(name, value) to call to __setattr__ an unknown flag. - Must raise NameError or ValueError for invalid name/value. - """ - self.__dict__['__set_unknown'] = setter - - def _SetUnknownFlag(self, name, value): - """Returns value if setting flag |name| to |value| returned True. - - Args: - name: Name of the flag to set. - value: Value to set. - - Returns: - Flag value on successful call. - - Raises: - UnrecognizedFlagError - IllegalFlagValueError - """ - setter = self.__dict__['__set_unknown'] - if setter: - try: - setter(name, value) - return value - except (TypeError, ValueError): # Flag value is not valid. - raise exceptions.IllegalFlagValueError('"{1}" is not valid for --{0}' - .format(name, value)) - except NameError: # Flag name is not valid. - pass - raise exceptions.UnrecognizedFlagError(name, value) - - def AppendFlagValues(self, flag_values): - """Appends flags registered in another FlagValues instance. - - Args: - flag_values: registry to copy from - """ - for flag_name, flag in six.iteritems(flag_values.FlagDict()): - # 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: - try: - self[flag_name] = flag - except exceptions.DuplicateFlagError: - raise exceptions.DuplicateFlagError.from_flag( - flag_name, self, other_flag_values=flag_values) - - def RemoveFlagValues(self, flag_values): - """Remove flags that were previously appended from another FlagValues. - - Args: - flag_values: registry containing flags to remove. - """ - for flag_name in flag_values.FlagDict(): - self.__delattr__(flag_name) - - def __setitem__(self, name, flag): - """Registers a new flag variable.""" - fl = self.FlagDict() - if not isinstance(flag, _flag.Flag): - raise exceptions.IllegalFlagValueError(flag) - if str is bytes and isinstance(name, unicode): - # When using Python 2 with unicode_literals, allow it but encode it - # into the bytes type we require. - name = name.encode('utf-8') - if not isinstance(name, type('')): - raise exceptions.Error('Flag name must be a string') - if not name: - raise exceptions.Error('Flag name cannot be empty') - if name in fl and not flag.allow_override and not fl[name].allow_override: - module, module_name = _helpers.GetCallingModuleObjectAndName() - if (self.FindModuleDefiningFlag(name) == module_name and - id(module) != self.FindModuleIdDefiningFlag(name)): - # If the flag has already been defined by a module with the same name, - # but a different ID, we can stop here because it indicates that the - # module is simply being imported a subsequent time. - return - raise exceptions.DuplicateFlagError.from_flag(name, self) - short_name = flag.short_name - # If a new flag overrides an old one, we need to cleanup the old flag's - # modules if it's not registered. - flags_to_cleanup = set() - if short_name is not None: - if (short_name in fl and not flag.allow_override and - not fl[short_name].allow_override): - raise exceptions.DuplicateFlagError.from_flag(short_name, self) - if short_name in fl and fl[short_name] != flag: - flags_to_cleanup.add(fl[short_name]) - fl[short_name] = flag - if (name not in fl # new flag - or fl[name].using_default_value - or not flag.using_default_value): - if name in fl and fl[name] != flag: - flags_to_cleanup.add(fl[name]) - fl[name] = flag - for f in flags_to_cleanup: - self._CleanupUnregisteredFlagFromModuleDicts(f) - - def __dir__(self): - """Returns list of names of all defined flags. - - Useful for TAB-completion in ipython. - - Returns: - list(str) - """ - return sorted(self.__dict__['__flags']) - - # TODO(olexiy): Call GetFlag() to raise UnrecognizedFlagError if name is - # unknown. - def __getitem__(self, name): - """Retrieves the Flag object for the flag --name.""" - return self.FlagDict()[name] - - def GetFlag(self, name): - """Same as __getitem__, but raises a specific error.""" - res = self.FlagDict().get(name) - if res is None: - raise exceptions.UnrecognizedFlagError(name) - return res - - def HideFlag(self, name): - """Mark the flag --name as hidden.""" - self.__dict__['__hiddenflags'].add(name) - - def _IsUnparsedFlagAccessAllowed(self, name): - """Determine whether to allow unparsed flag access or not.""" - if _UNPARSED_FLAG_ACCESS_ENV_NAME in os.environ: - # We've been told explicitly what to do. - allow_unparsed_flag_access = ( - os.getenv(_UNPARSED_FLAG_ACCESS_ENV_NAME) == '1') - elif self.__dict__['__reset_called']: - # Raise exception if .Reset() was called. This mostly happens in tests. - allow_unparsed_flag_access = False - elif _helpers.IsRunningTest(): - # Staged "rollout", based on name of the flag so that we don't break - # everyone. Hashing the flag is a way of choosing a random but - # consistent subset of flags to lock down which we can make larger - # over time. - name_bytes = name.encode('utf8') if not isinstance(name, bytes) else name - flag_percentile = ( - struct.unpack(' - - E.g., - - gflags.DEFINE_integer('foo', 1, 'Integer flag.') - del gflags.FLAGS.foo - - If a flag is also registered by its the other name (long name or short - name), the other name won't be deleted. - - 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] - - self._CleanupUnregisteredFlagFromModuleDicts(flag_obj) - - def _RemoveAllFlagAppearances(self, name): - """Removes flag with name for all appearances. - - A flag can be registered with its long name and an optional short name. - This method removes both of them. This is different than __delattr__. - - Args: - name: Either flag's long name or short name. - - Raises: - UnrecognizedFlagError: When flag name is not found. - """ - flag_dict = self.FlagDict() - if name not in flag_dict: - raise exceptions.UnrecognizedFlagError(name) - flag = flag_dict[name] - names_to_remove = {name} - names_to_remove.add(flag.name) - if flag.short_name: - names_to_remove.add(flag.short_name) - for n in names_to_remove: - self.__delattr__(n) - - def SetDefault(self, name, value): - """Changes the default value (and current value) of the named flag object. - - Call this method at the top level of a module to avoid overwriting the value - passed at the command line. - - Args: - name: A string, the name of the flag to modify. - value: The new default value. - - Raises: - UnrecognizedFlagError: When there is no registered flag named name. - IllegalFlagValueError: When value is not valid. - """ - fl = self.FlagDict() - if name not in fl: - self._SetUnknownFlag(name, value) - return - if self.IsParsed(): - logging.warn( - 'FLAGS.SetDefault called on flag "%s" after flag parsing. Call this ' - 'method at the top level of a module to avoid overwriting the value ' - 'passed at the command line.', - name) - fl[name]._set_default(value) # pylint: disable=protected-access - self._AssertValidators(fl[name].validators) - - 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 iter(self.FlagDict()) - - def __call__(self, argv, known_only=False): - """Parses flags from argv; stores parsed flags into this FlagValues object. - - All unparsed arguments are returned. - - Args: - argv: argument list. Can be of any type that may be converted to a list. - known_only: parse and remove known flags, return rest untouched. - - Returns: - The list of arguments not parsed as options, including argv[0]. - - Raises: - Error: on any parsing error. - ValueError: on flag value parsing error. - """ - if not argv: - # Unfortunately, the old parser used to accept an empty argv, and some - # users rely on that behaviour. Allow it as a special case for now. - self.MarkAsParsed() - self._AssertAllValidators() - return [] - - # This pre parses the argv list for --flagfile=<> options. - program_name = argv[0] - args = self.ReadFlagsFromFiles(argv[1:], force_gnu=False) - - # Parse the arguments. - unknown_flags, unparsed_args, undefok = self._ParseArgs(args, known_only) - - # Handle unknown flags by raising UnrecognizedFlagError. - # Note some users depend on us raising this particular error. - for name, value in unknown_flags: - if name in undefok: - continue - - suggestions = _helpers.GetFlagSuggestions( - name, self.RegisteredFlags()) - raise exceptions.UnrecognizedFlagError( - name, value, suggestions=suggestions) - - self.MarkAsParsed() - self._AssertAllValidators() - return [program_name] + unparsed_args - - def _ParseArgs(self, args, known_only): - """Helper function to do the main argument parsing. - - This function goes through args and does the bulk of the flag parsing. - It will find the corresponding flag in our flag dictionary, and call its - .parse() method on the flag value. - - Args: - args: List of strings with the arguments to parse. - known_only: parse and remove known flags, return rest in unparsed_args - - Returns: - A tuple with the following: - unknown_flags: List of (flag name, arg) for flags we don't know about. - unparsed_args: List of arguments we did not parse. - undefok: Set of flags that were given via --undefok. - - Raises: - Error: on any parsing error. - ValueError: on flag value parsing error. - """ - unknown_flags, unparsed_args, undefok = [], [], set() - - flag_dict = self.FlagDict() - args = iter(args) - for arg in args: - value = None - - def GetValue(): - # pylint: disable=cell-var-from-loop - try: - return next(args) if value is None else value - except StopIteration: - raise exceptions.Error('Missing value for flag ' + arg) - - if not arg.startswith('-'): - # A non-argument: default is break, GNU is skip. - unparsed_args.append(arg) - if self.IsGnuGetOpt(): - continue - else: - break - - if arg == '--': - if known_only: - unparsed_args.append(arg) - break - - if '=' in arg: - name, value = arg.lstrip('-').split('=', 1) - else: - name, value = arg.lstrip('-'), None - - if not name: - # The argument is all dashes (including one dash). - unparsed_args.append(arg) - if self.IsGnuGetOpt(): - continue - else: - break - - # --undefok is a special case. - if name == 'undefok': - if known_only: - unparsed_args.append(arg) - value = GetValue() - undefok.update(v.strip() for v in value.split(',')) - undefok.update('no' + v.strip() for v in value.split(',')) - continue - - flag = flag_dict.get(name) - if flag: - value = (flag.boolean and value is None) or GetValue() - elif name.startswith('no') and len(name) > 2: - # Boolean flags can take the form of --noflag, with no value. - noflag = flag_dict.get(name[2:]) - if noflag and noflag.boolean: - if value is not None: - raise ValueError(arg + ' does not take an argument') - flag = noflag - value = False - - - if flag: - flag.parse(value) - flag.using_default_value = False - elif known_only: - unparsed_args.append(arg) - else: - unknown_flags.append((name, arg)) - - unparsed_args.extend(args) - return unknown_flags, unparsed_args, undefok - - def IsParsed(self): - """Whether flags were parsed.""" - return self.__dict__['__flags_parsed'] - - def MarkAsParsed(self): - """Explicitly mark parsed. - - Use this when the caller knows that this FlagValues has been parsed as if - a __call__() invocation has happened. This is only a public method for - use by things like appcommands which do additional command like parsing. - """ - self.__dict__['__flags_parsed'] = True - - def Reset(self): - """Resets the values to the point before FLAGS(argv) was called.""" - for f in self.FlagDict().values(): - f.unparse() - # We log this message before marking flags as unparsed to avoid a - # problem when the logging library causes flags access. - logging.info('Reset() called; flags access will now raise errors.') - self.__dict__['__flags_parsed'] = False - self.__dict__['__reset_called'] = True - - def RegisteredFlags(self): - """Returns: a list of the names and short names of all registered flags.""" - return list(self.FlagDict()) - - 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='', include_special_flags=True): - """Generates a help string for all known flags. - - Args: - prefix: str, per-line output prefix. - include_special_flags: bool, whether to include description of - _SPECIAL_FLAGS, i.e. --flagfile and --undefok. - - Returns: - str, formatted help message. - """ - # TODO(vrusinov): this function needs a test. - helplist = [] - - flags_by_module = self.FlagsByModuleDict() - if flags_by_module: - modules = sorted(flags_by_module) - - # Print the help for the main module first, if possible. - main_module = sys.argv[0] - if main_module in modules: - modules.remove(main_module) - modules = [main_module] + modules - - for module in modules: - self.__RenderOurModuleFlags(module, helplist) - if include_special_flags: - self.__RenderModuleFlags('gflags', - _helpers.SPECIAL_FLAGS.FlagDict().values(), - helplist) - else: - # Just print one long list of flags. - values = self.FlagDict().values() - if include_special_flags: - values.append(_helpers.SPECIAL_FLAGS.FlagDict().values()) - self.__RenderFlagList(values, helplist, prefix) - - return '\n'.join(helplist) - - def __RenderModuleFlags(self, module, flags, output_lines, prefix=''): - """Generates a help string for a given module.""" - if not isinstance(module, str): - module = module.__name__ - 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 ModuleHelp(self, module): - """Describe the key flags of a module. - - Args: - module: A module object or a module name (a string). - - Returns: - string describing the key flags of a module. - """ - helplist = [] - self.__RenderOurModuleKeyFlags(module, helplist) - return '\n'.join(helplist) - - def MainModuleHelp(self): - """Describe the key flags of the main module. - - Returns: - string describing the key flags of a module. - """ - return self.ModuleHelp(sys.argv[0]) - - def __RenderFlagList(self, flaglist, output_lines, prefix=' '): - fl = self.FlagDict() - special_fl = _helpers.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 flag in flagset: 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 = _helpers.TextWrap( - flaghelp, indent=prefix+' ', firstline_indent=prefix) - if flag.default_as_str: - flaghelp += '\n' - flaghelp += _helpers.TextWrap( - '(default: %s)' % flag.default_as_str, indent=prefix+' ') - if flag.parser.syntactic_help: - flaghelp += '\n' - flaghelp += _helpers.TextWrap( - '(%s)' % flag.parser.syntactic_help, indent=prefix+' ') - output_lines.append(flaghelp) - - def get_flag_value(self, name, default): # pylint: disable=invalid-name - """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. - - Returns: - Requested flag value or default. - """ - - 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 - - # TODO(b/32098517): Remove this. - get = get_flag_value - - 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. - - Args: - flagfile_str: flagfile string. - - Returns: - str filename from a flagfile_str of form -[-]flagfile=filename. - - Raises: - Error: when illegal --flagfile provided. - """ - 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 exceptions.Error( - 'Hit illegal --flagfile type: %s' % flagfile_str) - - def __GetFlagFileLines(self, filename, parsed_file_stack=None): - """Returns the useful (!=comments, etc) lines from a file with flags. - - Args: - filename: A string, the name of the flag file. - parsed_file_stack: A list of the names of the files that we have - recursively encountered at the current depth. MUTATED BY THIS FUNCTION - (but the original value is preserved upon successfully returning from - function call). - - 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 '//'). - """ - if parsed_file_stack is None: - parsed_file_stack = [] - # We do a little safety check for reparsing a file we've already encountered - # at a previous depth. - if filename in parsed_file_stack: - sys.stderr.write('Warning: Hit circular flagfile dependency. Ignoring' - ' flagfile: %s\n' % (filename,)) - return [] - else: - parsed_file_stack.append(filename) - - 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 as e_msg: - raise exceptions.CantOpenFlagFileError( - 'ERROR:: Unable to open flagfile: %s' % e_msg) - - with file_obj: - line_list = file_obj.readlines() - - # 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) - included_flags = self.__GetFlagFileLines( - sub_filename, parsed_file_stack=parsed_file_stack) - flag_line_list.extend(included_flags) - else: - # Any line that's not a comment or a nested flagfile should get - # copied into 2nd position. This leaves earlier arguments - # further back in the list, thus giving them higher priority. - flag_line_list.append(line.strip()) - - parsed_file_stack.pop() - return flag_line_list - - def ReadFlagsFromFiles(self, argv, force_gnu=True): - """Processes command line args, but also allow args to be read from file. - - Args: - argv: A list of strings, usually sys.argv[1:], which may contain one or - more flagfile directives of the form --flagfile="./filename". - Note that the name of the program (sys.argv[0]) should be omitted. - force_gnu: If False, --flagfile parsing obeys normal flag semantics. - If True, --flagfile parsing instead follows gnu_getopt semantics. - *** WARNING *** force_gnu=False may become the future default! - - Returns: - A new list which has the original list combined with what we read - from any flagfile(s). - - Raises: - IllegalFlagValueError: when --flagfile provided with no argument. - - 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 in exactly the - place where the --flagfile arg is found. - - 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): - --> For duplicate flags, the last one we hit should "win". - --> Since flags that appear later win, a flagfile's settings can be "weak" - if the --flagfile comes at the beginning of the argument sequence, - and it can be "strong" if the --flagfile comes at the end. - --> A further "--flagfile=" CAN be nested in a flagfile. - It will be expanded in exactly the spot where it is found. - --> In a flagfile, a line beginning with # or // is a comment. - --> Entirely blank lines _should_ be ignored. - """ - 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 exceptions.IllegalFlagValueError( - '--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.extend(self.__GetFlagFileLines(flag_filename)) - else: - new_argv.append(current_arg) - # Stop parsing after '--', like getopt and gnu_getopt. - if current_arg == '--': - break - # Stop parsing after a non-flag, like getopt. - if not current_arg.startswith('-'): - if not force_gnu and not self.__dict__['__use_gnu_getopt']: - break - else: - if ('=' not in current_arg and - rest_of_args and not rest_of_args[0].startswith('-')): - # If this is an occurence of a legitimate --x y, skip the value - # so that it won't be mistaken for a standalone arg. - fl = self.FlagDict() - name = current_arg.lstrip('-') - if name in fl and not fl[name].boolean: - current_arg = rest_of_args[0] - rest_of_args = rest_of_args[1:] - new_argv.append(current_arg) - - if rest_of_args: - new_argv.extend(rest_of_args) - - 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++ CommandlineFlagsIntoString - from http://code.google.com/p/google-gflags - - Returns: - string with the flags assignments from this FlagValues object. - """ - 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++ AppendFlagsIntoFile - from http://code.google.com/p/google-gflags - - Args: - filename: string, name of the file. - """ - with open(filename, 'a') as out_file: - out_file.write(self.FlagsIntoString()) - - 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 - http://code.google.com/p/google-gflags - 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. - """ - doc = minidom.Document() - all_flag = doc.createElement('AllFlags') - doc.appendChild(all_flag) - - all_flag.appendChild(_helpers.CreateXMLDOMElement( - doc, 'program', os.path.basename(sys.argv[0]))) - - 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]) - all_flag.appendChild(_helpers.CreateXMLDOMElement(doc, 'usage', usage_doc)) - - # Get list of key flags for the main module. - key_flags = self._GetKeyFlagsForModule(sys.argv[0]) - - # 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 - all_flag.appendChild(flag._create_xml_dom_element( # pylint: disable=protected-access - doc, module_name, is_key=is_key)) - - outfile = outfile or sys.stdout - if six.PY2: - outfile.write(doc.toprettyxml(indent=' ', encoding='utf-8')) - else: - outfile.write( - doc.toprettyxml(indent=' ', encoding='utf-8').decode('utf-8')) - outfile.flush() - - # New PEP8 style functions. - def set_gnu_getopt(self, gnu_getopt=True): - self.UseGnuGetOpt(gnu_getopt) - - is_gnu_getopt = IsGnuGetOpt - flags_by_module_dict = FlagsByModuleDict - flags_by_module_id_dict = FlagsByModuleIdDict - key_flags_by_module_dict = KeyFlagsByModuleDict - register_key_flag_for_module = _RegisterKeyFlagForModule - find_module_defining_flag = FindModuleDefiningFlag - find_module_id_defining_flag = FindModuleIdDefiningFlag - append_flag_values = AppendFlagValues - remove_flag_values = RemoveFlagValues - set_default = SetDefault - is_parsed = IsParsed - mark_as_parsed = MarkAsParsed - flag_values_dict = FlagValuesDict - module_help = ModuleHelp - main_module_help = MainModuleHelp - read_flags_from_files = ReadFlagsFromFiles - flags_into_string = FlagsIntoString - append_flags_into_file = AppendFlagsIntoFile - write_help_in_xml_format = WriteHelpInXMLFormat - get_key_flags_for_module = _GetKeyFlagsForModule - unparse_flags = Reset - - -_helpers.SPECIAL_FLAGS = FlagValues() diff --git a/third_party/py/gflags/gflags/third_party/__init__.py b/third_party/py/gflags/gflags/third_party/__init__.py deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/third_party/py/gflags/gflags/third_party/pep257/LICENSE b/third_party/py/gflags/gflags/third_party/pep257/LICENSE deleted file mode 100644 index 9bf5acf7fb90a9..00000000000000 --- a/third_party/py/gflags/gflags/third_party/pep257/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -From "PEP 257 -- Docstring Conventions": - -Copyright -This document has been placed in the public domain. diff --git a/third_party/py/gflags/gflags/third_party/pep257/__init__.py b/third_party/py/gflags/gflags/third_party/pep257/__init__.py deleted file mode 100644 index e9443f8afcb9b7..00000000000000 --- a/third_party/py/gflags/gflags/third_party/pep257/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python - -def trim(docstring): - """Removes indentation from triple-quoted strings. - - This is the function specified in PEP 257 to handle docstrings: - http://www.python.org/dev/peps/pep-0257/ - """ - if not docstring: - return '' - - # Since Python 3 does not support sys.maxint so we use and arbitrary - # large integer instead. - maxint = 1 << 32 - - # Convert tabs to spaces (following the normal Python rules) - # and split into a list of lines: - lines = docstring.expandtabs().splitlines() - - # Determine minimum indentation (first line doesn't count): - indent = maxint - for line in lines[1:]: - stripped = line.lstrip() - if stripped: - indent = min(indent, len(line) - len(stripped)) - # Remove indentation (first line is special): - trimmed = [lines[0].strip()] - if indent < maxint: - for line in lines[1:]: - trimmed.append(line[indent:].rstrip()) - # Strip off trailing and leading blank lines: - while trimmed and not trimmed[-1]: - trimmed.pop() - while trimmed and not trimmed[0]: - trimmed.pop(0) - # Return a single string: - return '\n'.join(trimmed) diff --git a/third_party/py/gflags/gflags/validators.py b/third_party/py/gflags/gflags/validators.py deleted file mode 100644 index 3e32f7297f954a..00000000000000 --- a/third_party/py/gflags/gflags/validators.py +++ /dev/null @@ -1,194 +0,0 @@ -#!/usr/bin/env python -# Copyright 2014 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. - -"""Module to enforce different constraints on flags. - -Instead of importing this module directly, it's preferable to import the -flags package and use the aliases defined at the package level. - -A validator represents an invariant, enforced over a one or more flags. -See 'FLAGS VALIDATORS' in the flags module's docstring for a usage manual. -""" - -__author__ = 'olexiy@google.com (Olexiy Oryeshko)' - - -from gflags import exceptions - - -# TODO(yileiyang): Remove this. -Error = exceptions.ValidationError # pylint: disable=invalid-name - - -class Validator(object): - """Base class for flags validators. - - Users should NOT overload these classes, and use gflags.Register... - methods instead. - """ - - # Used to assign each validator an unique insertion_index - validators_count = 0 - - def __init__(self, checker, message): - """Constructor to create all validators. - - Args: - checker: function to verify the constraint. - Input of this method varies, see SingleFlagValidator and - multi_flags_validator for a detailed description. - message: string, error message to be shown to the user - """ - self.checker = checker - self.message = message - Validator.validators_count += 1 - # Used to assert validators in the order they were registered (CL/18694236) - self.insertion_index = Validator.validators_count - - def verify(self, flag_values): - """Verify that constraint is satisfied. - - flags library calls this method to verify Validator's constraint. - Args: - flag_values: gflags.FlagValues, containing all flags - Raises: - Error: if constraint is not satisfied. - """ - param = self._get_input_to_checker_function(flag_values) - if not self.checker(param): - raise exceptions.ValidationError(self.message) - - def get_flags_names(self): - """Return the names of the flags checked by this validator. - - Returns: - [string], names of the flags - """ - raise NotImplementedError('This method should be overloaded') - - def print_flags_with_values(self, flag_values): - raise NotImplementedError('This method should be overloaded') - - def _get_input_to_checker_function(self, flag_values): - """Given flag values, construct the input to be given to checker. - - Args: - flag_values: gflags.FlagValues, containing all flags. - Returns: - Return type depends on the specific validator. - """ - raise NotImplementedError('This method should be overloaded') - - -class SingleFlagValidator(Validator): - """Validator behind register_validator() method. - - Validates that a single flag passes its checker function. The checker function - takes the flag value and returns True (if value looks fine) or, if flag value - is not valid, either returns False or raises an Exception. - """ - - def __init__(self, flag_name, checker, message): - """Constructor. - - Args: - flag_name: string, name of the flag. - checker: function to verify the validator. - input - value of the corresponding flag (string, boolean, etc). - output - Boolean. Must return True if validator constraint is satisfied. - If constraint is not satisfied, it should either return False or - raise Error. - message: string, error message to be shown to the user if validator's - condition is not satisfied - """ - super(SingleFlagValidator, self).__init__(checker, message) - self.flag_name = flag_name - - def get_flags_names(self): - return [self.flag_name] - - def print_flags_with_values(self, flag_values): - return 'flag --%s=%s' % (self.flag_name, flag_values[self.flag_name].value) - - def _get_input_to_checker_function(self, flag_values): - """Given flag values, construct the input to be given to checker. - - Args: - flag_values: gflags.FlagValues - Returns: - value of the corresponding flag. - """ - return flag_values[self.flag_name].value - - -class MultiFlagsValidator(Validator): - """Validator behind register_multi_flags_validator method. - - Validates that flag values pass their common checker function. The checker - function takes flag values and returns True (if values look fine) or, - if values are not valid, either returns False or raises an Exception. - """ - - def __init__(self, flag_names, checker, message): - """Constructor. - - Args: - flag_names: [string], containing names of the flags used by checker. - checker: function to verify the validator. - input - dictionary, with keys() being flag_names, and value for each - key being the value of the corresponding flag (string, boolean, etc). - output - Boolean. Must return True if validator constraint is satisfied. - If constraint is not satisfied, it should either return False or - raise Error. - message: string, error message to be shown to the user if validator's - condition is not satisfied - """ - super(MultiFlagsValidator, self).__init__(checker, message) - self.flag_names = flag_names - - def _get_input_to_checker_function(self, flag_values): - """Given flag values, construct the input to be given to checker. - - Args: - flag_values: gflags.FlagValues - Returns: - dictionary, with keys() being self.lag_names, and value for each key - being the value of the corresponding flag (string, boolean, etc). - """ - return dict([key, flag_values[key].value] for key in self.flag_names) - - def print_flags_with_values(self, flag_values): - prefix = 'flags ' - flags_with_values = [] - for key in self.flag_names: - flags_with_values.append('%s=%s' % (key, flag_values[key].value)) - return prefix + ', '.join(flags_with_values) - - def get_flags_names(self): - return self.flag_names diff --git a/third_party/py/gflags/gflags2man.py b/third_party/py/gflags/gflags2man.py deleted file mode 100644 index 3a50f9e19fcf0f..00000000000000 --- a/third_party/py/gflags/gflags2man.py +++ /dev/null @@ -1,544 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2006, 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. - - - -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() -class App: - def usage(self, shorthelp=0): - print >>sys.stderr, __doc__ - print >>sys.stderr, "flags:" - print >>sys.stderr, str(FLAGS) - def run(self): - main(sys.argv) -app = App() - - -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: - app.usage(shorthelp=1) - 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__': - app.run() diff --git a/third_party/py/gflags/setup.py b/third_party/py/gflags/setup.py deleted file mode 100644 index 647db3621c08e5..00000000000000 --- a/third_party/py/gflags/setup.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python -# Copyright 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. - -"""Setup module for python-gflags.""" - -from distutils.core import setup - -setup(name='python-gflags', - version='3.1.1', - description='Google Commandline Flags Module', - license='BSD', - author='Google Inc. and others', - author_email='google-gflags@googlegroups.com', - url='https://github.com/google/python-gflags', - packages=['gflags', 'gflags.third_party', 'gflags.third_party.pep257'], - data_files=[('bin', ['gflags2man.py'])], - requires=['six'], - classifiers=[ - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', - 'Intended Audience :: Developers', - 'Topic :: Software Development :: Libraries :: Python Modules', - 'License :: OSI Approved :: BSD License', - 'Operating System :: OS Independent', - ] - )