From 6eb5c101a75b09eedf4ecd90b34b1fe31ce4675a Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Sat, 21 Mar 2020 20:45:43 +0700 Subject: [PATCH 1/2] fix bare pytest raises in indexes/datetimes --- .../indexes/datetimes/test_constructors.py | 24 +++++++----- .../indexes/datetimes/test_date_range.py | 22 ++++++----- .../tests/indexes/datetimes/test_indexing.py | 20 ++++++---- pandas/tests/indexes/datetimes/test_shift.py | 2 +- .../tests/indexes/datetimes/test_timezones.py | 39 ++++++++++++------- 5 files changed, 65 insertions(+), 42 deletions(-) diff --git a/pandas/tests/indexes/datetimes/test_constructors.py b/pandas/tests/indexes/datetimes/test_constructors.py index b293c008d6683..0247947ff19c5 100644 --- a/pandas/tests/indexes/datetimes/test_constructors.py +++ b/pandas/tests/indexes/datetimes/test_constructors.py @@ -415,7 +415,8 @@ def test_construction_dti_with_mixed_timezones(self): # tz mismatch affecting to tz-aware raises TypeError/ValueError - with pytest.raises(ValueError): + msg = "cannot be converted to datetime64" + with pytest.raises(ValueError, match=msg): DatetimeIndex( [ Timestamp("2011-01-01 10:00", tz="Asia/Tokyo"), @@ -424,7 +425,6 @@ def test_construction_dti_with_mixed_timezones(self): name="idx", ) - msg = "cannot be converted to datetime64" with pytest.raises(ValueError, match=msg): DatetimeIndex( [ @@ -435,7 +435,7 @@ def test_construction_dti_with_mixed_timezones(self): name="idx", ) - with pytest.raises(ValueError): + with pytest.raises(ValueError, match=msg): DatetimeIndex( [ Timestamp("2011-01-01 10:00", tz="Asia/Tokyo"), @@ -480,7 +480,8 @@ def test_construction_outofbounds(self): # coerces to object tm.assert_index_equal(Index(dates), exp) - with pytest.raises(OutOfBoundsDatetime): + msg = "Out of bounds nanosecond timestamp" + with pytest.raises(OutOfBoundsDatetime, match=msg): # can't create DatetimeIndex DatetimeIndex(dates) @@ -516,7 +517,8 @@ def test_constructor_coverage(self): with pytest.raises(TypeError, match=msg): date_range(start="1/1/2000", periods="foo", freq="D") - with pytest.raises(TypeError): + msg = "DatetimeIndex\\(\\) must be called with a collection" + with pytest.raises(TypeError, match=msg): DatetimeIndex("1/1/2000") # generator expression @@ -664,7 +666,8 @@ def test_constructor_dtype(self): @pytest.mark.parametrize("dtype", [object, np.int32, np.int64]) def test_constructor_invalid_dtype_raises(self, dtype): # GH 23986 - with pytest.raises(ValueError): + msg = "Unexpected value for 'dtype'" + with pytest.raises(ValueError, match=msg): DatetimeIndex([1, 2], dtype=dtype) def test_constructor_name(self): @@ -681,7 +684,8 @@ def test_000constructor_resolution(self): def test_disallow_setting_tz(self): # GH 3746 dti = DatetimeIndex(["2010"], tz="UTC") - with pytest.raises(AttributeError): + msg = "Cannot directly set timezone" + with pytest.raises(AttributeError, match=msg): dti.tz = pytz.timezone("US/Pacific") @pytest.mark.parametrize( @@ -770,7 +774,8 @@ def test_construction_from_replaced_timestamps_with_dst(self): def test_construction_with_tz_and_tz_aware_dti(self): # GH 23579 dti = date_range("2016-01-01", periods=3, tz="US/Central") - with pytest.raises(TypeError): + msg = "data is already tz-aware US/Central, unable to set specified tz" + with pytest.raises(TypeError, match=msg): DatetimeIndex(dti, tz="Asia/Tokyo") def test_construction_with_nat_and_tzlocal(self): @@ -790,7 +795,8 @@ def test_constructor_no_precision_raises(self): pd.Index(["2000"], dtype="datetime64") def test_constructor_wrong_precision_raises(self): - with pytest.raises(ValueError): + msg = "Unexpected value for 'dtype': 'datetime64\\[us\\]'" + with pytest.raises(ValueError, match=msg): pd.DatetimeIndex(["2000"], dtype="datetime64[us]") def test_index_constructor_with_numpy_object_array_and_timestamp_tz_with_nan(self): diff --git a/pandas/tests/indexes/datetimes/test_date_range.py b/pandas/tests/indexes/datetimes/test_date_range.py index d33351fe94a8c..9bcd1839662e5 100644 --- a/pandas/tests/indexes/datetimes/test_date_range.py +++ b/pandas/tests/indexes/datetimes/test_date_range.py @@ -153,9 +153,10 @@ def test_date_range_int64_overflow_stride_endpoint_different_signs(self): def test_date_range_out_of_bounds(self): # GH#14187 - with pytest.raises(OutOfBoundsDatetime): + msg = "Cannot generate range" + with pytest.raises(OutOfBoundsDatetime, match=msg): date_range("2016-01-01", periods=100000, freq="D") - with pytest.raises(OutOfBoundsDatetime): + with pytest.raises(OutOfBoundsDatetime, match=msg): date_range(end="1763-10-12", periods=100000, freq="D") def test_date_range_gen_error(self): @@ -736,9 +737,10 @@ def test_precision_finer_than_offset(self): ) def test_mismatching_tz_raises_err(self, start, end): # issue 18488 - with pytest.raises(TypeError): + msg = "Start and end cannot both be tz-aware with different timezones" + with pytest.raises(TypeError, match=msg): pd.date_range(start, end) - with pytest.raises(TypeError): + with pytest.raises(TypeError, match=msg): pd.date_range(start, end, freq=BDay()) @@ -771,16 +773,17 @@ def test_misc(self): def test_date_parse_failure(self): badly_formed_date = "2007/100/1" - with pytest.raises(ValueError): + msg = "could not convert string to Timestamp" + with pytest.raises(ValueError, match=msg): Timestamp(badly_formed_date) - with pytest.raises(ValueError): + with pytest.raises(ValueError, match=msg): bdate_range(start=badly_formed_date, periods=10) - with pytest.raises(ValueError): + with pytest.raises(ValueError, match=msg): bdate_range(end=badly_formed_date, periods=10) - with pytest.raises(ValueError): + with pytest.raises(ValueError, match=msg): bdate_range(badly_formed_date, badly_formed_date) def test_daterange_bug_456(self): @@ -813,8 +816,9 @@ def test_bday_near_overflow(self): def test_bday_overflow_error(self): # GH#24252 check that we get OutOfBoundsDatetime and not OverflowError + msg = "Out of bounds nanosecond timestamp" start = pd.Timestamp.max.floor("D").to_pydatetime() - with pytest.raises(OutOfBoundsDatetime): + with pytest.raises(OutOfBoundsDatetime, match=msg): pd.date_range(start, periods=2, freq="B") diff --git a/pandas/tests/indexes/datetimes/test_indexing.py b/pandas/tests/indexes/datetimes/test_indexing.py index 554ae76979ba8..fa8e6145b566f 100644 --- a/pandas/tests/indexes/datetimes/test_indexing.py +++ b/pandas/tests/indexes/datetimes/test_indexing.py @@ -312,7 +312,8 @@ def test_take_fill_value(self): with pytest.raises(ValueError, match=msg): idx.take(np.array([1, 0, -5]), fill_value=True) - with pytest.raises(IndexError): + msg = "index -5 is out of bounds for size 3" + with pytest.raises(IndexError, match=msg): idx.take(np.array([1, -5])) def test_take_fill_value_with_timezone(self): @@ -348,7 +349,8 @@ def test_take_fill_value_with_timezone(self): with pytest.raises(ValueError, match=msg): idx.take(np.array([1, 0, -5]), fill_value=True) - with pytest.raises(IndexError): + msg = "index -5 is out of bounds for size 3" + with pytest.raises(IndexError, match=msg): idx.take(np.array([1, -5])) @@ -428,7 +430,8 @@ def test_get_loc(self): tm.assert_numpy_array_equal( idx.get_loc(time(12, 30)), np.array([]), check_dtype=False ) - with pytest.raises(NotImplementedError): + msg = "cannot yet lookup inexact labels when key is a time object" + with pytest.raises(NotImplementedError, match=msg): idx.get_loc(time(12, 30), method="pad") def test_get_loc_tz_aware(self): @@ -462,7 +465,8 @@ def test_get_loc_nat(self): def test_get_loc_timedelta_invalid_key(self, key): # GH#20464 dti = pd.date_range("1970-01-01", periods=10) - with pytest.raises(TypeError): + msg = "Cannot index DatetimeIndex with [Tt]imedelta" + with pytest.raises(TypeError, match=msg): dti.get_loc(key) def test_get_loc_reasonable_key_error(self): @@ -571,9 +575,9 @@ def test_insert(self): idx.insert(3, pd.Timestamp("2000-01-04")) with pytest.raises(TypeError, match="Cannot compare tz-naive and tz-aware"): idx.insert(3, datetime(2000, 1, 4)) - with pytest.raises(ValueError): + with pytest.raises(ValueError, match="Timezones don't match"): idx.insert(3, pd.Timestamp("2000-01-04", tz="US/Eastern")) - with pytest.raises(ValueError): + with pytest.raises(ValueError, match="Timezones don't match"): idx.insert(3, datetime(2000, 1, 4, tzinfo=pytz.timezone("US/Eastern"))) for tz in ["US/Pacific", "Asia/Singapore"]: @@ -645,7 +649,7 @@ def test_delete(self): assert result.name == expected.name assert result.freq == expected.freq - with pytest.raises((IndexError, ValueError)): + with pytest.raises((IndexError, ValueError), match="out of bounds"): # either depending on numpy version idx.delete(5) @@ -804,5 +808,5 @@ def test_get_indexer(self): ] with pytest.raises(ValueError, match="abbreviation w/o a number"): idx.get_indexer(target, "nearest", tolerance=tol_bad) - with pytest.raises(ValueError): + with pytest.raises(ValueError, match="abbreviation w/o a number"): idx.get_indexer(idx[[0]], method="nearest", tolerance="foo") diff --git a/pandas/tests/indexes/datetimes/test_shift.py b/pandas/tests/indexes/datetimes/test_shift.py index 1c87995931c62..1e21404551fa8 100644 --- a/pandas/tests/indexes/datetimes/test_shift.py +++ b/pandas/tests/indexes/datetimes/test_shift.py @@ -80,7 +80,7 @@ def test_dti_shift_int(self): def test_dti_shift_no_freq(self): # GH#19147 dti = pd.DatetimeIndex(["2011-01-01 10:00", "2011-01-01"], freq=None) - with pytest.raises(NullFrequencyError): + with pytest.raises(NullFrequencyError, match="Cannot shift with no freq"): dti.shift(2) @pytest.mark.parametrize("tzstr", ["US/Eastern", "dateutil/US/Eastern"]) diff --git a/pandas/tests/indexes/datetimes/test_timezones.py b/pandas/tests/indexes/datetimes/test_timezones.py index 9c1e8cb0f563f..d2f68302d4dcf 100644 --- a/pandas/tests/indexes/datetimes/test_timezones.py +++ b/pandas/tests/indexes/datetimes/test_timezones.py @@ -319,10 +319,10 @@ def test_dti_tz_localize_nonexistent_raise_coerce(self): times = ["2015-03-08 01:00", "2015-03-08 02:00", "2015-03-08 03:00"] index = DatetimeIndex(times) tz = "US/Eastern" - with pytest.raises(pytz.NonExistentTimeError): + with pytest.raises(pytz.NonExistentTimeError, match="|".join(times)): index.tz_localize(tz=tz) - with pytest.raises(pytz.NonExistentTimeError): + with pytest.raises(pytz.NonExistentTimeError, match="|".join(times)): index.tz_localize(tz=tz, nonexistent="raise") result = index.tz_localize(tz=tz, nonexistent="NaT") @@ -336,7 +336,7 @@ def test_dti_tz_localize_ambiguous_infer(self, tz): # November 6, 2011, fall back, repeat 2 AM hour # With no repeated hours, we cannot infer the transition dr = date_range(datetime(2011, 11, 6, 0), periods=5, freq=pd.offsets.Hour()) - with pytest.raises(pytz.AmbiguousTimeError): + with pytest.raises(pytz.AmbiguousTimeError, match="Cannot infer dst time"): dr.tz_localize(tz) # With repeated hours, we can infer the transition @@ -365,7 +365,7 @@ def test_dti_tz_localize_ambiguous_infer(self, tz): def test_dti_tz_localize_ambiguous_times(self, tz): # March 13, 2011, spring forward, skip from 2 AM to 3 AM dr = date_range(datetime(2011, 3, 13, 1, 30), periods=3, freq=pd.offsets.Hour()) - with pytest.raises(pytz.NonExistentTimeError): + with pytest.raises(pytz.NonExistentTimeError, match="2011-03-13 02:30:00"): dr.tz_localize(tz) # after dst transition, it works @@ -375,7 +375,7 @@ def test_dti_tz_localize_ambiguous_times(self, tz): # November 6, 2011, fall back, repeat 2 AM hour dr = date_range(datetime(2011, 11, 6, 1, 30), periods=3, freq=pd.offsets.Hour()) - with pytest.raises(pytz.AmbiguousTimeError): + with pytest.raises(pytz.AmbiguousTimeError, match="Cannot infer dst time"): dr.tz_localize(tz) # UTC is OK @@ -411,11 +411,11 @@ def test_dti_tz_localize(self, prefix): tm.assert_numpy_array_equal(dti3.values, dti_utc.values) dti = pd.date_range(start="11/6/2011 1:59", end="11/6/2011 2:00", freq="L") - with pytest.raises(pytz.AmbiguousTimeError): + with pytest.raises(pytz.AmbiguousTimeError, match="Cannot infer dst time"): dti.tz_localize(tzstr) dti = pd.date_range(start="3/13/2011 1:59", end="3/13/2011 2:00", freq="L") - with pytest.raises(pytz.NonExistentTimeError): + with pytest.raises(pytz.NonExistentTimeError, match="2011-03-13 02:00:00"): dti.tz_localize(tzstr) @pytest.mark.parametrize( @@ -441,7 +441,7 @@ def test_dti_tz_localize_utc_conversion(self, tz): # DST ambiguity, this should fail rng = date_range("3/11/2012", "3/12/2012", freq="30T") # Is this really how it should fail?? - with pytest.raises(pytz.NonExistentTimeError): + with pytest.raises(pytz.NonExistentTimeError, match="2012-03-11 02:00:00"): rng.tz_localize(tz) def test_dti_tz_localize_roundtrip(self, tz_aware_fixture): @@ -452,7 +452,9 @@ def test_dti_tz_localize_roundtrip(self, tz_aware_fixture): tz = tz_aware_fixture localized = idx.tz_localize(tz) # cant localize a tz-aware object - with pytest.raises(TypeError): + with pytest.raises( + TypeError, match="Already tz-aware, use tz_convert to convert" + ): localized.tz_localize(tz) reset = localized.tz_localize(None) assert reset.tzinfo is None @@ -542,7 +544,8 @@ def test_dti_tz_localize_ambiguous_flags(self, tz): di = DatetimeIndex(times) # When the sizes are incompatible, make sure error is raised - with pytest.raises(Exception): + msg = "Length of ambiguous bool-array must be the same size as vals" + with pytest.raises(Exception, match=msg): di.tz_localize(tz, ambiguous=is_dst) # When sizes are compatible and there are repeats ('infer' won't work) @@ -564,7 +567,7 @@ def test_dti_construction_ambiguous_endpoint(self, tz): # construction with an ambiguous end-point # GH#11626 - with pytest.raises(pytz.AmbiguousTimeError): + with pytest.raises(pytz.AmbiguousTimeError, match="Cannot infer dst time"): date_range( "2013-10-26 23:00", "2013-10-27 01:00", tz="Europe/London", freq="H" ) @@ -588,7 +591,7 @@ def test_dti_construction_ambiguous_endpoint(self, tz): def test_dti_construction_nonexistent_endpoint(self, tz, option, expected): # construction with an nonexistent end-point - with pytest.raises(pytz.NonExistentTimeError): + with pytest.raises(pytz.NonExistentTimeError, match="2019-03-10 02:00:00"): date_range( "2019-03-10 00:00", "2019-03-10 02:00", tz="US/Pacific", freq="H" ) @@ -613,10 +616,15 @@ def test_dti_tz_localize_nonexistent(self, tz, method, exp): n = 60 dti = date_range(start="2015-03-29 02:00:00", periods=n, freq="min") if method == "raise": - with pytest.raises(pytz.NonExistentTimeError): + with pytest.raises(pytz.NonExistentTimeError, match="2015-03-29 02:00:00"): dti.tz_localize(tz, nonexistent=method) elif exp == "invalid": - with pytest.raises(ValueError): + msg = ( + "The nonexistent argument must be one of " + "'raise', 'NaT', 'shift_forward', 'shift_backward' " + "or a timedelta object" + ) + with pytest.raises(ValueError, match=msg): dti.tz_localize(tz, nonexistent=method) else: result = dti.tz_localize(tz, nonexistent=method) @@ -1082,7 +1090,8 @@ def test_with_tz(self, tz): dr = bdate_range( datetime(2005, 1, 1, tzinfo=pytz.utc), datetime(2009, 1, 1, tzinfo=pytz.utc) ) - with pytest.raises(Exception): + msg = "Start and end cannot both be tz-aware with different timezones" + with pytest.raises(Exception, match=msg): bdate_range(datetime(2005, 1, 1, tzinfo=pytz.utc), "1/1/2009", tz=tz) @pytest.mark.parametrize("prefix", ["", "dateutil/"]) From c40e22989fea34d5a612e5435409f5f1fe133510 Mon Sep 17 00:00:00 2001 From: Quang Nguyen Date: Sat, 21 Mar 2020 21:22:14 +0700 Subject: [PATCH 2/2] fix to more general msg for out of bounds --- pandas/tests/indexes/datetimes/test_indexing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/tests/indexes/datetimes/test_indexing.py b/pandas/tests/indexes/datetimes/test_indexing.py index fa8e6145b566f..5882f5c77428b 100644 --- a/pandas/tests/indexes/datetimes/test_indexing.py +++ b/pandas/tests/indexes/datetimes/test_indexing.py @@ -312,7 +312,7 @@ def test_take_fill_value(self): with pytest.raises(ValueError, match=msg): idx.take(np.array([1, 0, -5]), fill_value=True) - msg = "index -5 is out of bounds for size 3" + msg = "out of bounds" with pytest.raises(IndexError, match=msg): idx.take(np.array([1, -5])) @@ -349,7 +349,7 @@ def test_take_fill_value_with_timezone(self): with pytest.raises(ValueError, match=msg): idx.take(np.array([1, 0, -5]), fill_value=True) - msg = "index -5 is out of bounds for size 3" + msg = "out of bounds" with pytest.raises(IndexError, match=msg): idx.take(np.array([1, -5]))