Source code for caelus.scripts.core

# -*- coding: utf-8 -*-

"""\
Basic CLI Interface
-------------------

Defines the base classes that are used to build the CLI scripts.
"""

import argparse
import logging

from ..config import cmlenv
from ..config.config import configure_logging, get_config, rcfiles_loaded
from ..version import version

_lgr = logging.getLogger(__name__)


[docs] class CaelusScriptBase(object): """Base class for all Caelus CLI applications. Defines the common functionality for simple scripts and scripts with sub-commands that are used to access functionality from the library without writing additional python scripts. """ #: Description of the CLI app used in help messages description = "Caelus CLI Application" #: Epilog for help messages epilog = "Caelus Python Library (CPL) %s" % version script_levels = ["INFO", "DEBUG"] lib_levels = ["WARNING", "INFO", "DEBUG"] def __init__(self, name=None, args=None): """ Args: name (str): Custom name used in messages args (str): Pass arguments instead of using sys.argv """ #: Custom name when invoked from a python interface instead of command #: line self.name = name #: Instance of the ArgumentParser used to parse command line arguments self.parser = argparse.ArgumentParser( description=self.description, epilog=self.epilog, prog=name ) self.cli_options() if args: #: Arugments provided by user at the command line self.args = self.parser.parse_args(args.split()) else: self.args = self.parser.parse_args()
[docs] def cli_options(self): """Setup the command line options and arguments""" parser = self.parser parser.add_argument( '--version', action='version', version="Caelus Python Library (CPL) %s" % version, ) parser.add_argument( '--cml-version', default=None, help="CML version used for this invocation", ) verbosity = parser.add_mutually_exclusive_group(required=False) verbosity.add_argument( '--quiet', action='store_true', help="disable informational messages to screen", ) verbosity.add_argument( '-v', '--verbose', action='count', default=0, help="increase verbosity of logging. Default: No", ) dolog = parser.add_mutually_exclusive_group(required=False) dolog.add_argument( '--no-log', action='store_true', help="disable logging of script to file.", ) dolog.add_argument( '--cli-logs', default=None, help="name of the log file." )
def __call__(self): """Execute the CLI application""" args = self.args verbosity = args.verbose log_to_file = not args.no_log log_file = args.cli_logs self.setup_logging(log_to_file, log_file, verbosity, args.quiet) _lgr.info("Caelus Python Library (CPL) %s", version) if args.cml_version is not None: try: cmlenv.cml_get_version(args.cml_version) except (RuntimeError, KeyError): _lgr.error( "Invalid CML version specified: %s", args.cml_version ) self.parser.exit(1) self.cfg.caelus.caelus_cml.default = args.cml_version
[docs] def setup_logging( self, log_to_file=True, log_file=None, verbose_level=0, quiet=False ): """Setup logging for the script. Args: log_to_file (bool): If True, script will log to file log_file (path): Filename to log verbose_level (int): Level of verbosity """ script_levels = self.script_levels lib_levels = self.lib_levels cfg = get_config(init_logging=False) log_cfg = cfg.caelus.logging lggr_cfg = log_cfg.pylogger_options if quiet: lggr_cfg.handlers.console_caelus.level = "ERROR" lggr_cfg.handlers.console_script.level = "ERROR" else: lggr_cfg.handlers.console_caelus.level = lib_levels[ min(verbose_level, len(lib_levels) - 1) ] lggr_cfg.handlers.console_script.level = script_levels[ min(verbose_level, len(script_levels) - 1) ] lggr_cfg.loggers["caelus.scripts"].handlers.append("log_file") log_cfg.log_to_file = log_to_file if log_to_file: log_cfg.log_file = log_file or log_cfg.log_file configure_logging(log_cfg) rcfiles = rcfiles_loaded() msg = ( "Loaded configuration from files = %s" % rcfiles if rcfiles else "No configuration found; using defaults." ) _lgr.debug(msg) if not log_cfg.log_to_file: _lgr.warning("Logging to file disabled.") self.cfg = cfg
[docs] class CaelusSubCmdScript(CaelusScriptBase): """A CLI app with sub-commands."""
[docs] def cli_options(self): """Setup sub-parsers.""" super(CaelusSubCmdScript, self).cli_options() self.subparsers = self.parser.add_subparsers( help="Choose from one of the following sub-commands; use -h to see sub-command options" )
def __call__(self): """Execute sub-command""" super(CaelusSubCmdScript, self).__call__() if 'func' not in self.args: _lgr.error("No subcommand specified. Use '-h' for detailed help.") self.parser.print_usage() self.parser.exit(1) self.args.func()