[docs]defprint_wrapped_table(columns:List[Sequence[str]],floating_names:Optional[Sequence[str]]=None,sep:str=" ",window:Optional[int]=None,)->str:"""Pretty-print a table with aligned and wrapped columns. All column contents are padded so that they are right- justified. Wrapping is performed whenever a new column would exceed the window width, in which case the entire column (and all subsequent columns) are printed below the previous columns. Args: columns: List of list of strings, where each inner list is the same length and contains the visible contents of a column. Strings are typically generated by calling `repr()` on data column values. Callers are responsible for inserting ellipses, adding column type information (e.g., with :py:meth:`~print_type`) or truncating long strings (e.g., with :py:meth:`~truncate_strings`). floating_names: List of strings to be added to the left of the table. This is printed repeatedly for each set of wrapped columns. See also :py:meth:`~create_floating_names`. sep: Separator between columns. window: Size of the terminal window, in characters. We attempt to determine this automatically, otherwise it is set to 150. Returns: String containing the pretty-printed table. """ifwindowisNone:importostry:window=os.get_terminal_size().columnsexceptException:window=150iflen(columns)==0:raiseValueError("at least one column should be supplied in 'columns'")n=len(columns[0])floatwidth=0iffloating_namesisnotNone:floatwidth=_get_max_width(floating_names)new_floating_names=[]foryinfloating_names:new_floating_names.append(y.rjust(floatwidth))floating_names=new_floating_namesoutput=""defreinitialize():iffloating_namesisNone:return[""]*nelse:returnfloating_names[:]contents=reinitialize()init=Trueused=floatwidthforcolincolumns:width=_get_max_width(col)ifnotinitandused+width+len(sep)>window:forlineincontents:output+=line+"\n"contents=reinitialize()init=Trueused=floatwidthfori,yinenumerate(col):ifused>0:contents[i]+=sepcontents[i]+=y.rjust(width)used+=width+len(sep)init=Falseoutput+="\n".join(contents)returnoutput
[docs]defcreate_floating_names(names:Optional[List[str]],indices:Sequence[int])->List[str]:"""Create the floating names to use in :py:meth:`~print_wrapped_table`. If no names are present, positional indices are used instead. Args: names: List of row names, or None if no row names are available. indices: Integer indices for which to obtain the names. Returns: List of strings containing floating names. """ifnamesisnotNone:returnlist(subset_sequence(names,indices))else:return["["+str(i)+"]"foriinindices]
[docs]deftruncate_strings(values:List[str],width:int=40)->List[str]:"""Truncate long strings for printing in :py:meth:`~print_wrapped_table`. Args: values: List of strings to be printed. width: Width beyond which to truncate the string. Returns: List containing truncated strings. """replacement=values[:]fori,yinenumerate(values):iflen(y)>width:replacement[i]=y[:width-3]+"..."returnreplacement
[docs]defprint_type(x)->str:"""Print the type of an object, with some special behavior for certain classes (e.g., to add the data type of NumPy arrays). This is intended for display at the top of the columns of :py:meth:`~print_wrapped_table`. Args: x: Some object. Return: String containing the class of the object. """cls=type(x).__name__ifisinstance(x,numpy.ndarray):returncls+"["+x.dtype.name+"]"returncls