@@ -142,8 +142,10 @@ def _pipe_line_with_colons(colwidths, colaligns):
142142 alignment (as in `pipe` output format)."""
143143 if not colaligns : # e.g. printing an empty data frame (github issue #15)
144144 colaligns = ["" ] * len (colwidths )
145- segments = [_pipe_segment_with_colons (a , w ) for a , w in zip (colaligns , colwidths )]
146- return "|" + "|" .join (segments ) + "|"
145+ segments = "|" .join (
146+ _pipe_segment_with_colons (a , w ) for a , w in zip (colaligns , colwidths )
147+ )
148+ return f"|{ segments } |"
147149
148150
149151def _grid_segment_with_colons (colwidth , align ):
@@ -165,8 +167,10 @@ def _grid_line_with_colons(colwidths, colaligns):
165167 in a grid table."""
166168 if not colaligns :
167169 colaligns = ["" ] * len (colwidths )
168- segments = [_grid_segment_with_colons (w , a ) for a , w in zip (colaligns , colwidths )]
169- return "+" + "+" .join (segments ) + "+"
170+ segments = "+" .join (
171+ _grid_segment_with_colons (w , a ) for a , w in zip (colaligns , colwidths )
172+ )
173+ return f"+{ segments } +"
170174
171175
172176def _mediawiki_row_with_attrs (separator , cell_values , colwidths , colaligns ):
@@ -188,8 +192,8 @@ def _mediawiki_row_with_attrs(separator, cell_values, colwidths, colaligns):
188192def _textile_row_with_attrs (cell_values , colwidths , colaligns ):
189193 cell_values [0 ] += " "
190194 alignment = {"left" : "<." , "right" : ">." , "center" : "=." , "decimal" : ">." }
191- values = (alignment .get (a , "" ) + v for a , v in zip (colaligns , cell_values ))
192- return "|" + "|" . join ( values ) + " |"
195+ values = "|" . join (alignment .get (a , "" ) + v for a , v in zip (colaligns , cell_values ))
196+ return f"| { values } |"
193197
194198
195199def _html_begin_table_without_header (colwidths_ignore , colaligns_ignore ):
@@ -259,7 +263,7 @@ def make_header_line(is_header, colwidths, colaligns):
259263 colwidths , [alignment [colalign ] for colalign in colaligns ]
260264 )
261265 asciidoc_column_specifiers = [
262- f"{ width :d} { align } " for width , align in asciidoc_alignments
266+ f"{ align } { width :d} " for width , align in asciidoc_alignments
263267 ]
264268 header_list = ['cols="' + ("," .join (asciidoc_column_specifiers )) + '"' ]
265269
@@ -270,7 +274,8 @@ def make_header_line(is_header, colwidths, colaligns):
270274 options_list .append ("header" )
271275
272276 if options_list :
273- header_list += ['options="' + "," .join (options_list ) + '"' ]
277+ options_list = "," .join (options_list )
278+ header_list .append (f'options="{ options_list } "' )
274279
275280 # generate the list of entries in the table header field
276281
@@ -1352,12 +1357,18 @@ def _format(val, valtype, floatfmt, intfmt, missingval="", has_invisible=True):
13521357 is_a_colored_number = has_invisible and isinstance (val , (str , bytes ))
13531358 if is_a_colored_number :
13541359 raw_val = _strip_ansi (val )
1355- formatted_val = format (float (raw_val ), floatfmt )
1360+ try :
1361+ formatted_val = format (float (raw_val ), floatfmt )
1362+ except (ValueError , TypeError ):
1363+ return f"{ val } "
13561364 return val .replace (raw_val , formatted_val )
13571365 else :
13581366 if isinstance (val , str ) and "," in val :
13591367 val = val .replace ("," , "" ) # handle thousands-separators
1360- return format (float (val ), floatfmt )
1368+ try :
1369+ return format (float (val ), floatfmt )
1370+ except (ValueError , TypeError ):
1371+ return f"{ val } "
13611372 else :
13621373 return f"{ val } "
13631374
@@ -1480,7 +1491,7 @@ def _normalize_tabular_data(tabular_data, headers, showindex="default"):
14801491 index = None
14811492 if hasattr (tabular_data , "keys" ) and hasattr (tabular_data , "values" ):
14821493 # dict-like and pandas.DataFrame?
1483- if hasattr (tabular_data .values , "__call__" ):
1494+ if callable (tabular_data .values ):
14841495 # likely a conventional dict
14851496 keys = tabular_data .keys ()
14861497 try :
@@ -1644,6 +1655,10 @@ def _wrap_text_to_colwidths(
16441655 list_of_lists ,
16451656 colwidths ,
16461657 numparses = True ,
1658+ << << << < pre - commit
1659+ == == == =
1660+ missingval = _DEFAULT_MISSINGVAL ,
1661+ >> >> >> > master
16471662 break_long_words = _BREAK_LONG_WORDS ,
16481663 break_on_hyphens = _BREAK_ON_HYPHENS ,
16491664):
@@ -1668,7 +1683,21 @@ def _wrap_text_to_colwidths(
16681683 break_long_words = break_long_words ,
16691684 break_on_hyphens = break_on_hyphens ,
16701685 )
1686+ < << << << pre - commit
16711687 casted_cell = str (cell )
1688+ == == == =
1689+ # Cast based on our internal type handling. Any future custom
1690+ # formatting of types (such as datetimes) may need to be more
1691+ # explicit than just `str` of the object. Also doesn't work for
1692+ # custom floatfmt/intfmt, nor with any missing/blank cells.
1693+ casted_cell = (
1694+ missingval
1695+ if cell is None
1696+ else str (cell )
1697+ if cell == "" or _isnumber (cell )
1698+ else str (_type (cell , numparse )(cell ))
1699+ )
1700+ >> >> >> > master
16721701 wrapped = [
16731702 "\n " .join (wrapper .wrap (line ))
16741703 for line in casted_cell .splitlines ()
@@ -2226,8 +2255,8 @@ def tabulate(
22262255 Tabulate will, by default, set the width of each column to the length of the
22272256 longest element in that column. However, in situations where fields are expected
22282257 to reasonably be too long to look good as a single line, tabulate can help automate
2229- word wrapping long fields for you. Use the parameter `maxcolwidth ` to provide a
2230- list of maximal column widths
2258+ word wrapping long fields for you. Use the parameter `maxcolwidths ` to provide a
2259+ list of maximal column widths:
22312260
22322261 >>> print(tabulate( \
22332262 [('1', 'John Smith', \
@@ -2244,7 +2273,7 @@ def tabulate(
22442273 | | | better if it is wrapped a bit |
22452274 +------------+------------+-------------------------------+
22462275
2247- Header column width can be specified in a similar way using `maxheadercolwidth`
2276+ Header column width can be specified in a similar way using `maxheadercolwidths`.
22482277
22492278 """
22502279
@@ -2273,12 +2302,16 @@ def tabulate(
22732302 list_of_lists ,
22742303 maxcolwidths ,
22752304 numparses = numparses ,
2305+ << << << < pre - commit
2306+ == == == =
2307+ missingval = missingval ,
2308+ >> >> >> > master
22762309 break_long_words = break_long_words ,
22772310 break_on_hyphens = break_on_hyphens ,
22782311 )
22792312
22802313 if maxheadercolwidths is not None :
2281- num_cols = len (list_of_lists [0 ])
2314+ num_cols = len (list_of_lists [0 ]) if list_of_lists else len ( headers )
22822315 if isinstance (maxheadercolwidths , int ): # Expand scalar for all columns
22832316 maxheadercolwidths = _expand_iterable (
22842317 maxheadercolwidths , num_cols , maxheadercolwidths
@@ -2291,6 +2324,10 @@ def tabulate(
22912324 [headers ],
22922325 maxheadercolwidths ,
22932326 numparses = numparses ,
2327+ << << << < pre - commit
2328+ == == == =
2329+ missingval = missingval ,
2330+ >> >> >> > master
22942331 break_long_words = break_long_words ,
22952332 break_on_hyphens = break_on_hyphens ,
22962333 )[0 ]
@@ -2535,7 +2572,7 @@ def _build_row(padded_cells, colwidths, colaligns, rowfmt):
25352572 "Return a string which represents a row of data cells."
25362573 if not rowfmt :
25372574 return None
2538- if hasattr (rowfmt , "__call__" ):
2575+ if callable (rowfmt ):
25392576 return rowfmt (padded_cells , colwidths , colaligns )
25402577 else :
25412578 return _build_simple_row (padded_cells , rowfmt )
@@ -2586,7 +2623,7 @@ def _build_line(colwidths, colaligns, linefmt):
25862623 "Return a string which represents a horizontal line."
25872624 if not linefmt :
25882625 return None
2589- if hasattr (linefmt , "__call__" ):
2626+ if callable (linefmt ):
25902627 return linefmt (colwidths , colaligns )
25912628 else :
25922629 begin , fill , sep , end = linefmt
@@ -2758,13 +2795,16 @@ def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width):
27582795
27592796 # If we're allowed to break long words, then do so: put as much
27602797 # of the next chunk onto the current line as will fit.
2761- if self .break_long_words :
2798+ if self .break_long_words and space_left > 0 :
27622799 # Tabulate Custom: Build the string up piece-by-piece in order to
27632800 # take each charcter's width into account
27642801 chunk = reversed_chunks [- 1 ]
27652802 i = 1
27662803 # Only count printable characters, so strip_ansi first, index later.
2767- while len (_strip_ansi (chunk )[:i ]) <= space_left :
2804+ stripped_chunk = _strip_ansi (chunk )
2805+ while (
2806+ i <= len (stripped_chunk ) and self ._len (stripped_chunk [:i ]) <= space_left
2807+ ):
27682808 i = i + 1
27692809 # Consider escape codes when breaking words up
27702810 total_escape_len = 0
0 commit comments