scripts/settings.py
changeset 43 fdb9a6d839ae
parent 29 64b3e323210f
child 49 7b6914018044
equal deleted inserted replaced
42:7878a389d558 43:fdb9a6d839ae
    14 # See the License for the specific language governing permissions and
    14 # See the License for the specific language governing permissions and
    15 # limitations under the License.
    15 # limitations under the License.
    16 
    16 
    17 """Custom optparse OptionParser and functions for reading Python settings files.
    17 """Custom optparse OptionParser and functions for reading Python settings files.
    18 
    18 
       
    19 Default values for trunk/scripts flags can be specified in valid Python syntax
       
    20 in the ~/.soc_scripts_settings file.  For example, a default value for the
       
    21 --user flag can be specified with a variable assignment in the settings file
       
    22 like:
       
    23 
       
    24   user = 'joeuser'
       
    25 
       
    26 Defaults in the ~/.soc_scripts_settings file can be explicitly overridden by
       
    27 supplied the actual flag.  For example, supplying:
       
    28 
       
    29   --user=someotheruser
       
    30 
       
    31 would override the default value present in the settings file.
       
    32 
    19   Option:  class derived from optparse.Option that adds a 'required' parameter
    33   Option:  class derived from optparse.Option that adds a 'required' parameter
    20   OptionParser:  class derived from optparse.OptionParser for use with Option
    34   OptionParser:  class derived from optparse.OptionParser for use with Option
    21 
    35 
    22   readPythonSettings():  interprets a valid Python file as a settings file
    36   readPythonSettings():  interprets a valid Python file as a settings file
    23 """
    37 """
   100     for option in self.option_list:
   114     for option in self.option_list:
   101       if (isinstance(option, Option)
   115       if (isinstance(option, Option)
   102           and option.required
   116           and option.required
   103           and (not self.option_seen.has_key(option))):
   117           and (not self.option_seen.has_key(option))):
   104         errors.append(
   118         errors.append(
   105             'required %s option not supplied' % option)
   119             'required %s option not supplied'
       
   120             ' (and default settings not allowed)' % option)
   106 
   121 
   107     if errors:
   122     if errors:
   108       self.error(*errors)
   123       self.error(*errors)
   109 
   124 
   110     return values, args
   125     return values, args
       
   126 
       
   127 
       
   128 def printErrors(errors, exit_code=1):
       
   129   """Prints error message strings to sys.stderr and returns an exit code.
       
   130 
       
   131   Args:
       
   132     errors: error message string or list of error message strings to be printed
       
   133       to sys.stderr
       
   134     exit_code: exit code to return (so that this function can be used as an
       
   135       expression in sys.exit() for example); default is 1
       
   136 
       
   137   Returns:
       
   138     exit_code
       
   139   """
       
   140   sys.stderr.write('\nERRORS:\n')
       
   141 
       
   142   if (not isinstance(errors, tuple)) and (not isinstance(errors, list)):
       
   143     errors = [errors]
       
   144 
       
   145   for msg in errors:
       
   146     sys.stderr.write('  %s\n' % msg)
       
   147 
       
   148   sys.stderr.write('\n')
       
   149 
       
   150   return exit_code
       
   151 
       
   152 
       
   153 def printErrorsAndUsage(errors, parser, exit_code=1):
       
   154   """Prints error messages and usage text to sys.stderr and returns exit code.
       
   155 
       
   156   Args:
       
   157     errors: error message string or list of error message strings to be printed
       
   158       to sys.stderr
       
   159     parser: OptionParser with a print_help() method
       
   160     exit_code: exit code to return (so that this function can be used as an
       
   161       expression in sys.exit() for example); default is 1
       
   162 
       
   163   Returns:
       
   164     exit_code
       
   165   """
       
   166   exit_code = printErrors(errors, exit_code=exit_code)
       
   167   parser.print_help(file=sys.stderr)
       
   168 
       
   169   return exit_code
       
   170 
       
   171 
       
   172 def getExpandedPath(path):
       
   173   """Returns an expanded, normalized, absolute path.
       
   174 
       
   175   Args:
       
   176     path: path (possibly relative, possibly containing environment variables,
       
   177       etc.) to be expanded, normalized and made absolute
       
   178 
       
   179   Returns:
       
   180     absolute path, after expanding any environment variables and "~", then
       
   181     removing excess . and .. path elements
       
   182   """
       
   183   return os.path.abspath(
       
   184       os.path.normpath(
       
   185           os.path.expanduser(
       
   186               os.path.expandvars(path))))
   111 
   187 
   112 
   188 
   113 def readPythonSettings(defaults={},  # {} OK since defaults is always copied
   189 def readPythonSettings(defaults={},  # {} OK since defaults is always copied
   114                        settings_dir=DEF_SETTINGS_FILE_DIR,
   190                        settings_dir=DEF_SETTINGS_FILE_DIR,
   115                        settings_file=DEF_SETTINGS_FILE_NAME):
   191                        settings_file=DEF_SETTINGS_FILE_NAME):
   134   # do not let the original defaults be altered
   210   # do not let the original defaults be altered
   135   defaults = defaults.copy()
   211   defaults = defaults.copy()
   136 
   212 
   137   # form absolute path to the settings file, expanding any environment
   213   # form absolute path to the settings file, expanding any environment
   138   # variables and "~", then removing excess . and .. path elements
   214   # variables and "~", then removing excess . and .. path elements
   139   path = os.path.abspath(
   215   path = getExpandedPath(os.path.join(settings_dir, settings_file))
   140       os.path.normpath(
       
   141           os.path.expanduser(
       
   142               os.path.expandvars(
       
   143                   os.path.join(settings_dir, settings_file)))))
       
   144 
   216 
   145   # empty dict to capture the local variables in the settings file
   217   # empty dict to capture the local variables in the settings file
   146   settings_locals = {}
   218   settings_locals = {}
   147 
   219 
   148   try:
   220   try:
   160 
   232 
   161   # overwrite defaults copy with values from the (possibly empty) settings file
   233   # overwrite defaults copy with values from the (possibly empty) settings file
   162   defaults.update(settings_locals)
   234   defaults.update(settings_locals)
   163 
   235 
   164   return defaults
   236   return defaults
       
   237 
       
   238 
       
   239 def readPythonSettingsOrDie(parser=None,
       
   240                             defaults={},  # {} OK since defaults is always copied
       
   241                             settings_dir=DEF_SETTINGS_FILE_DIR,
       
   242                             settings_file=DEF_SETTINGS_FILE_NAME):
       
   243   """Calls readPythonSettings(), calling sys.exit() on any errors.
       
   244 
       
   245   Args:
       
   246     parser: if supplied, an OptionParser instance used to call print_help()
       
   247       to print usage information if errors occur
       
   248     defaults, settings_dir, settings_file: see readPythonSettings()
       
   249 
       
   250   Returns:
       
   251     On success, returns results of readPythonSettings().
       
   252 
       
   253   Exits:
       
   254     On any error from readPythonSettings(), prints error messages to stderr,
       
   255     possibly prints usage information, and calls sys.exit(1).
       
   256   """
       
   257   try:
       
   258     return readPythonSettings(defaults=defaults, settings_dir=settings_dir,
       
   259                               settings_file=settings_file)
       
   260   except Error, error:
       
   261     if parser:
       
   262       sys.exit(printErrorsAndUsage(error.args, parser))
       
   263     else:
       
   264       sys.exit(printErrors(error.args))
       
   265 
       
   266 
       
   267 def makeOptionParserOrDie(*args, **kwargs):
       
   268   """Creates and returns an OptionParser, calling sys.exit() on any errors.
       
   269 
       
   270   Args:
       
   271     *args, **kwargs: supplied directly to OptionParser constructor
       
   272 
       
   273   Returns:
       
   274     On success, returns an OptionParser instance.
       
   275 
       
   276   Exits:
       
   277     On any error, prints error messages to stderr and calls sys.exit(1).
       
   278   """
       
   279   try:
       
   280     return OptionParser(*args, **kwargs)
       
   281   except Error, error:
       
   282     sys.exit(printErrors(error.args))
       
   283 
       
   284 
       
   285 def parseOptionsOrDie(parser, args):
       
   286   """Parses command-line options, calling sys.exit() on any errors.
       
   287 
       
   288   Args:
       
   289     parser: an OptionParser instance
       
   290     args: list of command-line arguments to supply to parser
       
   291 
       
   292   Returns:
       
   293     On success, returns (options, args) returned by parser.parse_args(args).
       
   294 
       
   295   Exits:
       
   296     On any error, prints error messages and usage information to stderr and
       
   297     calls sys.exit(1).
       
   298   """
       
   299   try:
       
   300     return parser.parse_args(args)
       
   301   except Error, error:
       
   302     sys.exit(printErrorsAndUsage(error.args, parser))
       
   303 
       
   304 
       
   305 def checkCommonSvnOptions(options):
       
   306   """Checks a common subset of command-line options.
       
   307 
       
   308   Multiple scripts accept a subset of common command-line options.
       
   309 
       
   310   Args:
       
   311     options: OptionParser.parse_args() options instance to check
       
   312 
       
   313   Returns:
       
   314     list of error message strings, or an empty list if no errors
       
   315   """
       
   316   errors = []
       
   317 
       
   318   if not options.repo:
       
   319     errors.extend(
       
   320         ['--repo must be supplied or have a settings file default'])
       
   321 
       
   322   if not options.wc:
       
   323     errors.extend(
       
   324         ['--wc must be supplied or have a settings file default'])
       
   325 
       
   326   if not options.branch:
       
   327     if not options.user:
       
   328       errors.extend(
       
   329           ['at least one of --branch or --user must be supplied'])
       
   330 
       
   331   return errors
       
   332 
       
   333 
       
   334 def checkCommonSvnOptionsOrDie(options, parser):
       
   335   """Checks subset of command-line options, calling sys.exit() on any errors.
       
   336 
       
   337   Args:
       
   338     options: see checkCommonSvnOptions()
       
   339     parser: an OptionParser instance used to call print_help() to print
       
   340       usage information if errors occur
       
   341 
       
   342   Exits:
       
   343     On any error messages returned by checkCommonSvnOptions(), prints error
       
   344     messages and usage information to stderr and calls sys.exit(1).
       
   345   """
       
   346   errors = checkCommonSvnOptions(options)
       
   347 
       
   348   if errors:
       
   349     sys.exit(printErrorsAndUsage(errors, parser))