@@ -61,7 +61,8 @@ def _is_separating_line_value(value):
6161def _is_separating_line (row ):
6262 row_type = type (row )
6363 is_sl = (row_type == list or row_type == str ) and (
64- (len (row ) >= 1 and _is_separating_line_value (row [0 ])) or (len (row ) >= 2 and _is_separating_line_value (row [1 ]))
64+ (len (row ) >= 1 and _is_separating_line_value (row [0 ]))
65+ or (len (row ) >= 2 and _is_separating_line_value (row [1 ]))
6566 )
6667
6768 return is_sl
@@ -71,14 +72,15 @@ def _pipe_segment_with_colons(align, colwidth):
7172 """Return a segment of a horizontal line with optional colons which
7273 indicate column's alignment (as in `pipe` output format).
7374 """
74- w = colwidth
75- if align in {"right" , "decimal" }:
76- return ("-" * (w - 1 )) + ":"
77- if align == "center" :
78- return ":" + ("-" * (w - 2 )) + ":"
79- if align == "left" :
80- return ":" + ("-" * (w - 1 ))
81- return "-" * w
75+ # Fast path for common aligns
76+ if align == "right" or align == "decimal" :
77+ return "-" * (colwidth - 1 ) + ":"
78+ elif align == "left" :
79+ return ":" + "-" * (colwidth - 1 )
80+ elif align == "center" :
81+ return ":" + "-" * (colwidth - 2 ) + ":"
82+ else :
83+ return "-" * colwidth
8284
8385
8486def _pipe_line_with_colons (colwidths , colaligns ):
@@ -151,7 +153,9 @@ def _pipe_line_with_colons(colwidths, colaligns):
151153_ansi_codes_bytes = re .compile (_ansi_escape_pat .encode ("utf8" ), re .VERBOSE )
152154_ansi_color_reset_code = "\033 [0m"
153155
154- _float_with_thousands_separators = re .compile (r"^(([+-]?[0-9]{1,3})(?:,([0-9]{3}))*)?(?(1)\.[0-9]*|\.[0-9]+)?$" )
156+ _float_with_thousands_separators = re .compile (
157+ r"^(([+-]?[0-9]{1,3})(?:,([0-9]{3}))*)?(?(1)\.[0-9]*|\.[0-9]+)?$"
158+ )
155159
156160
157161def _isnumber_with_thousands_separator (string ):
@@ -200,12 +204,16 @@ def _isint(string, inttype=int):
200204 (hasattr (string , "is_integer" ) or hasattr (string , "__array__" ))
201205 and str (type (string )).startswith ("<class 'numpy.int" )
202206 ) # numpy.int64 and similar
203- or (isinstance (string , (bytes , str )) and _isconvertible (inttype , string )) # integer as string
207+ or (
208+ isinstance (string , (bytes , str )) and _isconvertible (inttype , string )
209+ ) # integer as string
204210 )
205211
206212
207213def _isbool (string ):
208- return type (string ) is bool or (isinstance (string , (bytes , str )) and string in {"True" , "False" })
214+ return type (string ) is bool or (
215+ isinstance (string , (bytes , str )) and string in {"True" , "False" }
216+ )
209217
210218
211219def _type (string , has_invisible = True , numparse = True ):
@@ -219,10 +227,18 @@ def _type(string, has_invisible=True, numparse=True):
219227 if _isbool (string ):
220228 return bool
221229 if numparse and (
222- _isint (string ) or (isinstance (string , str ) and _isnumber_with_thousands_separator (string ) and "." not in string )
230+ _isint (string )
231+ or (
232+ isinstance (string , str )
233+ and _isnumber_with_thousands_separator (string )
234+ and "." not in string
235+ )
223236 ):
224237 return int
225- if numparse and (_isnumber (string ) or (isinstance (string , str ) and _isnumber_with_thousands_separator (string ))):
238+ if numparse and (
239+ _isnumber (string )
240+ or (isinstance (string , str ) and _isnumber_with_thousands_separator (string ))
241+ ):
226242 return float
227243 if isinstance (string , bytes ):
228244 return bytes
@@ -365,19 +381,29 @@ def _align_column(
365381 is_multiline = False ,
366382 preserve_whitespace = False ,
367383):
368- strings , padfn = _align_column_choose_padfn (strings , alignment , has_invisible , preserve_whitespace )
369- width_fn = _align_column_choose_width_fn (has_invisible , enable_widechars , is_multiline )
384+ strings , padfn = _align_column_choose_padfn (
385+ strings , alignment , has_invisible , preserve_whitespace
386+ )
387+ width_fn = _align_column_choose_width_fn (
388+ has_invisible , enable_widechars , is_multiline
389+ )
370390
371391 s_widths = list (map (width_fn , strings ))
372392 maxwidth = max (max (_flat_list (s_widths )), minwidth )
373393 # TODO: refactor column alignment in single-line and multiline modes
374394 if is_multiline :
375395 if not enable_widechars and not has_invisible :
376- padded_strings = ["\n " .join ([padfn (maxwidth , s ) for s in ms .splitlines ()]) for ms in strings ]
396+ padded_strings = [
397+ "\n " .join ([padfn (maxwidth , s ) for s in ms .splitlines ()])
398+ for ms in strings
399+ ]
377400 else :
378401 # enable wide-character width corrections
379402 s_lens = [[len (s ) for s in re .split ("[\r \n ]" , ms )] for ms in strings ]
380- visible_widths = [[maxwidth - (w - l ) for w , l in zip (mw , ml )] for mw , ml in zip (s_widths , s_lens )]
403+ visible_widths = [
404+ [maxwidth - (w - l ) for w , l in zip (mw , ml )]
405+ for mw , ml in zip (s_widths , s_lens )
406+ ]
381407 # wcswidth and _visible_width don't count invisible characters;
382408 # padfn doesn't need to apply another correction
383409 padded_strings = [
@@ -419,13 +445,19 @@ def _format(val, valtype, floatfmt, intfmt, missingval="", has_invisible=True):
419445 if valtype is int :
420446 if isinstance (val , str ):
421447 val_striped = val .encode ("unicode_escape" ).decode ("utf-8" )
422- colored = re .search (r"(\\[xX]+[0-9a-fA-F]+\[\d+[mM]+)([0-9.]+)(\\.*)$" , val_striped )
448+ colored = re .search (
449+ r"(\\[xX]+[0-9a-fA-F]+\[\d+[mM]+)([0-9.]+)(\\.*)$" , val_striped
450+ )
423451 if colored :
424452 total_groups = len (colored .groups ())
425453 if total_groups == 3 :
426454 digits = colored .group (2 )
427455 if digits .isdigit ():
428- val_new = colored .group (1 ) + format (int (digits ), intfmt ) + colored .group (3 )
456+ val_new = (
457+ colored .group (1 )
458+ + format (int (digits ), intfmt )
459+ + colored .group (3 )
460+ )
429461 val = val_new .encode ("utf-8" ).decode ("unicode_escape" )
430462 intfmt = ""
431463 return format (val , intfmt )
@@ -447,11 +479,15 @@ def _format(val, valtype, floatfmt, intfmt, missingval="", has_invisible=True):
447479 return f"{ val } "
448480
449481
450- def _align_header (header , alignment , width , visible_width , is_multiline = False , width_fn = None ):
482+ def _align_header (
483+ header , alignment , width , visible_width , is_multiline = False , width_fn = None
484+ ):
451485 """Pad string header to width chars given known visible_width of the header."""
452486 if is_multiline :
453487 header_lines = re .split (_multiline_codes , header )
454- padded_lines = [_align_header (h , alignment , width , width_fn (h )) for h in header_lines ]
488+ padded_lines = [
489+ _align_header (h , alignment , width , width_fn (h )) for h in header_lines
490+ ]
455491 return "\n " .join (padded_lines )
456492 # else: not multiline
457493 ninvisible = len (header ) - visible_width
@@ -504,14 +540,19 @@ def _normalize_tabular_data(tabular_data, headers, showindex="default"):
504540 # likely a conventional dict
505541 keys = tabular_data .keys ()
506542 try :
507- rows = list (izip_longest (* tabular_data .values ())) # columns have to be transposed
543+ rows = list (
544+ izip_longest (* tabular_data .values ())
545+ ) # columns have to be transposed
508546 except TypeError : # not iterable
509547 raise TypeError (err_msg )
510548
511549 elif hasattr (tabular_data , "index" ):
512550 # values is a property, has .index => it's likely a pandas.DataFrame (pandas 0.11.0)
513551 keys = list (tabular_data )
514- if showindex in {"default" , "always" , True } and tabular_data .index .name is not None :
552+ if (
553+ showindex in {"default" , "always" , True }
554+ and tabular_data .index .name is not None
555+ ):
515556 if isinstance (tabular_data .index .name , list ):
516557 keys [:0 ] = tabular_data .index .name
517558 else :
@@ -535,10 +576,19 @@ def _normalize_tabular_data(tabular_data, headers, showindex="default"):
535576 if headers == "keys" and not rows :
536577 # an empty table (issue #81)
537578 headers = []
538- elif headers == "keys" and hasattr (tabular_data , "dtype" ) and tabular_data .dtype .names :
579+ elif (
580+ headers == "keys"
581+ and hasattr (tabular_data , "dtype" )
582+ and tabular_data .dtype .names
583+ ):
539584 # numpy record array
540585 headers = tabular_data .dtype .names
541- elif headers == "keys" and len (rows ) > 0 and isinstance (rows [0 ], tuple ) and hasattr (rows [0 ], "_fields" ):
586+ elif (
587+ headers == "keys"
588+ and len (rows ) > 0
589+ and isinstance (rows [0 ], tuple )
590+ and hasattr (rows [0 ], "_fields" )
591+ ):
542592 # namedtuple
543593 headers = list (map (str , rows [0 ]._fields ))
544594 elif len (rows ) > 0 and hasattr (rows [0 ], "keys" ) and hasattr (rows [0 ], "values" ):
@@ -569,7 +619,9 @@ def _normalize_tabular_data(tabular_data, headers, showindex="default"):
569619 else :
570620 headers = []
571621 elif headers :
572- raise ValueError ("headers for a list of dicts is not a dict or a keyword" )
622+ raise ValueError (
623+ "headers for a list of dicts is not a dict or a keyword"
624+ )
573625 rows = [[row .get (k ) for k in keys ] for row in rows ]
574626
575627 elif (
@@ -582,7 +634,11 @@ def _normalize_tabular_data(tabular_data, headers, showindex="default"):
582634 # print tabulate(cursor, headers='keys')
583635 headers = [column [0 ] for column in tabular_data .description ]
584636
585- elif dataclasses is not None and len (rows ) > 0 and dataclasses .is_dataclass (rows [0 ]):
637+ elif (
638+ dataclasses is not None
639+ and len (rows ) > 0
640+ and dataclasses .is_dataclass (rows [0 ])
641+ ):
586642 # Python's dataclass
587643 field_names = [field .name for field in dataclasses .fields (rows [0 ])]
588644 if headers == "keys" :
@@ -652,7 +708,9 @@ def tabulate(
652708 if tabular_data is None :
653709 tabular_data = []
654710
655- list_of_lists , headers , headers_pad = _normalize_tabular_data (tabular_data , headers , showindex = showindex )
711+ list_of_lists , headers , headers_pad = _normalize_tabular_data (
712+ tabular_data , headers , showindex = showindex
713+ )
656714 list_of_lists , separating_lines = _remove_separating_lines (list_of_lists )
657715
658716 # PrettyTable formatting does not use any extra padding.
@@ -694,7 +752,11 @@ def tabulate(
694752 has_invisible = _ansi_codes .search (plain_text ) is not None
695753
696754 enable_widechars = wcwidth is not None and WIDE_CHARS_MODE
697- if not isinstance (tablefmt , TableFormat ) and tablefmt in multiline_formats and _is_multiline (plain_text ):
755+ if (
756+ not isinstance (tablefmt , TableFormat )
757+ and tablefmt in multiline_formats
758+ and _is_multiline (plain_text )
759+ ):
698760 tablefmt = multiline_formats .get (tablefmt , tablefmt )
699761 is_multiline = True
700762 else :
@@ -706,13 +768,17 @@ def tabulate(
706768 numparses = _expand_numparse (disable_numparse , len (cols ))
707769 coltypes = [_column_type (col , numparse = np ) for col , np in zip (cols , numparses )]
708770 if isinstance (floatfmt , str ): # old version
709- float_formats = len (cols ) * [floatfmt ] # just duplicate the string to use in each column
771+ float_formats = len (cols ) * [
772+ floatfmt
773+ ] # just duplicate the string to use in each column
710774 else : # if floatfmt is list, tuple etc we have one per column
711775 float_formats = list (floatfmt )
712776 if len (float_formats ) < len (cols ):
713777 float_formats .extend ((len (cols ) - len (float_formats )) * [_DEFAULT_FLOATFMT ])
714778 if isinstance (intfmt , str ): # old version
715- int_formats = len (cols ) * [intfmt ] # just duplicate the string to use in each column
779+ int_formats = len (cols ) * [
780+ intfmt
781+ ] # just duplicate the string to use in each column
716782 else : # if intfmt is list, tuple etc we have one per column
717783 int_formats = list (intfmt )
718784 if len (int_formats ) < len (cols ):
@@ -725,7 +791,9 @@ def tabulate(
725791 missing_vals .extend ((len (cols ) - len (missing_vals )) * [_DEFAULT_MISSINGVAL ])
726792 cols = [
727793 [_format (v , ct , fl_fmt , int_fmt , miss_v , has_invisible ) for v in c ]
728- for c , ct , fl_fmt , int_fmt , miss_v in zip (cols , coltypes , float_formats , int_formats , missing_vals )
794+ for c , ct , fl_fmt , int_fmt , miss_v in zip (
795+ cols , coltypes , float_formats , int_formats , missing_vals
796+ )
729797 ]
730798
731799 # align columns
@@ -748,14 +816,24 @@ def tabulate(
748816 break
749817 if align != "global" :
750818 aligns [idx ] = align
751- minwidths = [width_fn (h ) + min_padding for h in headers ] if headers else [0 ] * len (cols )
819+ minwidths = (
820+ [width_fn (h ) + min_padding for h in headers ] if headers else [0 ] * len (cols )
821+ )
752822 aligns_copy = aligns .copy ()
753823 # Reset alignments in copy of alignments list to "left" for 'colon_grid' format,
754824 # which enforces left alignment in the text output of the data.
755825 if tablefmt == "colon_grid" :
756826 aligns_copy = ["left" ] * len (cols )
757827 cols = [
758- _align_column (c , a , minw , has_invisible , enable_widechars , is_multiline , preserve_whitespace )
828+ _align_column (
829+ c ,
830+ a ,
831+ minw ,
832+ has_invisible ,
833+ enable_widechars ,
834+ is_multiline ,
835+ preserve_whitespace ,
836+ )
759837 for c , a , minw in zip (cols , aligns_copy , minwidths )
760838 ]
761839
@@ -786,7 +864,10 @@ def tabulate(
786864 aligns_headers [hidx ] = aligns [hidx ]
787865 elif align != "global" :
788866 aligns_headers [hidx ] = align
789- minwidths = [max (minw , max (width_fn (cl ) for cl in c )) for minw , c in zip (minwidths , t_cols )]
867+ minwidths = [
868+ max (minw , max (width_fn (cl ) for cl in c ))
869+ for minw , c in zip (minwidths , t_cols )
870+ ]
790871 headers = [
791872 _align_header (h , a , minw , width_fn (h ), is_multiline , width_fn )
792873 for h , a , minw in zip (headers , aligns_headers , minwidths )
@@ -801,7 +882,16 @@ def tabulate(
801882
802883 ra_default = rowalign if isinstance (rowalign , str ) else None
803884 rowaligns = _expand_iterable (rowalign , len (rows ), ra_default )
804- return _format_table (tablefmt , headers , aligns_headers , rows , minwidths , aligns , is_multiline , rowaligns = rowaligns )
885+ return _format_table (
886+ tablefmt ,
887+ headers ,
888+ aligns_headers ,
889+ rows ,
890+ minwidths ,
891+ aligns ,
892+ is_multiline ,
893+ rowaligns = rowaligns ,
894+ )
805895
806896
807897def _expand_numparse (disable_numparse , column_count ):
@@ -864,7 +954,9 @@ def _append_line(lines, colwidths, colaligns, linefmt):
864954 return lines
865955
866956
867- def _format_table (fmt , headers , headersaligns , rows , colwidths , colaligns , is_multiline , rowaligns ):
957+ def _format_table (
958+ fmt , headers , headersaligns , rows , colwidths , colaligns , is_multiline , rowaligns
959+ ):
868960 lines = []
869961 hidden = fmt .with_header_hide if (headers and fmt .with_header_hide ) else []
870962 pad = fmt .padding
@@ -888,21 +980,41 @@ def _format_table(fmt, headers, headersaligns, rows, colwidths, colaligns, is_mu
888980 # initial rows with a line below
889981 for row , ralign in zip (rows [:- 1 ], rowaligns ):
890982 if row != SEPARATING_LINE :
891- append_row (lines , pad_row (row , pad ), padded_widths , colaligns , fmt .datarow , rowalign = ralign )
983+ append_row (
984+ lines ,
985+ pad_row (row , pad ),
986+ padded_widths ,
987+ colaligns ,
988+ fmt .datarow ,
989+ rowalign = ralign ,
990+ )
892991 _append_line (lines , padded_widths , colaligns , fmt .linebetweenrows )
893992 # the last row without a line below
894- append_row (lines , pad_row (rows [- 1 ], pad ), padded_widths , colaligns , fmt .datarow , rowalign = rowaligns [- 1 ])
993+ append_row (
994+ lines ,
995+ pad_row (rows [- 1 ], pad ),
996+ padded_widths ,
997+ colaligns ,
998+ fmt .datarow ,
999+ rowalign = rowaligns [- 1 ],
1000+ )
8951001 else :
8961002 separating_line = (
897- fmt .linebetweenrows or fmt .linebelowheader or fmt .linebelow or fmt .lineabove or Line ("" , "" , "" , "" )
1003+ fmt .linebetweenrows
1004+ or fmt .linebelowheader
1005+ or fmt .linebelow
1006+ or fmt .lineabove
1007+ or Line ("" , "" , "" , "" )
8981008 )
8991009 for row in rows :
9001010 # test to see if either the 1st column or the 2nd column (account for showindex) has
9011011 # the SEPARATING_LINE flag
9021012 if _is_separating_line (row ):
9031013 _append_line (lines , padded_widths , colaligns , separating_line )
9041014 else :
905- append_row (lines , pad_row (row , pad ), padded_widths , colaligns , fmt .datarow )
1015+ append_row (
1016+ lines , pad_row (row , pad ), padded_widths , colaligns , fmt .datarow
1017+ )
9061018
9071019 if fmt .linebelow and "linebelow" not in hidden :
9081020 _append_line (lines , padded_widths , colaligns , fmt .linebelow )
0 commit comments