Skip to content

Commit 8796ff5

Browse files
committed
GUI -common: add common logger/ini qualifier
This will remove the Qt naming when used with other GUIs
1 parent c43a18f commit 8796ff5

3 files changed

Lines changed: 1177 additions & 0 deletions

File tree

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#!/usr/bin/env python3
2+
3+
# Copyright (c) 2017 Kurt Jacobson
4+
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
import re
24+
from copy import copy
25+
from logging import Formatter
26+
27+
PREFIX = '\033['
28+
SUFFIX = '\033[0m'
29+
30+
COLORS = {
31+
'black': 30,
32+
'red': 31,
33+
'green': 32,
34+
'yellow': 33,
35+
'blue': 34,
36+
'magenta': 35,
37+
'cyan': 36,
38+
'white': 37,
39+
'bgred': 41,
40+
'bggreen': 42,
41+
'bgyellow': 43,
42+
'bggrey': 100
43+
}
44+
45+
MAPPING = {
46+
'VERBOSE': 'bggrey',
47+
'DEBUG': 'blue',
48+
'INFO': 'cyan',
49+
'WARNING': 'yellow',
50+
'ERROR': 'red',
51+
'CRITICAL': 'bgred',
52+
}
53+
54+
55+
# Returns `text` warped in ASCII escape codes to produce `color`
56+
def COLORIZE(text, color=None):
57+
seq = COLORS.get(color, 37) # default to white
58+
return '{0}{1}m{2}{3}'.format(PREFIX, seq, text, SUFFIX)
59+
60+
61+
# Matches only the first `color<text>` occurrence
62+
# ^(.*?)<([^)]+)>
63+
64+
# Matches all `color<text>` occurrences, both take the same number of steps
65+
# ([^<\s]+)<([^>]+)>
66+
# (\w+)<([^>]+)>
67+
68+
RE = re.compile(r'(\w+)<([^>]+)>')
69+
70+
71+
class ColoredFormatter(Formatter):
72+
73+
def __init__(self, pattern):
74+
Formatter.__init__(self, pattern)
75+
76+
# Override the Formatter's format method to add ASCII colors
77+
# to the levelname and any marked words in the log message.
78+
def format(self, record):
79+
colored_record = copy(record)
80+
81+
# Add colors to levelname
82+
levelname = colored_record.levelname
83+
color = MAPPING.get(levelname, 'white')
84+
colored_record.levelname = COLORIZE(levelname, color)
85+
86+
# Add colors to tagged message text
87+
msg = colored_record.getMessage()
88+
plain_msg, color_msg = self.color_words(msg)
89+
record.msg = plain_msg
90+
colored_record.msg = color_msg
91+
92+
return Formatter.format(self, colored_record)
93+
94+
# Replace `color<message>` in the log message with ASCII codes to colorize
95+
# the word or phrase in the terminal log handler. Also return a cleaned
96+
# version of the message with the tags removed for use by the file handler.
97+
def color_words(self, raw_msg):
98+
plain_msg = color_msg = raw_msg
99+
if '<' in raw_msg: # If no tag don't try to match
100+
iterator = RE.finditer(raw_msg)
101+
if iterator:
102+
for match in iterator:
103+
group = match.group()
104+
color = match.group(1)
105+
word = match.group(2)
106+
107+
# Could be optimized, but will rarely have more than one match
108+
color_msg = color_msg.replace(group, COLORIZE(word, color))
109+
plain_msg = plain_msg.replace(group, word)
110+
111+
return plain_msg, color_msg
112+
113+
114+
# ----------------------- E X A M P L E -----------------------
115+
116+
if __name__ == '__main__':
117+
118+
import logging
119+
120+
# Create logger
121+
log = logging.getLogger(__name__)
122+
log.setLevel(logging.DEBUG)
123+
124+
# Add console handler
125+
ch = logging.StreamHandler()
126+
ch.setLevel(logging.DEBUG)
127+
cf = ColoredFormatter("[%(name)s][%(levelname)s] %(message)s (%(filename)s:%(lineno)d)")
128+
ch.setFormatter(cf)
129+
log.addHandler(ch)
130+
131+
# Add file handler
132+
fh = logging.FileHandler('demo.log')
133+
fh.setLevel(logging.DEBUG)
134+
ff = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
135+
fh.setFormatter(ff)
136+
log.addHandler(fh)
137+
138+
# Log some stuff
139+
log.debug("Logging demo has green<STARTED>")
140+
log.info("Logging to yellow<demo.log> in the script dir")
141+
log.warning("This is my last warning, red<take heed>")
142+
log.error("This is an error")
143+
log.critical("He's dead, Jim")
144+
145+
# Example exception logging
146+
try:
147+
print(False + "True")
148+
except Exception as e:
149+
log.debug('That did not work!', exc_info=e)

0 commit comments

Comments
 (0)