2 from datetime import datetime
3 from decorators import invokation_logged
6 class renderer(object):
7 """Base class for something that can render."""
14 return self.__class__.__name__
17 class abstaining_renderer(renderer):
18 """A renderer that doesn't do it all the time."""
20 def __init__(self, name_to_timeout_dict):
21 self.name_to_timeout_dict = name_to_timeout_dict
23 for key in name_to_timeout_dict:
24 self.last_runs[key] = 0
26 def should_render(self, keys_to_skip):
28 for key in self.name_to_timeout_dict:
30 (now - self.last_runs[key]) > self.name_to_timeout_dict[key]
31 ) and key not in keys_to_skip:
39 key = self.should_render(keys_to_skip)
43 if key in tries_per_key:
44 tries_per_key[key] += 1
46 tries_per_key[key] = 0
48 if tries_per_key[key] >= 3:
50 'renderer: Too many failures for "%s.%s", giving up'
51 % (self.get_name(), key)
55 msg = 'renderer: executing "%s.%s"' % (self.get_name(), key)
56 if tries_per_key[key] > 1:
57 msg = msg + " (retry #%d)" % tries_per_key[key]
59 if self.periodic_render(key):
60 self.last_runs[key] = time.time()
63 def periodic_render(self, key):
67 class debuggable_abstaining_renderer(abstaining_renderer):
68 def __init__(self, name_to_timeout_dict, debug):
69 super(debuggable_abstaining_renderer, self).__init__(name_to_timeout_dict)
72 def debug_prefix(self):
73 return self.get_name()
75 def being_debugged(self):
78 def debug_print(self, template, *args):
80 if self.being_debugged():
82 msg = template.format(args)
86 # current date and time
88 timestamp = now.strftime("%d-%b-%Y (%H:%M:%S.%f)")
89 print("%s(%s): %s" % (self.debug_prefix(), timestamp, msg))
90 except Exception as e:
91 print("Exception in debug_print!")