]> scripts.mit.edu Git - wizard.git/blobdiff - wizard/command/__init__.py
Refactor to get rid of _package.py using __import__ magic.
[wizard.git] / wizard / command / __init__.py
index bbf389bc565df6b707cdc6c535595069f5cb86e1..e5cb0b4354f06b3d3c85b2ab9d43c92aa8e16ab8 100644 (file)
@@ -1,5 +1,147 @@
-import migrate
-import massmigrate
-import info
-import summary
-import upgrade
+import logging
+import os
+import sys
+import optparse
+import errno
+
+import wizard
+
+logging_setup = False
+
+class Error(wizard.Error):
+    """Base error class for all command errors"""
+    pass
+
+class PermissionsError(Error):
+    def __init__(self, dir):
+        self.dir = dir
+    def __str__(self):
+        return """
+
+ERROR: You don't have permissions to access this directory.
+Do you have tokens for AFS with your root instance, and
+is your root instance on scripts-security-upd?
+
+You can check by running the commands 'klist' and
+'blanche scripts-security-upd'.
+"""
+
+class NoSuchDirectoryError(Error):
+    def __init__(self, dir):
+        self.dir = dir
+    def __str__(self):
+        return """
+
+ERROR: No such directory... check your typing
+"""
+
+def chdir(dir):
+    try:
+        os.chdir(dir)
+    except OSError as e:
+        if e.errno == errno.EACCES:
+            raise PermissionsError(dir)
+        elif e.errno == errno.ENOENT:
+            raise NoSuchDirectoryError(dir)
+        else: raise e
+
+def makeLogger(options, numeric_args):
+    global logging_setup
+    if logging_setup: return logging.getLogger()
+    context = " ".join(numeric_args)
+    logger = logging.getLogger()
+    logger.setLevel(logging.INFO)
+    stderr = logging.StreamHandler(sys.stderr)
+    stderr.setFormatter(logging.Formatter(" " * int(options.indent) + '%(levelname)s: %(message)s'))
+    dateFormat = "%H:%M:%S"
+    if options.context:
+        logformatter = logging.Formatter("%(asctime)s %(levelname)s -- " + context + ": %(message)s", dateFormat)
+    else:
+        logformatter = logging.Formatter("%(asctime)s %(levelname)s: %(message)s", dateFormat)
+    if not options.quiet: logger.addHandler(stderr)
+    else: logger.addHandler(NullLogHandler()) # prevent default
+    if options.log_file:
+        file = logging.FileHandler(options.log_file)
+        file.setFormatter(logformatter)
+        logger.addHandler(file)
+        if options.log_file_chmod:
+            os.chmod(options.log_file, int(options.log_file_chmod, 8))
+    if options.debug:
+        logger.setLevel(logging.DEBUG)
+    else:
+        stderr.setLevel(logging.WARNING)
+        if options.verbose or hasattr(options, "dry_run"):
+            stderr.setLevel(logging.INFO)
+        if options.log_file:
+            file.setLevel(logging.INFO)
+    logging_setup = True
+    return logger
+
+def makeBaseArgs(options, **grab):
+    """Takes parsed options, and breaks them back into a command
+    line string that we can pass into a subcommand"""
+    args = []
+    grab["log_file"]= "--log-file"
+    grab["debug"]   = "--debug"
+    grab["verbose"] = "--verbose"
+    grab["indent"]  = "--indent"
+    grab["quiet"]   = "--quiet"
+    #grab["log_db"] = "--log-db"
+    for k,flag in grab.items():
+        value = getattr(options, k)
+        if not value and k != "indent": continue
+        args.append(flag)
+        if type(value) is not bool:
+            if k == "indent":
+                value += 4
+            args.append(str(value))
+    args.append("--context") # always have context for a subcommand
+    return args
+
+class NullLogHandler(logging.Handler):
+    """Log handler that doesn't do anything"""
+    def emit(self, record):
+        pass
+
+class WizardOptionParser(optparse.OptionParser):
+    """Configures some default user-level options"""
+    def __init__(self, *args, **kwargs):
+        kwargs["add_help_option"] = False
+        optparse.OptionParser.__init__(self, *args, **kwargs)
+    def parse_all(self, argv):
+        self.add_option("-h", "--help", action="help", help=optparse.SUPPRESS_HELP)
+        group = optparse.OptionGroup(self, "Common Options")
+        group.add_option("-v", "--verbose", dest="verbose", action="store_true",
+                default=False, help="Turns on verbose output")
+        group.add_option("--debug", dest="debug", action="store_true",
+                default=False, help="Turns on debugging output")
+        group.add_option("-q", "--quiet", dest="quiet", action="store_true",
+                default=False, help="Turns off output to stdout")
+        group.add_option("--log-file", dest="log_file",
+                default=None, help="Logs verbose output to file")
+        group.add_option("--log-file-chmod", dest="log_file_chmod",
+                default=None, help="Chmod the log file after opening.  Number is octal. You must chmod the log file 666 and place the file in /tmp if subprocesses are running as different users.")
+        group.add_option("--indent", dest="indent",
+                default=0, help="Indents stdout, useful for nested calls")
+        group.add_option("--context", dest="context", action="store_true",
+                default=False, help="Adds context to logs, useful for parallel processing")
+        self.add_option_group(group)
+        options, numeric_args = self.parse_args(argv)
+        makeLogger(options, numeric_args)
+        return options, numeric_args
+
+class OptionBaton(object):
+    """Command classes may define options that they sub-commands may
+    use.  Since wizard --global-command subcommand is not a supported
+    mode of operation, these options have to be passed down the command
+    chain until a option parser is ready to take it; this baton is
+    what is passed down."""
+    def __init__(self):
+        self.store = {}
+    def add(self, *args, **kwargs):
+        key = kwargs["dest"] # require this to be set
+        self.store[key] = optparse.make_option(*args, **kwargs)
+    def push(self, option_parser, *args):
+        """Hands off parameters to option parser"""
+        for key in args:
+            option_parser.add_option(self.store[key])