New settings.py functionality for new_branch.py and related scripts.
authorTodd Larsen <tlarsen@google.com>
Fri, 06 Jun 2008 03:15:26 +0000
changeset 43 fdb9a6d839ae
parent 42 7878a389d558
child 44 9d3a0f98df34
New settings.py functionality for new_branch.py and related scripts. Patch by: Todd Larsen TO BE REVIEWED Review issue: 281 Review URL: http://codereviews.googleopensourceprograms.com/281
scripts/settings.py
--- a/scripts/settings.py	Sat May 31 01:13:58 2008 +0000
+++ b/scripts/settings.py	Fri Jun 06 03:15:26 2008 +0000
@@ -16,6 +16,20 @@
 
 """Custom optparse OptionParser and functions for reading Python settings files.
 
+Default values for trunk/scripts flags can be specified in valid Python syntax
+in the ~/.soc_scripts_settings file.  For example, a default value for the
+--user flag can be specified with a variable assignment in the settings file
+like:
+
+  user = 'joeuser'
+
+Defaults in the ~/.soc_scripts_settings file can be explicitly overridden by
+supplied the actual flag.  For example, supplying:
+
+  --user=someotheruser
+
+would override the default value present in the settings file.
+
   Option:  class derived from optparse.Option that adds a 'required' parameter
   OptionParser:  class derived from optparse.OptionParser for use with Option
 
@@ -102,7 +116,8 @@
           and option.required
           and (not self.option_seen.has_key(option))):
         errors.append(
-            'required %s option not supplied' % option)
+            'required %s option not supplied'
+            ' (and default settings not allowed)' % option)
 
     if errors:
       self.error(*errors)
@@ -110,6 +125,67 @@
     return values, args
 
 
+def printErrors(errors, exit_code=1):
+  """Prints error message strings to sys.stderr and returns an exit code.
+
+  Args:
+    errors: error message string or list of error message strings to be printed
+      to sys.stderr
+    exit_code: exit code to return (so that this function can be used as an
+      expression in sys.exit() for example); default is 1
+
+  Returns:
+    exit_code
+  """
+  sys.stderr.write('\nERRORS:\n')
+
+  if (not isinstance(errors, tuple)) and (not isinstance(errors, list)):
+    errors = [errors]
+
+  for msg in errors:
+    sys.stderr.write('  %s\n' % msg)
+
+  sys.stderr.write('\n')
+
+  return exit_code
+
+
+def printErrorsAndUsage(errors, parser, exit_code=1):
+  """Prints error messages and usage text to sys.stderr and returns exit code.
+
+  Args:
+    errors: error message string or list of error message strings to be printed
+      to sys.stderr
+    parser: OptionParser with a print_help() method
+    exit_code: exit code to return (so that this function can be used as an
+      expression in sys.exit() for example); default is 1
+
+  Returns:
+    exit_code
+  """
+  exit_code = printErrors(errors, exit_code=exit_code)
+  parser.print_help(file=sys.stderr)
+
+  return exit_code
+
+
+def getExpandedPath(path):
+  """Returns an expanded, normalized, absolute path.
+
+  Args:
+    path: path (possibly relative, possibly containing environment variables,
+      etc.) to be expanded, normalized and made absolute
+
+  Returns:
+    absolute path, after expanding any environment variables and "~", then
+    removing excess . and .. path elements
+  """
+  return os.path.abspath(
+      os.path.normpath(
+          os.path.expanduser(
+              os.path.expandvars(path))))
+
+
 def readPythonSettings(defaults={},  # {} OK since defaults is always copied
                        settings_dir=DEF_SETTINGS_FILE_DIR,
                        settings_file=DEF_SETTINGS_FILE_NAME):
@@ -136,11 +212,7 @@
 
   # form absolute path to the settings file, expanding any environment
   # variables and "~", then removing excess . and .. path elements
-  path = os.path.abspath(
-      os.path.normpath(
-          os.path.expanduser(
-              os.path.expandvars(
-                  os.path.join(settings_dir, settings_file)))))
+  path = getExpandedPath(os.path.join(settings_dir, settings_file))
 
   # empty dict to capture the local variables in the settings file
   settings_locals = {}
@@ -162,3 +234,116 @@
   defaults.update(settings_locals)
 
   return defaults
+
+
+def readPythonSettingsOrDie(parser=None,
+                            defaults={},  # {} OK since defaults is always copied
+                            settings_dir=DEF_SETTINGS_FILE_DIR,
+                            settings_file=DEF_SETTINGS_FILE_NAME):
+  """Calls readPythonSettings(), calling sys.exit() on any errors.
+
+  Args:
+    parser: if supplied, an OptionParser instance used to call print_help()
+      to print usage information if errors occur
+    defaults, settings_dir, settings_file: see readPythonSettings()
+
+  Returns:
+    On success, returns results of readPythonSettings().
+
+  Exits:
+    On any error from readPythonSettings(), prints error messages to stderr,
+    possibly prints usage information, and calls sys.exit(1).
+  """
+  try:
+    return readPythonSettings(defaults=defaults, settings_dir=settings_dir,
+                              settings_file=settings_file)
+  except Error, error:
+    if parser:
+      sys.exit(printErrorsAndUsage(error.args, parser))
+    else:
+      sys.exit(printErrors(error.args))
+
+
+def makeOptionParserOrDie(*args, **kwargs):
+  """Creates and returns an OptionParser, calling sys.exit() on any errors.
+
+  Args:
+    *args, **kwargs: supplied directly to OptionParser constructor
+
+  Returns:
+    On success, returns an OptionParser instance.
+
+  Exits:
+    On any error, prints error messages to stderr and calls sys.exit(1).
+  """
+  try:
+    return OptionParser(*args, **kwargs)
+  except Error, error:
+    sys.exit(printErrors(error.args))
+
+
+def parseOptionsOrDie(parser, args):
+  """Parses command-line options, calling sys.exit() on any errors.
+
+  Args:
+    parser: an OptionParser instance
+    args: list of command-line arguments to supply to parser
+
+  Returns:
+    On success, returns (options, args) returned by parser.parse_args(args).
+
+  Exits:
+    On any error, prints error messages and usage information to stderr and
+    calls sys.exit(1).
+  """
+  try:
+    return parser.parse_args(args)
+  except Error, error:
+    sys.exit(printErrorsAndUsage(error.args, parser))
+
+
+def checkCommonSvnOptions(options):
+  """Checks a common subset of command-line options.
+
+  Multiple scripts accept a subset of common command-line options.
+
+  Args:
+    options: OptionParser.parse_args() options instance to check
+
+  Returns:
+    list of error message strings, or an empty list if no errors
+  """
+  errors = []
+
+  if not options.repo:
+    errors.extend(
+        ['--repo must be supplied or have a settings file default'])
+
+  if not options.wc:
+    errors.extend(
+        ['--wc must be supplied or have a settings file default'])
+
+  if not options.branch:
+    if not options.user:
+      errors.extend(
+          ['at least one of --branch or --user must be supplied'])
+
+  return errors
+
+
+def checkCommonSvnOptionsOrDie(options, parser):
+  """Checks subset of command-line options, calling sys.exit() on any errors.
+
+  Args:
+    options: see checkCommonSvnOptions()
+    parser: an OptionParser instance used to call print_help() to print
+      usage information if errors occur
+
+  Exits:
+    On any error messages returned by checkCommonSvnOptions(), prints error
+    messages and usage information to stderr and calls sys.exit(1).
+  """
+  errors = checkCommonSvnOptions(options)
+
+  if errors:
+    sys.exit(printErrorsAndUsage(errors, parser))