Home | History | Annotate | Download | only in python_gflags
      1 #!/usr/bin/env python
      2 
      3 # Copyright (c) 2010, Google Inc.
      4 # All rights reserved.
      5 #
      6 # Redistribution and use in source and binary forms, with or without
      7 # modification, are permitted provided that the following conditions are
      8 # met:
      9 #
     10 #     * Redistributions of source code must retain the above copyright
     11 # notice, this list of conditions and the following disclaimer.
     12 #     * Redistributions in binary form must reproduce the above
     13 # copyright notice, this list of conditions and the following disclaimer
     14 # in the documentation and/or other materials provided with the
     15 # distribution.
     16 #     * Neither the name of Google Inc. nor the names of its
     17 # contributors may be used to endorse or promote products derived from
     18 # this software without specific prior written permission.
     19 #
     20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     23 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     24 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     25 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     26 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     30 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31 
     32 """Module to enforce different constraints on flags.
     33 
     34 A validator represents an invariant, enforced over a one or more flags.
     35 See 'FLAGS VALIDATORS' in gflags.py's docstring for a usage manual.
     36 """
     37 
     38 __author__ = 'olexiy (at] google.com (Olexiy Oryeshko)'
     39 
     40 
     41 class Error(Exception):
     42   """Thrown If validator constraint is not satisfied."""
     43 
     44 
     45 class Validator(object):
     46   """Base class for flags validators.
     47 
     48   Users should NOT overload these classes, and use gflags.Register...
     49   methods instead.
     50   """
     51 
     52   # Used to assign each validator an unique insertion_index
     53   validators_count = 0
     54 
     55   def __init__(self, checker, message):
     56     """Constructor to create all validators.
     57 
     58     Args:
     59       checker: function to verify the constraint.
     60         Input of this method varies, see SimpleValidator and
     61           DictionaryValidator for a detailed description.
     62       message: string, error message to be shown to the user
     63     """
     64     self.checker = checker
     65     self.message = message
     66     Validator.validators_count += 1
     67     # Used to assert validators in the order they were registered (CL/18694236)
     68     self.insertion_index = Validator.validators_count
     69 
     70   def Verify(self, flag_values):
     71     """Verify that constraint is satisfied.
     72 
     73     flags library calls this method to verify Validator's constraint.
     74     Args:
     75       flag_values: gflags.FlagValues, containing all flags
     76     Raises:
     77       Error: if constraint is not satisfied.
     78     """
     79     param = self._GetInputToCheckerFunction(flag_values)
     80     if not self.checker(param):
     81       raise Error(self.message)
     82 
     83   def GetFlagsNames(self):
     84     """Return the names of the flags checked by this validator.
     85 
     86     Returns:
     87       [string], names of the flags
     88     """
     89     raise NotImplementedError('This method should be overloaded')
     90 
     91   def PrintFlagsWithValues(self, flag_values):
     92     raise NotImplementedError('This method should be overloaded')
     93 
     94   def _GetInputToCheckerFunction(self, flag_values):
     95     """Given flag values, construct the input to be given to checker.
     96 
     97     Args:
     98       flag_values: gflags.FlagValues, containing all flags.
     99     Returns:
    100       Return type depends on the specific validator.
    101     """
    102     raise NotImplementedError('This method should be overloaded')
    103 
    104 
    105 class SimpleValidator(Validator):
    106   """Validator behind RegisterValidator() method.
    107 
    108   Validates that a single flag passes its checker function. The checker function
    109   takes the flag value and returns True (if value looks fine) or, if flag value
    110   is not valid, either returns False or raises an Exception."""
    111   def __init__(self, flag_name, checker, message):
    112     """Constructor.
    113 
    114     Args:
    115       flag_name: string, name of the flag.
    116       checker: function to verify the validator.
    117         input  - value of the corresponding flag (string, boolean, etc).
    118         output - Boolean. Must return True if validator constraint is satisfied.
    119           If constraint is not satisfied, it should either return False or
    120           raise Error.
    121       message: string, error message to be shown to the user if validator's
    122         condition is not satisfied
    123     """
    124     super(SimpleValidator, self).__init__(checker, message)
    125     self.flag_name = flag_name
    126 
    127   def GetFlagsNames(self):
    128     return [self.flag_name]
    129 
    130   def PrintFlagsWithValues(self, flag_values):
    131     return 'flag --%s=%s' % (self.flag_name, flag_values[self.flag_name].value)
    132 
    133   def _GetInputToCheckerFunction(self, flag_values):
    134     """Given flag values, construct the input to be given to checker.
    135 
    136     Args:
    137       flag_values: gflags.FlagValues
    138     Returns:
    139       value of the corresponding flag.
    140     """
    141     return flag_values[self.flag_name].value
    142 
    143 
    144 class DictionaryValidator(Validator):
    145   """Validator behind RegisterDictionaryValidator method.
    146 
    147   Validates that flag values pass their common checker function. The checker
    148   function takes flag values and returns True (if values look fine) or,
    149   if values are not valid, either returns False or raises an Exception.
    150   """
    151   def __init__(self, flag_names, checker, message):
    152     """Constructor.
    153 
    154     Args:
    155       flag_names: [string], containing names of the flags used by checker.
    156       checker: function to verify the validator.
    157         input  - dictionary, with keys() being flag_names, and value for each
    158           key being the value of the corresponding flag (string, boolean, etc).
    159         output - Boolean. Must return True if validator constraint is satisfied.
    160           If constraint is not satisfied, it should either return False or
    161           raise Error.
    162       message: string, error message to be shown to the user if validator's
    163         condition is not satisfied
    164     """
    165     super(DictionaryValidator, self).__init__(checker, message)
    166     self.flag_names = flag_names
    167 
    168   def _GetInputToCheckerFunction(self, flag_values):
    169     """Given flag values, construct the input to be given to checker.
    170 
    171     Args:
    172       flag_values: gflags.FlagValues
    173     Returns:
    174       dictionary, with keys() being self.lag_names, and value for each key
    175         being the value of the corresponding flag (string, boolean, etc).
    176     """
    177     return dict([key, flag_values[key].value] for key in self.flag_names)
    178 
    179   def PrintFlagsWithValues(self, flag_values):
    180     prefix = 'flags '
    181     flags_with_values = []
    182     for key in self.flag_names:
    183       flags_with_values.append('%s=%s' % (key, flag_values[key].value))
    184     return prefix + ', '.join(flags_with_values)
    185 
    186   def GetFlagsNames(self):
    187     return self.flag_names
    188