[chirp_devel] [PATCH 6/9] Add chirp.logger module (#2347)

Zach Welch
Tue Feb 24 23:26:50 PST 2015


# HG changeset patch
# User Zach Welch <zach at 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 at 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:




More information about the chirp_devel mailing list