From 721095b25a1c7519f509099f8fefb69ce643fb7f Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Wed, 18 Sep 2019 06:54:11 -0700 Subject: [PATCH 1/6] checkpoint --- pandas/core/arrays/datetimes.py | 3 +++ pandas/core/dtypes/cast.py | 3 +++ pandas/core/indexes/base.py | 4 +++- pandas/core/indexes/datetimelike.py | 2 +- pandas/core/indexes/period.py | 4 ++++ pandas/core/indexes/timedeltas.py | 4 ++++ pandas/tests/arrays/test_datetimes.py | 5 +++++ pandas/tseries/frequencies.py | 9 +++++++++ 8 files changed, 32 insertions(+), 2 deletions(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 5dff1f93264c3..65bf7f1ceaa5c 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -1918,6 +1918,9 @@ def sequence_to_dt64ns( tz = validate_tz_from_dtype(dtype, tz) if isinstance(data, ABCIndexClass): + if data.nlevels > 1: + # MultiIndex + raise TypeError("Cannot create a DatetimeArray from a MultiIndex.") data = data._data # By this point we are assured to have either a numpy array or Index diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index ac9b57dc8d342..6e62ab534fecb 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -797,6 +797,7 @@ def maybe_convert_objects(values: np.ndarray, convert_numeric: bool = True): values, set(), coerce_numeric=True ) except Exception: + raise pass else: # if we are all nans then leave me alone @@ -876,6 +877,7 @@ def soft_convert_objects( try: converted = lib.maybe_convert_numeric(values, set(), coerce_numeric=True) except Exception: + raise pass else: # If all NaNs, then do not-alter @@ -963,6 +965,7 @@ def try_datetime(v): pass except Exception: + raise pass return v.reshape(shape) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index f3ee6450cc3bc..8f25004190679 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3136,6 +3136,7 @@ def is_int(v): try: indexer = self.slice_indexer(start, stop, step, kind=kind) except Exception: + raise if is_index_slice: if self.is_integer(): raise @@ -4328,7 +4329,8 @@ def equals(self, other): return array_equivalent( com.values_from_object(self), com.values_from_object(other) ) - except Exception: + except TypeError: + # FIXME: array_equivalent can raise TypeError for tzawareness_compat return False def identical(self, other): diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index c7664d9777c71..603972186e9ce 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -192,7 +192,7 @@ def equals(self, other): elif not isinstance(other, type(self)): try: other = type(self)(other) - except Exception: + except (ValueError, TypeError): return False if not is_dtype_equal(self.dtype, other.dtype): diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index ee85b0fb91acb..69d88042364cc 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -457,7 +457,10 @@ def __contains__(self, key): try: self.get_loc(key) return True + except KeyError: + return False except Exception: + raise return False @cache_readonly @@ -766,6 +769,7 @@ def _maybe_cast_slice_bound(self, label, side, kind): bounds = self._parsed_string_to_bounds(reso, parsed) return bounds[0 if side == "left" else 1] except Exception: + raise raise KeyError(label) elif is_integer(label) or is_float(label): self._invalid_indexer("slice", label) diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index b03d60c7b5b37..3a94a171d412f 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -626,7 +626,11 @@ def insert(self, loc, item): if _is_convertible_to_td(item): try: item = Timedelta(item) + except ValueError: + # str that cant be parsed + pass except Exception: + raise pass elif is_scalar(item) and isna(item): # GH 18295 diff --git a/pandas/tests/arrays/test_datetimes.py b/pandas/tests/arrays/test_datetimes.py index d749d9bb47d25..c3cda22497ecb 100644 --- a/pandas/tests/arrays/test_datetimes.py +++ b/pandas/tests/arrays/test_datetimes.py @@ -15,6 +15,11 @@ class TestDatetimeArrayConstructor: + def test_from_sequence_invalid_type(self): + mi = pd.MultiIndex.from_product([np.arange(5), np.arange(5)]) + with pytest.raises(TypeError, match="Cannot create a DatetimeArray"): + DatetimeArray._from_sequence(mi) + def test_only_1dim_accepted(self): arr = np.array([0, 1, 2, 3], dtype="M8[h]").astype("M8[ns]") diff --git a/pandas/tseries/frequencies.py b/pandas/tseries/frequencies.py index dfe91b514bbe1..4b7ce2d15a4b7 100644 --- a/pandas/tseries/frequencies.py +++ b/pandas/tseries/frequencies.py @@ -138,7 +138,11 @@ def to_offset(freq): delta = offset else: delta = delta + offset + except ValueError: + raise ValueError(libfreqs.INVALID_FREQ_ERR_MSG.format(freq)) + except Exception: + raise raise ValueError(libfreqs.INVALID_FREQ_ERR_MSG.format(freq)) else: @@ -170,7 +174,12 @@ def to_offset(freq): delta = offset else: delta = delta + offset + except (ValueError, TypeError, AttributeError): + # AttributeError is raised e.g. when trying to add 1W+1D and it + # finds Day has no "weekday" attribute + raise ValueError(libfreqs.INVALID_FREQ_ERR_MSG.format(freq)) except Exception: + raise raise ValueError(libfreqs.INVALID_FREQ_ERR_MSG.format(freq)) if delta is None: From 5b7d1fb6d3abfaa2ea9ec5f83a19c263cb45f3f1 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 19 Sep 2019 07:54:23 -0700 Subject: [PATCH 2/6] revert --- pandas/core/dtypes/cast.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index 6e62ab534fecb..ac9b57dc8d342 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -797,7 +797,6 @@ def maybe_convert_objects(values: np.ndarray, convert_numeric: bool = True): values, set(), coerce_numeric=True ) except Exception: - raise pass else: # if we are all nans then leave me alone @@ -877,7 +876,6 @@ def soft_convert_objects( try: converted = lib.maybe_convert_numeric(values, set(), coerce_numeric=True) except Exception: - raise pass else: # If all NaNs, then do not-alter @@ -965,7 +963,6 @@ def try_datetime(v): pass except Exception: - raise pass return v.reshape(shape) From fc1bf899aff8c0d9326afc5b7b5743b41fc97f45 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 19 Sep 2019 07:58:15 -0700 Subject: [PATCH 3/6] BUG: Week+Day raising wrong exception --- pandas/tests/tseries/offsets/test_offsets.py | 9 +++++++++ pandas/tseries/frequencies.py | 7 +------ pandas/tseries/offsets.py | 9 ++++++++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/pandas/tests/tseries/offsets/test_offsets.py b/pandas/tests/tseries/offsets/test_offsets.py index 3ed25b8d3edd5..ddf2c6e65b474 100644 --- a/pandas/tests/tseries/offsets/test_offsets.py +++ b/pandas/tests/tseries/offsets/test_offsets.py @@ -4348,3 +4348,12 @@ def test_last_week_of_month_on_offset(): slow = (ts + offset) - offset == ts fast = offset.onOffset(ts) assert fast == slow + + +def test_week_add_invalid(): + # Week with weekday should raise TypeError and _not_ AttributeError + # when adding invalid offset + offset = Week(weekday=1) + other = Day() + with pytest.raises(TypeError, match="Cannot add"): + offset + other diff --git a/pandas/tseries/frequencies.py b/pandas/tseries/frequencies.py index 4b7ce2d15a4b7..b7f352e67e119 100644 --- a/pandas/tseries/frequencies.py +++ b/pandas/tseries/frequencies.py @@ -174,12 +174,7 @@ def to_offset(freq): delta = offset else: delta = delta + offset - except (ValueError, TypeError, AttributeError): - # AttributeError is raised e.g. when trying to add 1W+1D and it - # finds Day has no "weekday" attribute - raise ValueError(libfreqs.INVALID_FREQ_ERR_MSG.format(freq)) - except Exception: - raise + except (ValueError, TypeError): raise ValueError(libfreqs.INVALID_FREQ_ERR_MSG.format(freq)) if delta is None: diff --git a/pandas/tseries/offsets.py b/pandas/tseries/offsets.py index edf58ba3850a1..82cbfa831bf32 100644 --- a/pandas/tseries/offsets.py +++ b/pandas/tseries/offsets.py @@ -605,7 +605,7 @@ def apply(self, other): return BDay(self.n, offset=self.offset + other, normalize=self.normalize) else: raise ApplyTypeError( - "Only know how to combine business day with " "datetime or timedelta." + "Only know how to combine business day with datetime or timedelta." ) @apply_index_wraps @@ -1545,6 +1545,13 @@ def apply(self, other): if self.weekday is None: return other + self.n * self._inc + if not isinstance(other, datetime): + raise TypeError( + "Cannot add {typ} to {cls}".format( + typ=type(other).__name__, cls=type(self).__name__ + ) + ) + k = self.n otherDay = other.weekday() if otherDay != self.weekday: From 7aae29df4cc04a7cdceb3ea4530a2dbdf3672810 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 19 Sep 2019 08:00:38 -0700 Subject: [PATCH 4/6] cleanup --- pandas/tseries/frequencies.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pandas/tseries/frequencies.py b/pandas/tseries/frequencies.py index b7f352e67e119..4491e6ad9ac7e 100644 --- a/pandas/tseries/frequencies.py +++ b/pandas/tseries/frequencies.py @@ -141,10 +141,6 @@ def to_offset(freq): except ValueError: raise ValueError(libfreqs.INVALID_FREQ_ERR_MSG.format(freq)) - except Exception: - raise - raise ValueError(libfreqs.INVALID_FREQ_ERR_MSG.format(freq)) - else: delta = None stride_sign = None From ab9134f56ff102f5415c0bb62571e03c5e25ada7 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 19 Sep 2019 08:06:57 -0700 Subject: [PATCH 5/6] revert --- pandas/core/arrays/datetimes.py | 3 --- pandas/core/indexes/base.py | 4 +--- pandas/core/indexes/datetimelike.py | 2 +- pandas/core/indexes/period.py | 4 ---- pandas/core/indexes/timedeltas.py | 4 ---- pandas/tests/arrays/test_datetimes.py | 5 ----- 6 files changed, 2 insertions(+), 20 deletions(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 65bf7f1ceaa5c..5dff1f93264c3 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -1918,9 +1918,6 @@ def sequence_to_dt64ns( tz = validate_tz_from_dtype(dtype, tz) if isinstance(data, ABCIndexClass): - if data.nlevels > 1: - # MultiIndex - raise TypeError("Cannot create a DatetimeArray from a MultiIndex.") data = data._data # By this point we are assured to have either a numpy array or Index diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 236556bdf268e..6ef9d78ff9e97 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3136,7 +3136,6 @@ def is_int(v): try: indexer = self.slice_indexer(start, stop, step, kind=kind) except Exception: - raise if is_index_slice: if self.is_integer(): raise @@ -4329,8 +4328,7 @@ def equals(self, other): return array_equivalent( com.values_from_object(self), com.values_from_object(other) ) - except TypeError: - # FIXME: array_equivalent can raise TypeError for tzawareness_compat + except Exception: return False def identical(self, other): diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index 603972186e9ce..c7664d9777c71 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -192,7 +192,7 @@ def equals(self, other): elif not isinstance(other, type(self)): try: other = type(self)(other) - except (ValueError, TypeError): + except Exception: return False if not is_dtype_equal(self.dtype, other.dtype): diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index 69d88042364cc..ee85b0fb91acb 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -457,10 +457,7 @@ def __contains__(self, key): try: self.get_loc(key) return True - except KeyError: - return False except Exception: - raise return False @cache_readonly @@ -769,7 +766,6 @@ def _maybe_cast_slice_bound(self, label, side, kind): bounds = self._parsed_string_to_bounds(reso, parsed) return bounds[0 if side == "left" else 1] except Exception: - raise raise KeyError(label) elif is_integer(label) or is_float(label): self._invalid_indexer("slice", label) diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index 3a94a171d412f..b03d60c7b5b37 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -626,11 +626,7 @@ def insert(self, loc, item): if _is_convertible_to_td(item): try: item = Timedelta(item) - except ValueError: - # str that cant be parsed - pass except Exception: - raise pass elif is_scalar(item) and isna(item): # GH 18295 diff --git a/pandas/tests/arrays/test_datetimes.py b/pandas/tests/arrays/test_datetimes.py index c3cda22497ecb..d749d9bb47d25 100644 --- a/pandas/tests/arrays/test_datetimes.py +++ b/pandas/tests/arrays/test_datetimes.py @@ -15,11 +15,6 @@ class TestDatetimeArrayConstructor: - def test_from_sequence_invalid_type(self): - mi = pd.MultiIndex.from_product([np.arange(5), np.arange(5)]) - with pytest.raises(TypeError, match="Cannot create a DatetimeArray"): - DatetimeArray._from_sequence(mi) - def test_only_1dim_accepted(self): arr = np.array([0, 1, 2, 3], dtype="M8[h]").astype("M8[ns]") From 457318cc5a708026e8d2b78845954628ad97bad9 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 19 Sep 2019 08:21:54 -0700 Subject: [PATCH 6/6] whatsnew --- doc/source/whatsnew/v1.0.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.0.0.rst b/doc/source/whatsnew/v1.0.0.rst index a5af4e727391a..3beaa2dfa788a 100644 --- a/doc/source/whatsnew/v1.0.0.rst +++ b/doc/source/whatsnew/v1.0.0.rst @@ -147,7 +147,7 @@ Datetimelike - Bug in :class:`Timestamp` subtraction when subtracting a :class:`Timestamp` from a ``np.datetime64`` object incorrectly raising ``TypeError`` (:issue:`28286`) - Addition and subtraction of integer or integer-dtype arrays with :class:`Timestamp` will now raise ``NullFrequencyError`` instead of ``ValueError`` (:issue:`28268`) - Bug in :class:`Series` and :class:`DataFrame` with integer dtype failing to raise ``TypeError`` when adding or subtracting a ``np.datetime64`` object (:issue:`28080`) -- +- Bug in :class:`Week` with ``weekday`` incorrectly raising ``AttributeError`` instead of ``TypeError`` when adding or subtracting an invalid type (:issue:`28530`) Timedelta