class Record(WidgetWrap): """Render details about a single test case.""" def __init__(self, repository): self._repository = repository self._log = Text("") self._box = LineBox(self._log) self._bind() super(Record, self).__init__(self._box) def _bind(self): self._repository.on_record_start += self._update_title self._repository.on_record_progress += self._update_logs def _update_title(self, repository, record): self._box.set_title(record.id) self._log.set_text("") def _update_logs(self, repository, record): log = "" traceback = "" for name, detail in record.details.items(): text = detail.as_text().strip() if detail.content_type.subtype == "x-log": log += text elif detail.content_type.subtype == "x-traceback": # XXX Figure out how to get the timestamp from the original # subunit packet, instead of letting LogRecord create # a local timestamp. log_record = LogRecord( name, ERROR, None, None, text, None, None) traceback += defaultFormatter.format(log_record) self._log.set_text(log + traceback)
class UIManager: SUPPORTED_WIDGETS = { 'graph': Graph, 'bar': Bar, } DEFAULT_TITLE = 'Coral Dashboard - {version}' DEFAULT_MESSAGE_WIDTH = 0.5 DEFAULT_MESSAGE_HEIGHT = 0.5 def __init__(self): self._body = WidgetPlaceholder( Pile([ Filler( Text( 'Coral Dashboard Initialized\n' 'Waiting for agent ...', align='center', ), ), ])) self._wrapper = LineBox( self._body, title=self.DEFAULT_TITLE.format(version=__version__), ) self.palette = () self.topmost = MessageShower( self._wrapper, width=self.DEFAULT_MESSAGE_WIDTH, height=self.DEFAULT_MESSAGE_HEIGHT, ) self.tree = OrderedDict() def build(self, widgets, title): rows = [] tree = OrderedDict() def _instance_and_register(widget, identifier, **kwargs): widgetclass = self.SUPPORTED_WIDGETS[widget] instance = widgetclass(identifier, **kwargs) tree[identifier] = instance return instance for descriptor in widgets: # Descriptor for an instance of a Graph or a Bar if type(descriptor) is dict: widget = _instance_and_register(**descriptor) if isinstance(widget, Bar): widget = ('pack', widget) # Descriptor for a divider elif descriptor is None: widget = ('pack', Divider(' ')) # Descriptor for a section title elif type(descriptor) is str: widget = ('pack', AttrMap(Text(descriptor, align='center'), 'section title')) # Descriptor for columns # IMPORTANT: # With this implementation, you may only have columns of the # same widget type, either all columns are graphs, or all # columns are bars. elif type(descriptor) is list: columns = [ _instance_and_register(**column) for column in descriptor ] widget = Columns(columns, dividechars=1) if any(isinstance(column, Bar) for column in columns): widget = ('pack', widget) else: raise RuntimeError('Unknown descriptor type {} for {}'.format( type(descriptor), descriptor, )) rows.append(widget) # Set new screen if title is None: title = self.DEFAULT_TITLE self._wrapper.set_title(title.format(version=__version__)) self._body.original_widget = Pile(rows) self.tree.clear() self.tree.update(tree) return {'tree': list(tree)} def push(self, data, title): pushed = [] for key, value in data.items(): if key not in self.tree: log.warning('Unknown UI field {} got value {}'.format( key, value)) continue self.tree[key].push(**value) pushed.append(key) if title is None: title = self.DEFAULT_TITLE self._wrapper.set_title(title.format(version=__version__)) return pushed