1
0
mirror of https://github.com/JoelBender/bacpypes synced 2025-10-20 00:52:12 +08:00
bacpypes/py25/bacpypes/consolelogging.py
2015-08-02 22:17:11 -04:00

198 lines
5.8 KiB
Python
Executable File

#!/usr/bin/python
"""
Console Logging
"""
import sys
import logging
try:
from argparse import ArgumentParser as _ArgumentParser
_argparse_success = True
except:
class _ArgumentParser: pass
_argparse_success = False
from .debugging import bacpypes_debugging, LoggingFormatter, ModuleLogger
from ConfigParser import ConfigParser as _ConfigParser
# some debugging
_debug = 0
_log = ModuleLogger(globals())
#
# ConsoleLogHandler
#
def ConsoleLogHandler(loggerRef='', level=logging.DEBUG, color=None):
"""Add a stream handler to stderr with our custom formatter to a logger."""
if isinstance(loggerRef, logging.Logger):
pass
elif isinstance(loggerRef, str):
# check for root
if not loggerRef:
loggerRef = _log
# check for a valid logger name
elif loggerRef not in logging.Logger.manager.loggerDict:
raise RuntimeError("not a valid logger name: %r" % (loggerRef,))
# get the logger
loggerRef = logging.getLogger(loggerRef)
else:
raise RuntimeError("not a valid logger reference: %r" % (loggerRef,))
# see if this (or its parent) is a module level logger
if hasattr(loggerRef, 'globs'):
loggerRef.globs['_debug'] += 1
elif hasattr(loggerRef.parent, 'globs'):
loggerRef.parent.globs['_debug'] += 1
# make a debug handler
hdlr = logging.StreamHandler()
hdlr.setLevel(level)
# use our formatter
hdlr.setFormatter(LoggingFormatter(color))
# add it to the logger
loggerRef.addHandler(hdlr)
# make sure the logger has at least this level
loggerRef.setLevel(level)
#
# ArgumentParser
#
class ArgumentParser(_ArgumentParser):
"""
ArgumentParser extends the one with the same name from the argparse module
by adding the common command line arguments found in BACpypes applications.
--buggers list the debugging logger names
--debug [DBEUG [DEBUG ...]] attach a console to loggers
--color debug in color
"""
def __init__(self, **kwargs):
"""Follow normal initialization and add BACpypes arguments."""
if _debug: ArgumentParser._debug("__init__")
if not _argparse_success:
raise ImportError("No module named argparse, install via pip or easy_install: https://pypi.python.org/pypi/argparse\n")
_ArgumentParser.__init__(self, **kwargs)
# add a way to get a list of the debugging hooks
self.add_argument("--buggers",
help="list the debugging logger names",
action="store_true",
)
# add a way to attach debuggers
self.add_argument('--debug', nargs='*',
help="add console log handler to each debugging logger",
)
# add a way to turn on color debugging
self.add_argument("--color",
help="turn on color debugging",
action="store_true",
)
def parse_args(self, *args, **kwargs):
"""Parse the arguments as usual, then add default processing."""
if _debug: ArgumentParser._debug("parse_args")
# pass along to the parent class
result_args = _ArgumentParser.parse_args(self, *args, **kwargs)
# check to dump labels
if result_args.buggers:
loggers = sorted(logging.Logger.manager.loggerDict.keys())
for loggerName in loggers:
sys.stdout.write(loggerName + '\n')
sys.exit(0)
# check for debug
if result_args.debug is None:
# --debug not specified
bug_list = []
elif not result_args.debug:
# --debug, but no arguments
bug_list = ["__main__"]
else:
# --debug with arguments
bug_list = result_args.debug
# attach any that are specified
if result_args.color:
for i, debug_name in enumerate(bug_list):
ConsoleLogHandler(debug_name, color=(i % 6) + 2)
else:
for debug_name in bug_list:
ConsoleLogHandler(debug_name)
# return what was parsed
return result_args
bacpypes_debugging(ArgumentParser)
#
# ConfigArgumentParser
#
class ConfigArgumentParser(ArgumentParser):
"""
ConfigArgumentParser extends the ArgumentParser with the functionality to
read in a configuration file.
--ini INI provide a separate INI file
"""
def __init__(self, **kwargs):
"""Follow normal initialization and add BACpypes arguments."""
if _debug: ConfigArgumentParser._debug("__init__")
ArgumentParser.__init__(self, **kwargs)
# add a way to read a configuration file
self.add_argument('--ini',
help="device object configuration file",
default="BACpypes.ini",
)
def parse_args(self, *args, **kwargs):
"""Parse the arguments as usual, then add default processing."""
if _debug: ConfigArgumentParser._debug("parse_args")
# pass along to the parent class
result_args = ArgumentParser.parse_args(self, *args, **kwargs)
# read in the configuration file
config = _ConfigParser()
config.read(result_args.ini)
if _debug: _log.debug(" - config: %r", config)
# check for BACpypes section
if not config.has_section('BACpypes'):
raise RuntimeError("INI file with BACpypes section required")
# convert the contents to an object
ini_obj = type('ini', (object,), dict(config.items('BACpypes')))
if _debug: _log.debug(" - ini_obj: %r", ini_obj)
# add the object to the parsed arguments
setattr(result_args, 'ini', ini_obj)
# return what was parsed
return result_args
bacpypes_debugging(ConfigArgumentParser)