def format_object_summary(obj, formatter, is_justify=True, name=None, indent_for_name=True): """ Return the formatted obj as a unicode string Parameters ---------- obj : object must be iterable and support __getitem__ formatter : callable string formatter for an element is_justify : boolean should justify the display name : name, optional defaults to the class name of the obj indent_for_name : bool, default True Whether subsequent lines should be be indented to align with the name. Returns ------- summary string """ from pandas.io.formats.console import get_console_size from pandas.io.formats.format import _get_adjustment display_width, _ = get_console_size() if display_width is None: display_width = get_option('display.width') or 80 if name is None: name = obj.__class__.__name__ if indent_for_name: name_len = len(name) space1 = "\n%s" % (' ' * (name_len + 1)) space2 = "\n%s" % (' ' * (name_len + 2)) else: space1 = "\n" space2 = "\n " # space for the opening '[' n = len(obj) sep = ',' max_seq_items = get_option('display.max_seq_items') or n # are we a truncated display is_truncated = n > max_seq_items # adj can optionally handle unicode eastern asian width adj = _get_adjustment() def _extend_line(s, line, value, display_width, next_line_prefix): if (adj.len(line.rstrip()) + adj.len(value.rstrip()) >= display_width): s += line.rstrip() line = next_line_prefix line += value return s, line def best_len(values): if values: return max(adj.len(x) for x in values) else: return 0 close = u', ' if n == 0: summary = u'[]{}'.format(close) elif n == 1: first = formatter(obj[0]) summary = u'[{}]{}'.format(first, close) elif n == 2: first = formatter(obj[0]) last = formatter(obj[-1]) summary = u'[{}, {}]{}'.format(first, last, close) else: if n > max_seq_items: n = min(max_seq_items // 2, 10) head = [formatter(x) for x in obj[:n]] tail = [formatter(x) for x in obj[-n:]] else: head = [] tail = [formatter(x) for x in obj] # adjust all values to max length if needed if is_justify: # however, if we are not truncated and we are only a single # line, then don't justify if (is_truncated or not (len(', '.join(head)) < display_width and len(', '.join(tail)) < display_width)): max_len = max(best_len(head), best_len(tail)) head = [x.rjust(max_len) for x in head] tail = [x.rjust(max_len) for x in tail] summary = "" line = space2 for i in range(len(head)): word = head[i] + sep + ' ' summary, line = _extend_line(summary, line, word, display_width, space2) if is_truncated: # remove trailing space of last line summary += line.rstrip() + space2 + '...' line = space2 for i in range(len(tail) - 1): word = tail[i] + sep + ' ' summary, line = _extend_line(summary, line, word, display_width, space2) # last value: no sep added + 1 space of width used for trailing ',' summary, line = _extend_line(summary, line, tail[-1], display_width - 2, space2) summary += line # right now close is either '' or ', ' # Now we want to include the ']', but not the maybe space. close = ']' + close.rstrip(' ') summary += close if len(summary) > (display_width): summary += space1 else: # one row summary += ' ' # remove initial space summary = '[' + summary[len(space2):] return summary
def format_object_summary( obj, formatter: Callable, is_justify: bool = True, name: Optional[str] = None, indent_for_name: bool = True, line_break_each_value: bool = False, ) -> str: """ Return the formatted obj as a unicode string Parameters ---------- obj : object must be iterable and support __getitem__ formatter : callable string formatter for an element is_justify : boolean should justify the display name : name, optional defaults to the class name of the obj indent_for_name : bool, default True Whether subsequent lines should be be indented to align with the name. line_break_each_value : bool, default False If True, inserts a line break for each value of ``obj``. If False, only break lines when the a line of values gets wider than the display width. .. versionadded:: 0.25.0 Returns ------- summary string """ from pandas.io.formats.console import get_console_size from pandas.io.formats.format import _get_adjustment display_width, _ = get_console_size() if display_width is None: display_width = get_option("display.width") or 80 if name is None: name = type(obj).__name__ if indent_for_name: name_len = len(name) space1 = f'\n{(" " * (name_len + 1))}' space2 = f'\n{(" " * (name_len + 2))}' else: space1 = "\n" space2 = "\n " # space for the opening '[' n = len(obj) if line_break_each_value: # If we want to vertically align on each value of obj, we need to # separate values by a line break and indent the values sep = ",\n " + " " * len(name) else: sep = "," max_seq_items = get_option("display.max_seq_items") or n # are we a truncated display is_truncated = n > max_seq_items # adj can optionally handle unicode eastern asian width adj = _get_adjustment() def _extend_line(s: str, line: str, value: str, display_width: int, next_line_prefix: str) -> Tuple[str, str]: if adj.len(line.rstrip()) + adj.len(value.rstrip()) >= display_width: s += line.rstrip() line = next_line_prefix line += value return s, line def best_len(values: List[str]) -> int: if values: return max(adj.len(x) for x in values) else: return 0 close = ", " if n == 0: summary = f"[]{close}" elif n == 1 and not line_break_each_value: first = formatter(obj[0]) summary = f"[{first}]{close}" elif n == 2 and not line_break_each_value: first = formatter(obj[0]) last = formatter(obj[-1]) summary = f"[{first}, {last}]{close}" else: if n > max_seq_items: n = min(max_seq_items // 2, 10) head = [formatter(x) for x in obj[:n]] tail = [formatter(x) for x in obj[-n:]] else: head = [] tail = [formatter(x) for x in obj] # adjust all values to max length if needed if is_justify: if line_break_each_value: # Justify each string in the values of head and tail, so the # strings will right align when head and tail are stacked # vertically. head, tail = _justify(head, tail) elif is_truncated or not (len(", ".join(head)) < display_width and len(", ".join(tail)) < display_width): # Each string in head and tail should align with each other max_length = max(best_len(head), best_len(tail)) head = [x.rjust(max_length) for x in head] tail = [x.rjust(max_length) for x in tail] # If we are not truncated and we are only a single # line, then don't justify if line_break_each_value: # Now head and tail are of type List[Tuple[str]]. Below we # convert them into List[str], so there will be one string per # value. Also truncate items horizontally if wider than # max_space max_space = display_width - len(space2) value = tail[0] for max_items in reversed(range(1, len(value) + 1)): pprinted_seq = _pprint_seq(value, max_seq_items=max_items) if len(pprinted_seq) < max_space: break head = [_pprint_seq(x, max_seq_items=max_items) for x in head] tail = [_pprint_seq(x, max_seq_items=max_items) for x in tail] summary = "" line = space2 for max_items in range(len(head)): word = head[max_items] + sep + " " summary, line = _extend_line(summary, line, word, display_width, space2) if is_truncated: # remove trailing space of last line summary += line.rstrip() + space2 + "..." line = space2 for max_items in range(len(tail) - 1): word = tail[max_items] + sep + " " summary, line = _extend_line(summary, line, word, display_width, space2) # last value: no sep added + 1 space of width used for trailing ',' summary, line = _extend_line(summary, line, tail[-1], display_width - 2, space2) summary += line # right now close is either '' or ', ' # Now we want to include the ']', but not the maybe space. close = "]" + close.rstrip(" ") summary += close if len(summary) > (display_width) or line_break_each_value: summary += space1 else: # one row summary += " " # remove initial space summary = "[" + summary[len(space2):] return summary
def format_object_summary(obj, formatter, is_justify=True, name=None): """ Return the formatted obj as a unicode string Parameters ---------- obj : object must be iterable and support __getitem__ formatter : callable string formatter for an element is_justify : boolean should justify the display name : name, optiona defaults to the class name of the obj Returns ------- summary string """ from pandas.io.formats.console import get_console_size from pandas.io.formats.format import _get_adjustment display_width, _ = get_console_size() if display_width is None: display_width = get_option('display.width') or 80 if name is None: name = obj.__class__.__name__ space1 = "\n%s" % (' ' * (len(name) + 1)) space2 = "\n%s" % (' ' * (len(name) + 2)) n = len(obj) sep = ',' max_seq_items = get_option('display.max_seq_items') or n # are we a truncated display is_truncated = n > max_seq_items # adj can optionally handle unicode eastern asian width adj = _get_adjustment() def _extend_line(s, line, value, display_width, next_line_prefix): if (adj.len(line.rstrip()) + adj.len(value.rstrip()) >= display_width): s += line.rstrip() line = next_line_prefix line += value return s, line def best_len(values): if values: return max(adj.len(x) for x in values) else: return 0 if n == 0: summary = '[], ' elif n == 1: first = formatter(obj[0]) summary = '[%s], ' % first elif n == 2: first = formatter(obj[0]) last = formatter(obj[-1]) summary = '[%s, %s], ' % (first, last) else: if n > max_seq_items: n = min(max_seq_items // 2, 10) head = [formatter(x) for x in obj[:n]] tail = [formatter(x) for x in obj[-n:]] else: head = [] tail = [formatter(x) for x in obj] # adjust all values to max length if needed if is_justify: # however, if we are not truncated and we are only a single # line, then don't justify if (is_truncated or not (len(', '.join(head)) < display_width and len(', '.join(tail)) < display_width)): max_len = max(best_len(head), best_len(tail)) head = [x.rjust(max_len) for x in head] tail = [x.rjust(max_len) for x in tail] summary = "" line = space2 for i in range(len(head)): word = head[i] + sep + ' ' summary, line = _extend_line(summary, line, word, display_width, space2) if is_truncated: # remove trailing space of last line summary += line.rstrip() + space2 + '...' line = space2 for i in range(len(tail) - 1): word = tail[i] + sep + ' ' summary, line = _extend_line(summary, line, word, display_width, space2) # last value: no sep added + 1 space of width used for trailing ',' summary, line = _extend_line(summary, line, tail[-1], display_width - 2, space2) summary += line summary += '],' if len(summary) > (display_width): summary += space1 else: # one row summary += ' ' # remove initial space summary = '[' + summary[len(space2):] return summary