From ecbd7c232fdc9fad2e1f3c82b0269113678a798b Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 18 May 2021 22:58:54 -0700 Subject: [PATCH] TST: tighten stacklevel checks --- pandas/core/arrays/datetimelike.py | 4 ++- pandas/core/arrays/datetimes.py | 1 + pandas/core/frame.py | 1 + pandas/core/generic.py | 10 +++++-- pandas/core/indexes/base.py | 2 +- pandas/core/indexes/datetimes.py | 3 ++- pandas/core/reshape/merge.py | 2 ++ pandas/tests/arrays/test_datetimelike.py | 10 ++++--- pandas/tests/dtypes/cast/test_promote.py | 4 ++- pandas/tests/dtypes/test_missing.py | 4 ++- pandas/tests/frame/methods/test_join.py | 6 ++++- .../tests/frame/methods/test_reset_index.py | 2 +- pandas/tests/frame/methods/test_to_dict.py | 3 ++- pandas/tests/generic/test_generic.py | 6 +++-- pandas/tests/indexes/common.py | 6 ++++- .../tests/indexes/datetimes/test_indexing.py | 6 ++--- pandas/tests/indexes/interval/test_astype.py | 2 +- pandas/tests/indexes/interval/test_base.py | 2 +- .../indexes/interval/test_constructors.py | 6 ++--- pandas/tests/indexes/test_common.py | 2 +- pandas/tests/indexing/test_loc.py | 6 ++--- pandas/tests/internals/test_internals.py | 2 +- pandas/tests/series/indexing/test_datetime.py | 10 +++---- pandas/tests/series/methods/test_truncate.py | 2 +- pandas/tests/series/test_arithmetic.py | 4 ++- pandas/tests/series/test_constructors.py | 24 ++++++++--------- pandas/tests/tools/test_to_timedelta.py | 3 ++- pandas/util/_exceptions.py | 26 +++++++++---------- 28 files changed, 96 insertions(+), 63 deletions(-) diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index a3c58b6c6ae15..ff46715d0a527 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -599,7 +599,9 @@ def _validate_shift_value(self, fill_value): "will raise in a future version, pass " f"{self._scalar_type.__name__} instead.", FutureWarning, - stacklevel=8, + # There is no way to hard-code the level since this might be + # reached directly or called from the Index or Block method + stacklevel=find_stack_level(), ) fill_value = new_fill diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index f07a04b8087e0..aee0d4fecd6ae 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -1175,6 +1175,7 @@ def to_perioddelta(self, freq) -> TimedeltaArray: "future version. " "Use `dtindex - dtindex.to_period(freq).to_timestamp()` instead", FutureWarning, + # stacklevel chosen to be correct for when called from DatetimeIndex stacklevel=3, ) from pandas.core.arrays.timedeltas import TimedeltaArray diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 1fa149cd834b0..18611cefa68bc 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -1763,6 +1763,7 @@ def to_dict(self, orient: str = "dict", into=dict): "will be used in a future version. Use one of the above " "to silence this warning.", FutureWarning, + stacklevel=2, ) if orient.startswith("d"): diff --git a/pandas/core/generic.py b/pandas/core/generic.py index a09cc0a6324c0..3014930110620 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -481,13 +481,19 @@ def _data(self): @property def _AXIS_NUMBERS(self) -> dict[str, int]: """.. deprecated:: 1.1.0""" - warnings.warn("_AXIS_NUMBERS has been deprecated.", FutureWarning, stacklevel=3) + level = self.ndim + 1 + warnings.warn( + "_AXIS_NUMBERS has been deprecated.", FutureWarning, stacklevel=level + ) return {"index": 0} @property def _AXIS_NAMES(self) -> dict[int, str]: """.. deprecated:: 1.1.0""" - warnings.warn("_AXIS_NAMES has been deprecated.", FutureWarning, stacklevel=3) + level = self.ndim + 1 + warnings.warn( + "_AXIS_NAMES has been deprecated.", FutureWarning, stacklevel=level + ) return {0: "index"} @final diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 96556df73ffaf..b9fd18dfdce73 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3691,7 +3691,7 @@ def is_int(v): "and will raise TypeError in a future version. " "Use .loc with labels or .iloc with positions instead.", FutureWarning, - stacklevel=6, + stacklevel=5, ) indexer = key else: diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index e8b21f3cec668..ac09159c23566 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -40,6 +40,7 @@ cache_readonly, doc, ) +from pandas.util._exceptions import find_stack_level from pandas.core.dtypes.common import ( DT64NS_DTYPE, @@ -660,7 +661,7 @@ def _deprecate_mismatched_indexing(self, key) -> None: "raise KeyError in a future version. " "Use a timezone-aware object instead." ) - warnings.warn(msg, FutureWarning, stacklevel=5) + warnings.warn(msg, FutureWarning, stacklevel=find_stack_level()) def get_loc(self, key, method=None, tolerance=None): """ diff --git a/pandas/core/reshape/merge.py b/pandas/core/reshape/merge.py index f8085b2bab1ed..4791bbf0ba7f7 100644 --- a/pandas/core/reshape/merge.py +++ b/pandas/core/reshape/merge.py @@ -673,6 +673,8 @@ def __init__( f"in a future version. ({left.columns.nlevels} levels on the left," f"{right.columns.nlevels} on the right)" ) + # stacklevel chosen to be correct when this is reached via pd.merge + # (and not DataFrame.join) warnings.warn(msg, FutureWarning, stacklevel=3) self._validate_specification() diff --git a/pandas/tests/arrays/test_datetimelike.py b/pandas/tests/arrays/test_datetimelike.py index 8581e9a20526f..c6f8efe7b939e 100644 --- a/pandas/tests/arrays/test_datetimelike.py +++ b/pandas/tests/arrays/test_datetimelike.py @@ -561,7 +561,8 @@ def test_shift_fill_int_deprecated(self): data = np.arange(10, dtype="i8") * 24 * 3600 * 10 ** 9 arr = self.array_cls(data, freq="D") - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + msg = "Passing to shift" + with tm.assert_produces_warning(FutureWarning, match=msg): result = arr.shift(1, fill_value=1) expected = arr.copy() @@ -783,10 +784,13 @@ def test_to_perioddelta(self, datetime_index, freqstr): dti = datetime_index arr = DatetimeArray(dti) - with tm.assert_produces_warning(FutureWarning): + msg = "to_perioddelta is deprecated and will be removed" + with tm.assert_produces_warning(FutureWarning, match=msg): # Deprecation GH#34853 expected = dti.to_perioddelta(freq=freqstr) - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + with tm.assert_produces_warning( + FutureWarning, match=msg, check_stacklevel=False + ): # stacklevel is chosen to be "correct" for DatetimeIndex, not # DatetimeArray result = arr.to_perioddelta(freq=freqstr) diff --git a/pandas/tests/dtypes/cast/test_promote.py b/pandas/tests/dtypes/cast/test_promote.py index 70af64064ff85..f4ad3c6285f74 100644 --- a/pandas/tests/dtypes/cast/test_promote.py +++ b/pandas/tests/dtypes/cast/test_promote.py @@ -406,11 +406,13 @@ def test_maybe_promote_any_with_datetime64( exp_val_for_scalar = fill_value warn = None + msg = "Using a `date` object for fill_value" if type(fill_value) is datetime.date and dtype.kind == "M": # Casting date to dt64 is deprecated warn = FutureWarning - with tm.assert_produces_warning(warn, check_stacklevel=False): + with tm.assert_produces_warning(warn, match=msg, check_stacklevel=False): + # stacklevel is chosen to make sense when called from higher-level functions _check_promote(dtype, fill_value, expected_dtype, exp_val_for_scalar) diff --git a/pandas/tests/dtypes/test_missing.py b/pandas/tests/dtypes/test_missing.py index 14fc18aff170e..778373fc7f0df 100644 --- a/pandas/tests/dtypes/test_missing.py +++ b/pandas/tests/dtypes/test_missing.py @@ -443,8 +443,10 @@ def test_array_equivalent(dtype_equal): ) def test_array_equivalent_series(val): arr = np.array([1, 2]) + msg = "elementwise comparison failed" cm = ( - tm.assert_produces_warning(FutureWarning, check_stacklevel=False) + # stacklevel is chosen to make sense when called from .equals + tm.assert_produces_warning(FutureWarning, match=msg, check_stacklevel=False) if isinstance(val, str) else nullcontext() ) diff --git a/pandas/tests/frame/methods/test_join.py b/pandas/tests/frame/methods/test_join.py index 36fd5d399c300..989a9be181a3f 100644 --- a/pandas/tests/frame/methods/test_join.py +++ b/pandas/tests/frame/methods/test_join.py @@ -345,7 +345,11 @@ def test_merge_join_different_levels(self): # join, see discussion in GH#12219 columns = ["a", "b", ("a", ""), ("c", "c1")] expected = DataFrame(columns=columns, data=[[1, 11, 0, 44], [0, 22, 1, 33]]) - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + msg = "merging between different levels is deprecated" + with tm.assert_produces_warning( + FutureWarning, match=msg, check_stacklevel=False + ): + # stacklevel is chosen to be correct for pd.merge, not DataFrame.join result = df1.join(df2, on="a") tm.assert_frame_equal(result, expected) diff --git a/pandas/tests/frame/methods/test_reset_index.py b/pandas/tests/frame/methods/test_reset_index.py index 5a87803ddc21e..f50b2c179ad9a 100644 --- a/pandas/tests/frame/methods/test_reset_index.py +++ b/pandas/tests/frame/methods/test_reset_index.py @@ -341,7 +341,7 @@ def test_reset_index_with_datetimeindex_cols(self, name): ) df.index.name = name - with tm.assert_produces_warning(warn, check_stacklevel=False): + with tm.assert_produces_warning(warn): result = df.reset_index() item = name if name is not None else "index" diff --git a/pandas/tests/frame/methods/test_to_dict.py b/pandas/tests/frame/methods/test_to_dict.py index 022b0f273493b..c33f649206f54 100644 --- a/pandas/tests/frame/methods/test_to_dict.py +++ b/pandas/tests/frame/methods/test_to_dict.py @@ -81,7 +81,8 @@ def test_to_dict_invalid_orient(self): def test_to_dict_short_orient_warns(self, orient): # GH#32515 df = DataFrame({"A": [0, 1]}) - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + msg = "Using short name for 'orient' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): df.to_dict(orient=orient) @pytest.mark.parametrize("mapping", [dict, defaultdict(list), OrderedDict]) diff --git a/pandas/tests/generic/test_generic.py b/pandas/tests/generic/test_generic.py index 771d31aa6865b..254a0b8dfd34e 100644 --- a/pandas/tests/generic/test_generic.py +++ b/pandas/tests/generic/test_generic.py @@ -474,14 +474,16 @@ def test_axis_names_deprecated(self, frame_or_series): # GH33637 box = frame_or_series obj = box(dtype=object) - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + msg = "_AXIS_NAMES has been deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): obj._AXIS_NAMES def test_axis_numbers_deprecated(self, frame_or_series): # GH33637 box = frame_or_series obj = box(dtype=object) - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + msg = "_AXIS_NUMBERS has been deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): obj._AXIS_NUMBERS def test_flags_identity(self, frame_or_series): diff --git a/pandas/tests/indexes/common.py b/pandas/tests/indexes/common.py index 1cef932f7bf0a..8c4f25c5b20fc 100644 --- a/pandas/tests/indexes/common.py +++ b/pandas/tests/indexes/common.py @@ -719,7 +719,11 @@ def test_engine_reference_cycle(self, simple_index): def test_getitem_2d_deprecated(self, simple_index): # GH#30588 idx = simple_index - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + msg = "Support for multi-dimensional indexing" + check = not isinstance(idx, (RangeIndex, CategoricalIndex)) + with tm.assert_produces_warning( + FutureWarning, match=msg, check_stacklevel=check + ): res = idx[:, None] assert isinstance(res, np.ndarray), type(res) diff --git a/pandas/tests/indexes/datetimes/test_indexing.py b/pandas/tests/indexes/datetimes/test_indexing.py index 2773543b74764..de6fa4e8f4238 100644 --- a/pandas/tests/indexes/datetimes/test_indexing.py +++ b/pandas/tests/indexes/datetimes/test_indexing.py @@ -735,7 +735,7 @@ def test_get_slice_bounds_datetime_within( key = box(year=2000, month=1, day=7) warn = None if tz is None else FutureWarning - with tm.assert_produces_warning(warn, check_stacklevel=False): + with tm.assert_produces_warning(warn): # GH#36148 will require tzawareness-compat result = index.get_slice_bound(key, kind=kind, side=side) assert result == expected @@ -753,7 +753,7 @@ def test_get_slice_bounds_datetime_outside( key = box(year=year, month=1, day=7) warn = None if tz is None else FutureWarning - with tm.assert_produces_warning(warn, check_stacklevel=False): + with tm.assert_produces_warning(warn): # GH#36148 will require tzawareness-compat result = index.get_slice_bound(key, kind=kind, side=side) assert result == expected @@ -767,7 +767,7 @@ def test_slice_datetime_locs(self, box, kind, tz_aware_fixture): key = box(2010, 1, 1) warn = None if tz is None else FutureWarning - with tm.assert_produces_warning(warn, check_stacklevel=False): + with tm.assert_produces_warning(warn): # GH#36148 will require tzawareness-compat result = index.slice_locs(key, box(2010, 1, 2)) expected = (0, 1) diff --git a/pandas/tests/indexes/interval/test_astype.py b/pandas/tests/indexes/interval/test_astype.py index f421a4695138c..cac145aa30fd0 100644 --- a/pandas/tests/indexes/interval/test_astype.py +++ b/pandas/tests/indexes/interval/test_astype.py @@ -205,7 +205,7 @@ def index(self, request): @pytest.mark.parametrize("subtype", ["int64", "uint64"]) def test_subtype_integer(self, index, subtype): dtype = IntervalDtype(subtype, "right") - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + with tm.assert_produces_warning(FutureWarning): result = index.astype(dtype) expected = IntervalIndex.from_arrays( index.left.astype(subtype), diff --git a/pandas/tests/indexes/interval/test_base.py b/pandas/tests/indexes/interval/test_base.py index b14db459f996d..3589fe726b3bb 100644 --- a/pandas/tests/indexes/interval/test_base.py +++ b/pandas/tests/indexes/interval/test_base.py @@ -64,7 +64,7 @@ def test_getitem_2d_deprecated(self, simple_index): # GH#30588 multi-dim indexing is deprecated, but raising is also acceptable idx = simple_index with pytest.raises(ValueError, match="multi-dimensional indexing not allowed"): - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + with tm.assert_produces_warning(FutureWarning): idx[:, None] diff --git a/pandas/tests/indexes/interval/test_constructors.py b/pandas/tests/indexes/interval/test_constructors.py index e3b41e6c5d6bb..65ae904d1083a 100644 --- a/pandas/tests/indexes/interval/test_constructors.py +++ b/pandas/tests/indexes/interval/test_constructors.py @@ -77,14 +77,14 @@ def test_constructor_dtype(self, constructor, breaks, subtype): # astype(int64) deprecated warn = FutureWarning - with tm.assert_produces_warning(warn, check_stacklevel=False): + with tm.assert_produces_warning(warn): expected_kwargs = self.get_kwargs_from_breaks(breaks.astype(subtype)) expected = constructor(**expected_kwargs) result_kwargs = self.get_kwargs_from_breaks(breaks) iv_dtype = IntervalDtype(subtype, "right") for dtype in (iv_dtype, str(iv_dtype)): - with tm.assert_produces_warning(warn, check_stacklevel=False): + with tm.assert_produces_warning(warn): result = constructor(dtype=dtype, **result_kwargs) tm.assert_index_equal(result, expected) @@ -112,7 +112,7 @@ def test_constructor_pass_closed(self, constructor, breaks): result_kwargs = self.get_kwargs_from_breaks(breaks) for dtype in (iv_dtype, str(iv_dtype)): - with tm.assert_produces_warning(warn, check_stacklevel=False): + with tm.assert_produces_warning(warn): result = constructor(dtype=dtype, closed="left", **result_kwargs) assert result.dtype.closed == "left" diff --git a/pandas/tests/indexes/test_common.py b/pandas/tests/indexes/test_common.py index 5cf0134795b74..ec01e35673647 100644 --- a/pandas/tests/indexes/test_common.py +++ b/pandas/tests/indexes/test_common.py @@ -343,7 +343,7 @@ def test_astype_preserves_name(self, index, dtype): warn = FutureWarning try: # Some of these conversions cannot succeed so we use a try / except - with tm.assert_produces_warning(warn, check_stacklevel=False): + with tm.assert_produces_warning(warn): result = index.astype(dtype) except (ValueError, TypeError, NotImplementedError, SystemError): return diff --git a/pandas/tests/indexing/test_loc.py b/pandas/tests/indexing/test_loc.py index 90e3ff29977ae..48bc3e18d9883 100644 --- a/pandas/tests/indexing/test_loc.py +++ b/pandas/tests/indexing/test_loc.py @@ -2400,7 +2400,7 @@ def test_loc_with_positional_slice_deprecation(): # GH#31840 ser = Series(range(4), index=["A", "B", "C", "D"]) - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + with tm.assert_produces_warning(FutureWarning): ser.loc[:3] = 2 expected = Series([2, 2, 2, 3], index=["A", "B", "C", "D"]) @@ -2423,14 +2423,14 @@ def test_loc_slice_disallows_positional(): with pytest.raises(TypeError, match=msg): obj.loc[1:3] - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + with tm.assert_produces_warning(FutureWarning): # GH#31840 deprecated incorrect behavior obj.loc[1:3] = 1 with pytest.raises(TypeError, match=msg): df.loc[1:3, 1] - with tm.assert_produces_warning(FutureWarning): + with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): # GH#31840 deprecated incorrect behavior df.loc[1:3, 1] = 2 diff --git a/pandas/tests/internals/test_internals.py b/pandas/tests/internals/test_internals.py index 08dba5aa76a2f..61bbd4e12e1ba 100644 --- a/pandas/tests/internals/test_internals.py +++ b/pandas/tests/internals/test_internals.py @@ -545,7 +545,7 @@ def test_astype(self, t): mgr = create_mgr("a,b: object; c: bool; d: datetime; e: f4; f: f2; g: f8") t = np.dtype(t) - with tm.assert_produces_warning(warn, check_stacklevel=False): + with tm.assert_produces_warning(warn): tmgr = mgr.astype(t, errors="ignore") assert tmgr.iget(2).dtype.type == t assert tmgr.iget(4).dtype.type == t diff --git a/pandas/tests/series/indexing/test_datetime.py b/pandas/tests/series/indexing/test_datetime.py index e4ba530d0741c..2c5c977624470 100644 --- a/pandas/tests/series/indexing/test_datetime.py +++ b/pandas/tests/series/indexing/test_datetime.py @@ -147,25 +147,25 @@ def test_getitem_setitem_datetimeindex(): assert result == expected result = ts.copy() - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + with tm.assert_produces_warning(FutureWarning): # GH#36148 will require tzawareness compat result[datetime(1990, 1, 1, 4)] = 0 - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + with tm.assert_produces_warning(FutureWarning): # GH#36148 will require tzawareness compat result[datetime(1990, 1, 1, 4)] = ts[4] tm.assert_series_equal(result, ts) - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + with tm.assert_produces_warning(FutureWarning): # GH#36148 will require tzawareness compat result = ts[datetime(1990, 1, 1, 4) : datetime(1990, 1, 1, 7)] expected = ts[4:8] tm.assert_series_equal(result, expected) result = ts.copy() - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + with tm.assert_produces_warning(FutureWarning): # GH#36148 will require tzawareness compat result[datetime(1990, 1, 1, 4) : datetime(1990, 1, 1, 7)] = 0 - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + with tm.assert_produces_warning(FutureWarning): # GH#36148 will require tzawareness compat result[datetime(1990, 1, 1, 4) : datetime(1990, 1, 1, 7)] = ts[4:8] tm.assert_series_equal(result, ts) diff --git a/pandas/tests/series/methods/test_truncate.py b/pandas/tests/series/methods/test_truncate.py index 672faf1e0d541..ca5c3e2639097 100644 --- a/pandas/tests/series/methods/test_truncate.py +++ b/pandas/tests/series/methods/test_truncate.py @@ -13,7 +13,7 @@ def test_truncate_datetimeindex_tz(self): # GH 9243 idx = date_range("4/1/2005", "4/30/2005", freq="D", tz="US/Pacific") s = Series(range(len(idx)), index=idx) - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + with tm.assert_produces_warning(FutureWarning): # GH#36148 in the future will require tzawareness compat s.truncate(datetime(2005, 4, 2), datetime(2005, 4, 4)) diff --git a/pandas/tests/series/test_arithmetic.py b/pandas/tests/series/test_arithmetic.py index 72b6b7527f57f..880fa6398d25a 100644 --- a/pandas/tests/series/test_arithmetic.py +++ b/pandas/tests/series/test_arithmetic.py @@ -783,7 +783,9 @@ def test_series_ops_name_retention( else: # GH#37374 logical ops behaving as set ops deprecated warn = FutureWarning if is_rlogical and box is Index else None - with tm.assert_produces_warning(warn, check_stacklevel=False): + msg = "operating as a set operation is deprecated" + with tm.assert_produces_warning(warn, match=msg, check_stacklevel=False): + # stacklevel is correct for Index op, not reversed op result = op(left, right) if box is Index and is_rlogical: diff --git a/pandas/tests/series/test_constructors.py b/pandas/tests/series/test_constructors.py index 67649e6e37b35..e74d900d1b04d 100644 --- a/pandas/tests/series/test_constructors.py +++ b/pandas/tests/series/test_constructors.py @@ -71,7 +71,7 @@ class TestSeriesConstructors: ) def test_empty_constructor(self, constructor, check_index_type): # TODO: share with frame test of the same name - with tm.assert_produces_warning(DeprecationWarning, check_stacklevel=False): + with tm.assert_produces_warning(DeprecationWarning): expected = Series() result = constructor() @@ -116,7 +116,7 @@ def test_scalar_extension_dtype(self, ea_scalar_and_dtype): tm.assert_series_equal(ser, expected) def test_constructor(self, datetime_series): - with tm.assert_produces_warning(DeprecationWarning, check_stacklevel=False): + with tm.assert_produces_warning(DeprecationWarning): empty_series = Series() assert datetime_series.index._is_all_dates @@ -134,7 +134,7 @@ def test_constructor(self, datetime_series): assert mixed[1] is np.NaN assert not empty_series.index._is_all_dates - with tm.assert_produces_warning(DeprecationWarning, check_stacklevel=False): + with tm.assert_produces_warning(DeprecationWarning): assert not Series().index._is_all_dates # exception raised is of type ValueError GH35744 @@ -154,7 +154,7 @@ def test_constructor(self, datetime_series): @pytest.mark.parametrize("input_class", [list, dict, OrderedDict]) def test_constructor_empty(self, input_class): - with tm.assert_produces_warning(DeprecationWarning, check_stacklevel=False): + with tm.assert_produces_warning(DeprecationWarning): empty = Series() empty2 = Series(input_class()) @@ -174,7 +174,7 @@ def test_constructor_empty(self, input_class): if input_class is not list: # With index: - with tm.assert_produces_warning(DeprecationWarning, check_stacklevel=False): + with tm.assert_produces_warning(DeprecationWarning): empty = Series(index=range(10)) empty2 = Series(input_class(), index=range(10)) tm.assert_series_equal(empty, empty2) @@ -208,7 +208,7 @@ def test_constructor_dtype_only(self, dtype, index): assert len(result) == 0 def test_constructor_no_data_index_order(self): - with tm.assert_produces_warning(DeprecationWarning, check_stacklevel=False): + with tm.assert_produces_warning(DeprecationWarning): result = Series(index=["b", "a", "c"]) assert result.index.tolist() == ["b", "a", "c"] @@ -674,7 +674,7 @@ def test_constructor_limit_copies(self, index): assert s._mgr.blocks[0].values is not index def test_constructor_pass_none(self): - with tm.assert_produces_warning(DeprecationWarning, check_stacklevel=False): + with tm.assert_produces_warning(DeprecationWarning): s = Series(None, index=range(5)) assert s.dtype == np.float64 @@ -683,7 +683,7 @@ def test_constructor_pass_none(self): # GH 7431 # inference on the index - with tm.assert_produces_warning(DeprecationWarning, check_stacklevel=False): + with tm.assert_produces_warning(DeprecationWarning): s = Series(index=np.array([None])) expected = Series(index=Index([None])) tm.assert_series_equal(s, expected) @@ -840,7 +840,7 @@ def test_constructor_dtype_datetime64_10(self): dts = Series(dates, dtype="datetime64[ns]") # valid astype - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + with tm.assert_produces_warning(FutureWarning): # astype(np.int64) deprecated dts.astype("int64") @@ -852,7 +852,7 @@ def test_constructor_dtype_datetime64_10(self): # ints are ok # we test with np.int64 to get similar results on # windows / 32-bit platforms - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + with tm.assert_produces_warning(FutureWarning): # astype(np.int64) deprecated result = Series(dts, dtype=np.int64) expected = Series(dts.astype(np.int64)) @@ -1341,7 +1341,7 @@ def test_constructor_dtype_timedelta64(self): # td.astype('m8[%s]' % t) # valid astype - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + with tm.assert_produces_warning(FutureWarning): # astype(int64) deprecated td.astype("int64") @@ -1465,7 +1465,7 @@ def test_constructor_cant_cast_datetimelike(self, index): # ints are ok # we test with np.int64 to get similar results on # windows / 32-bit platforms - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + with tm.assert_produces_warning(FutureWarning): # asype(np.int64) deprecated, use .view(np.int64) instead result = Series(index, dtype=np.int64) expected = Series(index.astype(np.int64)) diff --git a/pandas/tests/tools/test_to_timedelta.py b/pandas/tests/tools/test_to_timedelta.py index efcca0df639f6..1fc383521d31f 100644 --- a/pandas/tests/tools/test_to_timedelta.py +++ b/pandas/tests/tools/test_to_timedelta.py @@ -174,7 +174,8 @@ def test_to_timedelta_invalid(self): def test_unambiguous_timedelta_values(self, val, warning): # GH36666 Deprecate use of strings denoting units with 'M', 'Y', 'm' or 'y' # in pd.to_timedelta - with tm.assert_produces_warning(warning, check_stacklevel=False): + msg = "Units 'M', 'Y' and 'y' do not represent unambiguous timedelta" + with tm.assert_produces_warning(warning, match=msg, check_stacklevel=False): to_timedelta(val) def test_to_timedelta_via_apply(self): diff --git a/pandas/util/_exceptions.py b/pandas/util/_exceptions.py index 9a6c62df76ef2..806e2abe83a92 100644 --- a/pandas/util/_exceptions.py +++ b/pandas/util/_exceptions.py @@ -2,6 +2,7 @@ import contextlib import inspect +import os @contextlib.contextmanager @@ -25,23 +26,20 @@ def rewrite_exception(old_name: str, new_name: str): def find_stack_level() -> int: """ - Find the appropriate stacklevel with which to issue a warning for astype. + Find the first place in the stack that is not inside pandas + (tests notwithstanding). """ stack = inspect.stack() - # find the lowest-level "astype" call that got us here - for n in range(2, 6): - if stack[n].function == "astype": - break - - while stack[n].function in ["astype", "apply", "astype_array_safe", "astype_array"]: - # e.g. - # bump up Block.astype -> BlockManager.astype -> NDFrame.astype - # bump up Datetime.Array.astype -> DatetimeIndex.astype - n += 1 + import pandas as pd - if stack[n].function == "__init__": - # Series.__init__ - n += 1 + pkg_dir = os.path.dirname(pd.__file__) + test_dir = os.path.join(pkg_dir, "tests") + for n in range(len(stack)): + fname = stack[n].filename + if fname.startswith(pkg_dir) and not fname.startswith(test_dir): + continue + else: + break return n