diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 802a9fd7e2099..6dfce8bd086f5 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -24,6 +24,12 @@ enhancement1 enhancement2 ^^^^^^^^^^^^ +New Deprecation Policy +^^^^^^^^^^^^^^^^^^^^^^ +pandas 3.0.0 introduces a new 3-stage deprecation policy: using ``DeprecationWarning`` initially, then switching to ``FutureWarning`` for broader visibility in the last minor version before the next major release, and then removal of the deprecated functionality in the major release. + +This was done to give downstream packages more time to adjust to pandas deprecations, which should reduce the amount of warnings that a user gets from code that isn't theirs. + .. _whatsnew_300.enhancements.other: Other enhancements diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index 04bd439b40b8d..e75a73f5c0ab6 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -50,7 +50,10 @@ import datetime as dt from pandas._libs.tslibs cimport ccalendar from pandas._libs.tslibs.base cimport ABCTimestamp -from pandas.util._exceptions import find_stack_level +from pandas.util._exceptions import ( + Pandas4DeprecationWarning, + find_stack_level, +) from pandas._libs.tslibs.conversion cimport ( _TSObject, @@ -1533,7 +1536,7 @@ class Timestamp(_Timestamp): # GH#56680 "Timestamp.utcnow is deprecated and will be removed in a future " "version. Use Timestamp.now('UTC') instead.", - FutureWarning, + Pandas4DeprecationWarning, stacklevel=find_stack_level(), ) return cls.now(UTC) @@ -1561,7 +1564,7 @@ class Timestamp(_Timestamp): # to match. GH#56680 "Timestamp.utcfromtimestamp is deprecated and will be removed in a " "future version. Use Timestamp.fromtimestamp(ts, 'UTC') instead.", - FutureWarning, + Pandas4DeprecationWarning, stacklevel=find_stack_level(), ) return cls.fromtimestamp(ts, tz="UTC") diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 80314c2648f45..8f641b4a6c226 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -97,7 +97,10 @@ deprecate_kwarg, doc, ) -from pandas.util._exceptions import find_stack_level +from pandas.util._exceptions import ( + Pandas4DeprecationWarning, + find_stack_level, +) from pandas.util._validators import ( check_dtype_backend, validate_ascending, @@ -2570,7 +2573,7 @@ def to_json( warnings.warn( "The default 'epoch' date format is deprecated and will be removed " "in a future version, please use 'iso' date format instead.", - FutureWarning, + Pandas4DeprecationWarning, stacklevel=find_stack_level(), ) elif date_format == "epoch": @@ -2578,7 +2581,7 @@ def to_json( warnings.warn( "'epoch' date format is deprecated and will be removed in a future " "version, please use 'iso' date format instead.", - FutureWarning, + Pandas4DeprecationWarning, stacklevel=find_stack_level(), ) @@ -4306,7 +4309,7 @@ def _check_copy_deprecation(copy): "version. Copy-on-Write is active in pandas since 3.0 which utilizes " "a lazy copy mechanism that defers copies until necessary. Use " ".copy() to make an eager copy if necessary.", - DeprecationWarning, + Pandas4DeprecationWarning, stacklevel=find_stack_level(), ) diff --git a/pandas/core/groupby/generic.py b/pandas/core/groupby/generic.py index 945b9f9c14c0b..40a51d1c80c1f 100644 --- a/pandas/core/groupby/generic.py +++ b/pandas/core/groupby/generic.py @@ -33,7 +33,10 @@ Substitution, doc, ) -from pandas.util._exceptions import find_stack_level +from pandas.util._exceptions import ( + Pandas4DeprecationWarning, + find_stack_level, +) from pandas.core.dtypes.common import ( ensure_int64, @@ -2791,7 +2794,7 @@ def corrwith( """ warnings.warn( "DataFrameGroupBy.corrwith is deprecated", - FutureWarning, + Pandas4DeprecationWarning, stacklevel=find_stack_level(), ) result = self._op_via_apply( diff --git a/pandas/core/indexes/accessors.py b/pandas/core/indexes/accessors.py index 3cb51f7447677..62e8c49292499 100644 --- a/pandas/core/indexes/accessors.py +++ b/pandas/core/indexes/accessors.py @@ -14,7 +14,10 @@ import numpy as np from pandas._libs import lib -from pandas.util._exceptions import find_stack_level +from pandas.util._exceptions import ( + Pandas4DeprecationWarning, + find_stack_level, +) from pandas.core.dtypes.common import ( is_integer_dtype, @@ -218,7 +221,7 @@ def to_pytimedelta(self): "in a future version this will return a Series containing python " "datetime.timedelta objects instead of an ndarray. To retain the " "old behavior, call `np.array` on the result", - FutureWarning, + Pandas4DeprecationWarning, stacklevel=find_stack_level(), ) return cast(ArrowExtensionArray, self._parent.array)._dt_to_pytimedelta() @@ -479,7 +482,7 @@ def to_pytimedelta(self) -> np.ndarray: "in a future version this will return a Series containing python " "datetime.timedelta objects instead of an ndarray. To retain the " "old behavior, call `np.array` on the result", - FutureWarning, + Pandas4DeprecationWarning, stacklevel=find_stack_level(), ) return self._get_values().to_pytimedelta() diff --git a/pandas/core/internals/api.py b/pandas/core/internals/api.py index 04944db2ebd9c..1681eff7675e7 100644 --- a/pandas/core/internals/api.py +++ b/pandas/core/internals/api.py @@ -15,6 +15,7 @@ import numpy as np from pandas._libs.internals import BlockPlacement +from pandas.util._exceptions import Pandas4DeprecationWarning from pandas.core.dtypes.common import pandas_dtype from pandas.core.dtypes.dtypes import ( @@ -93,7 +94,7 @@ def make_block( "make_block is deprecated and will be removed in a future version. " "Use pd.api.internals.create_dataframe_from_blocks or " "(recommended) higher-level public APIs instead.", - DeprecationWarning, + Pandas4DeprecationWarning, stacklevel=2, ) diff --git a/pandas/core/reshape/concat.py b/pandas/core/reshape/concat.py index 7055201b5a1ee..41c0cb6ec9182 100644 --- a/pandas/core/reshape/concat.py +++ b/pandas/core/reshape/concat.py @@ -18,7 +18,10 @@ from pandas._libs import lib from pandas.util._decorators import cache_readonly -from pandas.util._exceptions import find_stack_level +from pandas.util._exceptions import ( + Pandas4DeprecationWarning, + find_stack_level, +) from pandas.core.dtypes.common import is_bool from pandas.core.dtypes.concat import concat_compat @@ -382,7 +385,7 @@ def concat( "version. Copy-on-Write is active in pandas since 3.0 which utilizes " "a lazy copy mechanism that defers copies until necessary. Use " ".copy() to make an eager copy if necessary.", - DeprecationWarning, + Pandas4DeprecationWarning, stacklevel=find_stack_level(), ) diff --git a/pandas/io/feather_format.py b/pandas/io/feather_format.py index 16d4e1f9ea25d..0d2bf449d2172 100644 --- a/pandas/io/feather_format.py +++ b/pandas/io/feather_format.py @@ -13,6 +13,7 @@ from pandas._libs import lib from pandas.compat._optional import import_optional_dependency from pandas.util._decorators import doc +from pandas.util._exceptions import Pandas4DeprecationWarning from pandas.util._validators import check_dtype_backend import pandas as pd @@ -136,7 +137,7 @@ def read_feather( warnings.filterwarnings( "ignore", "make_block is deprecated", - DeprecationWarning, + Pandas4DeprecationWarning, ) return feather.read_feather( diff --git a/pandas/io/parquet.py b/pandas/io/parquet.py index 306b144811898..e6e2f963db407 100644 --- a/pandas/io/parquet.py +++ b/pandas/io/parquet.py @@ -21,6 +21,7 @@ from pandas.compat._optional import import_optional_dependency from pandas.errors import AbstractMethodError from pandas.util._decorators import doc +from pandas.util._exceptions import Pandas4DeprecationWarning from pandas.util._validators import check_dtype_backend import pandas as pd @@ -278,7 +279,7 @@ def read( filterwarnings( "ignore", "make_block is deprecated", - DeprecationWarning, + Pandas4DeprecationWarning, ) result = pa_table.to_pandas(**to_pandas_kwargs) @@ -397,7 +398,7 @@ def read( filterwarnings( "ignore", "make_block is deprecated", - DeprecationWarning, + Pandas4DeprecationWarning, ) return parquet_file.to_pandas( columns=columns, filters=filters, **kwargs diff --git a/pandas/io/parsers/arrow_parser_wrapper.py b/pandas/io/parsers/arrow_parser_wrapper.py index cffdb28e2c9e4..ea26f620a924e 100644 --- a/pandas/io/parsers/arrow_parser_wrapper.py +++ b/pandas/io/parsers/arrow_parser_wrapper.py @@ -11,7 +11,10 @@ ParserError, ParserWarning, ) -from pandas.util._exceptions import find_stack_level +from pandas.util._exceptions import ( + Pandas4DeprecationWarning, + find_stack_level, +) from pandas.core.dtypes.common import pandas_dtype from pandas.core.dtypes.inference import is_integer @@ -291,7 +294,7 @@ def read(self) -> DataFrame: warnings.filterwarnings( "ignore", "make_block is deprecated", - DeprecationWarning, + Pandas4DeprecationWarning, ) if dtype_backend == "pyarrow": frame = table.to_pandas(types_mapper=pd.ArrowDtype) diff --git a/pandas/tests/copy_view/test_copy_deprecation.py b/pandas/tests/copy_view/test_copy_deprecation.py index 8ee37213b92ab..57bb10b8be12a 100644 --- a/pandas/tests/copy_view/test_copy_deprecation.py +++ b/pandas/tests/copy_view/test_copy_deprecation.py @@ -1,5 +1,7 @@ import pytest +from pandas.util._exceptions import Pandas4DeprecationWarning + import pandas as pd from pandas import ( concat, @@ -38,11 +40,11 @@ def test_copy_deprecation(meth, kwargs): df = df.set_index(["b", "c"]) if meth != "swaplevel": - with tm.assert_produces_warning(DeprecationWarning, match="copy"): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match="copy"): getattr(df, meth)(copy=False, **kwargs) if meth != "transpose": - with tm.assert_produces_warning(DeprecationWarning, match="copy"): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match="copy"): getattr(df.a, meth)(copy=False, **kwargs) @@ -50,22 +52,22 @@ def test_copy_deprecation_reindex_like_align(): df = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]}) # Somehow the stack level check is incorrect here with tm.assert_produces_warning( - DeprecationWarning, match="copy", check_stacklevel=False + Pandas4DeprecationWarning, match="copy", check_stacklevel=False ): df.reindex_like(df, copy=False) with tm.assert_produces_warning( - DeprecationWarning, match="copy", check_stacklevel=False + Pandas4DeprecationWarning, match="copy", check_stacklevel=False ): df.a.reindex_like(df.a, copy=False) with tm.assert_produces_warning( - DeprecationWarning, match="copy", check_stacklevel=False + Pandas4DeprecationWarning, match="copy", check_stacklevel=False ): df.align(df, copy=False) with tm.assert_produces_warning( - DeprecationWarning, match="copy", check_stacklevel=False + Pandas4DeprecationWarning, match="copy", check_stacklevel=False ): df.a.align(df.a, copy=False) @@ -74,16 +76,16 @@ def test_copy_deprecation_merge_concat(): df = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]}) with tm.assert_produces_warning( - DeprecationWarning, match="copy", check_stacklevel=False + Pandas4DeprecationWarning, match="copy", check_stacklevel=False ): df.merge(df, copy=False) with tm.assert_produces_warning( - DeprecationWarning, match="copy", check_stacklevel=False + Pandas4DeprecationWarning, match="copy", check_stacklevel=False ): merge(df, df, copy=False) with tm.assert_produces_warning( - DeprecationWarning, match="copy", check_stacklevel=False + Pandas4DeprecationWarning, match="copy", check_stacklevel=False ): concat([df, df], copy=False) diff --git a/pandas/tests/extension/test_arrow.py b/pandas/tests/extension/test_arrow.py index 5926d23b44dd0..619f846badfe2 100644 --- a/pandas/tests/extension/test_arrow.py +++ b/pandas/tests/extension/test_arrow.py @@ -43,6 +43,7 @@ pa_version_under13p0, pa_version_under14p0, ) +from pandas.util._exceptions import Pandas4DeprecationWarning import pandas.util._test_decorators as td from pandas.core.dtypes.dtypes import ( @@ -2862,14 +2863,14 @@ def test_dt_to_pytimedelta(): ser = pd.Series(data, dtype=ArrowDtype(pa.duration("ns"))) msg = "The behavior of ArrowTemporalProperties.to_pytimedelta is deprecated" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): result = ser.dt.to_pytimedelta() expected = np.array(data, dtype=object) tm.assert_numpy_array_equal(result, expected) assert all(type(res) is timedelta for res in result) msg = "The behavior of TimedeltaProperties.to_pytimedelta is deprecated" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): expected = ser.astype("timedelta64[ns]").dt.to_pytimedelta() tm.assert_numpy_array_equal(result, expected) diff --git a/pandas/tests/frame/methods/test_reindex_like.py b/pandas/tests/frame/methods/test_reindex_like.py index 03968dcbb6314..7c6822a166852 100644 --- a/pandas/tests/frame/methods/test_reindex_like.py +++ b/pandas/tests/frame/methods/test_reindex_like.py @@ -1,6 +1,8 @@ import numpy as np import pytest +from pandas.util._exceptions import Pandas4DeprecationWarning + from pandas import DataFrame import pandas._testing as tm @@ -22,10 +24,10 @@ def test_reindex_like(self, float_frame): def test_reindex_like_methods(self, method, expected_values): df = DataFrame({"x": list(range(5))}) - with tm.assert_produces_warning(FutureWarning): + with tm.assert_produces_warning(Pandas4DeprecationWarning): result = df.reindex_like(df, method=method, tolerance=0) tm.assert_frame_equal(df, result) - with tm.assert_produces_warning(FutureWarning): + with tm.assert_produces_warning(Pandas4DeprecationWarning): result = df.reindex_like(df, method=method, tolerance=[0, 0, 0, 0]) tm.assert_frame_equal(df, result) diff --git a/pandas/tests/groupby/test_all_methods.py b/pandas/tests/groupby/test_all_methods.py index 945c3e421a132..87b8155cf0ffc 100644 --- a/pandas/tests/groupby/test_all_methods.py +++ b/pandas/tests/groupby/test_all_methods.py @@ -13,6 +13,8 @@ import pytest +from pandas.util._exceptions import Pandas4DeprecationWarning + import pandas as pd from pandas import DataFrame import pandas._testing as tm @@ -26,7 +28,7 @@ def test_multiindex_group_all_columns_when_empty(groupby_func): method = getattr(gb, groupby_func) args = get_groupby_method_args(groupby_func, df) if groupby_func == "corrwith": - warn = FutureWarning + warn = Pandas4DeprecationWarning warn_msg = "DataFrameGroupBy.corrwith is deprecated" else: warn = None @@ -72,7 +74,7 @@ def test_dup_labels_output_shape(groupby_func, idx): args = get_groupby_method_args(groupby_func, df) if groupby_func == "corrwith": - warn = FutureWarning + warn = Pandas4DeprecationWarning warn_msg = "DataFrameGroupBy.corrwith is deprecated" else: warn = None diff --git a/pandas/tests/groupby/test_apply.py b/pandas/tests/groupby/test_apply.py index 75801b9e039f6..020e156c83554 100644 --- a/pandas/tests/groupby/test_apply.py +++ b/pandas/tests/groupby/test_apply.py @@ -6,6 +6,8 @@ import numpy as np import pytest +from pandas.util._exceptions import Pandas4DeprecationWarning + import pandas as pd from pandas import ( DataFrame, @@ -1198,7 +1200,7 @@ def test_apply_is_unchanged_when_other_methods_are_called_first(reduction_func): grp = df.groupby(by="a") args = get_groupby_method_args(reduction_func, df) if reduction_func == "corrwith": - warn = FutureWarning + warn = Pandas4DeprecationWarning msg = "DataFrameGroupBy.corrwith is deprecated" else: warn = None diff --git a/pandas/tests/groupby/test_categorical.py b/pandas/tests/groupby/test_categorical.py index 010bd9ee52555..a7a7eeae39085 100644 --- a/pandas/tests/groupby/test_categorical.py +++ b/pandas/tests/groupby/test_categorical.py @@ -3,6 +3,8 @@ import numpy as np import pytest +from pandas.util._exceptions import Pandas4DeprecationWarning + import pandas as pd from pandas import ( Categorical, @@ -1474,7 +1476,7 @@ def test_dataframe_groupby_on_2_categoricals_when_observed_is_true(reduction_fun args = get_groupby_method_args(reduction_func, df) if reduction_func == "corrwith": - warn = FutureWarning + warn = Pandas4DeprecationWarning warn_msg = "DataFrameGroupBy.corrwith is deprecated" else: warn = None @@ -1520,7 +1522,7 @@ def test_dataframe_groupby_on_2_categoricals_when_observed_is_false( return if reduction_func == "corrwith": - warn = FutureWarning + warn = Pandas4DeprecationWarning warn_msg = "DataFrameGroupBy.corrwith is deprecated" else: warn = None @@ -1919,7 +1921,7 @@ def test_category_order_reducer( getattr(gb, reduction_func)(*args) return if reduction_func == "corrwith": - warn = FutureWarning + warn = Pandas4DeprecationWarning warn_msg = "DataFrameGroupBy.corrwith is deprecated" else: warn = None diff --git a/pandas/tests/groupby/test_groupby_dropna.py b/pandas/tests/groupby/test_groupby_dropna.py index 4749e845a0e59..631c75bfb40b8 100644 --- a/pandas/tests/groupby/test_groupby_dropna.py +++ b/pandas/tests/groupby/test_groupby_dropna.py @@ -2,6 +2,7 @@ import pytest from pandas.compat.pyarrow import pa_version_under10p1 +from pandas.util._exceptions import Pandas4DeprecationWarning from pandas.core.dtypes.missing import na_value_for_dtype @@ -544,7 +545,7 @@ def test_categorical_reducers(reduction_func, observed, sort, as_index, index_ki gb_filled = df_filled.groupby(keys, observed=observed, sort=sort, as_index=True) if reduction_func == "corrwith": - warn = FutureWarning + warn = Pandas4DeprecationWarning msg = "DataFrameGroupBy.corrwith is deprecated" else: warn = None @@ -575,7 +576,7 @@ def test_categorical_reducers(reduction_func, observed, sort, as_index, index_ki expected = expected["size"].rename(None) if reduction_func == "corrwith": - warn = FutureWarning + warn = Pandas4DeprecationWarning msg = "DataFrameGroupBy.corrwith is deprecated" else: warn = None diff --git a/pandas/tests/groupby/test_numeric_only.py b/pandas/tests/groupby/test_numeric_only.py index afbc64429e93c..3d9574b978815 100644 --- a/pandas/tests/groupby/test_numeric_only.py +++ b/pandas/tests/groupby/test_numeric_only.py @@ -3,6 +3,7 @@ import pytest from pandas._libs import lib +from pandas.util._exceptions import Pandas4DeprecationWarning import pandas as pd from pandas import ( @@ -257,7 +258,7 @@ def test_numeric_only(kernel, has_arg, numeric_only, keys): if has_arg and numeric_only is True: # Cases where b does not appear in the result if kernel == "corrwith": - warn = FutureWarning + warn = Pandas4DeprecationWarning msg = "DataFrameGroupBy.corrwith is deprecated" else: warn = None @@ -304,7 +305,7 @@ def test_numeric_only(kernel, has_arg, numeric_only, keys): msg = "'>' not supported between instances of 'type' and 'type'" with pytest.raises(exception, match=msg): if kernel == "corrwith": - warn = FutureWarning + warn = Pandas4DeprecationWarning msg = "DataFrameGroupBy.corrwith is deprecated" else: warn = None diff --git a/pandas/tests/groupby/test_raises.py b/pandas/tests/groupby/test_raises.py index 5a8192a9ffe02..a1d3e05981e7c 100644 --- a/pandas/tests/groupby/test_raises.py +++ b/pandas/tests/groupby/test_raises.py @@ -8,6 +8,8 @@ import numpy as np import pytest +from pandas.util._exceptions import CurrentDeprecationWarning + from pandas import ( Categorical, DataFrame, @@ -85,7 +87,7 @@ def df_with_cat_col(): def _call_and_check(klass, msg, how, gb, groupby_func, args, warn_msg=""): - warn_klass = None if warn_msg == "" else FutureWarning + warn_klass = None if warn_msg == "" else CurrentDeprecationWarning with tm.assert_produces_warning(warn_klass, match=warn_msg, check_stacklevel=False): if klass is None: if how == "method": diff --git a/pandas/tests/groupby/transform/test_transform.py b/pandas/tests/groupby/transform/test_transform.py index 726c57081373c..2e35ae8d491c0 100644 --- a/pandas/tests/groupby/transform/test_transform.py +++ b/pandas/tests/groupby/transform/test_transform.py @@ -4,6 +4,7 @@ import pytest from pandas._libs import lib +from pandas.util._exceptions import Pandas4DeprecationWarning from pandas.core.dtypes.common import ensure_platform_int @@ -1105,7 +1106,7 @@ def test_transform_agg_by_name(request, reduction_func, frame_or_series): args = get_groupby_method_args(reduction_func, obj) if func == "corrwith": - warn = FutureWarning + warn = Pandas4DeprecationWarning msg = "DataFrameGroupBy.corrwith is deprecated" else: warn = None @@ -1476,7 +1477,7 @@ def test_as_index_no_change(keys, df, groupby_func): gb_as_index_true = df.groupby(keys, as_index=True) gb_as_index_false = df.groupby(keys, as_index=False) if groupby_func == "corrwith": - warn = FutureWarning + warn = Pandas4DeprecationWarning msg = "DataFrameGroupBy.corrwith is deprecated" else: warn = None diff --git a/pandas/tests/io/formats/test_to_markdown.py b/pandas/tests/io/formats/test_to_markdown.py index fffb1b9b9d2a4..cf3acbd87f1bb 100644 --- a/pandas/tests/io/formats/test_to_markdown.py +++ b/pandas/tests/io/formats/test_to_markdown.py @@ -2,6 +2,8 @@ import pytest +from pandas.util._exceptions import Pandas4DeprecationWarning + import pandas as pd import pandas._testing as tm @@ -15,7 +17,7 @@ def test_keyword_deprecation(): "except for the argument 'buf' will be keyword-only." ) s = pd.Series() - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): s.to_markdown(None, "wt") diff --git a/pandas/tests/io/formats/test_to_string.py b/pandas/tests/io/formats/test_to_string.py index 7c7069aa74eeb..5fd21806f724f 100644 --- a/pandas/tests/io/formats/test_to_string.py +++ b/pandas/tests/io/formats/test_to_string.py @@ -12,6 +12,8 @@ from pandas._config import using_pyarrow_string_dtype +from pandas.util._exceptions import Pandas4DeprecationWarning + from pandas import ( CategoricalIndex, DataFrame, @@ -42,7 +44,7 @@ def test_keyword_deprecation(self): "except for the argument 'buf' will be keyword-only." ) s = Series(["a", "b"]) - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): s.to_string(None, "NaN") def test_to_string_masked_ea_with_formatter(self): diff --git a/pandas/tests/io/json/test_json_table_schema.py b/pandas/tests/io/json/test_json_table_schema.py index a0d5b3a741aaf..a6a11a4ff7022 100644 --- a/pandas/tests/io/json/test_json_table_schema.py +++ b/pandas/tests/io/json/test_json_table_schema.py @@ -7,6 +7,8 @@ import numpy as np import pytest +from pandas.util._exceptions import Pandas4DeprecationWarning + from pandas.core.dtypes.dtypes import ( CategoricalDtype, DatetimeTZDtype, @@ -460,7 +462,9 @@ def test_date_format_raises(self, df_table): "version, please use 'iso' date format instead." ) with pytest.raises(ValueError, match=error_msg): - with tm.assert_produces_warning(FutureWarning, match=warning_msg): + with tm.assert_produces_warning( + Pandas4DeprecationWarning, match=warning_msg + ): df_table.to_json(orient="table", date_format="epoch") # others work diff --git a/pandas/tests/io/json/test_pandas.py b/pandas/tests/io/json/test_pandas.py index b53957a7e77d1..43edcd529f8be 100644 --- a/pandas/tests/io/json/test_pandas.py +++ b/pandas/tests/io/json/test_pandas.py @@ -13,6 +13,7 @@ from pandas._config import using_pyarrow_string_dtype from pandas.compat import IS64 +from pandas.util._exceptions import Pandas4DeprecationWarning import pandas.util._test_decorators as td import pandas as pd @@ -148,7 +149,7 @@ def test_frame_non_unique_columns(self, orient, data, request): "in a future version, please use 'iso' date format instead." ) if df.iloc[:, 0].dtype == "datetime64[s]": - expected_warning = FutureWarning + expected_warning = Pandas4DeprecationWarning with tm.assert_produces_warning(expected_warning, match=msg): result = read_json( @@ -780,7 +781,7 @@ def test_series_with_dtype_datetime(self, dtype, expected): "The default 'epoch' date format is deprecated and will be removed " "in a future version, please use 'iso' date format instead." ) - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): data = StringIO(s.to_json()) result = read_json(data, typ="series", dtype=dtype) tm.assert_series_equal(result, expected) @@ -831,13 +832,13 @@ def test_convert_dates(self, datetime_series, datetime_frame): "The default 'epoch' date format is deprecated and will be removed " "in a future version, please use 'iso' date format instead." ) - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): json = StringIO(df.to_json()) result = read_json(json) tm.assert_frame_equal(result, df) df["foo"] = 1.0 - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): json = StringIO(df.to_json(date_unit="ns")) result = read_json(json, convert_dates=False) @@ -848,7 +849,7 @@ def test_convert_dates(self, datetime_series, datetime_frame): # series ts = Series(Timestamp("20130101").as_unit("ns"), index=datetime_series.index) - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): json = StringIO(ts.to_json()) result = read_json(json, typ="series") tm.assert_series_equal(result, ts) @@ -870,7 +871,7 @@ def test_date_index_and_values(self, date_format, as_object, date_typ): expected_warning = None if date_format == "epoch": expected = '{"1577836800000":1577836800000,"null":null}' - expected_warning = FutureWarning + expected_warning = Pandas4DeprecationWarning else: expected = ( '{"2020-01-01T00:00:00.000":"2020-01-01T00:00:00.000","null":null}' @@ -984,7 +985,7 @@ def test_date_unit(self, unit, datetime_frame): "'epoch' date format is deprecated and will be removed in a future " "version, please use 'iso' date format instead." ) - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): json = df.to_json(date_format="epoch", date_unit=unit) # force date unit @@ -1004,13 +1005,13 @@ def test_date_unit(self, unit, datetime_frame): DataFrame( {"A": ["a", "b", "c"], "B": pd.to_timedelta(np.arange(3), unit="D")} ), - FutureWarning, + Pandas4DeprecationWarning, ), ( DataFrame( {"A": pd.to_datetime(["2020-01-01", "2020-02-01", "2020-03-01"])} ), - FutureWarning, + Pandas4DeprecationWarning, ), ], ) @@ -1096,7 +1097,7 @@ def test_doc_example(self): "The default 'epoch' date format is deprecated and will be removed " "in a future version, please use 'iso' date format instead." ) - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): json = StringIO(dfj2.to_json()) result = read_json(json, dtype={"ints": np.int64, "bools": np.bool_}) tm.assert_frame_equal(result, result) @@ -1138,20 +1139,20 @@ def test_timedelta(self): "The default 'epoch' date format is deprecated and will be removed " "in a future version, please use 'iso' date format instead." ) - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): result = read_json(StringIO(ser.to_json()), typ="series").apply(converter) tm.assert_series_equal(result, ser) ser = Series([timedelta(23), timedelta(seconds=5)], index=Index([0, 1])) assert ser.dtype == "timedelta64[ns]" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): result = read_json(StringIO(ser.to_json()), typ="series").apply(converter) tm.assert_series_equal(result, ser) frame = DataFrame([timedelta(23), timedelta(seconds=5)]) assert frame[0].dtype == "timedelta64[ns]" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): json = frame.to_json() tm.assert_frame_equal(frame, read_json(StringIO(json)).apply(converter)) @@ -1167,7 +1168,7 @@ def test_timedelta2(self): "The default 'epoch' date format is deprecated and will be removed " "in a future version, please use 'iso' date format instead." ) - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): data = StringIO(frame.to_json(date_unit="ns")) result = read_json(data) result["a"] = pd.to_timedelta(result.a, unit="ns") @@ -1202,7 +1203,7 @@ def test_timedelta_to_json(self, as_object, date_format, timedelta_typ): '{"P1DT0H0M0S":"P1DT0H0M0S","P2DT0H0M0S":"P2DT0H0M0S","null":null}' ) else: - expected_warning = FutureWarning + expected_warning = Pandas4DeprecationWarning expected = '{"86400000":86400000,"172800000":172800000,"null":null}' if as_object: @@ -1221,7 +1222,7 @@ def test_timedelta_to_json(self, as_object, date_format, timedelta_typ): def test_timedelta_to_json_fractional_precision(self, as_object, timedelta_typ): data = [timedelta_typ(milliseconds=42)] ser = Series(data, index=data) - warn = FutureWarning + warn = Pandas4DeprecationWarning if as_object: ser = ser.astype(object) warn = None @@ -1317,13 +1318,13 @@ def test_datetime_tz(self): "The default 'epoch' date format is deprecated and will be removed " "in a future version, please use 'iso' date format instead." ) - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): expected = df_naive.to_json() assert expected == df.to_json() stz = Series(tz_range) s_naive = Series(tz_naive) - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): assert stz.to_json() == s_naive.to_json() def test_sparse(self): @@ -1593,7 +1594,7 @@ def test_to_json_from_json_columns_dtypes(self, orient): "The default 'epoch' date format is deprecated and will be removed " "in a future version, please use 'iso' date format instead." ) - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): dfjson = expected.to_json(orient=orient) result = read_json( @@ -1787,7 +1788,7 @@ def test_timedelta_as_label(self, date_format, key): expected_warning = None if date_format == "epoch": - expected_warning = FutureWarning + expected_warning = Pandas4DeprecationWarning msg = ( "'epoch' date format is deprecated and will be removed in a future " @@ -2032,7 +2033,7 @@ def test_json_pandas_nulls(self, nulls_fixture, request): "in a future version, please use 'iso' date format instead." ) if nulls_fixture is pd.NaT: - expected_warning = FutureWarning + expected_warning = Pandas4DeprecationWarning with tm.assert_produces_warning(expected_warning, match=msg): result = DataFrame([[nulls_fixture]]).to_json() diff --git a/pandas/tests/io/test_gcs.py b/pandas/tests/io/test_gcs.py index 17b89c9f31616..b416c9bccd9fe 100644 --- a/pandas/tests/io/test_gcs.py +++ b/pandas/tests/io/test_gcs.py @@ -7,6 +7,8 @@ import numpy as np import pytest +from pandas.util._exceptions import Pandas4DeprecationWarning + from pandas import ( DataFrame, Index, @@ -82,7 +84,7 @@ def test_to_read_gcs(gcs_buffer, format, monkeypatch, capsys): "The default 'epoch' date format is deprecated and will be removed " "in a future version, please use 'iso' date format instead." ) - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): df1.to_json(path) df2 = read_json(path, convert_dates=["dt"]) elif format == "parquet": diff --git a/pandas/tests/resample/test_datetime_index.py b/pandas/tests/resample/test_datetime_index.py index c38d223c9d6a0..0b7d1a5382578 100644 --- a/pandas/tests/resample/test_datetime_index.py +++ b/pandas/tests/resample/test_datetime_index.py @@ -8,6 +8,7 @@ from pandas._libs import lib from pandas._typing import DatetimeNaTType from pandas.compat import is_platform_windows +from pandas.util._exceptions import Pandas4DeprecationWarning import pandas.util._test_decorators as td import pandas as pd @@ -1300,7 +1301,7 @@ def test_resample_consistency(unit): s10 = s.reindex(index=i10, method="bfill") s10_2 = s.reindex(index=i10, method="bfill", limit=2) - with tm.assert_produces_warning(FutureWarning): + with tm.assert_produces_warning(Pandas4DeprecationWarning): rl = s.reindex_like(s10, method="bfill", limit=2) r10_2 = s.resample("10Min").bfill(limit=2) r10 = s.resample("10Min").bfill() diff --git a/pandas/tests/scalar/timestamp/test_constructors.py b/pandas/tests/scalar/timestamp/test_constructors.py index 4ebdea3733484..5dce9c3660c28 100644 --- a/pandas/tests/scalar/timestamp/test_constructors.py +++ b/pandas/tests/scalar/timestamp/test_constructors.py @@ -20,6 +20,7 @@ from pandas._libs.tslibs.dtypes import NpyDatetimeUnit from pandas.compat import PY310 from pandas.errors import OutOfBoundsDatetime +from pandas.util._exceptions import Pandas4DeprecationWarning from pandas import ( NA, @@ -332,13 +333,13 @@ class TestTimestampClassMethodConstructors: def test_utcnow_deprecated(self): # GH#56680 msg = "Timestamp.utcnow is deprecated" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): Timestamp.utcnow() def test_utcfromtimestamp_deprecated(self): # GH#56680 msg = "Timestamp.utcfromtimestamp is deprecated" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): Timestamp.utcfromtimestamp(43) def test_constructor_strptime(self): diff --git a/pandas/tests/scalar/timestamp/test_timestamp.py b/pandas/tests/scalar/timestamp/test_timestamp.py index 79fd285073983..aa4234db92afd 100644 --- a/pandas/tests/scalar/timestamp/test_timestamp.py +++ b/pandas/tests/scalar/timestamp/test_timestamp.py @@ -31,6 +31,7 @@ tz_compare, ) from pandas.compat import IS64 +from pandas.util._exceptions import Pandas4DeprecationWarning from pandas import ( NaT, @@ -269,7 +270,7 @@ def test_disallow_setting_tz(self, tz): def test_default_to_stdlib_utc(self): msg = "Timestamp.utcnow is deprecated" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): assert Timestamp.utcnow().tz is timezone.utc assert Timestamp.now("UTC").tz is timezone.utc assert Timestamp("2016-01-01", tz="UTC").tz is timezone.utc @@ -314,13 +315,13 @@ def compare(x, y): compare(Timestamp.now("UTC"), datetime.now(pytz.timezone("UTC"))) compare(Timestamp.now("UTC"), datetime.now(tzutc())) msg = "Timestamp.utcnow is deprecated" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): compare(Timestamp.utcnow(), datetime.now(timezone.utc)) compare(Timestamp.today(), datetime.today()) current_time = calendar.timegm(datetime.now().utctimetuple()) msg = "Timestamp.utcfromtimestamp is deprecated" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): ts_utc = Timestamp.utcfromtimestamp(current_time) assert ts_utc.timestamp() == current_time compare( diff --git a/pandas/tests/series/accessors/test_cat_accessor.py b/pandas/tests/series/accessors/test_cat_accessor.py index ce8ea27ea1fa2..0df0e301a310f 100644 --- a/pandas/tests/series/accessors/test_cat_accessor.py +++ b/pandas/tests/series/accessors/test_cat_accessor.py @@ -1,6 +1,8 @@ import numpy as np import pytest +from pandas.util._exceptions import Pandas4DeprecationWarning + from pandas import ( Categorical, DataFrame, @@ -202,7 +204,7 @@ def test_dt_accessor_api_for_categorical(self, idx): warn_cls.append(UserWarning) elif func == "to_pytimedelta": # GH 57463 - warn_cls.append(FutureWarning) + warn_cls.append(Pandas4DeprecationWarning) if warn_cls: warn_cls = tuple(warn_cls) else: diff --git a/pandas/tests/series/accessors/test_dt_accessor.py b/pandas/tests/series/accessors/test_dt_accessor.py index 49ae0a60e6608..19bba4dd17f86 100644 --- a/pandas/tests/series/accessors/test_dt_accessor.py +++ b/pandas/tests/series/accessors/test_dt_accessor.py @@ -12,6 +12,7 @@ import pytz from pandas._libs.tslibs.timezones import maybe_get_tz +from pandas.util._exceptions import Pandas4DeprecationWarning from pandas.core.dtypes.common import ( is_integer_dtype, @@ -193,7 +194,7 @@ def test_dt_namespace_accessor_timedelta(self): tm.assert_index_equal(result.index, ser.index) msg = "The behavior of TimedeltaProperties.to_pytimedelta is deprecated" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(Pandas4DeprecationWarning, match=msg): result = ser.dt.to_pytimedelta() assert isinstance(result, np.ndarray) assert result.dtype == object diff --git a/pandas/tests/series/methods/test_reindex_like.py b/pandas/tests/series/methods/test_reindex_like.py index 10b8ac5817636..01f5ed308eeb7 100644 --- a/pandas/tests/series/methods/test_reindex_like.py +++ b/pandas/tests/series/methods/test_reindex_like.py @@ -2,6 +2,8 @@ import numpy as np +from pandas.util._exceptions import Pandas4DeprecationWarning + from pandas import Series import pandas._testing as tm @@ -20,7 +22,7 @@ def test_reindex_like(datetime_series): series1 = Series([5, None, None], [day1, day2, day3]) series2 = Series([None, None], [day1, day3]) - with tm.assert_produces_warning(FutureWarning): + with tm.assert_produces_warning(Pandas4DeprecationWarning): result = series1.reindex_like(series2, method="pad") expected = Series([5, np.nan], index=[day1, day3]) tm.assert_series_equal(result, expected) @@ -33,13 +35,13 @@ def test_reindex_like_nearest(): other = ser.reindex(target, method="nearest") expected = Series(np.around(target).astype("int64"), target) - with tm.assert_produces_warning(FutureWarning): + with tm.assert_produces_warning(Pandas4DeprecationWarning): result = ser.reindex_like(other, method="nearest") tm.assert_series_equal(expected, result) - with tm.assert_produces_warning(FutureWarning): + with tm.assert_produces_warning(Pandas4DeprecationWarning): result = ser.reindex_like(other, method="nearest", tolerance=1) tm.assert_series_equal(expected, result) - with tm.assert_produces_warning(FutureWarning): + with tm.assert_produces_warning(Pandas4DeprecationWarning): result = ser.reindex_like(other, method="nearest", tolerance=[1, 2, 3, 4]) tm.assert_series_equal(expected, result) diff --git a/pandas/tests/tools/test_to_datetime.py b/pandas/tests/tools/test_to_datetime.py index cbbd018720bad..ed77bd3887d59 100644 --- a/pandas/tests/tools/test_to_datetime.py +++ b/pandas/tests/tools/test_to_datetime.py @@ -1027,7 +1027,9 @@ def test_to_datetime_today(self, tz): def test_to_datetime_today_now_unicode_bytes(self, arg): to_datetime([arg]) - @pytest.mark.filterwarnings("ignore:Timestamp.utcnow is deprecated:FutureWarning") + @pytest.mark.filterwarnings( + "ignore:Timestamp.utcnow is deprecated:DeprecationWarning" + ) @pytest.mark.skipif(WASM, reason="tzset is not available on WASM") @pytest.mark.parametrize( "format, expected_ds", diff --git a/pandas/tests/util/test_deprecate.py b/pandas/tests/util/test_deprecate.py index 92f422b8269f5..bdbf2ca2d028d 100644 --- a/pandas/tests/util/test_deprecate.py +++ b/pandas/tests/util/test_deprecate.py @@ -37,7 +37,9 @@ def new_func_with_deprecation(): def test_deprecate_ok(): - depr_func = deprecate("depr_func", new_func, "1.0", msg="Use new_func instead.") + depr_func = deprecate( + "depr_func", new_func, "1.0", msg="Use new_func instead.", klass=FutureWarning + ) with tm.assert_produces_warning(FutureWarning): result = depr_func() @@ -48,7 +50,11 @@ def test_deprecate_ok(): def test_deprecate_no_docstring(): depr_func = deprecate( - "depr_func", new_func_no_docstring, "1.0", msg="Use new_func instead." + "depr_func", + new_func_no_docstring, + "1.0", + msg="Use new_func instead.", + klass=FutureWarning, ) with tm.assert_produces_warning(FutureWarning): result = depr_func() diff --git a/pandas/tests/util/test_deprecate_kwarg.py b/pandas/tests/util/test_deprecate_kwarg.py index b165e9fba0e4f..30923687a17e2 100644 --- a/pandas/tests/util/test_deprecate_kwarg.py +++ b/pandas/tests/util/test_deprecate_kwarg.py @@ -5,7 +5,7 @@ import pandas._testing as tm -@deprecate_kwarg("old", "new") +@deprecate_kwarg("old", "new", klass=FutureWarning) def _f1(new=False): return new @@ -13,7 +13,7 @@ def _f1(new=False): _f2_mappings = {"yes": True, "no": False} -@deprecate_kwarg("old", "new", _f2_mappings) +@deprecate_kwarg("old", "new", _f2_mappings, klass=FutureWarning) def _f2(new=False): return new @@ -22,7 +22,7 @@ def _f3_mapping(x): return x + 1 -@deprecate_kwarg("old", "new", _f3_mapping) +@deprecate_kwarg("old", "new", _f3_mapping, klass=FutureWarning) def _f3(new=0): return new @@ -70,7 +70,7 @@ def f4(new=None): return new -@deprecate_kwarg("old", None) +@deprecate_kwarg("old", None, klass=FutureWarning) def _f4(old=True, unchanged=True): return old, unchanged diff --git a/pandas/tests/util/test_deprecate_nonkeyword_arguments.py b/pandas/tests/util/test_deprecate_nonkeyword_arguments.py index f81d32b574682..ae2bd0b487019 100644 --- a/pandas/tests/util/test_deprecate_nonkeyword_arguments.py +++ b/pandas/tests/util/test_deprecate_nonkeyword_arguments.py @@ -10,7 +10,7 @@ @deprecate_nonkeyword_arguments( - version="1.1", allowed_args=["a", "b"], name="f_add_inputs" + version="1.1", allowed_args=["a", "b"], name="f_add_inputs", klass=FutureWarning ) def f(a, b=0, c=0, d=0): return a + b + c + d @@ -59,7 +59,7 @@ def test_three_arguments_with_name_in_warning(): assert f(6, 3, 3) == 12 -@deprecate_nonkeyword_arguments(version="1.1") +@deprecate_nonkeyword_arguments(version="1.1", klass=FutureWarning) def g(a, b=0, c=0, d=0): with tm.assert_produces_warning(None): return a + b + c + d @@ -88,7 +88,7 @@ def test_three_positional_argument_with_warning_message_analysis(): assert g(6, 3, 3) == 12 -@deprecate_nonkeyword_arguments(version="1.1") +@deprecate_nonkeyword_arguments(version="1.1", klass=FutureWarning) def h(a=0, b=0, c=0, d=0): return a + b + c + d @@ -113,7 +113,7 @@ def test_one_positional_argument_with_warning_message_analysis(): assert h(19) == 19 -@deprecate_nonkeyword_arguments(version="1.1") +@deprecate_nonkeyword_arguments(version="1.1", klass=UserWarning) def i(a=0, /, b=0, *, c=0, d=0): return a + b + c + d @@ -122,8 +122,15 @@ def test_i_signature(): assert str(inspect.signature(i)) == "(*, a=0, b=0, c=0, d=0)" +def test_i_warns_klass(): + with tm.assert_produces_warning(UserWarning): + assert i(1, 2) == 3 + + class Foo: - @deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "bar"]) + @deprecate_nonkeyword_arguments( + version=None, allowed_args=["self", "bar"], klass=FutureWarning + ) def baz(self, bar=None, foobar=None): ... diff --git a/pandas/tests/util/test_pandas_deprecation_warning.py b/pandas/tests/util/test_pandas_deprecation_warning.py new file mode 100644 index 0000000000000..f8a16e6ed8961 --- /dev/null +++ b/pandas/tests/util/test_pandas_deprecation_warning.py @@ -0,0 +1,25 @@ +import warnings + +from pandas.util._decorators import deprecate_kwarg +from pandas.util._exceptions import CurrentDeprecationWarning + +import pandas._testing as tm + + +def f1(): + warnings.warn("f1", CurrentDeprecationWarning) + + +def test_function_warns_pandas_deprecation_warning(): + with tm.assert_produces_warning(DeprecationWarning): + f1() + + +@deprecate_kwarg("old", "new") +def f2(new=0): + return new + + +def test_decorator_warns_pandas_deprecation_warning(): + with tm.assert_produces_warning(DeprecationWarning): + f2(old=1) diff --git a/pandas/util/_decorators.py b/pandas/util/_decorators.py index bdfb0b1cad8ae..33ab5b22557fc 100644 --- a/pandas/util/_decorators.py +++ b/pandas/util/_decorators.py @@ -16,7 +16,10 @@ F, T, ) -from pandas.util._exceptions import find_stack_level +from pandas.util._exceptions import ( + CurrentDeprecationWarning, + find_stack_level, +) if TYPE_CHECKING: from collections.abc import Mapping @@ -50,14 +53,15 @@ def deprecate( Version of pandas in which the method has been deprecated. alt_name : str, optional Name to use in preference of alternative.__name__. - klass : Warning, default FutureWarning + klass : Warning, optional + The warning class to use. stacklevel : int, default 2 msg : str The message to display in the warning. Default is '{name} is deprecated. Use {alt_name} instead.' """ alt_name = alt_name or alternative.__name__ - klass = klass or FutureWarning + klass = klass or CurrentDeprecationWarning warning_msg = msg or f"{name} is deprecated, use {alt_name} instead." @wraps(alternative) @@ -101,6 +105,7 @@ def deprecate_kwarg( old_arg_name: str, new_arg_name: str | None, mapping: Mapping[Any, Any] | Callable[[Any], Any] | None = None, + klass: type[Warning] | None = None, stacklevel: int = 2, ) -> Callable[[F], F]: """ @@ -109,7 +114,7 @@ def deprecate_kwarg( Parameters ---------- old_arg_name : str - Name of argument in function to deprecate + Name of argument in function to deprecate. new_arg_name : str or None Name of preferred argument in function. Use None to raise warning that ``old_arg_name`` keyword is deprecated. @@ -117,6 +122,9 @@ def deprecate_kwarg( If mapping is present, use it to translate old arguments to new arguments. A callable must do its own value checking; values not found in a dict will be forwarded unchanged. + klass : Warning, optional + The warning class to use. + stacklevel : int, default 2 Examples -------- @@ -151,20 +159,21 @@ def deprecate_kwarg( ... print(cols) >>> f(cols="should raise warning") # doctest: +SKIP FutureWarning: the 'cols' keyword is deprecated and will be removed in a - future version please takes steps to stop use of 'cols' + future version. Please take steps to stop the use of 'cols' should raise warning >>> f(another_param="should not raise warning") # doctest: +SKIP should not raise warning >>> f(cols="should raise warning", another_param="") # doctest: +SKIP FutureWarning: the 'cols' keyword is deprecated and will be removed in a - future version please takes steps to stop use of 'cols' + future version. Please take steps to stop the use of 'cols' should raise warning """ if mapping is not None and not hasattr(mapping, "get") and not callable(mapping): raise TypeError( "mapping from old to new argument values must be dict or callable!" ) + klass = klass or CurrentDeprecationWarning def _deprecate_kwarg(func: F) -> F: @wraps(func) @@ -178,7 +187,7 @@ def wrapper(*args, **kwargs) -> Callable[..., Any]: "will be removed in a future version. Please take " f"steps to stop the use of {old_arg_name!r}" ) - warnings.warn(msg, FutureWarning, stacklevel=stacklevel) + warnings.warn(msg, klass, stacklevel=stacklevel) kwargs[old_arg_name] = old_arg_value return func(*args, **kwargs) @@ -199,7 +208,7 @@ def wrapper(*args, **kwargs) -> Callable[..., Any]: f"use {new_arg_name!r} instead." ) - warnings.warn(msg, FutureWarning, stacklevel=stacklevel) + warnings.warn(msg, klass, stacklevel=stacklevel) if kwargs.get(new_arg_name) is not None: msg = ( f"Can only specify {old_arg_name!r} " @@ -264,6 +273,7 @@ def deprecate_nonkeyword_arguments( version: str | None, allowed_args: list[str] | None = None, name: str | None = None, + klass: type[Warning] | None = None, ) -> Callable[[F], F]: """ Decorator to deprecate a use of non-keyword arguments of a function. @@ -286,7 +296,11 @@ def deprecate_nonkeyword_arguments( The specific name of the function to show in the warning message. If None, then the Qualified name of the function is used. + + klass : Warning, optional + The warning class to use. """ + klass = klass or CurrentDeprecationWarning def decorate(func): old_sig = inspect.signature(func) @@ -324,7 +338,7 @@ def wrapper(*args, **kwargs): if len(args) > num_allow_args: warnings.warn( msg.format(arguments=_format_argument_list(allow_args)), - FutureWarning, + klass, stacklevel=find_stack_level(), ) return func(*args, **kwargs) diff --git a/pandas/util/_exceptions.py b/pandas/util/_exceptions.py index 5f50838d37315..4f3ec22d89fe1 100644 --- a/pandas/util/_exceptions.py +++ b/pandas/util/_exceptions.py @@ -11,6 +11,10 @@ from collections.abc import Generator from types import FrameType +Pandas4DeprecationWarning = DeprecationWarning +Pandas5DeprecationWarning = DeprecationWarning +CurrentDeprecationWarning = Pandas4DeprecationWarning + @contextlib.contextmanager def rewrite_exception(old_name: str, new_name: str) -> Generator[None, None, None]: