From 60a3efaa452b6a55d3dbff6c0dff6591d86a6f35 Mon Sep 17 00:00:00 2001 From: Alvaro Santiesteban Date: Sun, 16 Feb 2020 00:28:01 +0000 Subject: [PATCH 01/15] Last batch of changes --- pandas/_libs/tslibs/c_timestamp.pyx | 4 +- pandas/_libs/tslibs/timedeltas.pyx | 2 +- pandas/core/arrays/interval.py | 12 ++-- pandas/core/util/hashing.py | 2 +- pandas/io/formats/format.py | 68 ++++++++----------- pandas/io/formats/html.py | 27 +++----- pandas/io/formats/latex.py | 38 +++++------ pandas/io/formats/printing.py | 2 +- pandas/io/parsers.py | 4 +- .../tests/arrays/categorical/test_dtypes.py | 10 ++- .../arrays/categorical/test_operators.py | 12 ++-- 11 files changed, 75 insertions(+), 106 deletions(-) diff --git a/pandas/_libs/tslibs/c_timestamp.pyx b/pandas/_libs/tslibs/c_timestamp.pyx index 2c72cec18f096..9843a2f38e7c2 100644 --- a/pandas/_libs/tslibs/c_timestamp.pyx +++ b/pandas/_libs/tslibs/c_timestamp.pyx @@ -59,10 +59,10 @@ def integer_op_not_supported(obj): # GH#30886 using an fstring raises SystemError int_addsub_msg = ( - "Addition/subtraction of integers and integer-arrays with {cls} is " + f"Addition/subtraction of integers and integer-arrays with {cls} is " "no longer supported. Instead of adding/subtracting `n`, " "use `n * obj.freq`" - ).format(cls=cls) + ) return TypeError(int_addsub_msg) diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index 3742506a7f8af..67bc51892a4e1 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -639,7 +639,7 @@ cdef inline int64_t parse_iso_format_string(object ts) except? -1: bint have_dot = 0, have_value = 0, neg = 0 list number = [], unit = [] - err_msg = "Invalid ISO 8601 Duration format - {}".format(ts) + err_msg = f"Invalid ISO 8601 Duration format - {ts}" for c in ts: # number (ascii codes) diff --git a/pandas/core/arrays/interval.py b/pandas/core/arrays/interval.py index ab3ee5bbcdc3a..b11736248c12a 100644 --- a/pandas/core/arrays/interval.py +++ b/pandas/core/arrays/interval.py @@ -1127,8 +1127,8 @@ def __arrow_array__(self, type=None): subtype = pyarrow.from_numpy_dtype(self.dtype.subtype) except TypeError: raise TypeError( - "Conversion to arrow with subtype '{}' " - "is not supported".format(self.dtype.subtype) + f"Conversion to arrow with subtype '{self.dtype.subtype}' " + "is not supported" ) interval_type = ArrowIntervalType(subtype, self.closed) storage_array = pyarrow.StructArray.from_arrays( @@ -1157,14 +1157,12 @@ def __arrow_array__(self, type=None): if not type.equals(interval_type): raise TypeError( "Not supported to convert IntervalArray to type with " - "different 'subtype' ({0} vs {1}) and 'closed' ({2} vs {3}) " - "attributes".format( - self.dtype.subtype, type.subtype, self.closed, type.closed - ) + f"different 'subtype' ({self.dtype.subtype} vs {type.subtype}) " + f"and 'closed' ({self.closed} vs {type.closed}) attributes" ) else: raise TypeError( - "Not supported to convert IntervalArray to '{0}' type".format(type) + f"Not supported to convert IntervalArray to '{type}' type" ) return pyarrow.ExtensionArray.from_storage(interval_type, storage_array) diff --git a/pandas/core/util/hashing.py b/pandas/core/util/hashing.py index 160d328ec16ec..d9c8611c94cdb 100644 --- a/pandas/core/util/hashing.py +++ b/pandas/core/util/hashing.py @@ -294,7 +294,7 @@ def hash_array( elif issubclass(dtype.type, (np.datetime64, np.timedelta64)): vals = vals.view("i8").astype("u8", copy=False) elif issubclass(dtype.type, np.number) and dtype.itemsize <= 8: - vals = vals.view("u{}".format(vals.dtype.itemsize)).astype("u8") + vals = vals.view(f"u{vals.dtype.itemsize}").astype("u8") else: # With repeated values, its MUCH faster to categorize object dtypes, # then hash and rename categories. We allow skipping the categorization diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 0693c083c9ddc..fe864ca71fa95 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -187,7 +187,7 @@ def _get_footer(self) -> str: if self.length: if footer: footer += ", " - footer += "Length: {length}".format(length=len(self.categorical)) + footer += f"Length: {len(self.categorical)}" level_info = self.categorical._repr_categories_info() @@ -217,7 +217,7 @@ def to_string(self) -> str: fmt_values = self._get_formatted_values() - fmt_values = ["{i}".format(i=i) for i in fmt_values] + fmt_values = [f"{i}" for i in fmt_values] fmt_values = [i.strip() for i in fmt_values] values = ", ".join(fmt_values) result = ["[" + values + "]"] @@ -301,28 +301,26 @@ def _get_footer(self) -> str: assert isinstance( self.series.index, (ABCDatetimeIndex, ABCPeriodIndex, ABCTimedeltaIndex) ) - footer += "Freq: {freq}".format(freq=self.series.index.freqstr) + footer += f"Freq: {self.series.index.freqstr}" if self.name is not False and name is not None: if footer: footer += ", " series_name = pprint_thing(name, escape_chars=("\t", "\r", "\n")) - footer += ( - ("Name: {sname}".format(sname=series_name)) if name is not None else "" - ) + footer += f"Name: {series_name}" if name is not None else "" if self.length is True or (self.length == "truncate" and self.truncate_v): if footer: footer += ", " - footer += "Length: {length}".format(length=len(self.series)) + footer += f"Length: {len(self.series)}" if self.dtype is not False and self.dtype is not None: name = getattr(self.tr_series.dtype, "name", None) if name: if footer: footer += ", " - footer += "dtype: {typ}".format(typ=pprint_thing(name)) + footer += f"dtype: {pprint_thing(name)}" # level infos are added to the end and in a new line, like it is done # for Categoricals @@ -359,9 +357,7 @@ def to_string(self) -> str: footer = self._get_footer() if len(series) == 0: - return "{name}([], {footer})".format( - name=type(self.series).__name__, footer=footer - ) + return f"{type(self.series).__name__}([], {footer})" fmt_index, have_header = self._get_formatted_index() fmt_values = self._get_formatted_values() @@ -584,10 +580,8 @@ def __init__( self.formatters = formatters else: raise ValueError( - ( - "Formatters length({flen}) should match " - "DataFrame number of columns({dlen})" - ).format(flen=len(formatters), dlen=len(frame.columns)) + f"Formatters length({len(formatters)}) should match " + f"DataFrame number of columns({len(frame.columns)})" ) self.na_rep = na_rep self.decimal = decimal @@ -816,10 +810,10 @@ def write_result(self, buf: IO[str]) -> None: frame = self.frame if len(frame.columns) == 0 or len(frame.index) == 0: - info_line = "Empty {name}\nColumns: {col}\nIndex: {idx}".format( - name=type(self.frame).__name__, - col=pprint_thing(frame.columns), - idx=pprint_thing(frame.index), + info_line = ( + f"Empty {type(self.frame).__name__}\n" + f"Columns: {pprint_thing(frame.columns)}\n" + f"Index: {pprint_thing(frame.index)}" ) text = info_line else: @@ -865,11 +859,7 @@ def write_result(self, buf: IO[str]) -> None: buf.writelines(text) if self.should_show_dimensions: - buf.write( - "\n\n[{nrows} rows x {ncols} columns]".format( - nrows=len(frame), ncols=len(frame.columns) - ) - ) + buf.write(f"\n\n[{len(frame)} rows x {len(frame.columns)} columns]") def _join_multiline(self, *args) -> str: lwidth = self.line_width @@ -1074,7 +1064,7 @@ def _get_formatted_index(self, frame: "DataFrame") -> List[str]: # empty space for columns if self.show_col_idx_names: - col_header = ["{x}".format(x=x) for x in self._get_column_name_list()] + col_header = [f"{x}" for x in self._get_column_name_list()] else: col_header = [""] * columns.nlevels @@ -1209,10 +1199,8 @@ def _format_strings(self) -> List[str]: if self.float_format is None: float_format = get_option("display.float_format") if float_format is None: - fmt_str = "{{x: .{prec:d}g}}".format( - prec=get_option("display.precision") - ) - float_format = lambda x: fmt_str.format(x=x) + precision = get_option("display.precision") + float_format = lambda x: f"{x: .{precision:d}g}" else: float_format = self.float_format @@ -1238,10 +1226,10 @@ def _format(x): pass return self.na_rep elif isinstance(x, PandasObject): - return "{x}".format(x=x) + return f"{x}" else: # object dtype - return "{x}".format(x=formatter(x)) + return f"{formatter(x)}" vals = self.values if isinstance(vals, Index): @@ -1257,17 +1245,17 @@ def _format(x): fmt_values = [] for i, v in enumerate(vals): if not is_float_type[i] and leading_space: - fmt_values.append(" {v}".format(v=_format(v))) + fmt_values.append(f" {_format(v)}") elif is_float_type[i]: fmt_values.append(float_format(v)) else: if leading_space is False: # False specifically, so that the default is # to include a space if we get here. - tpl = "{v}" + tpl = f"{_format(v)}" else: - tpl = " {v}" - fmt_values.append(tpl.format(v=_format(v))) + tpl = f" {_format(v)}" + fmt_values.append(tpl) return fmt_values @@ -1437,7 +1425,7 @@ def _format_strings(self) -> List[str]: class IntArrayFormatter(GenericArrayFormatter): def _format_strings(self) -> List[str]: - formatter = self.formatter or (lambda x: "{x: d}".format(x=x)) + formatter = self.formatter or (lambda x: f"{x: d}") fmt_values = [formatter(x) for x in self.values] return fmt_values @@ -1716,7 +1704,7 @@ def _formatter(x): x = Timedelta(x) result = x._repr_base(format=format) if box: - result = "'{res}'".format(res=result) + result = f"'{result}'" return result return _formatter @@ -1880,16 +1868,16 @@ def __call__(self, num: Union[int, float]) -> str: prefix = self.ENG_PREFIXES[int_pow10] else: if int_pow10 < 0: - prefix = "E-{pow10:02d}".format(pow10=-int_pow10) + prefix = f"E-{-int_pow10:02d}" else: - prefix = "E+{pow10:02d}".format(pow10=int_pow10) + prefix = f"E+{int_pow10:02d}" mant = sign * dnum / (10 ** pow10) if self.accuracy is None: # pragma: no cover format_str = "{mant: g}{prefix}" else: - format_str = "{{mant: .{acc:d}f}}{{prefix}}".format(acc=self.accuracy) + format_str = f"{{mant: .{self.accuracy:d}f}}{{prefix}}" formatted = format_str.format(mant=mant, prefix=prefix) diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py index e3161415fe2bc..706b6e8ab17fa 100644 --- a/pandas/io/formats/html.py +++ b/pandas/io/formats/html.py @@ -56,7 +56,7 @@ def __init__( self.table_id = self.fmt.table_id self.render_links = self.fmt.render_links if isinstance(self.fmt.col_space, int): - self.fmt.col_space = "{colspace}px".format(colspace=self.fmt.col_space) + self.fmt.col_space = f"{self.fmt.col_space}px" @property def show_row_idx_names(self) -> bool: @@ -124,7 +124,7 @@ def write_th( """ if header and self.fmt.col_space is not None: tags = tags or "" - tags += 'style="min-width: {colspace};"'.format(colspace=self.fmt.col_space) + tags += f'style="min-width: {self.fmt.col_space};"' self._write_cell(s, kind="th", indent=indent, tags=tags) @@ -135,9 +135,9 @@ def _write_cell( self, s: Any, kind: str = "td", indent: int = 0, tags: Optional[str] = None ) -> None: if tags is not None: - start_tag = "<{kind} {tags}>".format(kind=kind, tags=tags) + start_tag = f"<{kind} {tags}>" else: - start_tag = "<{kind}>".format(kind=kind) + start_tag = f"<{kind}>" if self.escape: # escape & first to prevent double escaping of & @@ -149,16 +149,13 @@ def _write_cell( if self.render_links and is_url(rs): rs_unescaped = pprint_thing(s, escape_chars={}).strip() - start_tag += ''.format(url=rs_unescaped) + start_tag += f'' end_a = "" else: end_a = "" self.write( - "{start}{rs}{end_a}".format( - start=start_tag, rs=rs, end_a=end_a, kind=kind - ), - indent, + f"{start_tag}{rs}{end_a}", indent, ) def write_tr( @@ -177,7 +174,7 @@ def write_tr( if align is None: self.write("", indent) else: - self.write(''.format(align=align), indent) + self.write(f'', indent) indent += indent_delta for i, s in enumerate(line): @@ -196,9 +193,7 @@ def render(self) -> List[str]: if self.should_show_dimensions: by = chr(215) # × self.write( - "

