Skip to content

format replaced with f-strings #29701

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions pandas/core/groupby/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,7 @@ def _aggregate_multiple_funcs(self, arg, _level):
obj = self
if name in results:
raise SpecificationError(
"Function names must be unique, found multiple named "
"{name}".format(name=name)
f"Function names must be unique, found multiple named {name}"
)

# reset the cache so that we
Expand Down Expand Up @@ -528,7 +527,7 @@ def nunique(self, dropna: bool = True) -> Series:
try:
sorter = np.lexsort((val, ids))
except TypeError: # catches object dtypes
msg = "val.dtype must be object, got {}".format(val.dtype)
msg = f"val.dtype must be object, got {val.dtype}"
assert val.dtype == object, msg
val, _ = algorithms.factorize(val, sort=False)
sorter = np.lexsort((val, ids))
Expand Down Expand Up @@ -1502,8 +1501,8 @@ def filter(self, func, dropna=True, *args, **kwargs):
else:
# non scalars aren't allowed
raise TypeError(
"filter function returned a {typ}, "
"but expected a scalar bool".format(typ=type(res).__name__)
f"filter function returned a {type(res).__name__}, "
"but expected a scalar bool"
)

return self._apply_filter(indices, dropna)
Expand Down Expand Up @@ -1865,7 +1864,7 @@ def _managle_lambda_list(aggfuncs: Sequence[Any]) -> Sequence[Any]:
for aggfunc in aggfuncs:
if com.get_callable_name(aggfunc) == "<lambda>":
aggfunc = partial(aggfunc)
aggfunc.__name__ = "<lambda_{}>".format(i)
aggfunc.__name__ = f"<lambda_{i}>"
i += 1
mangled_aggfuncs.append(aggfunc)

Expand Down
8 changes: 3 additions & 5 deletions pandas/core/groupby/groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -556,9 +556,7 @@ def __getattr__(self, attr):
return self[attr]

raise AttributeError(
"'{typ}' object has no attribute '{attr}'".format(
typ=type(self).__name__, attr=attr
)
f"'{type(self).__name__}' object has no attribute '{attr}'"
)

