Skip to content

Commit

Permalink
MNT Replace DeprecationWarning with FutureWarning (#15080)
Browse files Browse the repository at this point in the history
* bruteforce renaming

* WIP

* WIP

* some more

* removed weird line

* update -Werror

* testiforest

* again

* Fixed some tests

* fixed some tests

* removed -Werror

* fixed test_docstring_param issue

* fixed some tests

* some more

* renamed to SklearnDeprecationWarning

* pep8

* updated docs

* pep8

* merge

* changed to FutureWarning

* fixes

* Update doc/developers/tips.rst

Co-Authored-By: Adrin Jalali <adrin.jalali@gmail.com>

* avoid duplicates

* fixed warning for deprecations

* Still make CI break if DeprecationWarning isn't caught

* updated one warning

* fixed test

* fixed some renamings

* updated new dep warnings

* fixed bad import

* ignore warnings

* update again

* ignore futurewarning when walking packages

* Fixed test

* pep8

* Added whatsnew
  • Loading branch information
NicolasHug authored and adrinjalali committed Oct 29, 2019
1 parent 546c42d commit 19ad136
Show file tree
Hide file tree
Showing 64 changed files with 251 additions and 207 deletions.
9 changes: 6 additions & 3 deletions doc/developers/contributing.rst
Expand Up @@ -826,15 +826,17 @@ E.g., renaming an attribute ``labels_`` to ``classes_`` can be done as::
def labels_(self):
return self.classes_

If a parameter has to be deprecated, use ``DeprecationWarning`` appropriately.
If a parameter has to be deprecated, a ``FutureWarning`` warning
must be raised too.
In the following example, k is deprecated and renamed to n_clusters::

import warnings

def example_function(n_clusters=8, k='deprecated'):
if k != 'deprecated':
warnings.warn("'k' was renamed to n_clusters in version 0.13 and "
"will be removed in 0.15.", DeprecationWarning)
"will be removed in 0.15.",
FutureWarning)
n_clusters = k

When the change is in a class, we validate and raise warning in ``fit``::
Expand All @@ -849,7 +851,8 @@ When the change is in a class, we validate and raise warning in ``fit``::
def fit(self, X, y):
if self.k != 'deprecated':
warnings.warn("'k' was renamed to n_clusters in version 0.13 and "
"will be removed in 0.15.", DeprecationWarning)
"will be removed in 0.15.",
FutureWarning)
self._n_clusters = self.k
else:
self._n_clusters = self.n_clusters
Expand Down
8 changes: 4 additions & 4 deletions doc/developers/tips.rst
Expand Up @@ -102,10 +102,10 @@ Other `pytest` options that may become useful include:
statements
- ``--tb=short`` or ``--tb=line`` to control the length of the logs

Since our continuous integration tests will error if ``DeprecationWarning``
or ``FutureWarning`` aren't properly caught, it is also recommended to run
``pytest`` along with the ``-Werror::DeprecationWarning`` and
``-Werror::FutureWarning`` flags.
Since our continuous integration tests will error if
``FutureWarning`` isn't properly caught,
it is also recommended to run ``pytest`` along with the
``-Werror::FutureWarning`` flag.

.. _saved_replies:

Expand Down
13 changes: 13 additions & 0 deletions doc/whats_new/v0.22.rst
Expand Up @@ -13,6 +13,19 @@ For a short description of the main highlights of the release, please
refer to
:ref:`sphx_glr_auto_examples_release_highlights_plot_release_highlights_0_22_0.py`.


Deprecations: using ``FutureWarning`` from now on
-------------------------------------------------

When deprecating a feature, previous versions of scikit-learn used to raise
a ``DeprecationWarning``. Since the ``DeprecationWarnings`` aren't shown by
default by Python, scikit-learn needed to resort to a custom warning filter
that would always show the warnings.

This filter is now removed, and starting from 0.22 scikit-learn will show
``FutureWarnings`` for deprecations. :pr:`15080` by `Nicolas Hug`_.


Changed models
--------------

