From fef8350f88af2da2d437e16cabdb3bfa3f83a40e Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 27 Oct 2022 18:09:48 +0300 Subject: [PATCH 1/5] CLN: run flynt to use f-strings (mechanical) --- pandas/core/arraylike.py | 3 +-- pandas/tests/io/excel/test_openpyxl.py | 2 +- pandas/tests/io/test_fsspec.py | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pandas/core/arraylike.py b/pandas/core/arraylike.py index 383ee2c53f0ae..c891ac2fcfc51 100644 --- a/pandas/core/arraylike.py +++ b/pandas/core/arraylike.py @@ -304,8 +304,7 @@ def array_ufunc(self, ufunc: np.ufunc, method: str, *inputs: Any, **kwargs: Any) # well. Previously this raised an internal ValueError. We might # support it someday, so raise a NotImplementedError. raise NotImplementedError( - "Cannot apply ufunc {} to mixed DataFrame and Series " - "inputs.".format(ufunc) + f"Cannot apply ufunc {ufunc} to mixed DataFrame and Series inputs." ) axes = self.axes for obj in alignable[1:]: diff --git a/pandas/tests/io/excel/test_openpyxl.py b/pandas/tests/io/excel/test_openpyxl.py index 3b122c8572751..d23989ea1656b 100644 --- a/pandas/tests/io/excel/test_openpyxl.py +++ b/pandas/tests/io/excel/test_openpyxl.py @@ -269,7 +269,7 @@ def test_to_excel_with_openpyxl_engine(ext): df2 = DataFrame({"B": np.linspace(1, 20, 10)}) df = pd.concat([df1, df2], axis=1) styled = df.style.applymap( - lambda val: "color: %s" % ("red" if val < 0 else "black") + lambda val: f"color: {'red' if val < 0 else 'black'}" ).highlight_max() styled.to_excel(filename, engine="openpyxl") diff --git a/pandas/tests/io/test_fsspec.py b/pandas/tests/io/test_fsspec.py index bdd4cd95ec1af..a1c597087788c 100644 --- a/pandas/tests/io/test_fsspec.py +++ b/pandas/tests/io/test_fsspec.py @@ -211,7 +211,7 @@ def test_from_s3_csv(s3_resource, tips_file, s3so): @td.skip_if_no("s3fs") def test_s3_protocols(s3_resource, tips_file, protocol, s3so): tm.assert_equal( - read_csv("%s://pandas-test/tips.csv" % protocol, storage_options=s3so), + read_csv(f"{protocol}://pandas-test/tips.csv", storage_options=s3so), read_csv(tips_file), ) From 910890032638d169fa0c8ed6d8e4a5c15b96e878 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 27 Oct 2022 18:11:16 +0300 Subject: [PATCH 2/5] CLN: apply manual f-string fixes inspired by flynt -a --- asv_bench/benchmarks/io/hdf.py | 2 +- pandas/tests/io/formats/style/test_html.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/asv_bench/benchmarks/io/hdf.py b/asv_bench/benchmarks/io/hdf.py index 4a2c1c872e6eb..12bc65f9e7bf5 100644 --- a/asv_bench/benchmarks/io/hdf.py +++ b/asv_bench/benchmarks/io/hdf.py @@ -43,7 +43,7 @@ def setup(self): np.random.randn(N, 100), index=date_range("1/1/2000", periods=N) ) self.df_dc = DataFrame( - np.random.randn(N, 10), columns=["C%03d" % i for i in range(10)] + np.random.randn(N, 10), columns=[f"C{i:03d}" for i in range(10)] ) self.fname = "__test__.h5" diff --git a/pandas/tests/io/formats/style/test_html.py b/pandas/tests/io/formats/style/test_html.py index 46891863975ea..6010823af1120 100644 --- a/pandas/tests/io/formats/style/test_html.py +++ b/pandas/tests/io/formats/style/test_html.py @@ -802,7 +802,7 @@ def test_rendered_links(type, text, exp, found): df = DataFrame([0], index=[text]) styler = df.style.format_index(hyperlinks="html") - rendered = '{0}'.format(found) + rendered = f'{found}' result = styler.to_html() assert (rendered in result) is exp assert (text in result) is not exp # test conversion done when expected and not From ea3c120b4b5ef3c6ebb1cc2842371d3765366c53 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 27 Oct 2022 18:14:03 +0300 Subject: [PATCH 3/5] CLN: apply manual f-string fixes inspired by flynt -tc --- asv_bench/benchmarks/categoricals.py | 2 +- asv_bench/benchmarks/frame_methods.py | 2 +- asv_bench/benchmarks/inference.py | 17 ++++++++------- pandas/_config/config.py | 6 +++--- pandas/conftest.py | 2 +- pandas/core/arrays/categorical.py | 4 ++-- pandas/core/arrays/masked.py | 2 +- pandas/core/arrays/string_arrow.py | 8 +++---- pandas/core/computation/expr.py | 2 +- pandas/core/computation/parsing.py | 2 +- pandas/core/computation/scope.py | 2 +- pandas/core/dtypes/dtypes.py | 2 +- pandas/core/frame.py | 5 ++--- pandas/core/groupby/groupby.py | 4 ++-- pandas/core/indexes/category.py | 2 +- pandas/core/indexes/interval.py | 2 +- pandas/core/interchange/column.py | 2 +- pandas/core/nanops.py | 2 +- pandas/core/ops/docstrings.py | 4 ++-- pandas/io/clipboard/__init__.py | 2 +- pandas/io/formats/css.py | 4 ++-- pandas/io/formats/format.py | 20 +++++++++--------- pandas/io/formats/printing.py | 18 +++++++--------- pandas/io/formats/style.py | 30 ++++++++++++--------------- pandas/io/formats/style_render.py | 8 +++---- pandas/io/html.py | 4 ++-- pandas/io/parquet.py | 2 +- pandas/io/parsers/python_parser.py | 9 ++++---- pandas/io/pytables.py | 2 +- pandas/io/sas/sas7bdat.py | 2 +- pandas/io/sas/sas_xport.py | 4 ++-- pandas/io/xml.py | 2 +- pandas/plotting/_matplotlib/core.py | 6 +++--- pandas/util/_decorators.py | 2 +- scripts/no_bool_in_generic.py | 2 +- web/pandas_web.py | 2 +- 36 files changed, 92 insertions(+), 99 deletions(-) diff --git a/asv_bench/benchmarks/categoricals.py b/asv_bench/benchmarks/categoricals.py index ff0b3b2fb651d..774503af4639c 100644 --- a/asv_bench/benchmarks/categoricals.py +++ b/asv_bench/benchmarks/categoricals.py @@ -89,7 +89,7 @@ def setup(self): ) for col in ("int", "float", "timestamp"): - self.df[col + "_as_str"] = self.df[col].astype(str) + self.df[f"{col}_as_str"] = self.df[col].astype(str) for col in self.df.columns: self.df[col] = self.df[col].astype("category") diff --git a/asv_bench/benchmarks/frame_methods.py b/asv_bench/benchmarks/frame_methods.py index a28e20a636ce2..244e37c67bc7f 100644 --- a/asv_bench/benchmarks/frame_methods.py +++ b/asv_bench/benchmarks/frame_methods.py @@ -125,7 +125,7 @@ def setup(self): self.df = DataFrame(np.random.randn(N * 10, N)) self.df2 = DataFrame(np.random.randn(N * 50, 10)) self.df3 = DataFrame( - np.random.randn(N, 5 * N), columns=["C" + str(c) for c in range(N * 5)] + np.random.randn(N, 5 * N), columns=[f"C{c}" for c in range(N * 5)] ) self.df4 = DataFrame(np.random.randn(N * 1000, 10)) diff --git a/asv_bench/benchmarks/inference.py b/asv_bench/benchmarks/inference.py index 0bbb599f2b045..b349ca6e36932 100644 --- a/asv_bench/benchmarks/inference.py +++ b/asv_bench/benchmarks/inference.py @@ -166,14 +166,15 @@ def time_unique_date_strings(self, cache, count): class ToDatetimeISO8601: + sep_format = "%Y-%m-%d %H:%M:%S" + nosep_format = "%Y%m%d %H:%M:%S" + def setup(self): rng = date_range(start="1/1/2000", periods=20000, freq="H") - self.strings = rng.strftime("%Y-%m-%d %H:%M:%S").tolist() - self.strings_nosep = rng.strftime("%Y%m%d %H:%M:%S").tolist() - self.strings_tz_space = [ - x.strftime("%Y-%m-%d %H:%M:%S") + " -0800" for x in rng - ] - self.strings_zero_tz = [x.strftime("%Y-%m-%d %H:%M:%S") + "Z" for x in rng] + self.strings = rng.strftime(self.sep_format).tolist() + self.strings_nosep = rng.strftime(self.nosep_format).tolist() + self.strings_tz_space = [f"{x.strftime(self.sep_format)} -0800" for x in rng] + self.strings_zero_tz = [f"{x.strftime(self.sep_format)}Z" for x in rng] def time_iso8601(self): to_datetime(self.strings) @@ -182,10 +183,10 @@ def time_iso8601_nosep(self): to_datetime(self.strings_nosep) def time_iso8601_format(self): - to_datetime(self.strings, format="%Y-%m-%d %H:%M:%S") + to_datetime(self.strings, format=self.sep_format) def time_iso8601_format_no_sep(self): - to_datetime(self.strings_nosep, format="%Y%m%d %H:%M:%S") + to_datetime(self.strings_nosep, format=self.nosep_format) def time_iso8601_tz_spaceformat(self): to_datetime(self.strings_tz_space) diff --git a/pandas/_config/config.py b/pandas/_config/config.py index a942da663889b..de79d2765f6df 100644 --- a/pandas/_config/config.py +++ b/pandas/_config/config.py @@ -499,7 +499,7 @@ def register_option( path = key.split(".") for k in path: - if not re.match("^" + tokenize.Name + "$", k): + if not re.match(f"^{tokenize.Name}$", k): raise ValueError(f"{k} is not a valid identifier") if keyword.iskeyword(k): raise ValueError(f"{k} is a python keyword") @@ -707,7 +707,7 @@ def pp_options_list(keys: Iterable[str], width: int = 80, _print: bool = False): from textwrap import wrap def pp(name: str, ks: Iterable[str]) -> list[str]: - pfx = "- " + name + ".[" if name else "" + pfx = f"- {name}.[" if name else "" ls = wrap( ", ".join(ks), width, @@ -716,7 +716,7 @@ def pp(name: str, ks: Iterable[str]) -> list[str]: break_long_words=False, ) if ls and ls[-1] and name: - ls[-1] = ls[-1] + "]" + ls[-1] = f"{ls[-1]}]" return ls ls: list[str] = [] diff --git a/pandas/conftest.py b/pandas/conftest.py index 61915b4070945..c0f2a6e4e630b 100644 --- a/pandas/conftest.py +++ b/pandas/conftest.py @@ -1770,7 +1770,7 @@ def spmatrix(request): """ from scipy import sparse - return getattr(sparse, request.param + "_matrix") + return getattr(sparse, f"{request.param}_matrix") @pytest.fixture( diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index becca2b668290..5356b1752d163 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -1890,7 +1890,7 @@ def _repr_categories_info(self) -> str: start = True cur_col_len = len(levheader) # header sep_len, sep = (3, " < ") if self.ordered else (2, ", ") - linesep = sep.rstrip() + "\n" # remove whitespace + linesep = f"{sep.rstrip()}\n" # remove whitespace for val in category_strs: if max_width != 0 and cur_col_len + sep_len + len(val) > max_width: levstring += linesep + (" " * (len(levheader) + 1)) @@ -1901,7 +1901,7 @@ def _repr_categories_info(self) -> str: levstring += val start = False # replace to simple save space by - return levheader + "[" + levstring.replace(" < ... < ", " ... ") + "]" + return f"{levheader}[{levstring.replace(' < ... < ', ' ... ')}]" def _repr_footer(self) -> str: info = self._repr_categories_info() diff --git a/pandas/core/arrays/masked.py b/pandas/core/arrays/masked.py index 746175ee3374d..61295a76f5b7f 100644 --- a/pandas/core/arrays/masked.py +++ b/pandas/core/arrays/masked.py @@ -1058,7 +1058,7 @@ def _reduce(self, name: str, *, skipna: bool = True, **kwargs): data = self.to_numpy("float64", na_value=np.nan) # median, var, std, skew, kurt, idxmin, idxmax - op = getattr(nanops, "nan" + name) + op = getattr(nanops, f"nan{name}") result = op(data, axis=0, skipna=skipna, mask=mask, **kwargs) if np.isnan(result): diff --git a/pandas/core/arrays/string_arrow.py b/pandas/core/arrays/string_arrow.py index 538adcbc47911..b8b1d64d7a093 100644 --- a/pandas/core/arrays/string_arrow.py +++ b/pandas/core/arrays/string_arrow.py @@ -317,11 +317,11 @@ def _str_contains( return result def _str_startswith(self, pat: str, na=None): - pat = "^" + re.escape(pat) + pat = f"^{re.escape(pat)}" return self._str_contains(pat, na=na, regex=True) def _str_endswith(self, pat: str, na=None): - pat = re.escape(pat) + "$" + pat = f"{re.escape(pat)}$" return self._str_contains(pat, na=na, regex=True) def _str_replace( @@ -345,14 +345,14 @@ def _str_match( self, pat: str, case: bool = True, flags: int = 0, na: Scalar | None = None ): if not pat.startswith("^"): - pat = "^" + pat + pat = f"^{pat}" return self._str_contains(pat, case, flags, na, regex=True) def _str_fullmatch( self, pat, case: bool = True, flags: int = 0, na: Scalar | None = None ): if not pat.endswith("$") or pat.endswith("//$"): - pat = pat + "$" + pat = f"{pat}$" return self._str_match(pat, case, flags, na) def _str_isalnum(self): diff --git a/pandas/core/computation/expr.py b/pandas/core/computation/expr.py index e7474ea5dd9f8..0578d9965df0c 100644 --- a/pandas/core/computation/expr.py +++ b/pandas/core/computation/expr.py @@ -410,7 +410,7 @@ def visit(self, node, **kwargs): e.msg = "Python keyword not valid identifier in numexpr query" raise e - method = "visit_" + type(node).__name__ + method = f"visit_{type(node).__name__}" visitor = getattr(self, method) return visitor(node, **kwargs) diff --git a/pandas/core/computation/parsing.py b/pandas/core/computation/parsing.py index 89d1f2133f77a..4020ec7b5e9eb 100644 --- a/pandas/core/computation/parsing.py +++ b/pandas/core/computation/parsing.py @@ -59,7 +59,7 @@ def create_valid_python_identifier(name: str) -> str: ) name = "".join([special_characters_replacements.get(char, char) for char in name]) - name = "BACKTICK_QUOTED_STRING_" + name + name = f"BACKTICK_QUOTED_STRING_{name}" if not name.isidentifier(): raise SyntaxError(f"Could not convert '{name}' to a valid Python identifier.") diff --git a/pandas/core/computation/scope.py b/pandas/core/computation/scope.py index 4b8ff48174ea2..6d070540de26a 100644 --- a/pandas/core/computation/scope.py +++ b/pandas/core/computation/scope.py @@ -250,7 +250,7 @@ def _get_vars(self, stack, scopes: list[str]) -> None: variables = itertools.product(scopes, stack) for scope, (frame, _, _, _, _, _) in variables: try: - d = getattr(frame, "f_" + scope) + d = getattr(frame, f"f_{scope}") self.scope = DeepChainMap(self.scope.new_child(d)) finally: # won't remove it, but DECREF it diff --git a/pandas/core/dtypes/dtypes.py b/pandas/core/dtypes/dtypes.py index e57e11f1bd2bd..cce7449d8472a 100644 --- a/pandas/core/dtypes/dtypes.py +++ b/pandas/core/dtypes/dtypes.py @@ -802,7 +802,7 @@ def __hash__(self) -> int: def __eq__(self, other: Any) -> bool: if isinstance(other, str): if other.startswith("M8["): - other = "datetime64[" + other[3:] + other = f"datetime64[{other[3:]}" return other == self.name return ( diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 044c40c58b85c..6672c8713878e 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -1095,7 +1095,7 @@ def _repr_html_(self) -> str | None: # need to escape the , should be the first line. val = buf.getvalue().replace("<", r"<", 1) val = val.replace(">", r">", 1) - return "
" + val + "
" + return f"
{val}
" if get_option("display.notebook_repr_html"): max_rows = get_option("display.max_rows") @@ -8945,8 +8945,7 @@ def explode( if not self.columns.is_unique: duplicate_cols = self.columns[self.columns.duplicated()].tolist() raise ValueError( - "DataFrame columns must be unique. " - + f"Duplicate columns: {duplicate_cols}" + f"DataFrame columns must be unique. Duplicate columns: {duplicate_cols}" ) columns: list[Hashable] diff --git a/pandas/core/groupby/groupby.py b/pandas/core/groupby/groupby.py index 369fd37bf3a92..d6f3c07bb7aa4 100644 --- a/pandas/core/groupby/groupby.py +++ b/pandas/core/groupby/groupby.py @@ -1533,9 +1533,9 @@ def f(g): with np.errstate(all="ignore"): return func(g, *args, **kwargs) - elif hasattr(nanops, "nan" + func): + elif hasattr(nanops, f"nan{func}"): # TODO: should we wrap this in to e.g. _is_builtin_func? - f = getattr(nanops, "nan" + func) + f = getattr(nanops, f"nan{func}") else: raise ValueError( diff --git a/pandas/core/indexes/category.py b/pandas/core/indexes/category.py index 58b533cb576d9..0c5710c789a3c 100644 --- a/pandas/core/indexes/category.py +++ b/pandas/core/indexes/category.py @@ -349,7 +349,7 @@ def _format_attrs(self): attrs = [ ( "categories", - "[" + ", ".join(self._data._repr_categories()) + "]", + f"[{', '.join(self._data._repr_categories())}]", ), ("ordered", self.ordered), ] diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index fa10aee4b6c72..7d44220b2659c 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -845,7 +845,7 @@ def _format_native_types( def _format_data(self, name=None) -> str: # TODO: integrate with categorical and make generic # name argument is unused here; just for compat with base / categorical - return self._data._format_data() + "," + self._format_space() + return f"{self._data._format_data()},{self._format_space()}" # -------------------------------------------------------------------- # Set Operations diff --git a/pandas/core/interchange/column.py b/pandas/core/interchange/column.py index f375048563c70..75d07d1c2f7f6 100644 --- a/pandas/core/interchange/column.py +++ b/pandas/core/interchange/column.py @@ -329,7 +329,7 @@ def _get_validity_buffer(self) -> tuple[PandasBuffer, Any]: return buffer, dtype try: - msg = _NO_VALIDITY_BUFFER[null] + " so does not have a separate mask" + msg = f"{_NO_VALIDITY_BUFFER[null]} so does not have a separate mask" except KeyError: # TODO: implement for other bit/byte masks? raise NotImplementedError("See self.describe_null") diff --git a/pandas/core/nanops.py b/pandas/core/nanops.py index 50ebf5c2032be..b8e2b1fafe326 100644 --- a/pandas/core/nanops.py +++ b/pandas/core/nanops.py @@ -1043,7 +1043,7 @@ def nansem( def _nanminmax(meth, fill_value_typ): - @bottleneck_switch(name="nan" + meth) + @bottleneck_switch(name=f"nan{meth}") @_datetimelike_compat def reduction( values: np.ndarray, diff --git a/pandas/core/ops/docstrings.py b/pandas/core/ops/docstrings.py index 9c3158b3465b7..470f7258b13ee 100644 --- a/pandas/core/ops/docstrings.py +++ b/pandas/core/ops/docstrings.py @@ -25,11 +25,11 @@ def make_flex_doc(op_name: str, typ: str) -> str: op_desc_op = op_desc["op"] assert op_desc_op is not None # for mypy if op_name.startswith("r"): - equiv = "other " + op_desc_op + " " + typ + equiv = f"other {op_desc_op} {typ}" elif op_name == "divmod": equiv = f"{op_name}({typ}, other)" else: - equiv = typ + " " + op_desc_op + " other" + equiv = f"{typ} {op_desc_op} other" if typ == "series": base_doc = _flex_doc_SERIES diff --git a/pandas/io/clipboard/__init__.py b/pandas/io/clipboard/__init__.py index 85fae6da07827..6be4396314cb9 100644 --- a/pandas/io/clipboard/__init__.py +++ b/pandas/io/clipboard/__init__.py @@ -312,7 +312,7 @@ def __init__(self, f) -> None: def __call__(self, *args): ret = self.f(*args) if not ret and get_errno(): - raise PyperclipWindowsException("Error calling " + self.f.__name__) + raise PyperclipWindowsException(f"Error calling {self.f.__name__}") return ret def __setattr__(self, key, value): diff --git a/pandas/io/formats/css.py b/pandas/io/formats/css.py index cfc95bc9d9569..4328683875223 100644 --- a/pandas/io/formats/css.py +++ b/pandas/io/formats/css.py @@ -194,11 +194,11 @@ class CSSResolver: CSS_EXPANSIONS = { **{ - "-".join(["border", prop] if prop else ["border"]): _border_expander(prop) + (f"border-{prop}" if prop else "border"): _border_expander(prop) for prop in ["", "top", "right", "bottom", "left"] }, **{ - "-".join(["border", prop]): _side_expander("border-{:s}-" + prop) + f"border-{prop}": _side_expander(f"border-{{:s}}-{prop}") for prop in ["color", "style", "width"] }, **{ diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index cdc21f04da43a..7e355cc873a78 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -256,7 +256,7 @@ def to_string(self) -> str: fmt_values = [i.strip() for i in fmt_values] values = ", ".join(fmt_values) - result = ["[" + values + "]"] + result = [f"[{values}]"] if self.footer: footer = self._get_footer() if footer: @@ -417,10 +417,10 @@ def to_string(self) -> str: result = self.adj.adjoin(3, fmt_values) if self.header and have_header: - result = fmt_index[0] + "\n" + result + result = f"{fmt_index[0]}\n{result}" if footer: - result += "\n" + footer + result += f"\n{footer}" return str("".join(result)) @@ -936,7 +936,7 @@ def space_format(x, y): and need_leadsp[x] and not restrict_formatting ): - return " " + y + return f" {y}" return y str_columns = list( @@ -951,7 +951,7 @@ def space_format(x, y): dtypes = self.frame.dtypes need_leadsp = dict(zip(fmt_columns, map(is_numeric_dtype, dtypes))) str_columns = [ - [" " + x if not self._get_formatter(i) and need_leadsp[x] else x] + [f" {x}" if not self._get_formatter(i) and need_leadsp[x] else x] for i, x in enumerate(fmt_columns) ] # self.str_columns = str_columns @@ -1534,7 +1534,7 @@ def format_values_with(float_format): # default formatter leaves a space to the left when formatting # floats, must be consistent for left-justifying NaNs (GH #25061) if self.justify == "left": - na_rep = " " + self.na_rep + na_rep = f" {self.na_rep}" else: na_rep = self.na_rep @@ -1726,7 +1726,7 @@ def format_percentiles( if np.all(int_idx): out = percentiles_round_type.astype(str) - return [i + "%" for i in out] + return [f"{i}%" for i in out] unique_pcts = np.unique(percentiles) to_begin = unique_pcts[0] if unique_pcts[0] > 0 else None @@ -1741,7 +1741,7 @@ def format_percentiles( out[int_idx] = percentiles[int_idx].round().astype(int).astype(str) out[~int_idx] = percentiles[~int_idx].round(prec).astype(str) - return [i + "%" for i in out] + return [f"{i}%" for i in out] def is_dates_only(values: np.ndarray | DatetimeArray | Index | DatetimeIndex) -> bool: @@ -1929,7 +1929,7 @@ def _make_fixed_width( def just(x: str) -> str: if conf_max is not None: if (conf_max > 3) & (adjustment.len(x) > max_len): - x = x[: max_len - 3] + "..." + x = f"{x[:max_len - 3]}..." return x strings = [just(x) for x in strings] @@ -2004,7 +2004,7 @@ def should_trim(values: np.ndarray | list[str]) -> bool: # leave one 0 after the decimal points if need be. result = [ - x + "0" if is_number_with_decimal(x) and x.endswith(decimal) else x + f"{x}0" if is_number_with_decimal(x) and x.endswith(decimal) else x for x in trimmed ] return result diff --git a/pandas/io/formats/printing.py b/pandas/io/formats/printing.py index 8091590e2e89d..b3ff524ed6efe 100644 --- a/pandas/io/formats/printing.py +++ b/pandas/io/formats/printing.py @@ -155,10 +155,8 @@ def _pprint_dict( ) ) - if nitems < len(seq): - return fmt.format(things=", ".join(pairs) + ", ...") - else: - return fmt.format(things=", ".join(pairs)) + things = ", ".join(pairs) + return fmt.format(things=(f"{things}, ..." if nitems < len(seq) else things)) def pprint_thing( @@ -339,7 +337,7 @@ def format_object_summary( if line_break_each_value: # If we want to vertically align on each value of obj, we need to # separate values by a line break and indent the values - sep = ",\n " + " " * len(name) + sep = f",\n {' ' * len(name)}" else: sep = "," max_seq_items = get_option("display.max_seq_items") or n @@ -427,16 +425,16 @@ def best_len(values: list[str]) -> int: line = space2 for head_value in head: - word = head_value + sep + " " + word = f"{head_value}{sep} " summary, line = _extend_line(summary, line, word, display_width, space2) if is_truncated: # remove trailing space of last line - summary += line.rstrip() + space2 + "..." + summary += f"{line.rstrip()}{space2}..." line = space2 for tail_item in tail[:-1]: - word = tail_item + sep + " " + word = f"{tail_item}{sep} " summary, line = _extend_line(summary, line, word, display_width, space2) # last value: no sep added + 1 space of width used for trailing ',' @@ -445,7 +443,7 @@ def best_len(values: list[str]) -> int: # right now close is either '' or ', ' # Now we want to include the ']', but not the maybe space. - close = "]" + close.rstrip(" ") + close = f"]{close.rstrip(' ')}" summary += close if len(summary) > (display_width) or line_break_each_value: @@ -454,7 +452,7 @@ def best_len(values: list[str]) -> int: summary += " " # remove initial space - summary = "[" + summary[len(space2) :] + summary = f"[{summary[len(space2):]}" return summary diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 8f21823ddcd02..4a5c4b908dd7c 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -2128,18 +2128,18 @@ def use(self, styles: dict[str, Any]) -> Styler: if styles.get("table_attributes") is None else str(styles.get("table_attributes")) ) - self.set_table_attributes((table_attributes + " " + obj_table_atts).strip()) + self.set_table_attributes(f"{table_attributes} {obj_table_atts}".strip()) if styles.get("table_styles"): self.set_table_styles(styles.get("table_styles"), overwrite=False) for obj in ["index", "columns"]: - hide_obj = styles.get("hide_" + obj) + hide_obj = styles.get(f"hide_{obj}") if hide_obj is not None: if isinstance(hide_obj, bool): n = getattr(self, obj).nlevels - setattr(self, "hide_" + obj + "_", [hide_obj] * n) + setattr(self, f"hide_{obj}_", [hide_obj] * n) else: - setattr(self, "hide_" + obj + "_", hide_obj) + setattr(self, f"hide_{obj}_", hide_obj) self.hide_index_names = styles.get("hide_index_names", False) self.hide_column_names = styles.get("hide_column_names", False) @@ -2245,18 +2245,16 @@ def set_sticky( styles: CSSStyles = [ { "selector": "thead tr:nth-child(1) th", - "props": props + "top:0px; z-index:2;", + "props": f"{props}top:0px; z-index:2;", } ] if not self.index.names[0] is None: - styles[0]["props"] = ( - props + f"top:0px; z-index:2; height:{pixel_size}px;" - ) + common_props = f"z-index:2; height:{pixel_size}px;" + styles[0]["props"] = f"{props}{common_props}top:0px;" styles.append( { "selector": "thead tr:nth-child(2) th", - "props": props - + f"top:{pixel_size}px; z-index:2; height:{pixel_size}px; ", + "props": f"{props}{common_props}top:{pixel_size}px;", } ) else: @@ -2266,11 +2264,11 @@ def set_sticky( styles = [ { "selector": "thead tr th:nth-child(1)", - "props": props + "left:0px; z-index:3 !important;", + "props": f"{props}left:0px; z-index:3 !important;", }, { "selector": "tbody tr th:nth-child(1)", - "props": props + "left:0px; z-index:1;", + "props": f"{props}left:0px; z-index:1;", }, ] @@ -2317,11 +2315,11 @@ def set_sticky( [ { "selector": f"thead tr th:nth-child({level+1})", - "props": props_ + "z-index:3 !important;", + "props": f"{props_}z-index:3 !important;", }, { "selector": f"tbody tr th.level{level}", - "props": props_ + "z-index:1;", + "props": f"{props_}z-index:1;", }, ] ) @@ -3859,9 +3857,7 @@ def css_calc(x, left: float, right: float, align: str, color: str | list | tuple ret = css_bar(start * width, end * width, color) if height < 1 and "background: linear-gradient(" in ret: - return ( - ret + f" no-repeat center; background-size: 100% {height * 100:.1f}%;" - ) + return f"{ret} no-repeat center; background-size: 100% {height * 100:.1f}%;" else: return ret diff --git a/pandas/io/formats/style_render.py b/pandas/io/formats/style_render.py index 035c5d88a7f4b..9db53123a85bc 100644 --- a/pandas/io/formats/style_render.py +++ b/pandas/io/formats/style_render.py @@ -799,7 +799,7 @@ def _generate_body_row( # add custom classes from cell context cls = "" if (r, c) in self.cell_context: - cls = " " + self.cell_context[r, c] + cls = f" {self.cell_context[r, c]}" data_element = _element( "td", @@ -1999,14 +1999,14 @@ def _pseudo_css(self, uuid: str, name: str, row: int, col: int, text: str): ------- pseudo_css : List """ - selector_id = "#T_" + uuid + "_row" + str(row) + "_col" + str(col) + selector_id = f"#T_{uuid}_row{row}_col{col}" return [ { - "selector": selector_id + f":hover .{name}", + "selector": f"{selector_id}:hover .{name}", "props": [("visibility", "visible")], }, { - "selector": selector_id + f" .{name}::after", + "selector": f"{selector_id} .{name}::after", "props": [("content", f'"{text}"')], }, ] diff --git a/pandas/io/html.py b/pandas/io/html.py index eceff2d2ec1f3..89013403b093f 100644 --- a/pandas/io/html.py +++ b/pandas/io/html.py @@ -678,7 +678,7 @@ def _build_doc(self): soup = BeautifulSoup(udoc, features="html5lib", from_encoding=from_encoding) for br in soup.find_all("br"): - br.replace_with("\n" + br.text) + br.replace_with(f"\n{br.text}") return soup @@ -823,7 +823,7 @@ def _build_doc(self): raise XMLSyntaxError("no text parsed from document", 0, 0, 0) for br in r.xpath("*//br"): - br.tail = "\n" + (br.tail or "") + br.tail = f"\n{br.tail or ''}" return r diff --git a/pandas/io/parquet.py b/pandas/io/parquet.py index df02a6fbca295..166253f79e1be 100644 --- a/pandas/io/parquet.py +++ b/pandas/io/parquet.py @@ -51,7 +51,7 @@ def get_engine(engine: str) -> BaseImpl: try: return engine_class() except ImportError as err: - error_msgs += "\n - " + str(err) + error_msgs += f"\n - {err}" raise ImportError( "Unable to find a usable engine; " diff --git a/pandas/io/parsers/python_parser.py b/pandas/io/parsers/python_parser.py index 4f15443ed5610..c3c86825b607a 100644 --- a/pandas/io/parsers/python_parser.py +++ b/pandas/io/parsers/python_parser.py @@ -764,8 +764,7 @@ def _alert_malformed(self, msg: str, row_num: int) -> None: if self.on_bad_lines == self.BadLineHandleMethod.ERROR: raise ParserError(msg) elif self.on_bad_lines == self.BadLineHandleMethod.WARN: - base = f"Skipping line {row_num}: " - sys.stderr.write(base + msg + "\n") + sys.stderr.write(f"Skipping line {row_num}: {msg}\n") def _next_iter_line(self, row_num: int) -> list[Scalar] | None: """ @@ -810,7 +809,7 @@ def _next_iter_line(self, row_num: int) -> list[Scalar] | None: "after Python's csv library has parsed " "all rows)." ) - msg += ". " + reason + msg += f". {reason}" self._alert_malformed(msg, row_num) return None @@ -1040,7 +1039,7 @@ def _rows_to_cols(self, content: list[list[Scalar]]) -> list[np.ndarray]: "Error could possibly be due to quotes being " "ignored when a multi-char delimiter is used." ) - msg += ". " + reason + msg += f". {reason}" self._alert_malformed(msg, row_num + 1) @@ -1172,7 +1171,7 @@ def __init__( ) -> None: self.f = f self.buffer: Iterator | None = None - self.delimiter = "\r\n" + delimiter if delimiter else "\n\r\t " + self.delimiter = "\r\n" + (delimiter or "\t ") self.comment = comment if colspecs == "infer": self.colspecs = self.detect_colspecs( diff --git a/pandas/io/pytables.py b/pandas/io/pytables.py index 1f2bb4c5d21b4..cff23b3c23b6d 100644 --- a/pandas/io/pytables.py +++ b/pandas/io/pytables.py @@ -1504,7 +1504,7 @@ def get_node(self, key: str) -> Node | None: """return the node with the key or None if it does not exist""" self._check_if_open() if not key.startswith("/"): - key = "/" + key + key = f"/{key}" assert self._handle is not None assert _table_mod is not None # for mypy diff --git a/pandas/io/sas/sas7bdat.py b/pandas/io/sas/sas7bdat.py index 80efef211ece5..86d9c4ac21716 100644 --- a/pandas/io/sas/sas7bdat.py +++ b/pandas/io/sas/sas7bdat.py @@ -726,7 +726,7 @@ def _chunk_to_dataframe(self) -> DataFrame: name = self.column_names[j] if self._column_types[j] == b"d": - col_arr = self._byte_chunk[jb, :].view(dtype=self.byte_order + "d") + col_arr = self._byte_chunk[jb, :].view(dtype=f"{self.byte_order}d") rslt[name] = pd.Series(col_arr, dtype=np.float64, index=ix) if self.convert_dates: if self.column_formats[j] in const.sas_date_formats: diff --git a/pandas/io/sas/sas_xport.py b/pandas/io/sas/sas_xport.py index a66910392d788..fa301f1316a0b 100644 --- a/pandas/io/sas/sas_xport.py +++ b/pandas/io/sas/sas_xport.py @@ -391,7 +391,7 @@ def _read_header(self): # Setup the dtype. dtypel = [ - ("s" + str(i), "S" + str(field["field_length"])) + (f"s{i}", f"S{field['field_length']}") for i, field in enumerate(self.fields) ] dtype = np.dtype(dtypel) @@ -482,7 +482,7 @@ def read(self, nrows: int | None = None) -> pd.DataFrame: df_data = {} for j, x in enumerate(self.columns): - vec = data["s" + str(j)] + vec = data[f"s{j}"] ntype = self.fields[j]["ntype"] if ntype == "numeric": vec = _handle_truncated_float_vec(vec, self.fields[j]["field_length"]) diff --git a/pandas/io/xml.py b/pandas/io/xml.py index 6432bba4c1a7c..c045093933ce6 100644 --- a/pandas/io/xml.py +++ b/pandas/io/xml.py @@ -610,7 +610,7 @@ def _validate_names(self) -> None: children = self.iterparse[next(iter(self.iterparse))] else: children = self.xml_doc.xpath( - self.xpath + "[1]/*", namespaces=self.namespaces + f"{self.xpath}[1]/*", namespaces=self.namespaces ) if is_list_like(self.names): diff --git a/pandas/plotting/_matplotlib/core.py b/pandas/plotting/_matplotlib/core.py index 605cc1d94e0af..bce9ae113ad66 100644 --- a/pandas/plotting/_matplotlib/core.py +++ b/pandas/plotting/_matplotlib/core.py @@ -1138,7 +1138,7 @@ class PlanePlot(MPLPlot, ABC): def __init__(self, data, x, y, **kwargs) -> None: MPLPlot.__init__(self, data, **kwargs) if x is None or y is None: - raise ValueError(self._kind + " requires an x and y column") + raise ValueError(f"{self._kind} requires an x and y column") if is_integer(x) and not self.data.columns.holds_integer(): x = self.data.columns[x] if is_integer(y) and not self.data.columns.holds_integer(): @@ -1147,9 +1147,9 @@ def __init__(self, data, x, y, **kwargs) -> None: # Scatter plot allows to plot objects data if self._kind == "hexbin": if len(self.data[x]._get_numeric_data()) == 0: - raise ValueError(self._kind + " requires x column to be numeric") + raise ValueError(f"{self._kind} requires x column to be numeric") if len(self.data[y]._get_numeric_data()) == 0: - raise ValueError(self._kind + " requires y column to be numeric") + raise ValueError(f"{self._kind} requires y column to be numeric") self.x = x self.y = y diff --git a/pandas/util/_decorators.py b/pandas/util/_decorators.py index 5d62f57126ef3..4fa9732065765 100644 --- a/pandas/util/_decorators.py +++ b/pandas/util/_decorators.py @@ -249,7 +249,7 @@ def _format_argument_list(allow_args: list[str]) -> str: return f" except for the argument '{allow_args[0]}'" else: last = allow_args[-1] - args = ", ".join(["'" + x + "'" for x in allow_args[:-1]]) + args = ", ".join([f"'{x}'" for x in allow_args[:-1]]) return f" except for the arguments {args} and '{last}'" diff --git a/scripts/no_bool_in_generic.py b/scripts/no_bool_in_generic.py index f63ae4ae1659c..ce65ac539007f 100644 --- a/scripts/no_bool_in_generic.py +++ b/scripts/no_bool_in_generic.py @@ -52,7 +52,7 @@ def replace_bool_with_bool_t(to_replace, content: str) -> str: for n, line in enumerate(content.splitlines(), start=1): if n in to_replace: for col_offset in reversed(to_replace[n]): - line = line[:col_offset] + "bool_t" + line[col_offset + 4 :] + line = f"{line[:col_offset]}bool_t{line[col_offset + 4:]}" new_lines.append(line) return "\n".join(new_lines) diff --git a/web/pandas_web.py b/web/pandas_web.py index d054e273cde5e..c0aaa3314e317 100755 --- a/web/pandas_web.py +++ b/web/pandas_web.py @@ -370,7 +370,7 @@ def main( ) content = extend_base_template(body, context["main"]["base_template"]) content = jinja_env.from_string(content).render(**context) - fname = os.path.splitext(fname)[0] + ".html" + fname = f"{os.path.splitext(fname)[0]}.html" with open(os.path.join(target_path, fname), "w") as f: f.write(content) else: From a84ff3aaf88bc969e29031c5fe1d7d57c8fecfa1 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Fri, 21 Oct 2022 16:03:40 +0300 Subject: [PATCH 4/5] CLN: replace variations of "..." + str(...) with f-strings This was done by hand. --- pandas/_testing/__init__.py | 2 +- pandas/core/dtypes/dtypes.py | 2 +- pandas/core/interchange/buffer.py | 17 +++----- pandas/core/ops/docstrings.py | 70 +++++++------------------------ pandas/io/formats/style.py | 2 +- pandas/io/sql.py | 24 ++++------- pandas/io/stata.py | 20 ++++----- 7 files changed, 41 insertions(+), 96 deletions(-) diff --git a/pandas/_testing/__init__.py b/pandas/_testing/__init__.py index 6cce1137e707b..72ab2c402cd72 100644 --- a/pandas/_testing/__init__.py +++ b/pandas/_testing/__init__.py @@ -569,7 +569,7 @@ def makeCustomIndex( if names is True: # build default names - names = [prefix + str(i) for i in range(nlevels)] + names = [f"{prefix}{i}" for i in range(nlevels)] if names is False: # pass None to index constructor for no name names = None diff --git a/pandas/core/dtypes/dtypes.py b/pandas/core/dtypes/dtypes.py index cce7449d8472a..b30becad497fe 100644 --- a/pandas/core/dtypes/dtypes.py +++ b/pandas/core/dtypes/dtypes.py @@ -1132,7 +1132,7 @@ def __new__(cls, subtype=None, closed: str_type | None = None): ) raise TypeError(msg) - key = str(subtype) + str(closed) + key = f"{subtype}{closed}" try: return cls._cache_dtypes[key] except KeyError: diff --git a/pandas/core/interchange/buffer.py b/pandas/core/interchange/buffer.py index 0f62dd00a0f41..aa8a2f799ba7a 100644 --- a/pandas/core/interchange/buffer.py +++ b/pandas/core/interchange/buffer.py @@ -64,14 +64,9 @@ def __dlpack_device__(self) -> tuple[DlpackDeviceType, int | None]: return (DlpackDeviceType.CPU, None) def __repr__(self) -> str: - return ( - "PandasBuffer(" - + str( - { - "bufsize": self.bufsize, - "ptr": self.ptr, - "device": self.__dlpack_device__()[0].name, - } - ) - + ")" - ) + spec = { + "bufsize": self.bufsize, + "ptr": self.ptr, + "device": self.__dlpack_device__()[0].name, + } + return f"PandasBuffer({spec})" diff --git a/pandas/core/ops/docstrings.py b/pandas/core/ops/docstrings.py index 470f7258b13ee..fa52ad7b2879a 100644 --- a/pandas/core/ops/docstrings.py +++ b/pandas/core/ops/docstrings.py @@ -99,9 +99,7 @@ def make_flex_doc(op_name: str, typ: str) -> str: f 1.0 dtype: float64""" -_add_example_SERIES = ( - _common_examples_algebra_SERIES - + """ +_add_example_SERIES = f"""{_common_examples_algebra_SERIES} >>> a.add(b, fill_value=0) a 2.0 b 1.0 @@ -110,11 +108,8 @@ def make_flex_doc(op_name: str, typ: str) -> str: e NaN dtype: float64 """ -) -_sub_example_SERIES = ( - _common_examples_algebra_SERIES - + """ +_sub_example_SERIES = f"""{_common_examples_algebra_SERIES} >>> a.subtract(b, fill_value=0) a 0.0 b 1.0 @@ -123,11 +118,8 @@ def make_flex_doc(op_name: str, typ: str) -> str: e NaN dtype: float64 """ -) -_mul_example_SERIES = ( - _common_examples_algebra_SERIES - + """ +_mul_example_SERIES = f"""{_common_examples_algebra_SERIES} >>> a.multiply(b, fill_value=0) a 1.0 b 0.0 @@ -136,11 +128,8 @@ def make_flex_doc(op_name: str, typ: str) -> str: e NaN dtype: float64 """ -) -_div_example_SERIES = ( - _common_examples_algebra_SERIES - + """ +_div_example_SERIES = f"""{_common_examples_algebra_SERIES} >>> a.divide(b, fill_value=0) a 1.0 b inf @@ -149,11 +138,8 @@ def make_flex_doc(op_name: str, typ: str) -> str: e NaN dtype: float64 """ -) -_floordiv_example_SERIES = ( - _common_examples_algebra_SERIES - + """ +_floordiv_example_SERIES = f"""{_common_examples_algebra_SERIES} >>> a.floordiv(b, fill_value=0) a 1.0 b NaN @@ -162,11 +148,8 @@ def make_flex_doc(op_name: str, typ: str) -> str: e NaN dtype: float64 """ -) -_divmod_example_SERIES = ( - _common_examples_algebra_SERIES - + """ +_divmod_example_SERIES = f"""{_common_examples_algebra_SERIES} >>> a.divmod(b, fill_value=0) (a 1.0 b NaN @@ -181,11 +164,8 @@ def make_flex_doc(op_name: str, typ: str) -> str: e NaN dtype: float64) """ -) -_mod_example_SERIES = ( - _common_examples_algebra_SERIES - + """ +_mod_example_SERIES = f"""{_common_examples_algebra_SERIES} >>> a.mod(b, fill_value=0) a 0.0 b NaN @@ -194,10 +174,7 @@ def make_flex_doc(op_name: str, typ: str) -> str: e NaN dtype: float64 """ -) -_pow_example_SERIES = ( - _common_examples_algebra_SERIES - + """ +_pow_example_SERIES = f"""{_common_examples_algebra_SERIES} >>> a.pow(b, fill_value=0) a 1.0 b 1.0 @@ -206,11 +183,8 @@ def make_flex_doc(op_name: str, typ: str) -> str: e NaN dtype: float64 """ -) -_ne_example_SERIES = ( - _common_examples_algebra_SERIES - + """ +_ne_example_SERIES = f"""{_common_examples_algebra_SERIES} >>> a.ne(b, fill_value=0) a False b True @@ -219,11 +193,8 @@ def make_flex_doc(op_name: str, typ: str) -> str: e True dtype: bool """ -) -_eq_example_SERIES = ( - _common_examples_algebra_SERIES - + """ +_eq_example_SERIES = f"""{_common_examples_algebra_SERIES} >>> a.eq(b, fill_value=0) a True b False @@ -232,11 +203,8 @@ def make_flex_doc(op_name: str, typ: str) -> str: e False dtype: bool """ -) -_lt_example_SERIES = ( - _common_examples_comparison_SERIES - + """ +_lt_example_SERIES = f"""{_common_examples_comparison_SERIES} >>> a.lt(b, fill_value=0) a False b False @@ -246,11 +214,8 @@ def make_flex_doc(op_name: str, typ: str) -> str: f True dtype: bool """ -) -_le_example_SERIES = ( - _common_examples_comparison_SERIES - + """ +_le_example_SERIES = f"""{_common_examples_comparison_SERIES} >>> a.le(b, fill_value=0) a False b True @@ -260,11 +225,8 @@ def make_flex_doc(op_name: str, typ: str) -> str: f True dtype: bool """ -) -_gt_example_SERIES = ( - _common_examples_comparison_SERIES - + """ +_gt_example_SERIES = f"""{_common_examples_comparison_SERIES} >>> a.gt(b, fill_value=0) a True b False @@ -274,11 +236,8 @@ def make_flex_doc(op_name: str, typ: str) -> str: f False dtype: bool """ -) -_ge_example_SERIES = ( - _common_examples_comparison_SERIES - + """ +_ge_example_SERIES = f"""{_common_examples_comparison_SERIES} >>> a.ge(b, fill_value=0) a True b True @@ -288,7 +247,6 @@ def make_flex_doc(op_name: str, typ: str) -> str: f False dtype: bool """ -) _returns_series = """Series\n The result of the operation.""" diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 4a5c4b908dd7c..1a0096364d20a 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -2452,7 +2452,7 @@ def set_table_styles( table_styles = [ { - "selector": str(s["selector"]) + idf + str(idx), + "selector": f"{s['selector']}{idf}{idx}", "props": maybe_convert_css_to_tuples(s["props"]), } for key, styles in table_styles.items() diff --git a/pandas/io/sql.py b/pandas/io/sql.py index 8bcee36cbef2b..9c86e8f45eb4d 100644 --- a/pandas/io/sql.py +++ b/pandas/io/sql.py @@ -1350,7 +1350,7 @@ def get_engine(engine: str) -> BaseEngine: try: return engine_class() except ImportError as err: - error_msgs += "\n - " + str(err) + error_msgs += f"\n - {err}" raise ImportError( "Unable to find a usable engine; " @@ -1911,7 +1911,7 @@ def _create_table_setup(self): escape = _get_valid_sqlite_name create_tbl_stmts = [ - escape(cname) + " " + ctype for cname, ctype, _ in column_names_and_types + f"{escape(cname)} {ctype}" for cname, ctype, _ in column_names_and_types ] if self.keys is not None and len(self.keys): @@ -1924,30 +1924,22 @@ def _create_table_setup(self): f"CONSTRAINT {self.name}_pk PRIMARY KEY ({cnames_br})" ) if self.schema: - schema_name = self.schema + "." + schema_name = f"{self.schema}." else: schema_name = "" + create_tbl_stmts_str = ",\n ".join(create_tbl_stmts) create_stmts = [ - "CREATE TABLE " - + schema_name - + escape(self.name) - + " (\n" - + ",\n ".join(create_tbl_stmts) - + "\n)" + f"CREATE TABLE {schema_name}{escape(self.name)} " + f"(\n{create_tbl_stmts_str}\n)" ] ix_cols = [cname for cname, _, is_index in column_names_and_types if is_index] if len(ix_cols): cnames = "_".join(ix_cols) cnames_br = ",".join([escape(c) for c in ix_cols]) + ix_name = f"ix_{self.name}_{cnames}" create_stmts.append( - "CREATE INDEX " - + escape("ix_" + self.name + "_" + cnames) - + "ON " - + escape(self.name) - + " (" - + cnames_br - + ")" + f"CREATE INDEX {escape(ix_name)} ON {escape(self.name)} ({cnames_br})" ) return create_stmts diff --git a/pandas/io/stata.py b/pandas/io/stata.py index 5860aa4ae7c3e..a62bc65659065 100644 --- a/pandas/io/stata.py +++ b/pandas/io/stata.py @@ -864,7 +864,7 @@ class StataMissingValue: # Conversion to long to avoid hash issues on 32 bit platforms #8968 MISSING_VALUES[b] = "." for i in range(1, 27): - MISSING_VALUES[i + b] = "." + chr(96 + i) + MISSING_VALUES[i + b] = f".{chr(96 + i)}" float32_base: bytes = b"\x00\x00\x00\x7f" increment: int = struct.unpack(" None: # with a label, but the underlying variable is -127 to 100 # we're going to drop the label and cast to int self.DTYPE_MAP = dict( - list(zip(range(1, 245), [np.dtype("a" + str(i)) for i in range(1, 245)])) + list(zip(range(1, 245), [np.dtype(f"a{i}") for i in range(1, 245)])) + [ (251, np.dtype(np.int8)), (252, np.dtype(np.int16)), @@ -1502,9 +1502,9 @@ def _setup_dtype(self) -> np.dtype: for i, typ in enumerate(self.typlist): if typ in self.NUMPY_TYPE_MAP: typ = cast(str, typ) # only strs in NUMPY_TYPE_MAP - dtypes.append(("s" + str(i), self.byteorder + self.NUMPY_TYPE_MAP[typ])) + dtypes.append((f"s{i}", self.byteorder + self.NUMPY_TYPE_MAP[typ])) else: - dtypes.append(("s" + str(i), "S" + str(typ))) + dtypes.append((f"s{i}", f"S{typ}")) self._dtype = np.dtype(dtypes) return self._dtype @@ -2092,7 +2092,7 @@ def _maybe_convert_to_int_keys(convert_dates: dict, varlist: list[Hashable]) -> new_dict = {} for key in convert_dates: if not convert_dates[key].startswith("%"): # make sure proper fmts - convert_dates[key] = "%" + convert_dates[key] + convert_dates[key] = f"%{convert_dates[key]}" if key in varlist: new_dict.update({varlist.index(key): convert_dates[key]}) else: @@ -2170,7 +2170,7 @@ def _dtype_to_default_stata_fmt( return "%9s" else: raise ValueError(excessive_string_length_error.format(column.name)) - return "%" + str(max(itemsize, 1)) + "s" + return f"%{max(itemsize, 1)}s" elif dtype == np.float64: return "%10.0g" elif dtype == np.float32: @@ -2475,11 +2475,11 @@ def _check_column_names(self, data: DataFrame) -> DataFrame: # Variable name must not be a reserved word if name in self.RESERVED_WORDS: - name = "_" + name + name = f"_{name}" # Variable name may not start with a number if "0" <= name[0] <= "9": - name = "_" + name + name = f"_{name}" name = name[: min(len(name), 32)] @@ -2487,7 +2487,7 @@ def _check_column_names(self, data: DataFrame) -> DataFrame: # check for duplicates while columns.count(name) > 0: # prepend ascending number to avoid duplicates - name = "_" + str(duplicate_var_id) + name + name = f"_{duplicate_var_id}{name}" name = name[: min(len(name), 32)] duplicate_var_id += 1 converted_names[orig_name] = name @@ -3244,7 +3244,7 @@ def _tag(val: str | bytes, tag: str) -> bytes: """Surround val with """ if isinstance(val, str): val = bytes(val, "utf-8") - return bytes("<" + tag + ">", "utf-8") + val + bytes("", "utf-8") + return bytes(f"<{tag}>", "utf-8") + val + bytes(f"", "utf-8") def _update_map(self, tag: str) -> None: """Update map location for tag with file position""" From 2e91643736617f2e81e67b89675513808fe203f0 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 27 Oct 2022 18:59:42 +0300 Subject: [PATCH 5/5] CLN: replace joins on static arguments with f-strings --- pandas/core/apply.py | 2 +- pandas/core/window/doc.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/apply.py b/pandas/core/apply.py index e8078dd4a28a4..81169a8a476e9 100644 --- a/pandas/core/apply.py +++ b/pandas/core/apply.py @@ -1287,7 +1287,7 @@ def _make_unique_kwarg_list( [('a', '_0'), ('a', '_1'), ('b', '')] """ return [ - (pair[0], "_".join([pair[1], str(seq[:i].count(pair))])) + (pair[0], f"{pair[1]}_{seq[:i].count(pair)}") if seq.count(pair) > 1 else pair for i, pair in enumerate(seq) diff --git a/pandas/core/window/doc.py b/pandas/core/window/doc.py index 835085d41cffa..950bc047a692a 100644 --- a/pandas/core/window/doc.py +++ b/pandas/core/window/doc.py @@ -10,7 +10,7 @@ def create_section_header(header: str) -> str: """Create numpydoc section header""" - return "\n".join((header, "-" * len(header))) + "\n" + return f"{header}\n{'-' * len(header)}\n" template_header = "\nCalculate the {window_method} {aggregation_description}.\n\n"