transformers/tests/utils/test_deprecation.py
Pavel Iakubovskii 517df566f5
Decorators for deprecation and named arguments validation (#30799)
* Fix do_reduce_labels for maskformer image processor

* Deprecate reduce_labels in favor to do_reduce_labels

* Deprecate reduce_labels in favor to do_reduce_labels (segformer)

* Deprecate reduce_labels in favor to do_reduce_labels (oneformer)

* Deprecate reduce_labels in favor to do_reduce_labels (maskformer)

* Deprecate reduce_labels in favor to do_reduce_labels (mask2former)

* Fix typo

* Update mask2former test

* fixup

* Update segmentation examples

* Update docs

* Fixup

* Imports fixup

* Add deprecation decorator draft

* Add deprecation decorator

* Fixup

* Add deprecate_kwarg decorator

* Validate kwargs decorator

* Kwargs validation (beit)

* fixup

* Kwargs validation (mask2former)

* Kwargs validation (maskformer)

* Kwargs validation (oneformer)

* Kwargs validation (segformer)

* Better message

* Fix oneformer processor save-load test

* Update src/transformers/utils/deprecation.py

Co-authored-by: amyeroberts <22614925+amyeroberts@users.noreply.github.com>

* Update src/transformers/utils/deprecation.py

Co-authored-by: amyeroberts <22614925+amyeroberts@users.noreply.github.com>

* Update src/transformers/utils/deprecation.py

Co-authored-by: Pablo Montalvo <39954772+molbap@users.noreply.github.com>

* Update src/transformers/utils/deprecation.py

Co-authored-by: Pablo Montalvo <39954772+molbap@users.noreply.github.com>

* Better handle classmethod warning

* Fix typo, remove warn

* Add header

* Docs and `additional_message`

* Move to filter decorator ot generic

* Proper deprecation for semantic segm scripts

* Add to __init__ and update import

* Basic tests for filter decorator

* Fix doc

* Override `to_dict()` to pop depracated `_max_size`

* Pop unused parameters

* Fix trailing whitespace

* Add test for deprecation

* Add deprecation warning control parameter

* Update generic test

* Fixup deprecation tests

* Introduce init service kwargs

* Revert popping unused params

* Revert oneformer test

* Allow "metadata" to pass

* Better docs

* Fix test

* Add notion in docstring

* Fix notification for both names

* Add func name to warning message

* Fixup

---------

Co-authored-by: amyeroberts <22614925+amyeroberts@users.noreply.github.com>
Co-authored-by: Pablo Montalvo <39954772+molbap@users.noreply.github.com>
2024-06-10 12:35:10 +01:00

171 lines
7.5 KiB
Python

# Copyright 2024 The HuggingFace Team. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import unittest
import warnings
from parameterized import parameterized
from transformers import __version__
from transformers.utils.deprecation import deprecate_kwarg
INFINITE_VERSION = "9999.0.0"
class DeprecationDecoratorTester(unittest.TestCase):
def test_rename_kwarg(self):
with warnings.catch_warnings():
warnings.simplefilter("ignore")
@deprecate_kwarg("deprecated_name", new_name="new_name", version=INFINITE_VERSION)
def dummy_function(new_name=None, other_name=None):
return new_name, other_name
# Test keyword argument is renamed
value, other_value = dummy_function(deprecated_name="old_value")
self.assertEqual(value, "old_value")
self.assertIsNone(other_value)
# Test deprecated keyword argument not passed
value, other_value = dummy_function(new_name="new_value")
self.assertEqual(value, "new_value")
self.assertIsNone(other_value)
# Test other keyword argument
value, other_value = dummy_function(other_name="other_value")
self.assertIsNone(value)
self.assertEqual(other_value, "other_value")
# Test deprecated and new args are passed, the new one should be returned
value, other_value = dummy_function(deprecated_name="old_value", new_name="new_value")
self.assertEqual(value, "new_value")
self.assertIsNone(other_value)
def test_rename_multiple_kwargs(self):
with warnings.catch_warnings():
warnings.simplefilter("ignore")
@deprecate_kwarg("deprecated_name1", new_name="new_name1", version=INFINITE_VERSION)
@deprecate_kwarg("deprecated_name2", new_name="new_name2", version=INFINITE_VERSION)
def dummy_function(new_name1=None, new_name2=None, other_name=None):
return new_name1, new_name2, other_name
# Test keyword argument is renamed
value1, value2, other_value = dummy_function(deprecated_name1="old_value1", deprecated_name2="old_value2")
self.assertEqual(value1, "old_value1")
self.assertEqual(value2, "old_value2")
self.assertIsNone(other_value)
# Test deprecated keyword argument is not passed
value1, value2, other_value = dummy_function(new_name1="new_value1", new_name2="new_value2")
self.assertEqual(value1, "new_value1")
self.assertEqual(value2, "new_value2")
self.assertIsNone(other_value)
# Test other keyword argument is passed and correctly returned
value1, value2, other_value = dummy_function(other_name="other_value")
self.assertIsNone(value1)
self.assertIsNone(value2)
self.assertEqual(other_value, "other_value")
def test_warnings(self):
# Test warning is raised for future version
@deprecate_kwarg("deprecated_name", new_name="new_name", version=INFINITE_VERSION)
def dummy_function(new_name=None, other_name=None):
return new_name, other_name
with self.assertWarns(FutureWarning):
dummy_function(deprecated_name="old_value")
# Test warning is not raised for past version, but arg is still renamed
@deprecate_kwarg("deprecated_name", new_name="new_name", version="0.0.0")
def dummy_function(new_name=None, other_name=None):
return new_name, other_name
with warnings.catch_warnings(record=True) as raised_warnings:
warnings.simplefilter("always")
value, other_value = dummy_function(deprecated_name="old_value")
self.assertEqual(value, "old_value")
self.assertIsNone(other_value)
self.assertEqual(len(raised_warnings), 0, f"Warning raised: {[w.message for w in raised_warnings]}")
# Test warning is raised for future version if warn_if_greater_or_equal_version is set
@deprecate_kwarg("deprecated_name", version="0.0.0", warn_if_greater_or_equal_version=True)
def dummy_function(deprecated_name=None):
return deprecated_name
with self.assertWarns(FutureWarning):
value = dummy_function(deprecated_name="deprecated_value")
self.assertEqual(value, "deprecated_value")
# Test arg is not renamed if new_name is not specified, but warning is raised
@deprecate_kwarg("deprecated_name", version=INFINITE_VERSION)
def dummy_function(deprecated_name=None):
return deprecated_name
with self.assertWarns(FutureWarning):
value = dummy_function(deprecated_name="deprecated_value")
self.assertEqual(value, "deprecated_value")
def test_raises(self):
# Test if deprecated name and new name are both passed and raise_if_both_names is set -> raise error
@deprecate_kwarg("deprecated_name", new_name="new_name", version=INFINITE_VERSION, raise_if_both_names=True)
def dummy_function(new_name=None, other_name=None):
return new_name, other_name
with self.assertRaises(ValueError):
dummy_function(deprecated_name="old_value", new_name="new_value")
# Test for current version == deprecation version
@deprecate_kwarg("deprecated_name", version=__version__, raise_if_greater_or_equal_version=True)
def dummy_function(deprecated_name=None):
return deprecated_name
with self.assertRaises(ValueError):
dummy_function(deprecated_name="old_value")
# Test for current version > deprecation version
@deprecate_kwarg("deprecated_name", version="0.0.0", raise_if_greater_or_equal_version=True)
def dummy_function(deprecated_name=None):
return deprecated_name
with self.assertRaises(ValueError):
dummy_function(deprecated_name="old_value")
def test_additional_message(self):
# Test additional message is added to the warning
@deprecate_kwarg("deprecated_name", version=INFINITE_VERSION, additional_message="Additional message")
def dummy_function(deprecated_name=None):
return deprecated_name
with warnings.catch_warnings(record=True) as raised_warnings:
warnings.simplefilter("always")
dummy_function(deprecated_name="old_value")
self.assertTrue("Additional message" in str(raised_warnings[0].message))
@parameterized.expand(["0.0.0", __version__, INFINITE_VERSION])
def test_warning_for_both_names(self, version):
# We should raise warning if both names are passed for any specified version
@deprecate_kwarg("deprecated_name", new_name="new_name", version=version)
def dummy_function(new_name=None, **kwargs):
return new_name
with self.assertWarns(FutureWarning):
result = dummy_function(deprecated_name="old_value", new_name="new_value")
self.assertEqual(result, "new_value")