def get_row_data(self, source, depth, row_idx): """ Create a header and a detailed log message, only create a head if should display a string message without the description. """ header = self.get_header(source, depth, row_idx) log_msg = (str(source["message"]) if isinstance( source["message"], str) else pprint.pformat(source["message"], depth=6)) left_padding = constants.INDENT * (depth + 1) for para in SlicedParagraph( parts=(log_msg, "{}"), width=constants.PAGE_WIDTH - left_padding - 6, ): header = header + RowData( content=[para, "", "", ""], style=[RowStyle(left_padding=left_padding, span=tuple())], start=header.end, ) return header
def get_row_data(self, source, depth, row_idx): """ Create a header and a detailed log message, only create a head if should display a string message without the description. """ header = self.get_header(source, depth, row_idx) if not source["description"] and isinstance( source["message"], six.string_types ): return header """ Create a header and a detailed log message, only create a head if should display a string message without the description. """ header = self.get_header(source, depth, row_idx) if not source["description"] and isinstance( source["message"], six.string_types ): return header log_msg = ( str(source["message"]) if isinstance(source["message"], six.string_types) else pprint.pformat(source["message"], depth=6) ) log_para = Paragraph( text="<br />\n".join(log_msg.split("\n")), style=constants.PARAGRAPH_STYLE, ) text_style = [ RowStyle(left_padding=constants.INDENT * (depth + 1), span=tuple()) ] return header + RowData( content=[log_para, "", "", ""], style=text_style, start=header.end )
# Displayed tables constants and style, used for table.log, table.match etc. PAGE_WIDTH = constants.PAGE_WIDTH NUM_DISPLAYED_ROWS = constants.NUM_DISPLAYED_ROWS CELL_STRING_LENGTH = constants.CELL_STRING_LENGTH INNER_BORDER = constants.INNER_BORDER OUTER_BORDER = constants.OUTER_BORDER DISPLAYED_TABLE_STYLE = [ RowStyle(start_column=0, end_column=-1, start_row=0, end_row=-1, font=(FONT, FONT_SIZE_SMALL), innergrid=(INNER_BORDER, colors.black), box=(OUTER_BORDER, colors.black)), RowStyle(start_column=0, end_column=-1, start_row=0, end_row=0, background=(colors.whitesmoke), linebelow=(OUTER_BORDER, colors.black)) ] # Space between lines in a paragraph COMPACT_LINE_SPACING = 2 PARAGRAPH_STYLE = ParagraphStyle(
def get_detail(self, source, depth, row_idx): raised_exc = source['raised_exception'] expected_exceptions = ', '.join(source['expected_exceptions']) label = 'not instance of' if source['type'] == 'ExceptionNotRaised' \ else 'instance of' msg = '{} {} {}'.format(raised_exc[0], label, expected_exceptions) exc_style = RowStyle( left_padding=const.INDENT * (depth + 1), font=(const.FONT, const.FONT_SIZE_SMALL), text_color=colors.black ) exc_row = RowData(content=msg, style=exc_style, start=row_idx) end_idx = exc_row.end if source['func']: msg = 'Function: {}'.format( _format_text( colour='black' if source['passed'] else 'red', text=escape(source['func']), bold=not source['passed'] ) ) func_paragraph = Paragraph( text=msg, style=const.PARAGRAPH_STYLE ) func_style = RowStyle( left_padding=const.INDENT * (depth + 2), span=tuple() ) func_row = RowData( content=[func_paragraph, '', '', ''], style=func_style, start=end_idx ) exc_row += func_row end_idx = func_row.end if source['pattern']: msg = 'Pattern: {}'.format( _format_text( colour='black' if source['passed'] else 'red', text=escape(source['pattern']), bold=not source['passed'] ) ) msg += '<br />Exception message: {}'.format(raised_exc[1]) ptrn_paragraph = Paragraph( text=msg, style=const.PARAGRAPH_STYLE ) ptrn_style = RowStyle( left_padding=const.INDENT * (depth + 2), span=tuple() ) exc_row += RowData( content=[ptrn_paragraph, '', '', ''], style=ptrn_style, start=end_idx ) return exc_row
def get_detail(self, source, depth, row_idx): """ Render the message if there is any, then render XMLTagComparison items. """ msg = [] msg.append('xpath: {}'.format(escape(source['xpath']))) if source['namespaces']: msg.append( 'Namespaces: {}'.format( escape( str( source['namespaces'] ) ) ) ) if source['message']: msg.append( _format_text( colour='black' if source['passed'] else 'red', text=escape(source['message']), bold = not source['passed'] ) ) if source['data']: msg.append('Tags:') msg_style = RowStyle( left_padding=const.INDENT * (depth + 1), bottom_padding=0, span=tuple() ) msg_para = Paragraph( text='<br />\n'.join(msg), style=const.PARAGRAPH_STYLE ) msg_row = RowData( content=[msg_para, '', '', ''], style=msg_style, start=row_idx ) tags = [] for data in source['data']: tag_comp = assertions.XMLTagComparison( tag=data[0], diff=data[1], error=data[2], extra=data[3] ) template = '{actual} {operator} {expected}' common = dict( actual=tag_comp.tag, expected=tag_comp.comparison_value ) if tag_comp.passed: tags.append( escape( template.format( operator='==', **common ) ) ) else: tags.append( _format_text( text=escape( template.format( operator='!=', **common ) ), colour='red', bold=True ) ) if tags: tags_style = RowStyle( left_padding=const.INDENT * (depth + 2), span=tuple() ) tags_para = Paragraph( text='<br />\n'.join(tags), style=const.PARAGRAPH_STYLE ) tags_row = RowData( content=[tags_para, '', '', ''], style=tags_style, start=msg_row.end ) return msg_row + tags_row else: return msg_row
def get_detail(self, source, depth, row_idx): """ `RegexMatchLine` returns line indexes along with begin/end character indexes per matched line. """ pattern_style = [ RowStyle( font=(const.FONT, const.FONT_SIZE_SMALL), left_padding=const.INDENT * (depth + 1), text_color=colors.black, span=tuple() ), ] text_style = [ RowStyle( left_padding=const.INDENT * (depth + 1), span=tuple() ), ] if not source['passed']: pattern_style.append(RowStyle(background=colors.whitesmoke)) text_style.append(RowStyle(background=colors.whitesmoke)) p = 'Pattern: `{}`'.format(source['pattern']) pattern = RowData( content=[p, '', '', ''], style=pattern_style, start=row_idx ) if source['match_indexes']: parts = [] match_map = { line_no: (begin, end) for line_no, begin, end in source['match_indexes'] } for idx, line in enumerate(source['string'].splitlines()): if idx in match_map: begin, end = match_map[idx] formatted = '{start}{middle}{end}'.format( start=escape(line[:begin]), middle=_format_text( text=escape(line[begin:end]), colour='green', bold=False ), end=escape(line[end:])) parts.append(formatted) else: parts.append(escape(line)) text = Paragraph( text='<br />\n'.join(parts), style= const.PARAGRAPH_STYLE ) else: formatted = escape(source['string']).replace('\n', '<br />\n') text = Paragraph( text=formatted, style=const.PARAGRAPH_STYLE ) return pattern + RowData(content=[text, '', '', ''], style=text_style, start=pattern.end)
def get_detail(self, source, depth, row_idx): """ Return highlighted patterns within the string, if there is a match. """ pattern_style = [ RowStyle( font=(const.FONT, const.FONT_SIZE_SMALL), left_padding=const.INDENT * (depth + 1), text_color=colors.black, span=tuple() ), ] text_style = [ RowStyle( left_padding=const.INDENT * (depth + 1), span=tuple() ), ] if not source['passed']: pattern_style.append(RowStyle(background=colors.whitesmoke)) text_style.append(RowStyle(background=colors.whitesmoke)) p = 'Pattern: `{}`'.format(source['pattern']) pattern = RowData( content=[p, '', '', ''], style=pattern_style, start=row_idx ) string = source['string'] if source['match_indexes']: curr_idx = 0 parts = [] for begin, end in source['match_indexes']: if begin > curr_idx: s = string[curr_idx:begin].replace('\n', '<br />\n') parts.append(s) s = string[begin:end].replace('\n','<br />\n') parts.append(_format_text(s, self.highlight_color, self.bold)) curr_idx = end if curr_idx < len(string): s = string[curr_idx:].replace('\n','<br />\n') parts.append(s) text_paragraph = Paragraph( text=''.join(parts), style=const.PARAGRAPH_STYLE ) else: text_paragraph = Paragraph( text=string, style=const.PARAGRAPH_STYLE ) return pattern + RowData(content=[text_paragraph, '', '', ''], style=text_style, start=pattern.end)
def get_detail(self, source, depth, row_idx): result = RowData(start=row_idx) ellipsis = ' ...' reserved = stringWidth(ellipsis, const.FONT, const.FONT_SIZE_SMALL) max_width = const.PAGE_WIDTH - ((depth + 2) * const.INDENT) - reserved get_width = lambda text, font=const.FONT, size=const.FONT_SIZE_SMALL: \ stringWidth(text, font, size) options = '' options += '-b ' if source['ignore_space_change'] else '' options += '-w ' if source['ignore_whitespaces'] else '' options += '-B ' if source['ignore_blank_lines'] else '' options += '-u ' if source['unified'] else '' options += '-c ' if source['context'] and not source['unified'] else '' options = ' ( ' + options + ')' if options else '' detailed_text = [] if source['passed'] else [ ('*** a.text ***', self._get_truncated_lines(source['first'], const.NUM_DISPLAYED_ROWS)), ('*** b.text ***', self._get_truncated_lines(source['second'], const.NUM_DISPLAYED_ROWS)) ] detailed_text.append( ('No difference found{}'.format(options) if source['passed'] else 'Differences{}:'.format(options), [] if source['passed'] else self._get_truncated_lines(source['delta'], const.NUM_DISPLAYED_ROWS * 5)) ) for title, body in detailed_text: title_line = RowData( content=title, start=row_idx, style= RowStyle( font=(const.FONT, const.FONT_SIZE_SMALL), left_padding=const.INDENT * (depth + 1), text_color=colors.black if source['passed'] else colors.red ) ) result += title_line row_idx = title_line.end for flag, line in body: lines = split_line(line, max_width, get_width) body_text = RowData( content=[ # Be aware of the case len(line) == 0 lines[0] + ellipsis if len(lines) > 1 else line, '', '', '' ], start=row_idx, style=RowStyle( font=(const.FONT, const.FONT_SIZE_SMALL), left_padding=const.INDENT * (depth + 2), top_padding=0, bottom_padding=const.COMPACT_LINE_SPACING, text_color=colors.gray if flag else colors.black ) ) result += body_text row_idx = body_text.end return result
def get_row_style(self, source, depth, **kwargs): """Default styling for all serialized entries, with small font size.""" return RowStyle(font=(constants.FONT, constants.FONT_SIZE_SMALL), left_padding=constants.INDENT * depth, **kwargs)
def get_detail(self, source, depth, row_idx): result = RowData(start=row_idx) ellipsis = " ..." reserved = stringWidth(ellipsis, const.FONT, const.FONT_SIZE_SMALL) max_width = const.PAGE_WIDTH - ((depth + 2) * const.INDENT) - reserved def get_width(text, font=const.FONT, size=const.FONT_SIZE_SMALL): return stringWidth(text, font, size) options = "" options += "-b " if source["ignore_space_change"] else "" options += "-w " if source["ignore_whitespaces"] else "" options += "-B " if source["ignore_blank_lines"] else "" options += "-u " if source["unified"] else "" options += "-c " if source["context"] and not source["unified"] else "" options = " ( " + options + ")" if options else "" detailed_text = ([] if source["passed"] else [ ( "*** a.text ***", self._get_truncated_lines(source["first"], const.NUM_DISPLAYED_ROWS), ), ( "*** b.text ***", self._get_truncated_lines(source["second"], const.NUM_DISPLAYED_ROWS), ), ]) detailed_text.append(( "No difference found{}".format(options) if source["passed"] else "Differences{}:".format(options), [] if source["passed"] else self._get_truncated_lines( source["delta"], const.NUM_DISPLAYED_ROWS * 5), )) for title, body in detailed_text: title_line = RowData( content=title, start=row_idx, style=RowStyle( font=(const.FONT, const.FONT_SIZE_SMALL), left_padding=const.INDENT * (depth + 1), text_color=colors.black if source["passed"] else colors.red, ), ) result += title_line row_idx = title_line.end for flag, line in body: lines = split_line(line, max_width, get_width) body_text = RowData( content=[ # Be aware of the case len(line) == 0 lines[0] + ellipsis if len(lines) > 1 else line, "", "", "", ], start=row_idx, style=RowStyle( font=(const.FONT, const.FONT_SIZE_SMALL), left_padding=const.INDENT * (depth + 2), top_padding=0, bottom_padding=const.COMPACT_LINE_SPACING, text_color=colors.gray if flag else colors.black, ), ) result += body_text row_idx = body_text.end return result
def get_detail(self, source, depth, row_idx): """ Render the message if there is any, then render XMLTagComparison items. """ msg = [] msg.append("xpath: {}".format(html_escape(source["xpath"]))) if source["namespaces"]: msg.append("Namespaces: {}".format( html_escape(str(source["namespaces"])))) if source["message"]: msg.append( _format_text( colour="black" if source["passed"] else "red", text=html_escape(source["message"]), bold=not source["passed"], )) if source["data"]: msg.append("Tags:") msg_style = RowStyle( left_padding=const.INDENT * (depth + 1), bottom_padding=0, span=tuple(), ) msg_para = Paragraph(text="<br />\n".join(msg), style=const.PARAGRAPH_STYLE) msg_row = RowData(content=[msg_para, "", "", ""], style=msg_style, start=row_idx) tags = [] for data in source["data"]: tag_comp = assertions.XMLTagComparison(tag=data[0], diff=data[1], error=data[2], extra=data[3]) template = "{actual} {operator} {expected}" common = dict(actual=tag_comp.tag, expected=tag_comp.comparison_value) if tag_comp.passed: tags.append( html_escape(template.format(operator="==", **common))) else: tags.append( _format_text( text=html_escape( template.format(operator="!=", **common)), colour="red", bold=True, )) if tags: tags_style = RowStyle(left_padding=const.INDENT * (depth + 2), span=tuple()) tags_para = Paragraph(text="<br />\n".join(tags), style=const.PARAGRAPH_STYLE) tags_row = RowData( content=[tags_para, "", "", ""], style=tags_style, start=msg_row.end, ) return msg_row + tags_row else: return msg_row