# HG changeset patch # User Zach Welch zach@mandolincreekfarm.com
Add chirp.logger module (#2347)
This patch adds the chirp.logger module, using it in chirpc and chirpw. It adds a handful of optional command line arguments to control the new logging features. In addition, CHIRP_DEBUG, CHIRP_LOG, and CHIRP_LOG_LEVEL can be used to control the logging features from the environment.
diff --git a/chirp/logger.py b/chirp/logger.py new file mode 100644 index 0000000..753f75f --- /dev/null +++ b/chirp/logger.py @@ -0,0 +1,127 @@ +# Copyright 2015 Zachary T Welch zach@mandolincreekfarm.com +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. + + +r""" +The chirp.logger module provides the core logging facilties for CHIRP. +It sets up the console and (optionally) a log file. For early debugging, +it checks the CHIRP_DEBUG, CHIRP_LOG, and CHIRP_LOG_LEVEL environment +variables. +""" + +import logging +import os + +#: Map human-readable logging levels to their internal values. +log_level_names = {"critical": logging.CRITICAL, + "error": logging.ERROR, + "warn": logging.WARNING, + "info": logging.INFO, + "debug": logging.DEBUG, + } + + +class Logger(object): + def __init__(self): + # create root logger + self.logger = logging.getLogger() + self.logger.setLevel(logging.DEBUG) + + self.LOG = logging.getLogger(__name__) + + # Set CHIRP_DEBUG in environment for early console debugging. + # It can be a number or a name; otherwise, level is set to 'debug' + # in order to maintain backward compatibility. + CHIRP_DEBUG = os.getenv("CHIRP_DEBUG") + level = logging.WARNING + if CHIRP_DEBUG: + try: + level = int(CHIRP_DEBUG) + except: + try: + level = log_evel_names[CHIRP_DEBUG] + except: + level = logging.DEBUG + + self.console = logging.StreamHandler() + self.console.setLevel(level) + format_str = '%(levelname)s: %(message)s' + self.console.setFormatter(logging.Formatter(format_str)) + self.logger.addHandler(self.console) + + # Set CHIRP_LOG in envoronment to the name of log file. + logname = os.getenv("CHIRP_LOG") + self.logfile = None + if logname is not None: + self.create_log_file(logname) + level = os.getenv("CHIRP_LOG_LEVEL") + if level is not None: + self.set_log_verbosity(level) + else: + self.set_log_level(logging.DEBUG) + + self.LOG.debug("logging started") + + def create_log_file(self, name): + if self.logfile is None: + self.logname = name + self.logfile = logging.FileHandler(name) + format_str = '[%(asctime)s] %(name)s - %(levelname)s: %(message)s' + self.logfile.setFormatter(logging.Formatter(format_str)) + self.logger.addHandler(self.logfile) + else: + self.logger.error("already logging to " + self.logname) + + def set_verbosity(self, level): + if level > logging.CRITICAL: + level = logging.CRITICAL + self.console.setLevel(level) + self.LOG.debug("verbosity=%d", level) + + def set_log_level(self, level): + if level > logging.CRITICAL: + level = logging.CRITICAL + self.logfile.setLevel(level) + self.LOG.debug("log level=%d", level) + + def set_log_level_by_name(self, level): + self.set_log_level(log_level_names[level]) + +LOG = Logger() + + +def add_arguments(parser): + parser.add_argument("-q", "--quiet", action="count", default=0, + help="Decrease verbosity") + parser.add_argument("-v", "--verbose", action="count", default=0, + help="Increase verbosity") + parser.add_argument("--log", dest="log_file", action="store", default=0, + help="Log messages to a file") + parser.add_argument("--log-level", action="store", default="debug", + help="Log file verbosity (critical, error, warn, " + + "info, debug). Defaults to 'debug'.") + + +def handle_options(options): + if options.verbose or options.quiet: + LOG.set_verbosity(30 + 10 * (options.quiet - options.verbose)) + + if options.log_file: + LOG.create_log_file(options.log_file) + try: + level = int(options.log_level) + LOG.set_log_level(level) + except: + LOG.set_log_level_by_name(options.log_level) diff --git a/chirpc b/chirpc index c3ff224..dc55de3 100755 --- a/chirpc +++ b/chirpc @@ -19,10 +19,14 @@ import serial import sys import argparse +import logging
+from chirp import logger from chirp import * from chirp import chirp_common, errors, idrp, directory, util
+LOG = logging.getLogger("chirpc") + def fail_unsupported(): print "Operation not supported by selected radio" sys.exit(1) @@ -152,8 +156,10 @@ if __name__ == "__main__": action="store_true", default=False, help="Upload memory map to radio") + logger.add_arguments(parser) parser.add_argument("args", metavar="arg", nargs='*', help="Some commands require additional arguments") + if len(sys.argv) <= 1: parser.print_help() sys.exit(0) @@ -161,6 +167,8 @@ if __name__ == "__main__": options = parser.parse_args() args = options.args
+ logger.handle_options(options) + if options.list_radios: print "Supported Radios:\n\t", "\n\t".join(sorted(RADIOS.keys())) sys.exit(0) @@ -182,7 +190,7 @@ if __name__ == "__main__": if options.mmap: rclass = directory.get_radio_by_image(options.mmap).__class__ else: - print "Must specify a radio model" + LOG.critical("You must specify a radio model.") sys.exit(1) else: rclass = directory.get_radio(options.radio) diff --git a/chirpw b/chirpw index 4f53e0d..c1fd0ea 100755 --- a/chirpw +++ b/chirpw @@ -18,7 +18,7 @@ import os
from chirp import elib_intl -from chirp import platform, version +from chirp import platform, version, logger from chirpui import config
# Hack to setup environment @@ -126,8 +126,11 @@ parser.add_argument("files", metavar="file", nargs='*', help="File to open") version.add_argument(parser) parser.add_argument("--profile", action="store_true", help="Enable profiling") +logger.add_arguments(parser) args = parser.parse_args()
+logger.handle_options(args) + a = mainapp.ChirpMain()
for i in args.files: