import time from datetime import datetime class renderer(object): """Base class for something that can render.""" def render(self): pass def get_name(self): return self.__class__.__name__ class abstaining_renderer(renderer): """A renderer that doesn't do it all the time.""" def __init__(self, name_to_timeout_dict): self.name_to_timeout_dict = name_to_timeout_dict; self.last_runs = {} for key in name_to_timeout_dict: self.last_runs[key] = 0 def should_render(self, keys_to_skip): now = time.time() for key in self.name_to_timeout_dict: if (((now - self.last_runs[key]) > self.name_to_timeout_dict[key]) and key not in keys_to_skip): return key return None def render(self): tries_per_key = {} keys_to_skip = set() while True: key = self.should_render(keys_to_skip) if key == None: break if key in tries_per_key: tries_per_key[key] += 1 else: tries_per_key[key] = 0 if tries_per_key[key] >= 3: print('renderer: Too many failures for "%s.%s", giving up' % ( self.get_name(), key)) keys_to_skip.add(key) else: msg = 'renderer: executing "%s.%s"' % (self.get_name(), key) if (tries_per_key[key] > 1): msg = msg + " (retry #%d)" % tries_per_key[key] print(msg) if (self.periodic_render(key)): self.last_runs[key] = time.time() def periodic_render(self, key): pass class debuggable_abstaining_renderer(abstaining_renderer): def __init__(self, name_to_timeout_dict, debug): super(debuggable_abstaining_renderer, self).__init__(name_to_timeout_dict); self.debug = debug def debug_prefix(self): return self.get_name() def being_debugged(self): return self.debug def debug_print(self, template, *args): try: if self.being_debugged(): if args: msg = template.format(args) else: msg = template # current date and time now = datetime.now() timestamp = now.strftime("%d-%b-%Y (%H:%M:%S.%f)") print("%s(%s): %s" % (self.debug_prefix(), timestamp, msg)) except Exception as e: print("Exception in debug_print!") print(e)