From 32261cc59e9938633a869d75aad8e6b1836c5574 Mon Sep 17 00:00:00 2001 From: Guillaume Lemaitre Date: Sun, 16 Jan 2022 22:04:35 +0100 Subject: [PATCH 1/4] MAINT remove deprecated function --- doc/developers_utils.rst | 45 +-------------- .../_cluster_centroids.py | 16 ------ imblearn/utils/deprecation.py | 4 +- imblearn/utils/testing.py | 56 ------------------- imblearn/utils/tests/test_testing.py | 36 ------------ 5 files changed, 3 insertions(+), 154 deletions(-) diff --git a/doc/developers_utils.rst b/doc/developers_utils.rst index 5a1dc5559..5999c974d 100644 --- a/doc/developers_utils.rst +++ b/doc/developers_utils.rst @@ -75,7 +75,7 @@ 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, use ``FutureWarning`` appropriately. In the following example, k is deprecated and renamed to n_clusters:: import warnings @@ -106,49 +106,6 @@ On the top of all the functionality provided by scikit-learn. imbalanced-learn provides :func:`deprecate_parameter`: which is used to deprecate a sampler's parameter (attribute) by another one. -Testing utilities -~~~~~~~~~~~~~~~~~ -Currently, imbalanced-learn provide a warning management utility. This feature -is going to be merge in pytest and will be removed when the pytest release will -have it. - -If using Python 2.7 or above, you may use this function as a -context manager:: - - >>> import warnings - >>> from imblearn.utils.testing import warns - >>> with warns(RuntimeWarning): - ... warnings.warn("my runtime warning", RuntimeWarning) - - >>> with warns(RuntimeWarning): - ... pass - Traceback (most recent call last): - ... - Failed: DID NOT WARN. No warnings of type ...RuntimeWarning... was emitted... - - >>> with warns(RuntimeWarning): - ... warnings.warn(UserWarning) - Traceback (most recent call last): - ... - Failed: DID NOT WARN. No warnings of type ...RuntimeWarning... was emitted... - -In the context manager form you may use the keyword argument ``match`` to assert -that the exception matches a text or regex:: - - >>> import warnings - >>> from imblearn.utils.testing import warns - >>> with warns(UserWarning, match='must be 0 or None'): - ... warnings.warn("value must be 0 or None", UserWarning) - - >>> with warns(UserWarning, match=r'must be \d+$'): - ... warnings.warn("value must be 42", UserWarning) - - >>> with warns(UserWarning, match=r'must be \d+$'): - ... warnings.warn("this is not here", UserWarning) - Traceback (most recent call last): - ... - AssertionError: 'must be \d+$' pattern not found in ['this is not here'] - Making a release ---------------- This section document the different steps that are necessary to make a new diff --git a/imblearn/under_sampling/_prototype_generation/_cluster_centroids.py b/imblearn/under_sampling/_prototype_generation/_cluster_centroids.py index b7f56274e..556f0c980 100644 --- a/imblearn/under_sampling/_prototype_generation/_cluster_centroids.py +++ b/imblearn/under_sampling/_prototype_generation/_cluster_centroids.py @@ -6,8 +6,6 @@ # Christos Aridas # License: MIT -import warnings - import numpy as np from scipy import sparse @@ -18,7 +16,6 @@ from ..base import BaseUnderSampler from ...utils import Substitution -from ...utils._docstring import _n_jobs_docstring from ...utils._docstring import _random_state_docstring from ...utils._validation import _deprecate_positional_args @@ -27,7 +24,6 @@ @Substitution( sampling_strategy=BaseUnderSampler._sampling_strategy_docstring, - n_jobs=_n_jobs_docstring, random_state=_random_state_docstring, ) class ClusterCentroids(BaseUnderSampler): @@ -65,11 +61,6 @@ class ClusterCentroids(BaseUnderSampler): .. versionadded:: 0.3.0 - {n_jobs} - - .. deprecated:: 0.7 - `n_jobs` was deprecated in 0.7 and will be removed in 0.9. - Attributes ---------- sampling_strategy_ : dict @@ -125,21 +116,14 @@ def __init__( random_state=None, estimator=None, voting="auto", - n_jobs="deprecated", ): super().__init__(sampling_strategy=sampling_strategy) self.random_state = random_state self.estimator = estimator self.voting = voting - self.n_jobs = n_jobs def _validate_estimator(self): """Private function to create the KMeans estimator""" - if self.n_jobs != "deprecated": - warnings.warn( - "'n_jobs' was deprecated in 0.7 and will be removed in 0.9", - FutureWarning, - ) if self.estimator is None: self.estimator_ = KMeans(random_state=self.random_state) else: diff --git a/imblearn/utils/deprecation.py b/imblearn/utils/deprecation.py index 1120dae0f..6d459b8d2 100644 --- a/imblearn/utils/deprecation.py +++ b/imblearn/utils/deprecation.py @@ -33,7 +33,7 @@ def deprecate_parameter(sampler, version_deprecation, param_deprecated, new_para f"'{param_deprecated}' is deprecated from {version_deprecation} and " f" will be removed in {version_removed} for the estimator " f"{sampler.__class__}.", - category=DeprecationWarning, + category=FutureWarning, ) else: if getattr(sampler, param_deprecated) is not None: @@ -41,6 +41,6 @@ def deprecate_parameter(sampler, version_deprecation, param_deprecated, new_para f"'{param_deprecated}' is deprecated from {version_deprecation} and " f"will be removed in {version_removed} for the estimator " f"{sampler.__class__}. Use '{new_param}' instead.", - category=DeprecationWarning, + category=FutureWarning, ) setattr(sampler, new_param, getattr(sampler, param_deprecated)) diff --git a/imblearn/utils/testing.py b/imblearn/utils/testing.py index 88abebd1b..4f3f1c8b9 100644 --- a/imblearn/utils/testing.py +++ b/imblearn/utils/testing.py @@ -6,15 +6,11 @@ import inspect import pkgutil -import warnings -from contextlib import contextmanager from importlib import import_module from operator import itemgetter from pathlib import Path -from re import compile from scipy import sparse -from pytest import warns as _warns from sklearn.base import BaseEstimator from sklearn.neighbors import KDTree @@ -116,58 +112,6 @@ def is_abstract(c): return sorted(set(estimators), key=itemgetter(0)) -@contextmanager -def warns(expected_warning, match=None): - r"""Assert that a warning is raised with an optional matching pattern. - - .. deprecated:: 0.8 - This function is deprecated in 0.8 and will be removed in 0.10. - Use `pytest.warns()` instead. - - Assert that a code block/function call warns ``expected_warning`` - and raise a failure exception otherwise. It can be used within a context - manager ``with``. - - Parameters - ---------- - expected_warning : Warning - Warning type. - - match : regex str or None, optional - The pattern to be matched. By default, no check is done. - - Yields - ------ - Nothing. - - Examples - -------- - >>> import warnings - >>> from imblearn.utils.testing import warns - >>> with warns(UserWarning, match=r'must be \d+$'): - ... warnings.warn("value must be 42", UserWarning) - """ - warnings.warn( - "The warns function is deprecated in 0.8 and will be removed in 0.10. " - "Use pytest.warns() instead." - ) - - with _warns(expected_warning) as record: - yield - - if match is not None: - for each in record: - if compile(match).search(str(each.message)) is not None: - break - else: - msg = "'{}' pattern not found in {}".format( - match, "{}".format([str(r.message) for r in record]) - ) - assert False, msg - else: - pass - - class _CustomNearestNeighbors(BaseEstimator): """Basic implementation of nearest neighbors not relying on scikit-learn. diff --git a/imblearn/utils/tests/test_testing.py b/imblearn/utils/tests/test_testing.py index 5d4ce2bde..9d1aaa5e9 100644 --- a/imblearn/utils/tests/test_testing.py +++ b/imblearn/utils/tests/test_testing.py @@ -12,8 +12,6 @@ from imblearn.base import SamplerMixin from imblearn.utils.testing import all_estimators, _CustomNearestNeighbors -from imblearn.utils.testing import warns - def test_all_estimators(): # check if the filtering is working with a list or a single string @@ -31,40 +29,6 @@ def test_all_estimators(): all_estimators(type_filter=type_filter) -@pytest.mark.filterwarnings("ignore:The warns function is deprecated in 0.8") -def test_warns(): - import warnings - - with warns(UserWarning, match=r"must be \d+$"): - warnings.warn("value must be 42", UserWarning) - - with pytest.raises(AssertionError, match="pattern not found"): - with warns(UserWarning, match=r"must be \d+$"): - warnings.warn("this is not here", UserWarning) - - with warns(UserWarning, match=r"aaa"): - warnings.warn("cccccccccc", UserWarning) - warnings.warn("bbbbbbbbbb", UserWarning) - warnings.warn("aaaaaaaaaa", UserWarning) - - a, b, c = ("aaa", "bbbbbbbbbb", "cccccccccc") - expected_msg = r"'{}' pattern not found in \['{}', '{}'\]".format(a, b, c) - with pytest.raises(AssertionError, match=expected_msg): - with warns(UserWarning, match=r"aaa"): - warnings.warn("bbbbbbbbbb", UserWarning) - warnings.warn("cccccccccc", UserWarning) - - -# TODO: remove in 0.9 -def test_warns_deprecation(): - import warnings - - with pytest.warns(None) as record: - with warns(UserWarning): - warnings.warn("value must be 42") - assert "The warns function is deprecated" in str(record[0].message) - - def test_custom_nearest_neighbors(): """Check that our custom nearest neighbors can be used for our internal duck-typing.""" From 9383dee8caac181371a59bbe2e6f666c97fca9c1 Mon Sep 17 00:00:00 2001 From: Guillaume Lemaitre Date: Sun, 16 Jan 2022 22:14:37 +0100 Subject: [PATCH 2/4] iter --- imblearn/utils/tests/test_deprecation.py | 7 ++++--- imblearn/utils/tests/test_validation.py | 10 +++------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/imblearn/utils/tests/test_deprecation.py b/imblearn/utils/tests/test_deprecation.py index 4f352aaae..f7e084dda 100644 --- a/imblearn/utils/tests/test_deprecation.py +++ b/imblearn/utils/tests/test_deprecation.py @@ -3,8 +3,9 @@ # Authors: Guillaume Lemaitre # License: MIT +import pytest + from imblearn.utils.deprecation import deprecate_parameter -from imblearn.utils.testing import warns class Sampler: @@ -14,7 +15,7 @@ def __init__(self): def test_deprecate_parameter(): - with warns(DeprecationWarning, match="is deprecated from"): + with pytest.warns(FutureWarning, match="is deprecated from"): deprecate_parameter(Sampler(), "0.2", "a") - with warns(DeprecationWarning, match="Use 'b' instead."): + with pytest.warns(FutureWarning, match="Use 'b' instead."): deprecate_parameter(Sampler(), "0.2", "a", "b") diff --git a/imblearn/utils/tests/test_validation.py b/imblearn/utils/tests/test_validation.py index 81db35a37..2cfe8e018 100644 --- a/imblearn/utils/tests/test_validation.py +++ b/imblearn/utils/tests/test_validation.py @@ -16,7 +16,7 @@ from imblearn.utils import check_neighbors_object from imblearn.utils import check_sampling_strategy from imblearn.utils import check_target_type -from imblearn.utils.testing import warns, _CustomNearestNeighbors +from imblearn.utils.testing import _CustomNearestNeighbors from imblearn.utils._validation import ArraysTransformer from imblearn.utils._validation import _deprecate_positional_args @@ -262,12 +262,8 @@ def test_check_sampling_strategy( def test_sampling_strategy_dict_over_sampling(): y = np.array([1] * 50 + [2] * 100 + [3] * 25) sampling_strategy = {1: 70, 2: 140, 3: 70} - expected_msg = ( - r"After over-sampling, the number of samples \(140\) in" - r" class 2 will be larger than the number of samples in" - r" the majority class \(class #2 -> 100\)" - ) - with warns(UserWarning, expected_msg): + expected_msg = "After over-sampling, the number of samples " + with pytest.warns(UserWarning, match=expected_msg): check_sampling_strategy(sampling_strategy, y, "over-sampling") From e26dd57b3c0491debd7d35e9fb182a605225786d Mon Sep 17 00:00:00 2001 From: Guillaume Lemaitre Date: Sun, 16 Jan 2022 22:15:51 +0100 Subject: [PATCH 3/4] iter --- imblearn/metrics/tests/test_classification.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/imblearn/metrics/tests/test_classification.py b/imblearn/metrics/tests/test_classification.py index 47a37a5b8..abd904a58 100644 --- a/imblearn/metrics/tests/test_classification.py +++ b/imblearn/metrics/tests/test_classification.py @@ -31,8 +31,6 @@ from imblearn.metrics import classification_report_imbalanced from imblearn.metrics import macro_averaged_mean_absolute_error -from imblearn.utils.testing import warns - RND_SEED = 42 R_TOL = 1e-2 @@ -182,7 +180,8 @@ def test_sensitivity_specificity_support_errors(): def test_sensitivity_specificity_unused_pos_label(): # but average != 'binary'; even if data is binary - with warns(UserWarning, r"use labels=\[pos_label\] to specify a single"): + msg = r"use labels=\[pos_label\] to specify a single" + with pytest.warns(UserWarning, match=msg): sensitivity_specificity_support( [1, 2, 1], [1, 2, 2], pos_label=2, average="macro" ) From 9fd16e4e025e22e0c2e3280698511eb531a60afb Mon Sep 17 00:00:00 2001 From: Guillaume Lemaitre Date: Sun, 16 Jan 2022 22:27:54 +0100 Subject: [PATCH 4/4] iter --- .../tests/test_cluster_centroids.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/imblearn/under_sampling/_prototype_generation/tests/test_cluster_centroids.py b/imblearn/under_sampling/_prototype_generation/tests/test_cluster_centroids.py index d7399dffd..02f9aaf1b 100644 --- a/imblearn/under_sampling/_prototype_generation/tests/test_cluster_centroids.py +++ b/imblearn/under_sampling/_prototype_generation/tests/test_cluster_centroids.py @@ -112,15 +112,6 @@ def test_fit_resample_error(cluster_centroids_params, err_msg): cc.fit_resample(X, Y) -def test_cluster_centroids_n_jobs(): - # check that we deprecate the `n_jobs` parameter. - cc = ClusterCentroids(n_jobs=1) - with pytest.warns(FutureWarning) as record: - cc.fit_resample(X, Y) - assert len(record) == 1 - assert "'n_jobs' was deprecated" in record[0].message.args[0] - - def test_cluster_centroids_hard_target_class(): # check that the samples selecting by the hard voting corresponds to the # targeted class