-
-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathDebug.py
More file actions
executable file
·142 lines (110 loc) · 4.19 KB
/
Copy pathDebug.py
File metadata and controls
executable file
·142 lines (110 loc) · 4.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
from logging import Logger, Formatter, getLogger, setLoggerClass, StreamHandler
from logging.handlers import TimedRotatingFileHandler
from logging import DEBUG, INFO, WARNING, ERROR, CRITICAL
from pathlib import Path
from tqdm import tqdm
"""Global tqdm arguments"""
TQDM_KWARGS = {
# Progress bar format string
'bar_format': ('{desc:.50s} {percentage:2.0f}%|{bar}| {n_fmt}/{total_fmt} '
'[{elapsed}]'),
# Progress bars should disappear when finished
'leave': False,
# Progress bars can not be used if no TTY is present
'disable': None,
}
"""Log file"""
LOG_FILE = Path(__file__).parent.parent / 'logs' / 'maker.log'
LOG_FILE.parent.mkdir(parents=True, exist_ok=True)
class BetterExceptionLogger(Logger):
"""
Logger class that overrides `Logger.exception` to log as
`Logger.error`, and then print the traceback at the debug level.
"""
def exception(self, msg: object, *args, **kwargs) -> None:
super().exception(msg, *args, exc_info=True, **kwargs)
setLoggerClass(BetterExceptionLogger)
class LogHandler(StreamHandler):
"""Handler to integrate log messages with tqdm."""
def emit(self, record):
# Write after flushing buffer to integrate with tqdm
try:
tqdm.write(self.format(record))
self.flush()
except Exception:
self.handleError(record)
# Formatter classes to handle exceptions
class ErrorFormatterColor(Formatter):
"""
Formatter class to handle exception traceback printing with color.
"""
def formatException(self, ei) -> str:
return f'\x1b[1;30m[TRACEBACK] {super().formatException(ei)}\x1b[0m'
class ErrorFormatterNoColor(Formatter):
"""
Formatter class to handle exception traceback printing without
color.
"""
def formatException(self, ei) -> str:
return f'[TRACEBACK] {super().formatException(ei)}'
class LogFormatterColor(Formatter):
"""
Formatter containing ErrorFormatterColor objects instantiated with
different format strings for various colors depending on the log
level.
"""
"""Color codes"""
GRAY = '\x1b[1;30m'
CYAN = '\033[96m'
YELLOW = '\x1b[33;20m'
RED = '\x1b[31;20m'
BOLD_RED = '\x1b[31;1m'
RESET = '\x1b[0m'
format_layout = '[%(levelname)s] %(message)s'
LEVEL_FORMATS = {
DEBUG: ErrorFormatterColor(f'{GRAY}{format_layout}{RESET}'),
INFO: ErrorFormatterColor(f'{CYAN}{format_layout}{RESET}'),
WARNING: ErrorFormatterColor(f'{YELLOW}{format_layout}{RESET}'),
ERROR: ErrorFormatterColor(f'{RED}{format_layout}{RESET}'),
CRITICAL: ErrorFormatterColor(f'{BOLD_RED}{format_layout}{RESET}'),
}
def format(self, record):
return self.LEVEL_FORMATS[record.levelno].format(record)
class LogFormatterNoColor(Formatter):
"""Colorless version of the `LogFormatterColor` class."""
FORMATTER = ErrorFormatterNoColor('[%(levelname)s] %(message)s')
def format(self, record):
return self.FORMATTER.format(record)
# Create global logger
log = getLogger('tcm')
log.setLevel(DEBUG)
# Add TQDM handler and color formatter to the logger
handler = LogHandler()
handler.setFormatter(LogFormatterColor())
handler.setLevel(DEBUG)
log.addHandler(handler)
# Add rotating file handler to the logger
file_handler = TimedRotatingFileHandler(
filename=LOG_FILE, when='midnight', backupCount=14,
)
file_handler.setFormatter(ErrorFormatterNoColor(
'[%(levelname)s] [%(asctime)s.%(msecs)03d] %(message)s',
'%m-%d-%y %H:%M:%S'
))
file_handler.setLevel(DEBUG)
log.addHandler(file_handler)
def apply_no_color_formatter() -> None:
"""
Modify the global logger object by replacing the colored Handler
with an instance of the LogFormatterNoColor Handler class. Also set
the log level to that of the removed handler.
"""
# Get existing handler's log level, then delete
log_level = log.handlers[0].level
log.removeHandler(log.handlers[0])
# Create colorless Handler with Colorless Formatter
handler = LogHandler()
handler.setFormatter(LogFormatterNoColor())
handler.setLevel(log_level)
# Add colorless handler in place of deleted one
log.addHandler(handler)