diff options
Diffstat (limited to 'third_party/py/abseil/absl/flags/_defines.py')
-rw-r--r-- | third_party/py/abseil/absl/flags/_defines.py | 559 |
1 files changed, 559 insertions, 0 deletions
diff --git a/third_party/py/abseil/absl/flags/_defines.py b/third_party/py/abseil/absl/flags/_defines.py new file mode 100644 index 0000000000..35680db0d7 --- /dev/null +++ b/third_party/py/abseil/absl/flags/_defines.py @@ -0,0 +1,559 @@ +# Copyright 2017 The Abseil Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""This modules contains flags DEFINE functions. + +Do NOT import this module directly. Import the flags package and use the +aliases defined at the package level instead. +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import logging +import sys +import types + +from absl.flags import _argument_parser +from absl.flags import _exceptions +from absl.flags import _flag +from absl.flags import _flagvalues +from absl.flags import _helpers +from absl.flags import _validators + + +_helpers.disclaim_module_ids.add(id(sys.modules[__name__])) + + +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: str, 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 _exceptions.ValidationError(message) + return True + + _validators.register_validator(name, checker, flag_values=flag_values) + + +def DEFINE(parser, name, default, help, flag_values=_flagvalues.FLAGS, # pylint: disable=redefined-builtin,invalid-name + serializer=None, 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_<type> + function instead. + + Args: + parser: ArgumentParser, used to parse the flag arguments. + name: str, the flag name. + default: The default value of the flag. + help: str, the help message. + flag_values: FlagValues, the FlagValues instance with which the flag will + be registered. This should almost never need to be overridden. + serializer: ArgumentSerializer, the flag serializer instance. + module_name: str, the name of the Python module declaring this flag. + If not provided, it will be computed using the stack trace of this call. + **args: dict, the extra keyword args that are passed to Flag __init__. + """ + DEFINE_flag(_flag.Flag(parser, serializer, name, default, help, **args), + flag_values, module_name) + + +def DEFINE_flag(flag, flag_values=_flagvalues.FLAGS, module_name=None): # pylint: disable=invalid-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: Flag, a flag that is key to the module. + flag_values: FlagValues, the FlagValues instance with which the flag will + be registered. This should almost never need to be overridden. + module_name: str, 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 module_name: + module = sys.modules.get(module_name) + else: + module, module_name = _helpers.get_calling_module_object_and_name() + flag_values.register_flag_by_module(module_name, flag) + flag_values.register_flag_by_module_id(id(module), flag) + + +def _internal_declare_key_flags( + flag_names, flag_values=_flagvalues.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: [str], a list of strings that are names of already-registered + Flag objects. + flag_values: FlagValues, the FlagValues instance with which the flags listed + in flag_names have registered (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: FlagValues, the FlagValues instance 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: Raised when the flag is not defined. + """ + key_flag_values = key_flag_values or flag_values + + module = _helpers.get_calling_module() + + for flag_name in flag_names: + flag = flag_values[flag_name] + key_flag_values.register_key_flag_for_module(module, flag) + + +def declare_key_flag(flag_name, flag_values=_flagvalues.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: + + flags.declare_key_flag('flag_1') + + Args: + flag_name: str, 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: FlagValues, the FlagValues instance in which the flag will + be declared as a key flag. This should almost never need to be + overridden. + + Raises: + ValueError: Raised if flag_name not defined as a Python flag. + """ + 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 + try: + _internal_declare_key_flags([flag_name], flag_values=flag_values) + except KeyError: + raise ValueError( + 'Key flag --%s needs to be defined in Python' % flag_name) + + +def adopt_module_key_flags(module, flag_values=_flagvalues.FLAGS): + """Declares that all flags key to a module are key to the current module. + + Args: + module: module, the module object from which all key flags will be declared + as key flags to the current module. + flag_values: FlagValues, the FlagValues instance in which the flags will + be declared as key flags. This should almost never need to be + overridden. + + Raises: + Error: Raised when given an argument that is a module name (a string), + instead of a module object. + """ + if not isinstance(module, types.ModuleType): + raise _exceptions.Error('Expected a module object, not %r.' % (module,)) + _internal_declare_key_flags( + [f.name for f in flag_values.get_key_flags_for_module(module.__name__)], + flag_values=flag_values) + # If module is this flag module, take _helpers.SPECIAL_FLAGS into account. + if module == _helpers.FLAGS_MODULE: + _internal_declare_key_flags( + # As we associate flags with get_calling_module_object_and_name(), the + # special flags defined in this module are incorrectly registered with + # a different module. So, we can't use get_key_flags_for_module. + # Instead, we take all flags from _helpers.SPECIAL_FLAGS (a private + # FlagValues, where no other module should register flags). + [_helpers.SPECIAL_FLAGS[name].name for name in _helpers.SPECIAL_FLAGS], + flag_values=_helpers.SPECIAL_FLAGS, + key_flag_values=flag_values) + + +def disclaim_key_flags(): + """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.get_module_object_and_name(globals_for_caller) + _helpers.disclaim_module_ids.add(id(module)) + + +def DEFINE_string( # pylint: disable=invalid-name,redefined-builtin + name, default, help, flag_values=_flagvalues.FLAGS, **args): + """Registers a flag whose value can be any string.""" + parser = _argument_parser.ArgumentParser() + serializer = _argument_parser.ArgumentSerializer() + DEFINE(parser, name, default, help, flag_values, serializer, **args) + + +def DEFINE_boolean( # pylint: disable=invalid-name,redefined-builtin + name, default, help, flag_values=_flagvalues.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: str, the flag name. + default: bool|str|None, the default value of the flag. + help: str, the help message. + flag_values: FlagValues, the FlagValues instance with which the flag will + be registered. This should almost never need to be overridden. + module_name: str, the name of the Python module declaring this flag. + If not provided, it will be computed using the stack trace of this call. + **args: dict, the extra keyword args that are passed to Flag __init__. + """ + DEFINE_flag(_flag.BooleanFlag(name, default, help, **args), + flag_values, module_name) + + +def DEFINE_float( # pylint: disable=invalid-name,redefined-builtin + name, default, help, lower_bound=None, upper_bound=None, + flag_values=_flagvalues.FLAGS, **args): # pylint: disable=invalid-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, the flag name. + default: float|str|None, the default value of the flag. + help: str, the help message. + lower_bound: float, min value of the flag. + upper_bound: float, max value of the flag. + flag_values: FlagValues, the FlagValues instance with which the flag will + be registered. This should almost never need to be overridden. + **args: dict, the extra keyword args that are passed to DEFINE. + """ + parser = _argument_parser.FloatParser(lower_bound, upper_bound) + serializer = _argument_parser.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=invalid-name,redefined-builtin + name, default, help, lower_bound=None, upper_bound=None, + flag_values=_flagvalues.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, the flag name. + default: int|str|None, the default value of the flag. + help: str, the help message. + lower_bound: int, min value of the flag. + upper_bound: int, max value of the flag. + flag_values: FlagValues, the FlagValues instance with which the flag will + be registered. This should almost never need to be overridden. + **args: dict, the extra keyword args that are passed to DEFINE. + """ + parser = _argument_parser.IntegerParser(lower_bound, upper_bound) + serializer = _argument_parser.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=invalid-name,redefined-builtin + name, default, enum_values, help, flag_values=_flagvalues.FLAGS, + module_name=None, **args): + """Registers a flag whose value can be any string from enum_values. + + Args: + name: str, the flag name. + default: str|None, the default value of the flag. + enum_values: [str], a non-empty list of strings with the possible values for + the flag. + help: str, the help message. + flag_values: FlagValues, the FlagValues instance with which the flag will + be registered. This should almost never need to be overridden. + module_name: str, the name of the Python module declaring this flag. + If not provided, it will be computed using the stack trace of this call. + **args: dict, the extra keyword args that are passed to Flag __init__. + """ + DEFINE_flag(_flag.EnumFlag(name, default, help, enum_values, **args), + flag_values, module_name) + + +def DEFINE_list( # pylint: disable=invalid-name,redefined-builtin + name, default, help, flag_values=_flagvalues.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: str, the flag name. + default: list|str|None, the default value of the flag. + help: str, the help message. + flag_values: FlagValues, the FlagValues instance with which the flag will + be registered. This should almost never need to be overridden. + **args: Dictionary with extra keyword args that are passed to the + Flag __init__. + """ + parser = _argument_parser.ListParser() + serializer = _argument_parser.CsvListSerializer(',') + DEFINE(parser, name, default, help, flag_values, serializer, **args) + + +def DEFINE_spaceseplist( # pylint: disable=invalid-name,redefined-builtin + name, default, help, comma_compat=False, flag_values=_flagvalues.FLAGS, + **args): + """Registers a flag whose value is a whitespace-separated list of strings. + + Any whitespace can be used as a separator. + + Args: + name: str, the flag name. + default: list|str|None, the default value of the flag. + help: str, the help message. + 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, the FlagValues instance with which the flag will + be registered. This should almost never need to be overridden. + **args: Dictionary with extra keyword args that are passed to the + Flag __init__. + """ + parser = _argument_parser.WhitespaceSeparatedListParser( + comma_compat=comma_compat) + serializer = _argument_parser.ListSerializer(' ') + DEFINE(parser, name, default, help, flag_values, serializer, **args) + + +def DEFINE_multi( # pylint: disable=invalid-name,redefined-builtin + parser, serializer, name, default, help, flag_values=_flagvalues.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, used to parse the flag arguments. + serializer: ArgumentSerializer, the flag serializer instance. + name: str, the flag name. + default: list|str|None, the default value of the flag. + help: str, the help message. + flag_values: FlagValues, the FlagValues instance with which the flag will + be registered. This should almost never need to be overridden. + 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.MultiFlag(parser, serializer, name, default, help, **args), + flag_values, module_name) + + +def DEFINE_multi_string( # pylint: disable=invalid-name,redefined-builtin + name, default, help, flag_values=_flagvalues.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: str, the flag name. + default: [str]|str|None, the default value of the flag. + help: str, the help message. + flag_values: FlagValues, the FlagValues instance with which the flag will + be registered. This should almost never need to be overridden. + **args: Dictionary with extra keyword args that are passed to the + Flag __init__. + """ + parser = _argument_parser.ArgumentParser() + serializer = _argument_parser.ArgumentSerializer() + DEFINE_multi(parser, serializer, name, default, help, flag_values, **args) + + +def DEFINE_multi_integer( # pylint: disable=invalid-name,redefined-builtin + name, default, help, lower_bound=None, upper_bound=None, + flag_values=_flagvalues.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: str, the flag name. + default: [int]|str|None, the default value of the flag. + help: str, the help message. + lower_bound: int, min values of the flag. + upper_bound: int, max values of the flag. + flag_values: FlagValues, the FlagValues instance with which the flag will + be registered. This should almost never need to be overridden. + **args: Dictionary with extra keyword args that are passed to the + Flag __init__. + """ + parser = _argument_parser.IntegerParser(lower_bound, upper_bound) + serializer = _argument_parser.ArgumentSerializer() + DEFINE_multi(parser, serializer, name, default, help, flag_values, **args) + + +def DEFINE_multi_float( # pylint: disable=invalid-name,redefined-builtin + name, default, help, lower_bound=None, upper_bound=None, + flag_values=_flagvalues.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: str, the flag name. + default: [float]|str|None, the default value of the flag. + help: str, the help message. + lower_bound: float, min values of the flag. + upper_bound: float, max values of the flag. + flag_values: FlagValues, the FlagValues instance with which the flag will + be registered. This should almost never need to be overridden. + **args: Dictionary with extra keyword args that are passed to the + Flag __init__. + """ + parser = _argument_parser.FloatParser(lower_bound, upper_bound) + serializer = _argument_parser.ArgumentSerializer() + DEFINE_multi(parser, serializer, name, default, help, flag_values, **args) + + +def DEFINE_multi_enum( # pylint: disable=invalid-name,redefined-builtin + name, default, enum_values, help, flag_values=_flagvalues.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: str, the flag name. + default: [str]|str|None, the default value of the flag. + enum_values: [str], a non-empty list of strings with the possible values for + the flag. + help: str, the help message. + flag_values: FlagValues, the FlagValues instance with which the flag will + be registered. This should almost never need to be overridden. + 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 = _argument_parser.EnumParser(enum_values, case_sensitive) + serializer = _argument_parser.ArgumentSerializer() + DEFINE_multi(parser, serializer, name, default, help, flag_values, **args) + + +def DEFINE_alias(name, original_name, flag_values=_flagvalues.FLAGS, # pylint: disable=invalid-name + module_name=None): + """Defines an alias flag for an existing one. + + Args: + name: str, the flag name. + original_name: str, the original flag name. + flag_values: FlagValues, the FlagValues instance with which the flag will + be registered. This should almost never need to be overridden. + module_name: A string, the name of the module that defines this flag. + + Raises: + flags.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 _exceptions.UnrecognizedFlagError(original_name) + flag = flag_values[original_name] + + class _Parser(_argument_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.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, flags.DuplicatedFlag will be raised. + DEFINE_flag(_FlagAlias(_Parser(), flag.serializer, name, flag.default, + help_msg, boolean=flag.boolean), + flag_values, module_name) |