3
# Phatch - Photo Batch Processor
4
# Copyright (C) 2009 www.stani.be
6
# This program is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation, either version 3 of the License, or
9
# (at your option) any later version.
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with this program. If not, see http://www.gnu.org/licenses/
19
# Phatch recommends SPE (http://pythonide.stani.be) for editing python files.
25
from operator import itemgetter
27
ERROR_KEYS = ('count', 'error', 'description', 'actionlist', 'action',
30
RE_ERROR = re.compile('20[0-9]{2}.+?actionlist:\s*(?P<actionlist>.+?)\s*'\
31
'generated.+?logs:\n.+?:(?P<description>.+?)\s*Action:(?P<action>.+?)\s*'\
32
'Traceback.+?:\n\s*(?P<traceback>.+?\n[A-Z].+?:\s*(?P<error>.+?))\n[*]',
33
re.DOTALL|re.MULTILINE)
34
SEPARATOR = '-'*40+'\n'
35
OUTPUT = os.path.join('output')
38
def output(filename=''):
39
"""Gives the full path for an output file
41
:param filename: filename without path
42
:type filename: string
43
:returns: full output path
46
>>> output('report.csv')
47
'images/output/report.csv'
49
return os.path.join(OUTPUT, filename)
52
def parse_errors(filename):
53
"""Parses the log file and convert all errors to dictionaries.
55
:param filename: logs filename
56
:type filename: string
63
return [match.groupdict() for match in RE_ERROR.finditer(source)]
66
def count_errors(errors):
69
:type errors: list of dictionaries
70
:returns: one example of each error with its frequency
77
count[name]['count'] += 1
79
example = error.copy()
82
counted_errors = count.values()
83
counted_errors.sort(key=itemgetter('count'), reverse=True)
87
def write_csv(filename, counted_errors):
88
"""Write error in descending frequency to a csv file.
90
:param filename: filename of the csv file
91
:type filename: string
92
:param counted_errors: errors counted by :func:`count_errors`
93
:type counted_errors: list of dictionaries
95
f = open(filename, 'w')
96
f.write('count, error, actionlist\n')
97
for error in counted_errors:
98
f.write('%(count)02d, %(error)s, %(actionlist)s\n'%error)
102
def write_txt(filename, counted_errors):
103
"""Write error in descending frequency to a txt file.
105
:param filename: filename of the csv file
106
:type filename: string
107
:param counted_errors: errors counted by :func:`count_errors`
108
:type counted_errors: list of dictionaries
110
f = open(filename, 'w')
111
f.write('count, error, actionlist\n')
112
for error in counted_errors:
113
for key in ERROR_KEYS:
114
f.write('%s = %s\n\n'%(key.upper(), error[key]))
124
def main(logs='logs'):
125
if not os.path.exists(output()):
127
errors = parse_errors(logs)
128
counted_errors = count_errors(errors)
129
for ext, write in WRITE.items():
130
logs_filename = output(logs+'.'+ext)
131
write(logs_filename, counted_errors)
132
print('%d different errors written to "%s"'
133
%(len(counted_errors), logs_filename))
136
if __name__ == '__main__':