def human_readable_lines(self, wrap=80, label=""): """A pretty human readable representation of the object. Args: wrap: maximum number of characters per line. 0 or negative wrap means no limit. Should be chosen long enough to comfortably fit formatted data; otherwise it is simply ignored and output may look funny. label: a label prefix. Returns: a list of line strings of at most |wrap| characters each. """ to_print = str(self) formatted_label = label + ": " if label else "" if (to_print.find("\n") == -1 and (wrap <= 0 or len(to_print) + len(formatted_label) <= wrap)): # Fits on one line, like this: # label: value return [formatted_label + to_print] else: # Multiline output: # label: # firstlongvalueline # secondvalueline ret = [] indent = 2 if label: ret += print_util.wrap_lines(label + ":", wrap) return ret + [" " * indent + x for x in self.wrap_lines(to_print, wrap-indent)]
def wrap_lines(cls, long_string, wrap): """Split long lines into multiple chunks according to the wrap limit. Derived classes can override char_wrap if they wish to, e.g., not split hex bytes. Args: long_string: a string_value() representation of the object wrap: maximum number of characters per line. 0 or negative wrap means no limit. Should be chosen long enough to comfortably fit formatted data; otherwise it is simply ignored and output may look funny. Returns: long_string split into lines of at most |wrap| characters each. """ wrap -= wrap % cls.char_wrap return print_util.wrap_lines(long_string, wrap)
def human_readable_lines(self, wrap=80, label=""): """A pretty human readable representation of the object. Args: wrap: maximum number of characters per line. 0 or negative wrap means no limit. Should be chosen long enough to comfortably fit formatted data; otherwise it is simply ignored and output may look funny. label: a label prefix. Returns: a list of line strings of at most |wrap| characters each. """ # A "\n" becomes ["", ""] which magically starts a new line when we call # append_lines() on it. Things like "\n-----\n" work, too. delimiter = (print_util.wrap_lines(self.print_delimiter, wrap=wrap)) lines = [] # Component count. Needed so we can print "<no components>" when none # are found. count = 0 # Whether the next component should start on a new line. Set to true # when the previous component was multiline. For example, a mix of short # and long components with a ", " delimiter is thus printed as # short1, short2, short3, # myextremelylongcomponentth # atspansmultiplelines # short4, short5 newline = False if label: lines += print_util.wrap_lines(label + ":", wrap) # If the delimiter is multiline, then output looks prettier if the # label is also on a separate line. if len(delimiter) > 1: newline = True elif len(lines[-1]) < wrap: # Else add a whitespace so we get "label: value" lines[-1] += " " indent = 2 for key, value in self.iteritems(): if value is None: continue label = str(key) if self.print_labels else "" print_component = value.human_readable_lines(wrap=wrap-indent, label=label) if not print_component: continue if count: print_util.append_lines(delimiter, wrap, lines) count += 1 # Make multiline components a separate block on a new line, unless # we already are on a new line. if (newline or len(print_component) > 1) and lines and lines[-1]: lines += print_component else: print_util.append_lines(print_component, wrap, lines) newline = len(print_component) > 1 if not count: print_util.append_lines(["<no components>"], wrap, lines) # Indent everything apart from the first line. return [lines[0]] + [" " + x for x in lines[1:]]
def test_wrap_lines_no_wrap(self): long_multiline_string = "hello\nworld" self.assertEqual(["hello", "world"], print_util.wrap_lines(long_multiline_string, 0))