@Substitution(
Expand Down Expand Up @@ -1751,7 +1749,7 @@ def nth(self, n: Union[int, List[int]], dropna: Optional[str] = None) -> DataFra
raise ValueError(
"For a DataFrame groupby, dropna must be "
"either None, 'any' or 'all', "
"(was passed {dropna}).".format(dropna=dropna)
f"(was passed {dropna})."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@datapythonista do we have a preferred usage for cases where this line needs the "f" and the preceeding does not? I could imagine we might want to put the "f" on all of them anyway

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is correct - should just keep it on lines where needed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @WillAyd, my preference is to just have the f were it's needed. Even in strings splitted in different lines.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As described in pep-498-concatenating-strings, regular strings are concatenated at compile time, and f-strings are concatenated at run time.

I think what we should not concatenate regular strings with f-strings because this could lead to unexpected results.

)

# old behaviour, but with all and any support for DataFrames.
Expand Down Expand Up @@ -2488,7 +2486,7 @@ def get_groupby(

klass = DataFrameGroupBy
else:
raise TypeError("invalid type: {obj}".format(obj=obj))
raise TypeError(f"invalid type: {obj}")

return klass(
obj=obj,
Expand Down
39 changes: 12 additions & 27 deletions pandas/core/groupby/grouper.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,7 @@ def _set_grouper(self, obj: FrameOrSeries, sort: bool = False):
ax = self._grouper.take(obj.index)
else:
if key not in obj._info_axis:
raise KeyError(
"The grouper name {key} is not found".format(key=key)
)
raise KeyError(f"The grouper name {key} is not found")
ax = Index(obj[key], name=key)

else:
Expand All @@ -191,9 +189,7 @@ def _set_grouper(self, obj: FrameOrSeries, sort: bool = False):

else:
if level not in (0, ax.name):
raise ValueError(
"The level {level} is not valid".format(level=level)
)
raise ValueError(f"The level {level} is not valid")

# possibly sort
if (self.sort or sort) and not ax.is_monotonic:
Expand All @@ -212,13 +208,13 @@ def groups(self):

def __repr__(self) -> str:
attrs_list = (
"{name}={val!r}".format(name=attr_name, val=getattr(self, attr_name))
f"{attr_name}={getattr(self, attr_name)!r}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you do this in two steps so as to not have the getattr inside the fstring

Copy link
Contributor Author

@lucassa3 lucassa3 Nov 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jbrockmendel Not really sure how to do this in two steps since attr_name is generated from a list comprehension. Do I just drop list comprehension usage in that case?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attr_tups = ((name, getatttr(self, name)) for name in self._attributes)
attr_tups = (x for x in attr_tups if x[1] is not None)
attrs_list = (f"{attr_name}={attr_val!r}" of attr_name, attr_val in attr_tups)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this usage seems ok to me

for attr_name in self._attributes
if getattr(self, attr_name) is not None
)
attrs = ", ".join(attrs_list)
cls_name = self.__class__.__name__
return "{cls}({attrs})".format(cls=cls_name, attrs=attrs)
return f"{cls_name}({attrs})"


class Grouping:
Expand Down Expand Up @@ -280,9 +276,7 @@ def __init__(
if level is not None:
if not isinstance(level, int):
if level not in index.names:
raise AssertionError(
"Level {level} not in index".format(level=level)
)
raise AssertionError(f"Level {level} not in index")
level = index.names.index(level)

if self.name is None:
Expand Down Expand Up @@ -350,17 +344,16 @@ def __init__(
):
if getattr(self.grouper, "ndim", 1) != 1:
t = self.name or str(type(self.grouper))
raise ValueError("Grouper for '{t}' not 1-dimensional".format(t=t))
raise ValueError(f"Grouper for '{t}' not 1-dimensional")
self.grouper = self.index.map(self.grouper)
if not (
hasattr(self.grouper, "__len__")
and len(self.grouper) == len(self.index)
):
grper = pprint_thing(self.grouper)
errmsg = (
"Grouper result violates len(labels) == "
"len(data)\nresult: {grper}".format(
grper=pprint_thing(self.grouper)
)
f"len(data)\nresult: {grper}"
)
self.grouper = None # Try for sanity
raise AssertionError(errmsg)
Expand All @@ -375,7 +368,7 @@ def __init__(
self.grouper = self.grouper.astype("timedelta64[ns]")

def __repr__(self) -> str:
return "Grouping({name})".format(name=self.name)
return f"Grouping({self.name})"

def __iter__(self):
return iter(self.indices)
Expand Down Expand Up @@ -500,11 +493,7 @@ def get_grouper(

if isinstance(level, str):
if obj.index.name != level:
raise ValueError(
"level name {level} is not the name of the index".format(
level=level
)
)
raise ValueError(f"level name {level} is not the name of the index")
elif level > 0 or level < -1:
raise ValueError("level > 0 or level < -1 only valid with MultiIndex")

Expand Down Expand Up @@ -636,12 +625,8 @@ def is_in_obj(gpr) -> bool:

if is_categorical_dtype(gpr) and len(gpr) != obj.shape[axis]:
raise ValueError(
(
"Length of grouper ({len_gpr}) and axis ({len_axis})"
" must be same length".format(
len_gpr=len(gpr), len_axis=obj.shape[axis]
)
)
f"Length of grouper ({len(gpr)}) and axis ({obj.shape[axis]})"
" must be same length"
)

# create the Grouping
Expand Down
12 changes: 4 additions & 8 deletions pandas/core/groupby/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,18 +445,16 @@ def _cython_operation(
# categoricals are only 1d, so we
# are not setup for dim transforming
if is_categorical_dtype(values) or is_sparse(values):
raise NotImplementedError(
"{dtype} dtype not supported".format(dtype=values.dtype)
)
raise NotImplementedError(f"{values.dtype} dtype not supported")
elif is_datetime64_any_dtype(values):
if how in ["add", "prod", "cumsum", "cumprod"]:
raise NotImplementedError(
"datetime64 type does not support {how} operations".format(how=how)
f"datetime64 type does not support {how} operations"
)
elif is_timedelta64_dtype(values):
if how in ["prod", "cumprod"]:
raise NotImplementedError(
"timedelta64 type does not support {how} operations".format(how=how)
f"timedelta64 type does not support {how} operations"
)

if is_datetime64tz_dtype(values.dtype):
Expand Down Expand Up @@ -509,9 +507,7 @@ def _cython_operation(
out_dtype = "float"
else:
if is_numeric:
out_dtype = "{kind}{itemsize}".format(
kind=values.dtype.kind, itemsize=values.dtype.itemsize
)
out_dtype = f"{values.dtype.kind}{values.dtype.itemsize}"
else:
out_dtype = "object"

Expand Down