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
|
import os
import sys
import time
from . import error
class Logger:
""" Abstract class for all logger implementations.
Concrete classes will log messages using various methods,
e.g. write to a file.
"""
(ERROR, INFO, DEBUG) = (0, 1, 2)
TYPES = ("ERROR", "Info", "Debug")
debug_level = ERROR
def __init__(self, debug_level):
self.debug_level = int(debug_level)
def log(self, string, level):
""" Log a message """
if level > self.debug_level:
return
self._actual_log(string, level)
def _actual_log(self, string, level):
""" Actually perform the logging (to be implemented in subclasses) """
pass
def shutdown(self):
""" Action to perform when closing the logger """
pass
@staticmethod
def time():
""" Get a nicely formatted time string """
return time.strftime("%a %d %Y %H:%M:%S", time.localtime())
def format(self, string, level):
""" Format the error message in a standard way """
display_level = self.TYPES[level]
return "- [%s] {%s} %s" % (display_level, self.time(), string)
class WindowLogger(Logger):
""" Log messages to a window.
The window object is passed in on construction, but
only created if a message is written.
"""
def __init__(self, debug_level, window):
self.window = window
super(WindowLogger, self).__init__(debug_level)
def shutdown(self):
if self.window is not None:
self.window.is_open = False
def _actual_log(self, string, level):
if not self.window.is_open:
self.window.create("rightbelow 6new")
self.window.write(self.format(string, level)+"\n")
class FileLogger(Logger):
""" Log messages to a window.
The window object is passed in on construction, but
only created if a message is written.
"""
def __init__(self, debug_level, filename):
self.filename = os.path.expanduser(filename)
self.f = None
super(FileLogger, self).__init__(debug_level)
def __open(self):
try:
self.f = open(self.filename, 'w', encoding='utf-8')
except IOError as e:
raise error.LogError("Invalid file name '%s' for log file: %s"
% (self.filename, e))
except:
raise error.LogError("Error using file '%s' as a log file: %s"
% (self.filename, sys.exc_info()[0]))
def shutdown(self):
if self.f is not None:
self.f.close()
def _actual_log(self, string, level):
if self.f is None:
self.__open()
self.f.write(self.format(string, level)+"\n")
self.f.flush()
class Log:
loggers = {}
def __init__(self, string, level=Logger.INFO):
Log.log(string, level)
@classmethod
def log(cls, string, level=Logger.INFO):
for logger in cls.loggers.values():
logger.log(string, level)
@classmethod
def set_logger(cls, logger):
k = logger.__class__.__name__
if k in cls.loggers:
cls.loggers[k].shutdown()
cls.loggers[k] = logger
@classmethod
def remove_logger(cls, type):
if type in cls.loggers:
cls.loggers[type].shutdown()
return True
print("Failed to find logger %s in list of loggers" % type)
return False
@classmethod
def shutdown(cls):
for logger in cls.loggers.values():
logger.shutdown()
cls.loggers = {}
|