{rows} rows {by} {cols} columns

".format( - rows=len(self.frame), by=by, cols=len(self.frame.columns) - ) + f"

{len(self.frame)} rows {by} {len(self.frame.columns)} columns

" ) return self.elements @@ -224,12 +219,10 @@ def _write_table(self, indent: int = 0) -> None: if self.table_id is None: id_section = "" else: - id_section = ' id="{table_id}"'.format(table_id=self.table_id) + id_section = f' id="{self.table_id}"' self.write( - ''.format( - border=self.border, cls=" ".join(_classes), id_section=id_section - ), + f'
', indent, ) diff --git a/pandas/io/formats/latex.py b/pandas/io/formats/latex.py index 935762598f78a..217de94074d8d 100644 --- a/pandas/io/formats/latex.py +++ b/pandas/io/formats/latex.py @@ -58,10 +58,9 @@ def write_result(self, buf: IO[str]) -> None: """ # string representation of the columns if len(self.frame.columns) == 0 or len(self.frame.index) == 0: - info_line = "Empty {name}\nColumns: {col}\nIndex: {idx}".format( - name=type(self.frame).__name__, - col=self.frame.columns, - idx=self.frame.index, + info_line = ( + f"Empty {type(self.frame).__name__}\n" + f"Columns: {self.frame.columns}\nIndex: {self.frame.index}" ) strcols = [[info_line]] else: @@ -140,8 +139,8 @@ def pad_empties(x): buf.write("\\endhead\n") buf.write("\\midrule\n") buf.write( - "\\multicolumn{{{n}}}{{r}}{{{{Continued on next " - "page}}}} \\\\\n".format(n=len(row)) + f"\\multicolumn{{{len(row)}}}{{r}}{{{{Continued on next " + "page}}}} \\\\\n" ) buf.write("\\midrule\n") buf.write("\\endfoot\n\n") @@ -171,7 +170,7 @@ def pad_empties(x): if self.bold_rows and self.fmt.index: # bold row labels crow = [ - "\\textbf{{{x}}}".format(x=x) + f"\\textbf{{{x}}}" if j < ilevels and x.strip() not in ["", "{}"] else x for j, x in enumerate(crow) @@ -210,9 +209,8 @@ def append_col(): # write multicolumn if needed if ncol > 1: row2.append( - "\\multicolumn{{{ncol:d}}}{{{fmt:s}}}{{{txt:s}}}".format( - ncol=ncol, fmt=self.multicolumn_format, txt=coltext.strip() - ) + f"\\multicolumn{{{ncol:d}}}{{{self.multicolumn_format:s}}}" + f"{{{coltext.strip():s}}}" ) # don't modify where not needed else: @@ -255,9 +253,7 @@ def _format_multirow( break if nrow > 1: # overwrite non-multirow entry - row[j] = "\\multirow{{{nrow:d}}}{{*}}{{{row:s}}}".format( - nrow=nrow, row=row[j].strip() - ) + row[j] = f"\\multirow{{{nrow:d}}}{{*}}{{{row[j].strip():s}}}" # save when to end the current block with \cline self.clinebuf.append([i + nrow - 1, j + 1]) return row @@ -268,7 +264,7 @@ def _print_cline(self, buf: IO[str], i: int, icol: int) -> None: """ for cl in self.clinebuf: if cl[0] == i: - buf.write("\\cline{{{cl:d}-{icol:d}}}\n".format(cl=cl[1], icol=icol)) + buf.write(f"\\cline{{{cl[1]:d}-{icol:d}}}\n") # remove entries that have been written to buffer self.clinebuf = [x for x in self.clinebuf if x[0] != i] @@ -292,19 +288,19 @@ def _write_tabular_begin(self, buf, column_format: str): if self.caption is None: caption_ = "" else: - caption_ = "\n\\caption{{{}}}".format(self.caption) + caption_ = f"\n\\caption{{{self.caption}}}" if self.label is None: label_ = "" else: - label_ = "\n\\label{{{}}}".format(self.label) + label_ = f"\n\\label{{{self.label}}}" - buf.write("\\begin{{table}}\n\\centering{}{}\n".format(caption_, label_)) + buf.write(f"\\begin{{table}}\n\\centering{caption_}{label_}\n") else: # then write output only in a tabular environment pass - buf.write("\\begin{{tabular}}{{{fmt}}}\n".format(fmt=column_format)) + buf.write(f"\\begin{{tabular}}{{{column_format}}}\n") def _write_tabular_end(self, buf): """ @@ -340,18 +336,18 @@ def _write_longtable_begin(self, buf, column_format: str): `__ e.g 'rcl' for 3 columns """ - buf.write("\\begin{{longtable}}{{{fmt}}}\n".format(fmt=column_format)) + buf.write(f"\\begin{{longtable}}{{{column_format}}}\n") if self.caption is not None or self.label is not None: if self.caption is None: pass else: - buf.write("\\caption{{{}}}".format(self.caption)) + buf.write(f"\\caption{{{self.caption}}}") if self.label is None: pass else: - buf.write("\\label{{{}}}".format(self.label)) + buf.write(f"\\label{{{self.label}}}") # a double-backslash is required at the end of the line # as discussed here: diff --git a/pandas/io/formats/printing.py b/pandas/io/formats/printing.py index 13b18a0b5fb6f..36e774305b577 100644 --- a/pandas/io/formats/printing.py +++ b/pandas/io/formats/printing.py @@ -229,7 +229,7 @@ def as_escaped_string( max_seq_items=max_seq_items, ) elif isinstance(thing, str) and quote_strings: - result = "'{thing}'".format(thing=as_escaped_string(thing)) + result = f"'{as_escaped_string(thing)}'" else: result = as_escaped_string(thing) diff --git a/pandas/io/parsers.py b/pandas/io/parsers.py index d7eb69d3a6048..8a3ad6cb45b57 100755 --- a/pandas/io/parsers.py +++ b/pandas/io/parsers.py @@ -3605,8 +3605,8 @@ def get_rows(self, infer_nrows, skiprows=None): def detect_colspecs(self, infer_nrows=100, skiprows=None): # Regex escape the delimiters - delimiters = "".join(r"\{}".format(x) for x in self.delimiter) - pattern = re.compile("([^{}]+)".format(delimiters)) + delimiters = "".join(fr"\{x}" for x in self.delimiter) + pattern = re.compile(f"([^{delimiters}]+)") rows = self.get_rows(infer_nrows, skiprows) if not rows: raise EmptyDataError("No rows from which to infer column width") diff --git a/pandas/tests/arrays/categorical/test_dtypes.py b/pandas/tests/arrays/categorical/test_dtypes.py index 19746d7d72162..9922a8863ebc2 100644 --- a/pandas/tests/arrays/categorical/test_dtypes.py +++ b/pandas/tests/arrays/categorical/test_dtypes.py @@ -92,22 +92,20 @@ def test_codes_dtypes(self): result = Categorical(["foo", "bar", "baz"]) assert result.codes.dtype == "int8" - result = Categorical(["foo{i:05d}".format(i=i) for i in range(400)]) + result = Categorical([f"foo{i:05d}" for i in range(400)]) assert result.codes.dtype == "int16" - result = Categorical(["foo{i:05d}".format(i=i) for i in range(40000)]) + result = Categorical([f"foo{i:05d}" for i in range(40000)]) assert result.codes.dtype == "int32" # adding cats result = Categorical(["foo", "bar", "baz"]) assert result.codes.dtype == "int8" - result = result.add_categories(["foo{i:05d}".format(i=i) for i in range(400)]) + result = result.add_categories([f"foo{i:05d}" for i in range(400)]) assert result.codes.dtype == "int16" # removing cats - result = result.remove_categories( - ["foo{i:05d}".format(i=i) for i in range(300)] - ) + result = result.remove_categories([f"foo{i:05d}" for i in range(300)]) assert result.codes.dtype == "int8" @pytest.mark.parametrize("ordered", [True, False]) diff --git a/pandas/tests/arrays/categorical/test_operators.py b/pandas/tests/arrays/categorical/test_operators.py index 0c830c65e0f8b..6ea003c122eea 100644 --- a/pandas/tests/arrays/categorical/test_operators.py +++ b/pandas/tests/arrays/categorical/test_operators.py @@ -338,7 +338,7 @@ def test_compare_unordered_different_order(self): def test_numeric_like_ops(self): df = DataFrame({"value": np.random.randint(0, 10000, 100)}) - labels = ["{0} - {1}".format(i, i + 499) for i in range(0, 10000, 500)] + labels = [f"{i} - {i + 499}" for i in range(0, 10000, 500)] cat_labels = Categorical(labels, labels) df = df.sort_values(by=["value"], ascending=True) @@ -353,9 +353,7 @@ def test_numeric_like_ops(self): ("__mul__", r"\*"), ("__truediv__", "/"), ]: - msg = r"Series cannot perform the operation {}|unsupported operand".format( - str_rep - ) + msg = f"Series cannot perform the operation {str_rep}|unsupported operand" with pytest.raises(TypeError, match=msg): getattr(df, op)(df) @@ -363,7 +361,7 @@ def test_numeric_like_ops(self): # min/max) s = df["value_group"] for op in ["kurt", "skew", "var", "std", "mean", "sum", "median"]: - msg = "Categorical cannot perform the operation {}".format(op) + msg = f"Categorical cannot perform the operation {op}" with pytest.raises(TypeError, match=msg): getattr(s, op)(numeric_only=False) @@ -383,9 +381,7 @@ def test_numeric_like_ops(self): ("__mul__", r"\*"), ("__truediv__", "/"), ]: - msg = r"Series cannot perform the operation {}|unsupported operand".format( - str_rep - ) + msg = f"Series cannot perform the operation {str_rep}|unsupported operand" with pytest.raises(TypeError, match=msg): getattr(s, op)(2) From 99448b3ece882195b966c97cdcddee4078edfd84 Mon Sep 17 00:00:00 2001 From: Alvaro Santiesteban Date: Sun, 16 Feb 2020 06:23:38 +0000 Subject: [PATCH 02/15] Revert .pyx files --- pandas/_libs/tslibs/c_timestamp.pyx | 4 ++-- pandas/_libs/tslibs/timedeltas.pyx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/_libs/tslibs/c_timestamp.pyx b/pandas/_libs/tslibs/c_timestamp.pyx index 9843a2f38e7c2..2c72cec18f096 100644 --- a/pandas/_libs/tslibs/c_timestamp.pyx +++ b/pandas/_libs/tslibs/c_timestamp.pyx @@ -59,10 +59,10 @@ def integer_op_not_supported(obj): # GH#30886 using an fstring raises SystemError int_addsub_msg = ( - f"Addition/subtraction of integers and integer-arrays with {cls} is " + "Addition/subtraction of integers and integer-arrays with {cls} is " "no longer supported. Instead of adding/subtracting `n`, " "use `n * obj.freq`" - ) + ).format(cls=cls) return TypeError(int_addsub_msg) diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index 67bc51892a4e1..3742506a7f8af 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -639,7 +639,7 @@ cdef inline int64_t parse_iso_format_string(object ts) except? -1: bint have_dot = 0, have_value = 0, neg = 0 list number = [], unit = [] - err_msg = f"Invalid ISO 8601 Duration format - {ts}" + err_msg = "Invalid ISO 8601 Duration format - {}".format(ts) for c in ts: # number (ascii codes) From 881e7bd47499b233b989c05d74f4165784f69c59 Mon Sep 17 00:00:00 2001 From: Alvaro Santiesteban Date: Sun, 16 Feb 2020 07:58:23 +0000 Subject: [PATCH 03/15] Fix Unit tests --- pandas/_libs/tslibs/c_timestamp.pyx | 4 ++-- pandas/_libs/tslibs/timedeltas.pyx | 2 +- pandas/io/formats/latex.py | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pandas/_libs/tslibs/c_timestamp.pyx b/pandas/_libs/tslibs/c_timestamp.pyx index 2c72cec18f096..9843a2f38e7c2 100644 --- a/pandas/_libs/tslibs/c_timestamp.pyx +++ b/pandas/_libs/tslibs/c_timestamp.pyx @@ -59,10 +59,10 @@ def integer_op_not_supported(obj): # GH#30886 using an fstring raises SystemError int_addsub_msg = ( - "Addition/subtraction of integers and integer-arrays with {cls} is " + f"Addition/subtraction of integers and integer-arrays with {cls} is " "no longer supported. Instead of adding/subtracting `n`, " "use `n * obj.freq`" - ).format(cls=cls) + ) return TypeError(int_addsub_msg) diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index 3742506a7f8af..67bc51892a4e1 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -639,7 +639,7 @@ cdef inline int64_t parse_iso_format_string(object ts) except? -1: bint have_dot = 0, have_value = 0, neg = 0 list number = [], unit = [] - err_msg = "Invalid ISO 8601 Duration format - {}".format(ts) + err_msg = f"Invalid ISO 8601 Duration format - {ts}" for c in ts: # number (ascii codes) diff --git a/pandas/io/formats/latex.py b/pandas/io/formats/latex.py index 217de94074d8d..73ca08f40566a 100644 --- a/pandas/io/formats/latex.py +++ b/pandas/io/formats/latex.py @@ -139,8 +139,8 @@ def pad_empties(x): buf.write("\\endhead\n") buf.write("\\midrule\n") buf.write( - f"\\multicolumn{{{len(row)}}}{{r}}{{{{Continued on next " - "page}}}} \\\\\n" + f"\\multicolumn{{{len(row)}}}{{r}}" + "{{Continued on next page}} \\\\\n" ) buf.write("\\midrule\n") buf.write("\\endfoot\n\n") @@ -209,8 +209,8 @@ def append_col(): # write multicolumn if needed if ncol > 1: row2.append( - f"\\multicolumn{{{ncol:d}}}{{{self.multicolumn_format:s}}}" - f"{{{coltext.strip():s}}}" + f"\\multicolumn{{{ncol:d}}}{{{self.multicolumn_format}}}" + f"{{{coltext.strip()}}}" ) # don't modify where not needed else: @@ -253,7 +253,7 @@ def _format_multirow( break if nrow > 1: # overwrite non-multirow entry - row[j] = f"\\multirow{{{nrow:d}}}{{*}}{{{row[j].strip():s}}}" + row[j] = f"\\multirow{{{nrow:d}}}{{*}}{{{row[j].strip()}}}" # save when to end the current block with \cline self.clinebuf.append([i + nrow - 1, j + 1]) return row From d29c78c834a719b29884f56099b9c6469cd8313d Mon Sep 17 00:00:00 2001 From: Alvaro Santiesteban Date: Sun, 16 Feb 2020 08:16:49 +0000 Subject: [PATCH 04/15] Revert .pyx files --- pandas/_libs/tslibs/c_timestamp.pyx | 4 ++-- pandas/_libs/tslibs/timedeltas.pyx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/_libs/tslibs/c_timestamp.pyx b/pandas/_libs/tslibs/c_timestamp.pyx index 9843a2f38e7c2..2c72cec18f096 100644 --- a/pandas/_libs/tslibs/c_timestamp.pyx +++ b/pandas/_libs/tslibs/c_timestamp.pyx @@ -59,10 +59,10 @@ def integer_op_not_supported(obj): # GH#30886 using an fstring raises SystemError int_addsub_msg = ( - f"Addition/subtraction of integers and integer-arrays with {cls} is " + "Addition/subtraction of integers and integer-arrays with {cls} is " "no longer supported. Instead of adding/subtracting `n`, " "use `n * obj.freq`" - ) + ).format(cls=cls) return TypeError(int_addsub_msg) diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index 67bc51892a4e1..3742506a7f8af 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -639,7 +639,7 @@ cdef inline int64_t parse_iso_format_string(object ts) except? -1: bint have_dot = 0, have_value = 0, neg = 0 list number = [], unit = [] - err_msg = f"Invalid ISO 8601 Duration format - {ts}" + err_msg = "Invalid ISO 8601 Duration format - {}".format(ts) for c in ts: # number (ascii codes) From 11f3649358cff17930a7e382d572734baff803e9 Mon Sep 17 00:00:00 2001 From: 3vts <3vts@users.noreply.github.com> Date: Sun, 16 Feb 2020 20:54:25 -0600 Subject: [PATCH 05/15] Apply suggestions from code review Co-Authored-By: Simon Hawkins --- pandas/io/formats/format.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index fe864ca71fa95..0aca6f2575bd9 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1064,7 +1064,7 @@ def _get_formatted_index(self, frame: "DataFrame") -> List[str]: # empty space for columns if self.show_col_idx_names: - col_header = [f"{x}" for x in self._get_column_name_list()] + col_header = [str(x) for x in self._get_column_name_list()] else: col_header = [""] * columns.nlevels @@ -1226,10 +1226,10 @@ def _format(x): pass return self.na_rep elif isinstance(x, PandasObject): - return f"{x}" + return str(x) else: # object dtype - return f"{formatter(x)}" + return str(formatter(x)) vals = self.values if isinstance(vals, Index): From 2643064ca7598e627c28b4ba8a8540328e3b903f Mon Sep 17 00:00:00 2001 From: Alvaro Santiesteban Date: Mon, 17 Feb 2020 03:10:01 +0000 Subject: [PATCH 06/15] Address feedback --- pandas/_libs/tslibs/c_timestamp.pyx | 4 ++-- pandas/_libs/tslibs/timedeltas.pyx | 2 +- pandas/io/formats/format.py | 11 +++++------ pandas/io/formats/latex.py | 3 ++- pandas/io/formats/printing.py | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pandas/_libs/tslibs/c_timestamp.pyx b/pandas/_libs/tslibs/c_timestamp.pyx index 2c72cec18f096..9843a2f38e7c2 100644 --- a/pandas/_libs/tslibs/c_timestamp.pyx +++ b/pandas/_libs/tslibs/c_timestamp.pyx @@ -59,10 +59,10 @@ def integer_op_not_supported(obj): # GH#30886 using an fstring raises SystemError int_addsub_msg = ( - "Addition/subtraction of integers and integer-arrays with {cls} is " + f"Addition/subtraction of integers and integer-arrays with {cls} is " "no longer supported. Instead of adding/subtracting `n`, " "use `n * obj.freq`" - ).format(cls=cls) + ) return TypeError(int_addsub_msg) diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index 3742506a7f8af..67bc51892a4e1 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -639,7 +639,7 @@ cdef inline int64_t parse_iso_format_string(object ts) except? -1: bint have_dot = 0, have_value = 0, neg = 0 list number = [], unit = [] - err_msg = "Invalid ISO 8601 Duration format - {}".format(ts) + err_msg = f"Invalid ISO 8601 Duration format - {ts}" for c in ts: # number (ascii codes) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index fe864ca71fa95..be89a077f52d9 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -217,7 +217,6 @@ def to_string(self) -> str: fmt_values = self._get_formatted_values() - fmt_values = [f"{i}" for i in fmt_values] fmt_values = [i.strip() for i in fmt_values] values = ", ".join(fmt_values) result = ["[" + values + "]"] @@ -308,7 +307,7 @@ def _get_footer(self) -> str: footer += ", " series_name = pprint_thing(name, escape_chars=("\t", "\r", "\n")) - footer += f"Name: {series_name}" if name is not None else "" + footer += f"Name: {series_name}" if self.length is True or (self.length == "truncate" and self.truncate_v): if footer: @@ -1252,10 +1251,10 @@ def _format(x): if leading_space is False: # False specifically, so that the default is # to include a space if we get here. - tpl = f"{_format(v)}" + tpl = "{v}" else: - tpl = f" {_format(v)}" - fmt_values.append(tpl) + tpl = " {v}" + fmt_values.append(tpl.format(v=_format(v))) return fmt_values @@ -1704,7 +1703,7 @@ def _formatter(x): x = Timedelta(x) result = x._repr_base(format=format) if box: - result = f"'{result}'" + result = repr(result) return result return _formatter diff --git a/pandas/io/formats/latex.py b/pandas/io/formats/latex.py index 73ca08f40566a..3a3ca84642d51 100644 --- a/pandas/io/formats/latex.py +++ b/pandas/io/formats/latex.py @@ -60,7 +60,8 @@ def write_result(self, buf: IO[str]) -> None: if len(self.frame.columns) == 0 or len(self.frame.index) == 0: info_line = ( f"Empty {type(self.frame).__name__}\n" - f"Columns: {self.frame.columns}\nIndex: {self.frame.index}" + f"Columns: {self.frame.columns}\n" + f"Index: {self.frame.index}" ) strcols = [[info_line]] else: diff --git a/pandas/io/formats/printing.py b/pandas/io/formats/printing.py index 36e774305b577..32f06f4e487f8 100644 --- a/pandas/io/formats/printing.py +++ b/pandas/io/formats/printing.py @@ -229,7 +229,7 @@ def as_escaped_string( max_seq_items=max_seq_items, ) elif isinstance(thing, str) and quote_strings: - result = f"'{as_escaped_string(thing)}'" + result = repr(as_escaped_string(thing)) else: result = as_escaped_string(thing) From f7a391ee960df150a5e46dcbeb3734f19e460673 Mon Sep 17 00:00:00 2001 From: 3vts <3vts@users.noreply.github.com> Date: Sun, 16 Feb 2020 21:13:14 -0600 Subject: [PATCH 07/15] Update pandas/io/formats/html.py Co-Authored-By: Simon Hawkins --- pandas/io/formats/html.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py index 706b6e8ab17fa..aeb4faf2e4688 100644 --- a/pandas/io/formats/html.py +++ b/pandas/io/formats/html.py @@ -155,7 +155,7 @@ def _write_cell( end_a = "" self.write( - f"{start_tag}{rs}{end_a}", indent, + f"{start_tag}{rs}{end_a}", indent ) def write_tr( From dcb382b63ccc2bb3616b418c06f8f78a1a2a3808 Mon Sep 17 00:00:00 2001 From: Alvaro Santiesteban Date: Mon, 17 Feb 2020 03:19:23 +0000 Subject: [PATCH 08/15] Revert .pyx files --- pandas/_libs/tslibs/c_timestamp.pyx | 4 ++-- pandas/_libs/tslibs/timedeltas.pyx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/_libs/tslibs/c_timestamp.pyx b/pandas/_libs/tslibs/c_timestamp.pyx index 9843a2f38e7c2..2c72cec18f096 100644 --- a/pandas/_libs/tslibs/c_timestamp.pyx +++ b/pandas/_libs/tslibs/c_timestamp.pyx @@ -59,10 +59,10 @@ def integer_op_not_supported(obj): # GH#30886 using an fstring raises SystemError int_addsub_msg = ( - f"Addition/subtraction of integers and integer-arrays with {cls} is " + "Addition/subtraction of integers and integer-arrays with {cls} is " "no longer supported. Instead of adding/subtracting `n`, " "use `n * obj.freq`" - ) + ).format(cls=cls) return TypeError(int_addsub_msg) diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index 67bc51892a4e1..3742506a7f8af 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -639,7 +639,7 @@ cdef inline int64_t parse_iso_format_string(object ts) except? -1: bint have_dot = 0, have_value = 0, neg = 0 list number = [], unit = [] - err_msg = f"Invalid ISO 8601 Duration format - {ts}" + err_msg = "Invalid ISO 8601 Duration format - {}".format(ts) for c in ts: # number (ascii codes) From 5e4436468668bd9f545340d1d15d81bbb364bd62 Mon Sep 17 00:00:00 2001 From: Alvaro Santiesteban Date: Mon, 17 Feb 2020 13:29:23 +0000 Subject: [PATCH 09/15] Solve black issue --- pandas/io/formats/html.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py index aeb4faf2e4688..585e1af3dbc01 100644 --- a/pandas/io/formats/html.py +++ b/pandas/io/formats/html.py @@ -154,9 +154,7 @@ def _write_cell( else: end_a = "" - self.write( - f"{start_tag}{rs}{end_a}", indent - ) + self.write(f"{start_tag}{rs}{end_a}", indent) def write_tr( self, From 9fd0c7b283a2b76f6a993c314d5f83b9d78554e4 Mon Sep 17 00:00:00 2001 From: Alvaro Santiesteban Date: Mon, 17 Feb 2020 19:56:07 +0000 Subject: [PATCH 10/15] Remove unnecesary is not None expression --- pandas/core/arrays/interval.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pandas/core/arrays/interval.py b/pandas/core/arrays/interval.py index b11736248c12a..1b9fed31e16a6 100644 --- a/pandas/core/arrays/interval.py +++ b/pandas/core/arrays/interval.py @@ -195,13 +195,13 @@ def _simple_new( left = ensure_index(left, copy=copy) right = ensure_index(right, copy=copy) - if dtype is not None: + if dtype: # GH 19262: dtype must be an IntervalDtype to override inferred dtype = pandas_dtype(dtype) if not is_interval_dtype(dtype): msg = f"dtype must be an IntervalDtype, got {dtype}" raise TypeError(msg) - elif dtype.subtype is not None: + elif dtype.subtype: left = left.astype(dtype.subtype) right = right.astype(dtype.subtype) @@ -637,9 +637,9 @@ def fillna(self, value=None, method=None, limit=None): ------- filled : IntervalArray with NA/NaN filled """ - if method is not None: + if method: raise TypeError("Filling by method is not supported for IntervalArray.") - if limit is not None: + if limit: raise TypeError("limit is not supported for IntervalArray.") if not isinstance(value, ABCInterval): @@ -1149,7 +1149,7 @@ def __arrow_array__(self, type=None): children=[storage_array.field(0), storage_array.field(1)], ) - if type is not None: + if type: if type.equals(interval_type.storage_type): return storage_array elif isinstance(type, ArrowIntervalType): From 39531c14c8be2626b779ca6517ff09151ea05641 Mon Sep 17 00:00:00 2001 From: Alvaro Santiesteban Date: Mon, 17 Feb 2020 15:29:52 -0600 Subject: [PATCH 11/15] Revert "Remove unnecesary is not None expression" This reverts commit 9fd0c7b283a2b76f6a993c314d5f83b9d78554e4. --- pandas/core/arrays/interval.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pandas/core/arrays/interval.py b/pandas/core/arrays/interval.py index 1b9fed31e16a6..b11736248c12a 100644 --- a/pandas/core/arrays/interval.py +++ b/pandas/core/arrays/interval.py @@ -195,13 +195,13 @@ def _simple_new( left = ensure_index(left, copy=copy) right = ensure_index(right, copy=copy) - if dtype: + if dtype is not None: # GH 19262: dtype must be an IntervalDtype to override inferred dtype = pandas_dtype(dtype) if not is_interval_dtype(dtype): msg = f"dtype must be an IntervalDtype, got {dtype}" raise TypeError(msg) - elif dtype.subtype: + elif dtype.subtype is not None: left = left.astype(dtype.subtype) right = right.astype(dtype.subtype) @@ -637,9 +637,9 @@ def fillna(self, value=None, method=None, limit=None): ------- filled : IntervalArray with NA/NaN filled """ - if method: + if method is not None: raise TypeError("Filling by method is not supported for IntervalArray.") - if limit: + if limit is not None: raise TypeError("limit is not supported for IntervalArray.") if not isinstance(value, ABCInterval): @@ -1149,7 +1149,7 @@ def __arrow_array__(self, type=None): children=[storage_array.field(0), storage_array.field(1)], ) - if type: + if type is not None: if type.equals(interval_type.storage_type): return storage_array elif isinstance(type, ArrowIntervalType): From 226b72d8f4fcb598275b5b0c0b2fa9a82fcbdae3 Mon Sep 17 00:00:00 2001 From: Alvaro Santiesteban Date: Tue, 18 Feb 2020 02:22:10 +0000 Subject: [PATCH 12/15] Test for repr --- pandas/io/formats/format.py | 2 +- pandas/io/formats/printing.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index cf9ac9b61fa2c..f6c4fad51f6b6 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1703,7 +1703,7 @@ def _formatter(x): x = Timedelta(x) result = x._repr_base(format=format) if box: - result = repr(result) + result = f"'{result}'" return result return _formatter diff --git a/pandas/io/formats/printing.py b/pandas/io/formats/printing.py index 32f06f4e487f8..36e774305b577 100644 --- a/pandas/io/formats/printing.py +++ b/pandas/io/formats/printing.py @@ -229,7 +229,7 @@ def as_escaped_string( max_seq_items=max_seq_items, ) elif isinstance(thing, str) and quote_strings: - result = repr(as_escaped_string(thing)) + result = f"'{as_escaped_string(thing)}'" else: result = as_escaped_string(thing) From 9894c28afce1ed379e13833ddaf989da43d3e4b6 Mon Sep 17 00:00:00 2001 From: Alvaro Santiesteban Date: Tue, 18 Feb 2020 12:37:26 +0000 Subject: [PATCH 13/15] Address feedback comments --- pandas/io/formats/format.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index f6c4fad51f6b6..b5ddd15c1312a 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -315,11 +315,11 @@ def _get_footer(self) -> str: footer += f"Length: {len(self.series)}" if self.dtype is not False and self.dtype is not None: - name = getattr(self.tr_series.dtype, "name", None) - if name: + dtype_name = getattr(self.tr_series.dtype, "name", None) + if dtype_name: if footer: footer += ", " - footer += f"dtype: {pprint_thing(name)}" + footer += f"dtype: {pprint_thing(dtype_name)}" # level infos are added to the end and in a new line, like it is done # for Categoricals From ff3e5d2977ea4abe6f6cd9406cafd04739bb34f0 Mon Sep 17 00:00:00 2001 From: Alvaro Santiesteban Date: Tue, 18 Feb 2020 06:54:26 -0600 Subject: [PATCH 14/15] Revert "Test for repr" This reverts commit 226b72d8f4fcb598275b5b0c0b2fa9a82fcbdae3. --- pandas/io/formats/format.py | 2 +- pandas/io/formats/printing.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index b5ddd15c1312a..fe1aac10a4803 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1703,7 +1703,7 @@ def _formatter(x): x = Timedelta(x) result = x._repr_base(format=format) if box: - result = f"'{result}'" + result = repr(result) return result return _formatter diff --git a/pandas/io/formats/printing.py b/pandas/io/formats/printing.py index 36e774305b577..32f06f4e487f8 100644 --- a/pandas/io/formats/printing.py +++ b/pandas/io/formats/printing.py @@ -229,7 +229,7 @@ def as_escaped_string( max_seq_items=max_seq_items, ) elif isinstance(thing, str) and quote_strings: - result = f"'{as_escaped_string(thing)}'" + result = repr(as_escaped_string(thing)) else: result = as_escaped_string(thing) From a7bfe07c5d925298d25bb00108976a8dac70f5da Mon Sep 17 00:00:00 2001 From: Alvaro Santiesteban Date: Wed, 19 Feb 2020 23:51:35 -0600 Subject: [PATCH 15/15] Revert "Revert "Test for repr"" This reverts commit ff3e5d2977ea4abe6f6cd9406cafd04739bb34f0. --- pandas/io/formats/format.py | 2 +- pandas/io/formats/printing.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index fe1aac10a4803..b5ddd15c1312a 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1703,7 +1703,7 @@ def _formatter(x): x = Timedelta(x) result = x._repr_base(format=format) if box: - result = repr(result) + result = f"'{result}'" return result return _formatter diff --git a/pandas/io/formats/printing.py b/pandas/io/formats/printing.py index 32f06f4e487f8..36e774305b577 100644 --- a/pandas/io/formats/printing.py +++ b/pandas/io/formats/printing.py @@ -229,7 +229,7 @@ def as_escaped_string( max_seq_items=max_seq_items, ) elif isinstance(thing, str) and quote_strings: - result = repr(as_escaped_string(thing)) + result = f"'{as_escaped_string(thing)}'" else: result = as_escaped_string(thing)