Jeff Long 5b5234d519 grc: formatting for qt-gui
Signed-off-by: Jeff Long <willcode4@gmail.com>
2024-03-15 15:11:27 -04:00

133 lines
4.9 KiB
Python

import logging
class GRCHandler(logging.Handler): # Inherit from logging.Handler
''' Custom log handler for GRC. Stores log entries to be viewed using the GRC debug window. '''
def __init__(self, maxLength=256):
# run the regular Handler __init__
logging.Handler.__init__(self)
# Our custom argument
self.log = collections.deque(maxlen=maxLength)
def emit(self, record):
self.log.append(record)
def getLogs(self, level):
pass
class ConsoleFormatter(logging.Formatter):
'''
Custom log formatter that nicely truncates the log message and log levels
- Verbose mode outputs: time, level, message, name, filename, and line number
- Normal mode output varies based on terminal size:
w < 80 - Level, Message (min length 40)
80 < w < 120 - Level, Message, File, Line (25)
120 < w - Level, Message, Name, File, Line
- Color mode ouptuts the same variable sizes and uses the blessings module
to add color
'''
# TODO: Better handle multi line messages. Need to indent them or something
def __init__(self, verbose=False, short_level=True):
# Test for blessings formatter
try:
from blessings import Terminal
self.terminal = Terminal()
self.formatLevel = self.formatLevelColor
except:
self.terminal = None
self.formatLevel = self.formatLevelPlain
# Default to short
self.formatLevelLength = self.formatLevelShort
if not short_level:
self.formatLevelLength = self.formatLevelLong
# Setup the format function as a pointer to the correct formatting function
# Determine size and mode
# TODO: Need to update the sizes depending on short or long outputs
import shutil
size = shutil.get_terminal_size()
width = max(40, size.columns - 10)
if size.columns < 80:
self.format = self.short
self.width = width
elif size.columns < 120:
self.format = self.medium
self.width = width - 30
elif size.columns >= 120:
self.format = self.long
self.width = width - 45
# Check if verbose mode. If so override other options
if verbose:
self.format = self.verbose
# Normal log formmatters
def short(self, record):
message = self.formatMessage(record.msg, self.width)
level = self.formatLevel(record.levelname)
return "{0} -- {1}".format(level, message)
def medium(self, record):
message = self.formatMessage(record.msg, self.width)
level = self.formatLevel(record.levelname)
output = '{0} -- {1:<' + str(self.width) + '} ({2}:{3})'
return output.format(level, message, record.filename, record.lineno)
def long(self, record):
message = self.formatMessage(record.msg, self.width)
level = self.formatLevel(record.levelname)
output = '{0} -- {1:<' + str(self.width) + '} {2} ({3}:{4})'
return output.format(level, message, record.name, record.filename, record.lineno)
''' Verbose formatter '''
def verbose(self, record):
# TODO: Still need to implement this
pass
''' Level and message formatters '''
# Nicely format the levelname
# Level name can be formated to either short or long, and also with color
def formatLevelColor(self, levelname):
term = self.terminal
output = "{0}{1}{2}{3}"
level = self.formatLevelLength(levelname)
if levelname == "DEBUG":
return output.format(term.blue, "", level, term.normal)
elif levelname == "INFO":
return output.format(term.green, "", level, term.normal)
elif levelname == "WARNING":
return output.format(term.yellow, "", level, term.normal)
elif levelname == "ERROR":
return output.format(term.red, term.bold, level, term.normal)
elif levelname == "CRITICAL":
return output.format(term.red, term.bold, level, term.normal)
else:
return output.format(term.blue, "", level, term.normal)
def formatLevelPlain(self, levelname):
''' Format the level name without color. formatLevelLength points to the right function '''
return self.formatLevelLength(levelname)
def formatLevelShort(self, levelname):
return "[{0}]".format(levelname[0:1])
def formatLevelLong(self, levelname):
output = "{0:<10}"
if levelname in ["DEBUG", "INFO", "WARNING"]:
return output.format("[{0}]".format(levelname.capitalize()))
else:
return output.format("[{0}]".format(levelname.upper()))
def formatMessage(self, message, width):
# First, strip out any newline for console output
message = message.rstrip()
if len(message) > width:
return (message[:(width - 3)] + "...")
return message