Expand Down
5 changes: 0 additions & 5 deletions sklearn/__init__.py
Expand Up @@ -14,7 +14,6 @@
"""
import sys
import re
import warnings
import logging
import os

Expand All @@ -25,10 +24,6 @@
logger.setLevel(logging.INFO)


# Make sure that DeprecationWarning within this package always gets printed
warnings.filterwarnings('always', category=DeprecationWarning,
module=r'^{0}\.'.format(re.escape(__name__)))

# PEP0440 compatible formatted version, see:
# https://www.python.org/dev/peps/pep-0440/
#
Expand Down
2 changes: 1 addition & 1 deletion sklearn/cluster/tests/test_hierarchical.py
Expand Up @@ -734,6 +734,6 @@ def test_n_components_deprecation():

match = ("``n_components_`` attribute was deprecated "
"in favor of ``n_connected_components_``")
with pytest.warns(DeprecationWarning, match=match):
with pytest.warns(FutureWarning, match=match):
n = agc.n_components_
assert n == agc.n_connected_components_
2 changes: 1 addition & 1 deletion sklearn/compose/_column_transformer.py
Expand Up @@ -422,7 +422,7 @@ def _validate_features(self, n_features, feature_names):
warnings.warn("Given feature/column names or counts do not match "
"the ones for the data given during fit. This will "
"fail from v0.24.",
DeprecationWarning)
FutureWarning)

def _log_message(self, name, idx, total):
if not self.verbose:
Expand Down
10 changes: 5 additions & 5 deletions sklearn/compose/tests/test_column_transformer.py
Expand Up @@ -500,7 +500,7 @@ def test_column_transformer_invalid_columns(remainder):
X_array_more = np.array([[0, 1, 2], [2, 4, 6], [3, 6, 9]]).T
msg = ("Given feature/column names or counts do not match the ones for "
"the data given during fit.")
with pytest.warns(DeprecationWarning, match=msg):
with pytest.warns(FutureWarning, match=msg):
ct.transform(X_array_more) # Should accept added columns, for now
X_array_fewer = np.array([[0, 1, 2], ]).T
err_msg = 'Number of features'
Expand Down Expand Up @@ -1108,7 +1108,7 @@ def test_column_transformer_reordered_column_names_remainder(explicit_colname):
# No error for added columns if ordering is identical
X_extended_df = X_fit_df.copy()
X_extended_df['third'] = [3, 6, 9]
with pytest.warns(DeprecationWarning, match=warn_msg):
with pytest.warns(FutureWarning, match=warn_msg):
tf.transform(X_extended_df) # No error should be raised, for now

# No 'columns' AttributeError when transform input is a numpy array
Expand All @@ -1133,13 +1133,13 @@ def test_feature_name_validation():

msg = ("Given feature/column names or counts do not match the ones for "
"the data given during fit.")
with pytest.warns(DeprecationWarning, match=msg):
with pytest.warns(FutureWarning, match=msg):
tf.transform(df_extra)

tf = ColumnTransformer([('bycol', Trans(), [0])])
tf.fit(df)

with pytest.warns(DeprecationWarning, match=msg):
with pytest.warns(FutureWarning, match=msg):
tf.transform(X_extra)

with warnings.catch_warnings(record=True) as warns:
Expand All @@ -1149,7 +1149,7 @@ def test_feature_name_validation():
tf = ColumnTransformer([('bycol', Trans(), ['a'])],
remainder=Trans())
tf.fit(df)
with pytest.warns(DeprecationWarning, match=msg):
with pytest.warns(FutureWarning, match=msg):
tf.transform(df_extra)

tf = ColumnTransformer([('bycol', Trans(), [0, -1])])
Expand Down
2 changes: 1 addition & 1 deletion sklearn/datasets/_base.py
Expand Up @@ -932,6 +932,6 @@ def _refresh_cache(files, compress):
"import path. Consider removing the following files "
"and allowing it to be cached anew:\n%s"
% ("\n".join(files)))
warnings.warn(message=message, category=DeprecationWarning)
warnings.warn(message=message, category=FutureWarning)

return data[0] if len(data) == 1 else data
8 changes: 4 additions & 4 deletions sklearn/datasets/tests/test_base.py
Expand Up @@ -292,11 +292,11 @@ def _load_warn(*args, **kwargs):
"If this warning is raised when loading pickled models, you "
"may need to re-serialize those models with scikit-learn "
"0.21+.")
warnings.warn(msg, DeprecationWarning)
warnings.warn(msg, FutureWarning)
return 0

def _load_warn_unrelated(*args, **kwargs):
warnings.warn("unrelated warning", DeprecationWarning)
warnings.warn("unrelated warning", FutureWarning)
return 0

def _dump_safe(*args, **kwargs):
Expand All @@ -312,7 +312,7 @@ def _dump_raise(*args, **kwargs):
monkeypatch.setattr(joblib, "load", _load_warn)
monkeypatch.setattr(joblib, "dump", _dump_raise)
msg = "This dataset will stop being loadable in scikit-learn"
with pytest.warns(DeprecationWarning, match=msg):
with pytest.warns(FutureWarning, match=msg):
_refresh_cache('test', 0)

# make sure no warning is raised if load raises the warning, but dump
Expand All @@ -327,5 +327,5 @@ def _dump_raise(*args, **kwargs):
# by _refresh_cache
monkeypatch.setattr(joblib, "load", _load_warn_unrelated)
monkeypatch.setattr(joblib, "dump", _dump_safe)
with pytest.warns(DeprecationWarning, match="unrelated warning"):
with pytest.warns(FutureWarning, match="unrelated warning"):
_refresh_cache('test', 0)
2 changes: 1 addition & 1 deletion sklearn/decomposition/_sparse_pca.py
Expand Up @@ -20,7 +20,7 @@ def _check_normalize_components(normalize_components, estimator_name):
warnings.warn(
"'normalize_components' has been deprecated in 0.22 and "
"will be removed in 0.24. Remove the parameter from the "
" constructor.", DeprecationWarning
" constructor.", FutureWarning
)
else:
raise NotImplementedError(
Expand Down
3 changes: 1 addition & 2 deletions sklearn/decomposition/tests/test_sparse_pca.py
Expand Up @@ -13,7 +13,6 @@
from sklearn.decomposition import SparsePCA, MiniBatchSparsePCA, PCA
from sklearn.utils import check_random_state


def generate_toy_data(n_components, n_samples, image_size, random_state=None):
n_features = image_size[0] * image_size[1]

Expand Down Expand Up @@ -196,7 +195,7 @@ def test_spca_deprecation_warning(spca):
Y, _, _ = generate_toy_data(3, 10, (8, 8), random_state=rng)

warn_msg = "'normalize_components' has been deprecated in 0.22"
with pytest.warns(DeprecationWarning, match=warn_msg):
with pytest.warns(FutureWarning, match=warn_msg):
spca(normalize_components=True).fit(Y)


Expand Down
2 changes: 1 addition & 1 deletion sklearn/ensemble/_base.py
Expand Up @@ -230,7 +230,7 @@ def _validate_estimators(self):
warnings.warn(
"Using 'None' to drop an estimator from the ensemble is "
"deprecated in 0.22 and support will be dropped in 0.24. "
"Use the string 'drop' instead.", DeprecationWarning
"Use the string 'drop' instead.", FutureWarning
)

has_estimator = any(est not in (None, 'drop') for est in estimators)
Expand Down
2 changes: 1 addition & 1 deletion sklearn/ensemble/_gb.py
Expand Up @@ -1339,7 +1339,7 @@ def _check_params(self):
"suppress this warning by not passing any value "
"to the 'presort' parameter. We also recommend "
"using HistGradientBoosting models instead.",
DeprecationWarning)
FutureWarning)

def _init_state(self):
"""Initialize model state and allocate model state data structures. """
Expand Down
2 changes: 1 addition & 1 deletion sklearn/ensemble/_iforest.py
Expand Up @@ -233,7 +233,7 @@ def fit(self, X, y=None, sample_weight=None):
warn(
"'behaviour' is deprecated in 0.22 and will be removed "
"in 0.24. You should not pass or set this parameter.",
DeprecationWarning
FutureWarning
)
else:
raise NotImplementedError(
Expand Down
3 changes: 2 additions & 1 deletion sklearn/ensemble/tests/test_forest.py
Expand Up @@ -1238,7 +1238,8 @@ def test_min_impurity_split():

for Estimator in all_estimators:
est = Estimator(min_impurity_split=0.1)
est = assert_warns_message(DeprecationWarning, "min_impurity_decrease",
est = assert_warns_message(FutureWarning,
"min_impurity_decrease",
est.fit, X, y)
for tree in est.estimators_:
assert tree.min_impurity_split == 0.1
Expand Down
5 changes: 3 additions & 2 deletions sklearn/ensemble/tests/test_gradient_boosting.py
Expand Up @@ -1087,7 +1087,8 @@ def test_min_impurity_split(GBEstimator):
X, y = datasets.make_hastie_10_2(n_samples=100, random_state=1)

est = GBEstimator(min_impurity_split=0.1)
est = assert_warns_message(DeprecationWarning, "min_impurity_decrease",
est = assert_warns_message(FutureWarning,
"min_impurity_decrease",
est.fit, X, y)
for tree in est.estimators_.flat:
assert tree.min_impurity_split == 0.1
Expand Down Expand Up @@ -1400,6 +1401,6 @@ def test_presort_deprecated(Cls, presort):
X = np.zeros((10, 10))
y = np.r_[[0] * 5, [1] * 5]
gb = Cls(presort=presort)
with pytest.warns(DeprecationWarning,
with pytest.warns(FutureWarning,
match="The parameter 'presort' is deprecated "):
gb.fit(X, y)
2 changes: 1 addition & 1 deletion sklearn/ensemble/tests/test_iforest.py
Expand Up @@ -320,7 +320,7 @@ def test_iforest_chunks_works2(
def test_iforest_deprecation():
iforest = IsolationForest(behaviour='new')
warn_msg = "'behaviour' is deprecated in 0.22 and will be removed in 0.24"
with pytest.warns(DeprecationWarning, match=warn_msg):
with pytest.warns(FutureWarning, match=warn_msg):
iforest.fit(iris.data)


Expand Down
18 changes: 9 additions & 9 deletions sklearn/ensemble/tests/test_partial_dependence.py
Expand Up @@ -27,7 +27,7 @@
iris = datasets.load_iris()


@ignore_warnings(category=DeprecationWarning)
@ignore_warnings(category=FutureWarning)
def test_partial_dependence_classifier():
# Test partial dependence for classifier
clf = GradientBoostingClassifier(n_estimators=10, random_state=1)
Expand Down Expand Up @@ -66,7 +66,7 @@ def test_partial_dependence_classifier():
assert np.all(np.abs(pdp_w2 - pdp_w) / np.abs(pdp_w) > 0.1)


@ignore_warnings(category=DeprecationWarning)
@ignore_warnings(category=FutureWarning)
def test_partial_dependence_multiclass():
# Test partial dependence for multi-class classifier
clf = GradientBoostingClassifier(n_estimators=10, random_state=1)
Expand All @@ -82,7 +82,7 @@ def test_partial_dependence_multiclass():
assert axes[0].shape[0] == grid_resolution


@ignore_warnings(category=DeprecationWarning)
@ignore_warnings(category=FutureWarning)
def test_partial_dependence_regressor():
# Test partial dependence for regressor
clf = GradientBoostingRegressor(n_estimators=10, random_state=1)
Expand All @@ -96,7 +96,7 @@ def test_partial_dependence_regressor():
assert axes[0].shape[0] == grid_resolution


@ignore_warnings(category=DeprecationWarning)
@ignore_warnings(category=FutureWarning)
def test_partial_dependence_sample_weight():
# Test near perfect correlation between partial dependence and diagonal
# when sample weights emphasize y = x predictions
Expand All @@ -122,7 +122,7 @@ def test_partial_dependence_sample_weight():
assert np.corrcoef(np.ravel(pdp[0]), grid)[0, 1] > 0.99


@ignore_warnings(category=DeprecationWarning)
@ignore_warnings(category=FutureWarning)
def test_partial_dependecy_input():
# Test input validation of partial dependence.
clf = GradientBoostingClassifier(n_estimators=10, random_state=1)
Expand Down Expand Up @@ -151,7 +151,7 @@ def test_partial_dependecy_input():
assert_raises(ValueError, partial_dependence, clf, [0], grid=grid)


@ignore_warnings(category=DeprecationWarning)
@ignore_warnings(category=FutureWarning)
@pytest.mark.filterwarnings('ignore: Using or importing the ABCs from')
# matplotlib Python3.7 warning
def test_plot_partial_dependence(pyplot):
Expand Down Expand Up @@ -187,7 +187,7 @@ def test_plot_partial_dependence(pyplot):

@pytest.mark.filterwarnings('ignore: Using or importing the ABCs from')
# matplotlib Python3.7 warning
@ignore_warnings(category=DeprecationWarning)
@ignore_warnings(category=FutureWarning)
def test_plot_partial_dependence_input(pyplot):
# Test partial dependence plot function input checks.
clf = GradientBoostingClassifier(n_estimators=10, random_state=1)
Expand Down Expand Up @@ -224,7 +224,7 @@ def test_plot_partial_dependence_input(pyplot):

@pytest.mark.filterwarnings('ignore: Using or importing the ABCs from')
# matplotlib Python3.7 warning
@ignore_warnings(category=DeprecationWarning)
@ignore_warnings(category=FutureWarning)
def test_plot_partial_dependence_multiclass(pyplot):
# Test partial dependence plot function on multi-class input.
clf = GradientBoostingClassifier(n_estimators=10, random_state=1)
Expand Down Expand Up @@ -273,5 +273,5 @@ def test_raise_deprecation_warning(pyplot, func, params):
warn_msg = "The function ensemble.{} has been deprecated".format(
func.__name__
)
with pytest.warns(DeprecationWarning, match=warn_msg):
with pytest.warns(FutureWarning, match=warn_msg):
func(clf, **params, grid_resolution=grid_resolution)
2 changes: 1 addition & 1 deletion sklearn/ensemble/tests/test_voting.py
Expand Up @@ -558,7 +558,7 @@ def test_deprecate_none_transformer(Voter, BaseEstimator):
msg = ("Using 'None' to drop an estimator from the ensemble is "
"deprecated in 0.22 and support will be dropped in 0.24. "
"Use the string 'drop' instead.")
with pytest.warns(DeprecationWarning, match=msg):
with pytest.warns(FutureWarning, match=msg):
est.fit(X, y)


Expand Down
2 changes: 1 addition & 1 deletion sklearn/externals/joblib/__init__.py
Expand Up @@ -12,4 +12,4 @@
"those models with scikit-learn 0.21+.")

if not hasattr(sys, "_is_pytest_session"):
warnings.warn(msg, category=DeprecationWarning)
warnings.warn(msg, category=FutureWarning)
2 changes: 1 addition & 1 deletion sklearn/externals/six.py
Expand Up @@ -28,7 +28,7 @@
warnings.warn("The module is deprecated in version 0.21 and will be removed "
"in version 0.23 since we've dropped support for Python 2.7. "
"Please rely on the official version of six "
"(https://pypi.org/project/six/).", DeprecationWarning)
"(https://pypi.org/project/six/).", FutureWarning)

__author__ = "Benjamin Peterson <benjamin@python.org>"
__version__ = "1.4.1"
Expand Down
2 changes: 1 addition & 1 deletion sklearn/feature_extraction/tests/test_feature_hasher.py
Expand Up @@ -144,7 +144,7 @@ def test_hasher_zeros():
assert X.data.shape == (0,)


@ignore_warnings(category=DeprecationWarning)
@ignore_warnings(category=FutureWarning)
def test_hasher_alternate_sign():
X = [list("Thequickbrownfoxjumped")]

Expand Down
2 changes: 1 addition & 1 deletion sklearn/feature_extraction/tests/test_image.py
Expand Up @@ -340,5 +340,5 @@ def test_width_patch():
def test_extract_patches_deprecated():
msg = ("The function feature_extraction.image.extract_patches has been "
"deprecated in 0.22 and will be removed in 0.24.")
with pytest.warns(DeprecationWarning, match=msg):
with pytest.warns(FutureWarning, match=msg):
extract_patches(downsampled_face)

0 comments on commit 19ad136

Please sign in to comment.