1
2
3
4 """
5 This module provides a class to store and represent statistics about the
6 data acquisition by plugins and portals.
7
8 @author: Johannes Schwenk
9 @copyright: 2010, Johannes Schwenk
10 @version: 2.0
11 @date: 2010-09-15
12
13
14 """
15
16 import sys
17 from datetime import datetime, timedelta
18
19
20 reload(sys)
21 sys.setdefaultencoding('utf-8')
22
23 from operator import itemgetter
24
25 from xmlgetter.log import BaseLogger
26
27
28 -class Stats(dict, BaseLogger):
29 """
30 Stores and represents statistics about the update process.
31
32 This is a dict-like object, that can contain only other instances of
33 C{Stats}.
34
35 """
36
37 source = None
38 """
39 @ivar: The sources name.
40 @type: string
41
42 """
43
44 entries = -1
45 """
46 @ivar: Number of entries in total.
47 @type: int
48
49 """
50
51 new_entries = -1
52 """
53 @ivar: Number of newly added entries since the last update.
54 @type: int
55
56 """
57
58 modified_entries = -1
59 """
60 @ivar: Number of entries that hav been modified since the last update.
61 @type: int
62
63 """
64
65 unmodified_entries = -1
66 """
67 @ivar: Number of unmodified entries.
68 @type: int
69
70 """
71
72 static_entries = -1
73 """
74 @ivar: Number of static entries. "Static" meaning entries that can not be
75 send as a stub, because there is no modification timestamp.
76 @type: int
77
78 """
79
80 status = None
81 """
82 @ivar: A string denoting the status of the update process.
83 Currently it is set to C{u'ok'} for success and C{u'FAILED'}
84 for a failed run.
85 TODO update, finish implementation!
86 @type: string
87
88 """
89
90 messages = None
91 """
92 @ivar: A list of messages added during the update process. Can be used to
93 notify the user about uncritical errors and warnings.
94 @type: list
95
96 """
97
98 update_time_start = None
99 """
100 @ivar: The date and time of the start of the update process.
101 @type: datetime
102
103 """
104
105 update_time_end = None
106 """
107 @ivar: The date and time of the end of the update process.
108 @type: datetime
109
110 """
111
112
113
114 - def __init__(self, source=u'__main__'):
135
136
138 """
139 Provided to produce dict-like behavior. All it does is logging
140 a warning on DEBUG level, if someone tries to set a item.
141
142 """
143 self.logger.debug(u'Attempt to set item of Stats object')
144
145
147 """
148 Add a instance of C{Stats} to the internal dictionary using the
149 C{source} property as key. Abort if C{stat_entry} is not an instance of
150 C{Stats}
151
152 @param stat_entry: A C{Stats} instance.
153 @type stat_entry: Stats
154
155 """
156 if not isinstance(stat_entry, Stats):
157 return
158 dict.__setitem__(self, stat_entry.source, stat_entry)
159
160
162 """
163 Return a table representing the information in this instance and
164 all C{Stats} instances contained in the internal dictionary.
165
166 @return: A table with the statistical information.
167 @rtype: string
168
169 """
170 p_head = u'[Source] '
171 s_head = u'[Static] '
172 e_head = u'[Entries]'
173 ne_head = u'[New] '
174 mod_head = u'[Modified]'
175 unmod_head = u'[Unmodified]'
176 status_head = u'[Status] '
177 s_stats = s_head.ljust(len(s_head) + 3, u' ')
178 p_stats = p_head.ljust(len(p_head) + 3, u' ')
179 e_stats = e_head.ljust(len(e_head) + 3, u' ')
180 ne_stats = ne_head.ljust(len(ne_head) + 3, u' ')
181 mod_stats = mod_head.ljust(len(mod_head) + 3, u' ')
182 unmod_stats = unmod_head.ljust(len(unmod_head) + 3, u' ')
183 status_stats = status_head.ljust(len(status_head) + 3, u' ')
184 stats = u'\n%s%s%s%s%s%s%s' % (p_stats, s_stats, e_stats, ne_stats,
185 mod_stats, unmod_stats, status_stats)
186 messages = u''
187 keys = sorted(self.keys())
188 for k in keys:
189 p_stats = (u' %s' % self[k].source).ljust(len(p_head) + 5, u' ')
190 s_stats = (u'%s' % self[k].static_entries) \
191 .ljust(len(s_head) + 3, u' ')
192 e_stats = (u'%s' % self[k].entries).ljust(len(e_head) + 3, u' ')
193 ne_stats = (u'%s' % self[k].new_entries) \
194 .ljust(len(ne_head) + 3, u' ')
195 mod_stats = (u'%s' % self[k].modified_entries) \
196 .ljust(len(mod_head) + 3, u' ')
197 unmod_stats = (u'%s' % self[k].unmodified_entries) \
198 .ljust(len(unmod_head) + 3, u' ')
199 status_stats = (u'%s' % self[k].status) \
200 .ljust(len(unmod_head) + 3, u' ')
201 stats = u'%s\n%s%s%s%s%s%s%s' % (stats, p_stats, s_stats, e_stats,
202 ne_stats, mod_stats, unmod_stats, status_stats)
203 if len(self[k].messages) > 0:
204 if messages == u'':
205 messages = u'\nThere are messages:\n'
206 messages = u'%s\n[%s]' % (messages, self[k].source)
207 for message in self[k].messages:
208 messages = u'%s\n\t%s' % (messages, message)
209 stats = u'%s\n%s\n' % (stats, messages)
210 stats = u'%s\nTimes [h:m:s.ms]:\nTotal : %s' % (stats,
211 self.update_time_diff)
212 for k in keys:
213 stats = u'%s\n[%s] : %s' % (stats, self[k].source,
214 self[k].update_time_diff)
215 return stats
216
217
218 @property
220 """
221 @return: The C{timedelta} for the two variables L{update_time_end}
222 and L{update_time_start}.
223 @rtype: C{timedelta}
224
225 """
226 return self.update_time_end - self.update_time_start
227