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..b5ddd15c1312a 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,6 @@ def to_string(self) -> str: fmt_values = self._get_formatted_values() - fmt_values = ["{i}".format(i=i) for i in fmt_values] fmt_values = [i.strip() for i in fmt_values] values = ", ".join(fmt_values) result = ["[" + values + "]"] @@ -301,28 +300,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 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: + dtype_name = getattr(self.tr_series.dtype, "name", None) + if dtype_name: if footer: footer += ", " - footer += "dtype: {typ}".format(typ=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 @@ -359,9 +356,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 +579,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 +809,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 +858,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 +1063,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 = [str(x) for x in self._get_column_name_list()] else: col_header = [""] * columns.nlevels @@ -1209,10 +1198,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 +1225,10 @@ def _format(x): pass return self.na_rep elif isinstance(x, PandasObject): - return "{x}".format(x=x) + return str(x) else: # object dtype - return "{x}".format(x=formatter(x)) + return str(formatter(x)) vals = self.values if isinstance(vals, Index): @@ -1257,7 +1244,7 @@ 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: @@ -1437,7 +1424,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 +1703,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 +1867,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..585e1af3dbc01 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,17 +149,12 @@ 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, - ) + self.write(f"{start_tag}{rs}{end_a}", indent) def write_tr( self, @@ -177,7 +172,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 +191,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 +217,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..3a3ca84642d51 100644 --- a/pandas/io/formats/latex.py +++ b/pandas/io/formats/latex.py @@ -58,10 +58,10 @@ 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}\n" + f"Index: {self.frame.index}" ) strcols = [[info_line]] else: @@ -140,8 +140,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 +171,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 +210,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}}}" + f"{{{coltext.strip()}}}" ) # don't modify where not needed else: @@ -255,9 +254,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()}}}" # save when to end the current block with \cline self.clinebuf.append([i + nrow - 1, j + 1]) return row @@ -268,7 +265,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 +289,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 +337,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)