@@ -933,8 +933,13 @@ def _isbool(string):
933933def _type (string , has_invisible = True , numparse = True ):
934934 """The least generic type (type(None), int, float, str, unicode).
935935
936+ Treats empty string as missing for the purposes of type deduction, so as to not influence
937+ the type of an otherwise complete column; does *not* result in missingval replacement!
938+
936939 >>> _type(None) is type(None)
937940 True
941+ >>> _type("") is type(None)
942+ True
938943 >>> _type("foo") is type("")
939944 True
940945 >>> _type("1") is type(1)
@@ -949,15 +954,26 @@ def _type(string, has_invisible=True, numparse=True):
949954 if has_invisible and isinstance (string , (str , bytes )):
950955 string = _strip_ansi (string )
951956
952- if string is None :
957+ if string is None or ( isinstance ( string , ( bytes , str )) and not string ) :
953958 return type (None )
954959 elif hasattr (string , "isoformat" ): # datetime.datetime, date, and time
955960 return str
956961 elif _isbool (string ):
957962 return bool
958- elif _isint (string ) and numparse :
963+ elif numparse and (
964+ _isint (string ) or (
965+ isinstance (string , str )
966+ and _isnumber_with_thousands_separator (string )
967+ and '.' not in string
968+ )
969+ ):
959970 return int
960- elif _isnumber (string ) and numparse :
971+ elif numparse and (
972+ _isnumber (string ) or (
973+ isinstance (string , str )
974+ and _isnumber_with_thousands_separator (string )
975+ )
976+ ):
961977 return float
962978 elif isinstance (string , bytes ):
963979 return bytes
@@ -1251,7 +1267,7 @@ def _column_type(strings, has_invisible=True, numparse=True):
12511267
12521268
12531269def _format (val , valtype , floatfmt , intfmt , missingval = "" , has_invisible = True ):
1254- """Format a value according to its type.
1270+ """Format a value according to its deduced type. Empty values are deemed valid for any type.
12551271
12561272 Unicode is supported:
12571273
@@ -1264,6 +1280,8 @@ def _format(val, valtype, floatfmt, intfmt, missingval="", has_invisible=True):
12641280 """ # noqa
12651281 if val is None :
12661282 return missingval
1283+ if isinstance (val , (bytes , str )) and not val :
1284+ return ""
12671285
12681286 if valtype is str :
12691287 return f"{ val } "
@@ -1298,6 +1316,8 @@ def _format(val, valtype, floatfmt, intfmt, missingval="", has_invisible=True):
12981316 formatted_val = format (float (raw_val ), floatfmt )
12991317 return val .replace (raw_val , formatted_val )
13001318 else :
1319+ if isinstance (val ,str ) and ',' in val :
1320+ val = val .replace (',' , '' ) # handle thousands-separators
13011321 return format (float (val ), floatfmt )
13021322 else :
13031323 return f"{ val } "
@@ -1592,9 +1612,10 @@ def _wrap_text_to_colwidths(list_of_lists, colwidths, numparses=True):
15921612
15931613 if width is not None :
15941614 wrapper = _CustomTextWrap (width = width )
1595- # Cast based on our internal type handling
1596- # Any future custom formatting of types (such as datetimes)
1597- # may need to be more explicit than just `str` of the object
1615+ # Cast based on our internal type handling. Any future custom
1616+ # formatting of types (such as datetimes) may need to be more
1617+ # explicit than just `str` of the object. Also doesn't work for
1618+ # custom floatfmt/intfmt, nor with any missing/blank cells.
15981619 casted_cell = (
15991620 str (cell ) if _isnumber (cell ) else _type (cell , numparse )(cell )
16001621 )
0 commit comments