Various changes
[kiosk.git] / renderer.py
1 import time
2 from datetime import datetime
3 from decorators import invokation_logged
4
5 class renderer(object):
6     """Base class for something that can render."""
7
8     @invokation_logged
9     def render(self):
10         pass
11
12     def get_name(self):
13         return self.__class__.__name__
14
15 class abstaining_renderer(renderer):
16     """A renderer that doesn't do it all the time."""
17     def __init__(self, name_to_timeout_dict):
18         self.name_to_timeout_dict = name_to_timeout_dict;
19         self.last_runs = {}
20         for key in name_to_timeout_dict:
21             self.last_runs[key] = 0
22
23     def should_render(self, keys_to_skip):
24         now = time.time()
25         for key in self.name_to_timeout_dict:
26             if (((now - self.last_runs[key]) > self.name_to_timeout_dict[key]) and
27                 key not in keys_to_skip):
28                 return key
29         return None
30
31     def render(self):
32         tries_per_key = {}
33         keys_to_skip = set()
34         while True:
35             key = self.should_render(keys_to_skip)
36             if key == None:
37                 break
38
39             if key in tries_per_key:
40                 tries_per_key[key] += 1
41             else:
42                 tries_per_key[key] = 0
43
44             if tries_per_key[key] >= 3:
45                 print('renderer: Too many failures for "%s.%s", giving up' % (
46                     self.get_name(), key))
47                 keys_to_skip.add(key)
48             else:
49                 msg = 'renderer: executing "%s.%s"' % (self.get_name(), key)
50                 if (tries_per_key[key] > 1):
51                     msg = msg + " (retry #%d)" % tries_per_key[key]
52                 print(msg)
53                 if (self.periodic_render(key)):
54                     self.last_runs[key] = time.time()
55
56     @invokation_logged
57     def periodic_render(self, key):
58         pass
59
60 class debuggable_abstaining_renderer(abstaining_renderer):
61     def __init__(self, name_to_timeout_dict, debug):
62         super(debuggable_abstaining_renderer, self).__init__(name_to_timeout_dict);
63         self.debug = debug
64
65     def debug_prefix(self):
66         return self.get_name()
67
68     def being_debugged(self):
69         return self.debug
70
71     def debug_print(self, template, *args):
72         try:
73             if self.being_debugged():
74                 if args:
75                     msg = template.format(args)
76                 else:
77                     msg = template
78
79                 # current date and time
80                 now = datetime.now()
81                 timestamp = now.strftime("%d-%b-%Y (%H:%M:%S.%f)")
82                 print("%s(%s): %s" % (self.debug_prefix(), timestamp, msg))
83         except Exception as e:
84             print("Exception in debug_print!")
85             print(e)