From 877869a1c1d75e5da3d7c3cdf2caf2887cd82e18 Mon Sep 17 00:00:00 2001 From: tp Date: Wed, 27 Nov 2019 21:57:06 +0000 Subject: [PATCH 1/3] add f-strings to indexes.base.py --- pandas/core/indexes/base.py | 66 ++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 37 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 4a3fa26c3460e..89a5ceb525325 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -120,7 +120,7 @@ def cmp_method(self, other): return result return ops.invalid_comparison(self, other, op) - name = "__{name}__".format(name=op.__name__) + name = f"__{op.__name__}__" return set_function_name(cmp_method, name, cls) @@ -136,7 +136,7 @@ def index_arithmetic_method(self, other): return (Index(result[0]), Index(result[1])) return Index(result) - name = "__{name}__".format(name=op.__name__) + name = f"__{op.__name__}__" # TODO: docstring? return set_function_name(index_arithmetic_method, name, cls) @@ -768,8 +768,7 @@ def astype(self, dtype, copy=True): self.values.astype(dtype, copy=copy), name=self.name, dtype=dtype ) except (TypeError, ValueError): - msg = "Cannot cast {name} to dtype {dtype}" - raise TypeError(msg.format(name=type(self).__name__, dtype=dtype)) + raise TypeError(f"Cannot cast {type(self).__name__} to dtype {dtype}") _index_shared_docs[ "take" @@ -814,8 +813,10 @@ def take(self, indices, axis=0, allow_fill=True, fill_value=None, **kwargs): ) else: if allow_fill and fill_value is not None: - msg = "Unable to fill values because {0} cannot contain NA" - raise ValueError(msg.format(type(self).__name__)) + cls_name = self.__class__.__name__ + raise ValueError( + f"Unable to fill values because {cls_name} cannot contain NA" + ) taken = self.values.take(indices) return self._shallow_copy(taken) @@ -1287,7 +1288,7 @@ def _set_names(self, values, level=None): for name in values: if not is_hashable(name): raise TypeError( - "{}.name must be a hashable type".format(type(self).__name__) + f"{self.__class__.__name__}.name must be a hashable type" ) self.name = values[0] @@ -1456,13 +1457,11 @@ def _validate_index_level(self, level): ) elif level > 0: raise IndexError( - "Too many levels: Index has only 1 level, not %d" % (level + 1) + f"Too many levels: Index has only 1 level, not {level + 1}" ) elif level != self.name: raise KeyError( - "Requested level ({}) does not match index name ({})".format( - level, self.name - ) + f"Requested level ({level}) does not match index name ({self.name})" ) def _get_level_number(self, level): @@ -1558,9 +1557,8 @@ def droplevel(self, level=0): return self if len(level) >= self.nlevels: raise ValueError( - "Cannot remove {} levels from an index with {} " - "levels: at least one level must be " - "left.".format(len(level), self.nlevels) + f"Cannot remove {len(level)} levels from an index with {self.nlevels} " + "levels: at least one level must be left." ) # The two checks above guarantee that here self is a MultiIndex @@ -2014,7 +2012,7 @@ def fillna(self, value=None, downcast=None): @Appender(_index_shared_docs["dropna"]) def dropna(self, how="any"): if how not in ("any", "all"): - raise ValueError("invalid how option: {0}".format(how)) + raise ValueError(f"invalid how option: {how}") if self.hasnans: return self._shallow_copy(self.values[~self._isnan]) @@ -2288,10 +2286,8 @@ def __xor__(self, other): def __nonzero__(self): raise ValueError( - "The truth value of a {0} is ambiguous. " - "Use a.empty, a.bool(), a.item(), a.any() or a.all().".format( - type(self).__name__ - ) + f"The truth value of a {self.__class__.__name__} is ambiguous. " + "Use a.empty, a.bool(), a.item(), a.any() or a.all()." ) __bool__ = __nonzero__ @@ -2354,7 +2350,7 @@ def _validate_sort_keyword(self, sort): if sort not in [None, False]: raise ValueError( "The 'sort' keyword only takes the values of " - "None or False; {0} was passed.".format(sort) + f"None or False; {sort} was passed." ) def union(self, other, sort=None): @@ -2481,10 +2477,9 @@ def _union(self, other, sort): if sort is None: try: result = algos.safe_sort(result) - except TypeError as e: + except TypeError as err: warnings.warn( - "{}, sort order is undefined for " - "incomparable objects".format(e), + f"{err}, sort order is undefined for incomparable objects", RuntimeWarning, stacklevel=3, ) @@ -2939,8 +2934,8 @@ def _get_fill_indexer_searchsorted(self, target, method, limit=None): """ if limit is not None: raise ValueError( - "limit argument for %r method only well-defined " - "if index and target are monotonic" % method + f"limit argument for {method!r} method only well-defined " + "if index and target are monotonic" ) side = "left" if method == "pad" else "right" @@ -3227,10 +3222,8 @@ def _invalid_indexer(self, form, key): Consistent invalid indexer message. """ raise TypeError( - "cannot do {form} indexing on {klass} with these " - "indexers [{key}] of {kind}".format( - form=form, klass=type(self), key=key, kind=type(key) - ) + f"cannot do {form} indexing on {type(self)} with these " + f"indexers [{key}] of {type(key)}" ) # -------------------------------------------------------------------- @@ -3992,8 +3985,8 @@ def _scalar_data_error(cls, data): # We return the TypeError so that we can raise it from the constructor # in order to keep mypy happy return TypeError( - "{0}(...) must be called with a collection of some " - "kind, {1} was passed".format(cls.__name__, repr(data)) + f"{cls.__name__}(...) must be called with a collection of some " + f"kind, {data!r} was passed" ) @classmethod @@ -4037,8 +4030,7 @@ def _assert_can_do_op(self, value): Check value is valid for scalar op. """ if not is_scalar(value): - msg = "'value' must be a scalar, passed: {0}" - raise TypeError(msg.format(type(value).__name__)) + raise TypeError(f"'value' must be a scalar, passed: {type(value).__name__}") def _is_memory_usage_qualified(self) -> bool: """ @@ -4113,7 +4105,7 @@ def contains(self, key) -> bool: return key in self def __hash__(self): - raise TypeError("unhashable type: %r" % type(self).__name__) + raise TypeError(f"unhashable type: {type(self).__name__!r}") def __setitem__(self, key, value): raise TypeError("Index does not support mutable operations") @@ -5052,8 +5044,8 @@ def get_slice_bound(self, label, side, kind): slc = lib.maybe_indices_to_slice(slc.astype("i8"), len(self)) if isinstance(slc, np.ndarray): raise KeyError( - "Cannot get %s slice bound for non-unique " - "label: %r" % (side, original_label) + f"Cannot get {side} slice bound for non-unique " + f"label: {original_label!r}" ) if isinstance(slc, slice): @@ -5211,7 +5203,7 @@ def drop(self, labels, errors="raise"): mask = indexer == -1 if mask.any(): if errors != "ignore": - raise KeyError("{} not found in axis".format(labels[mask])) + raise KeyError(f"{labels[mask]} not found in axis") indexer = indexer[~mask] return self.delete(indexer) From e0ea38ddd09910e8579fe6f2509e2ef3dfe5107d Mon Sep 17 00:00:00 2001 From: tp Date: Wed, 27 Nov 2019 22:48:08 +0000 Subject: [PATCH 2/3] renamed self.__class__ to type(self) --- pandas/core/indexes/base.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 89a5ceb525325..c57a5a03f1058 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -813,7 +813,7 @@ def take(self, indices, axis=0, allow_fill=True, fill_value=None, **kwargs): ) else: if allow_fill and fill_value is not None: - cls_name = self.__class__.__name__ + cls_name = type(self).__name__ raise ValueError( f"Unable to fill values because {cls_name} cannot contain NA" ) @@ -1287,9 +1287,7 @@ def _set_names(self, values, level=None): # All items in 'name' need to be hashable: for name in values: if not is_hashable(name): - raise TypeError( - f"{self.__class__.__name__}.name must be a hashable type" - ) + raise TypeError(f"{type(self).__name__}.name must be a hashable type") self.name = values[0] names = property(fset=_set_names, fget=_get_names) @@ -2286,7 +2284,7 @@ def __xor__(self, other): def __nonzero__(self): raise ValueError( - f"The truth value of a {self.__class__.__name__} is ambiguous. " + f"The truth value of a {type(self).__name__} is ambiguous. " "Use a.empty, a.bool(), a.item(), a.any() or a.all()." ) From 38d9d691832a0fe10b388c8f000d3adf19433287 Mon Sep 17 00:00:00 2001 From: tp Date: Sat, 30 Nov 2019 09:36:59 +0000 Subject: [PATCH 3/3] use repr --- pandas/core/indexes/base.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index c57a5a03f1058..aa2326eeab8fa 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -441,7 +441,7 @@ def __new__( except IncompatibleFrequency: pass if kwargs: - raise TypeError(f"Unexpected keyword arguments {set(kwargs)!r}") + raise TypeError(f"Unexpected keyword arguments {repr(set(kwargs))}") return cls._simple_new(subarr, name, **kwargs) elif hasattr(data, "__array__"): @@ -2932,7 +2932,7 @@ def _get_fill_indexer_searchsorted(self, target, method, limit=None): """ if limit is not None: raise ValueError( - f"limit argument for {method!r} method only well-defined " + f"limit argument for {repr(method)} method only well-defined " "if index and target are monotonic" ) @@ -3984,7 +3984,7 @@ def _scalar_data_error(cls, data): # in order to keep mypy happy return TypeError( f"{cls.__name__}(...) must be called with a collection of some " - f"kind, {data!r} was passed" + f"kind, {repr(data)} was passed" ) @classmethod @@ -4103,7 +4103,7 @@ def contains(self, key) -> bool: return key in self def __hash__(self): - raise TypeError(f"unhashable type: {type(self).__name__!r}") + raise TypeError(f"unhashable type: {repr(type(self).__name__)}") def __setitem__(self, key, value): raise TypeError("Index does not support mutable operations") @@ -5043,7 +5043,7 @@ def get_slice_bound(self, label, side, kind): if isinstance(slc, np.ndarray): raise KeyError( f"Cannot get {side} slice bound for non-unique " - f"label: {original_label!r}" + f"label: {repr(original_label)}" ) if isinstance(slc, slice):