~stani/phatch/trunk

« back to all changes in this revision

Viewing changes to tests/count.py

  • Committer: Juho Vepsäläinen
  • Date: 2009-09-15 12:39:24 UTC
  • mto: This revision was merged to the branch mainline in revision 1306.
  • Revision ID: bebraw@gmail.com-20090915123924-h9gu98dzdf3sztkq
Reverted to revision 1234.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
 
 
3
# Phatch - Photo Batch Processor
 
4
# Copyright (C) 2009 www.stani.be
 
5
#
 
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.
 
10
#
 
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.
 
15
#
 
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/
 
18
#
 
19
# Phatch recommends SPE (http://pythonide.stani.be) for editing python files.
 
20
#
 
21
# Follows PEP8
 
22
 
 
23
import os
 
24
import re
 
25
from operator import itemgetter
 
26
 
 
27
ERROR_KEYS = ('count', 'error', 'description', 'actionlist', 'action',
 
28
    'traceback')
 
29
LOGS = 'logs'
 
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')
 
36
 
 
37
 
 
38
def output(filename=''):
 
39
    """Gives the full path for an output file
 
40
 
 
41
    :param filename: filename without path
 
42
    :type filename: string
 
43
    :returns: full output path
 
44
    :rtype: string
 
45
 
 
46
    >>> output('report.csv')
 
47
    'images/output/report.csv'
 
48
    """
 
49
    return os.path.join(OUTPUT, filename)
 
50
 
 
51
 
 
52
def parse_errors(filename):
 
53
    """Parses the log file and convert all errors to dictionaries.
 
54
 
 
55
    :param filename: logs filename
 
56
    :type filename: string
 
57
    :returns: all errors
 
58
    :rtype: list of dict
 
59
    """
 
60
    f = open(filename)
 
61
    source = f.read()
 
62
    f.close()
 
63
    return [match.groupdict() for match in RE_ERROR.finditer(source)]
 
64
 
 
65
 
 
66
def count_errors(errors):
 
67
    """
 
68
    :param errors: errors
 
69
    :type errors: list of dictionaries
 
70
    :returns: one example of each error with its frequency
 
71
    :rtype: dictionary
 
72
    """
 
73
    count = {}
 
74
    for error in errors:
 
75
        name = error['error']
 
76
        if name in count:
 
77
            count[name]['count'] += 1
 
78
        else:
 
79
            example = error.copy()
 
80
            example['count'] = 1
 
81
            count[name] = example
 
82
    counted_errors = count.values()
 
83
    counted_errors.sort(key=itemgetter('count'), reverse=True)
 
84
    return counted_errors
 
85
 
 
86
 
 
87
def write_csv(filename, counted_errors):
 
88
    """Write error in descending frequency to a csv file.
 
89
 
 
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
 
94
    """
 
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)
 
99
    f.close()
 
100
 
 
101
 
 
102
def write_txt(filename, counted_errors):
 
103
    """Write error in descending frequency to a txt file.
 
104
 
 
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
 
109
    """
 
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]))
 
115
        f.write(SEPARATOR)
 
116
    f.close()
 
117
 
 
118
WRITE = {
 
119
    'csv': write_csv,
 
120
    'txt': write_txt,
 
121
}
 
122
 
 
123
 
 
124
def main(logs='logs'):
 
125
    if not os.path.exists(output()):
 
126
        os.mkdir(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))
 
134
 
 
135
 
 
136
if __name__ == '__main__':
 
137
    main()