diff --git a/qiskit_optimization/deprecation.py b/qiskit_optimization/deprecation.py deleted file mode 100644 index 772d9791d..000000000 --- a/qiskit_optimization/deprecation.py +++ /dev/null @@ -1,423 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2021, 2022. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -"""Contains the Deprecation message methods.""" - -from abc import abstractmethod -import warnings -import functools -import inspect -from typing import NamedTuple, Optional, Callable, Dict, Set, cast, Any -from enum import Enum, EnumMeta - - -class DeprecatedEnum(Enum): - """ - Shows deprecate message whenever member is accessed - """ - - def __new__(cls, value, *args): - member = object.__new__(cls) - member._value_ = value - member._args = args - member._show_deprecate = member.deprecate - return member - - @abstractmethod - def deprecate(self): - """show deprecate message""" - pass - - -class DeprecatedEnumMeta(EnumMeta): - """ - Shows deprecate message whenever member is accessed - """ - - def __getattribute__(cls, name): - obj = super().__getattribute__(name) - if isinstance(obj, DeprecatedEnum) and obj._show_deprecate: - obj._show_deprecate() - return obj - - def __getitem__(cls, name): - member = super().__getitem__(name) - if member._show_deprecate: - member._show_deprecate() - return member - - # pylint: disable=redefined-builtin - def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1): - obj = super().__call__( - value, names, module=module, qualname=qualname, type=type, start=start - ) - if isinstance(obj, DeprecatedEnum) and obj._show_deprecate: - obj._show_deprecate() - return obj - - -class DeprecatedType(Enum): - """ " Deprecation Types""" - - PACKAGE = "package" - ENUM = "enum" - CLASS = "class" - METHOD = "method" - FUNCTION = "function" - ARGUMENT = "argument" - PROPERTY = "property" - - -class _DeprecatedTypeName(NamedTuple): - version: str - old_type: DeprecatedType - old_name: str - new_type: DeprecatedType - new_name: str - additional_msg: str - - -class _DeprecatedArgument(NamedTuple): - version: str - func_qualname: str - old_arg: str - new_arg: str - additional_msg: str - - -class _DeprecatedValue(NamedTuple): - version: str - func_qualname: str - argument: str - old_value: str - new_value: str - additional_msg: str - - -_DEPRECATED_OBJECTS: Set[NamedTuple] = set() - - -def warn_deprecated( - version: str, - old_type: DeprecatedType, - old_name: str, - new_type: Optional[DeprecatedType] = None, - new_name: Optional[str] = None, - additional_msg: Optional[str] = None, - stack_level: int = 2, -) -> None: - """Emits deprecation warning the first time only - Args: - version: Version to be used - old_type: Old type to be used - old_name: Old name to be used - new_type: New type to be used, if None, old_type is used instead. - new_name: New name to be used - additional_msg: any additional message - stack_level: stack level - """ - # skip if it was already added - obj = _DeprecatedTypeName(version, old_type, old_name, new_type, new_name, additional_msg) - if obj in _DEPRECATED_OBJECTS: - return - - _DEPRECATED_OBJECTS.add(cast(NamedTuple, obj)) - - msg = ( - f"The {old_name} {old_type.value} is deprecated as of version {version} " - "and will be removed no sooner than 3 months after the release" - ) - if new_name: - type_str = new_type.value if new_type is not None else old_type.value - msg += f". Instead use the {new_name} {type_str}" - if additional_msg: - msg += f" {additional_msg}" - msg += "." - - warnings.warn(msg, DeprecationWarning, stacklevel=stack_level + 1) - - -def warn_deprecated_same_type_name( - version: str, - new_type: DeprecatedType, - new_name: str, - additional_msg: Optional[str] = None, - stack_level: int = 2, -) -> None: - """Emits deprecation warning the first time only - Used when the type and name remained the same. - Args: - version: Version to be used - new_type: new type to be used - new_name: new name to be used - additional_msg: any additional message - stack_level: stack level - """ - warn_deprecated( - version, new_type, new_name, new_type, new_name, additional_msg, stack_level + 1 - ) - - -def _rename_kwargs(version, qualname, func_name, kwargs, kwarg_map, additional_msg, stack_level): - for old_arg, new_arg in kwarg_map.items(): - if old_arg in kwargs: - if new_arg in kwargs: - raise TypeError(f"{func_name} received both {new_arg} and {old_arg} (deprecated).") - - # skip if it was already added - obj = _DeprecatedArgument(version, qualname, old_arg, new_arg, additional_msg) - if obj not in _DEPRECATED_OBJECTS: - _DEPRECATED_OBJECTS.add(obj) - - msg = ( - f"{func_name}: the {old_arg} {DeprecatedType.ARGUMENT.value} is deprecated " - f"as of version {version} and will be removed no sooner " - "than 3 months after the release. Instead use the " - f"{new_arg} {DeprecatedType.ARGUMENT.value}" - ) - if additional_msg: - msg += f" {additional_msg}" - msg += "." - warnings.warn(msg, DeprecationWarning, stacklevel=stack_level) - kwargs[new_arg] = kwargs.pop(old_arg) - - -def deprecate_arguments( - version: str, - kwarg_map: Dict[str, str], - additional_msg: Optional[str] = None, - stack_level: int = 3, -) -> Callable: - """Decorator to alias deprecated argument names and warn upon use. - Args: - version: Version to be used - kwarg_map: Args dictionary with old, new arguments - additional_msg: any additional message - stack_level: stack level - - Returns: - The decorated function - """ - - def decorator(func): - @functools.wraps(func) - def wrapper(*args, **kwargs): - if kwargs: - _rename_kwargs( - version, - func.__qualname__, - func.__name__, - kwargs, - kwarg_map, - additional_msg, - stack_level, - ) - return func(*args, **kwargs) - - return wrapper - - return decorator - - -def _check_values(version, qualname, args, kwargs, kwarg_map, additional_msg, stack_level): - for arg, value_dict in kwarg_map.items(): - index = value_dict["index"] - values_map = value_dict["values"] - old_value = None - if args and 0 < index < len(args): - old_value = args[index] - if kwargs and arg in kwargs: - old_value = kwargs[arg] - - if old_value in values_map: - new_value = values_map[old_value] - - # skip if it was already added - obj = _DeprecatedValue(version, qualname, arg, old_value, new_value, additional_msg) - if obj in _DEPRECATED_OBJECTS: - continue - - _DEPRECATED_OBJECTS.add(obj) - - msg = ( - f'The {arg} {DeprecatedType.ARGUMENT.value} value "{old_value}" is deprecated ' - f"as of version {version} and will be removed no sooner " - "than 3 months after the release. Instead use the " - f'"{new_value}" value' - ) - if additional_msg: - msg += f" {additional_msg}" - msg += "." - warnings.warn(msg, DeprecationWarning, stacklevel=stack_level) - - -def deprecate_values( - version: str, - kwarg_map: Dict[str, Dict[Any, Any]], - additional_msg: Optional[str] = None, - stack_level: int = 3, -) -> Callable: - """Decorator to alias deprecated default values and warn upon use. - Args: - version: Version to be used - kwarg_map: Args dictionary with argument and map of old, new values - additional_msg: any additional message - stack_level: stack level - - Returns: - The decorated function - """ - - def decorator(func): - @functools.wraps(func) - def wrapper(*args, **kwargs): - if args or kwargs: - parameter_names = list(inspect.signature(func).parameters.keys()) - new_kwarg_map = {} - for name, values_map in kwarg_map.items(): - new_kwarg_map[name] = { - "index": parameter_names.index(name), - "values": values_map, - } - _check_values( - version, - func.__qualname__, - args, - kwargs, - new_kwarg_map, - additional_msg, - stack_level, - ) - return func(*args, **kwargs) - - return wrapper - - return decorator - - -def _deprecate_object( - version: str, - old_type: DeprecatedType, - new_type: DeprecatedType, - new_name: str, - additional_msg: str, - stack_level: int, -) -> Callable: - """Decorator that prints deprecated message - Args: - version: Version to be used - old_type: New type to be used - new_type: New type to be used, if None, old_type is used instead. - new_name: New name to be used - additional_msg: any additional message - stack_level: stack level - - Returns: - The decorated method - """ - - def decorator(func): - msg = ( - f"The {func.__name__} {old_type.value} is deprecated as of version {version} " - "and will be removed no sooner than 3 months after the release" - ) - if new_name: - type_str = new_type.value if new_type is not None else old_type.value - msg += f". Instead use the {new_name} {type_str}" - if additional_msg: - msg += f" {additional_msg}" - msg += "." - - @functools.wraps(func) - def wrapper(*args, **kwargs): - # warn only once - if not wrapper._warned: - warnings.warn(msg, DeprecationWarning, stacklevel=stack_level) - wrapper._warned = True - return func(*args, **kwargs) - - wrapper._warned = False - return wrapper - - return decorator - - -def deprecate_method( - version: str, - new_type: Optional[DeprecatedType] = None, - new_name: Optional[str] = None, - additional_msg: Optional[str] = None, - stack_level: int = 2, -) -> Callable: - """Decorator that prints deprecated message for an instance method - Args: - version: Version to be used - new_type: New type to be used - new_name: New name to be used - additional_msg: any additional message - stack_level: stack level - - Returns: - The decorated method - """ - return _deprecate_object( - version, DeprecatedType.METHOD, new_type, new_name, additional_msg, stack_level - ) - - -def deprecate_property( - version: str, - new_type: Optional[DeprecatedType] = None, - new_name: Optional[str] = None, - additional_msg: Optional[str] = None, - stack_level: int = 2, -) -> Callable: - """Decorator that prints deprecated message for a property - - *** This decorator must be placed below the property decorator *** - - Args: - version: Version to be used - new_type: New type to be used - new_name: New name to be used - additional_msg: any additional message - stack_level: stack level - - Returns: - The decorated property - """ - return _deprecate_object( - version, DeprecatedType.PROPERTY, new_type, new_name, additional_msg, stack_level - ) - - -def deprecate_function( - version: str, - new_type: Optional[DeprecatedType] = None, - new_name: Optional[str] = None, - additional_msg: Optional[str] = None, - stack_level: int = 2, -) -> Callable: - """Decorator that prints deprecated message for a function - Args: - version: Version to be used - new_type: New type to be used - new_name: New name to be used - additional_msg: any additional message - stack_level: stack level - - Returns: - The decorated function - """ - return _deprecate_object( - version, DeprecatedType.FUNCTION, new_type, new_name, additional_msg, stack_level - ) diff --git a/test/test_deprecation.py b/test/test_deprecation.py deleted file mode 100644 index 13b687507..000000000 --- a/test/test_deprecation.py +++ /dev/null @@ -1,517 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2021, 2022. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -""" -Test The deprecation methods -""" - -import unittest -import sys -import inspect -import warnings -from typing import Tuple, Optional -from test import QiskitOptimizationTestCase -from ddt import data, ddt -from qiskit_optimization.deprecation import ( - DeprecatedEnum, - DeprecatedEnumMeta, - DeprecatedType, - warn_deprecated, - warn_deprecated_same_type_name, - deprecate_function, - deprecate_property, - deprecate_method, - deprecate_arguments, - deprecate_values, -) - -# pylint: disable=bad-docstring-quotes - - -class EnumTest(DeprecatedEnum, metaclass=DeprecatedEnumMeta): - """Enumeration Test""" - - ONE = "one" - TWO = "two" - - def deprecate(self): - """show deprecate message""" - warn_deprecated( - "0.2.0", DeprecatedType.ENUM, self.__class__.__name__, new_name="NewEnum", stack_level=3 - ) - - -@deprecate_function("0.1.1", DeprecatedType.CLASS, "some_class", "and more information") -def func1(arg1: int) -> int: - """function 1""" - return arg1 - - -@deprecate_function("0.2.0", new_name="some_function2") -def func2(arg2: int) -> int: - """function 2""" - return arg2 - - -@deprecate_arguments("0.1.2", {"old_arg": "new_arg"}) -def func3(new_arg: Optional[int] = None, old_arg: Optional[int] = None) -> Tuple[int, int]: - """function 3""" - return new_arg, old_arg - - -class DeprecatedClass1: - """Deprecated Test class 1""" - - def __init__(self): - warn_deprecated( - "0.3.0", DeprecatedType.CLASS, "DeprecatedClass1", DeprecatedType.CLASS, "NewClass" - ) - self.value = 10 - - -class DeprecatedClass2: - """Deprecated Test class 2""" - - def __init__(self): - warn_deprecated_same_type_name( - "0.3.0", DeprecatedType.CLASS, "DeprecatedClass2", "from package test2" - ) - self.value = 10 - - -class DeprecatedClass3: - """Deprecated Test class 3""" - - @deprecate_values("0.2.0", {"loss": {"l1": "absolute_error", "l2": "squared_error"}}) - def __init__(self, arg1: int, loss: str = "squared_error") -> None: - self.value = arg1 - self.loss = loss - - @deprecate_values("0.2.0", {"loss": {"l1": "absolute_error", "l2": "squared_error"}}) - def method1(self, arg1: int, loss: str = "squared_error") -> None: - """method 1""" - self.value = arg1 - self.loss = loss - - -class DeprecatedClass4: - """Deprecated Test class 4""" - - def __init__( - self, - ) -> None: - self.status = 2 - - @deprecate_values("0.2.0", {"status": {3: 2, 4: 5}}) - def method1(self, status: int = 2) -> None: - """method 1""" - self.status = status - - -class TestClass: - """Test class with deprecation""" - - def __init__(self): - self._value = 20 - - # Bug in mypy, if property decorator is used with another one - # https://github.com/python/mypy/issues/1362 - - @property - @deprecate_property("0.1.0") - def property1(self) -> int: - """property1 get""" - return self._value - - @property1.setter - @deprecate_property( - "0.1.0", new_name="new_property", additional_msg="and some additional information" - ) - def property1(self, value: int): - """property 1 set""" - self._value = value - - @deprecate_method("0.1.0", new_name="some_method1", additional_msg="and additional information") - def method1(self, arg: int) -> int: - """method 1""" - return arg - - @deprecate_method("0.2.0", new_name="some_method2") - def method2(self, arg: int) -> int: - """method 2""" - return arg - - @deprecate_arguments("0.1.2", {"old_arg": "new_arg"}) - def method3( - self, new_arg: Optional[int] = None, old_arg: Optional[int] = None - ) -> Tuple[int, int]: - """method3""" - return new_arg, old_arg - - -@ddt -class TestDeprecation(QiskitOptimizationTestCase): - """Test deprecation methods""" - - def setUp(self) -> None: - super().setUp() - self._source = inspect.getsource(sys.modules[self.__module__]).splitlines() - - def _get_line_from_str(self, text: str) -> int: - for idx, line in enumerate(self._source): - if text in line: - return idx + 1 - return -1 - - def test_enum_deprecation(self): - """test enumeration deprecation""" - - msg_ref = ( - "The EnumTest enum is deprecated as of version 0.2.0 " - "and will be removed no sooner than 3 months after the release. " - "Instead use the NewEnum enum." - ) - - # emit deprecation the first time it is used - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - _ = EnumTest.ONE - msg = str(c_m[0].message) - self.assertEqual(msg, msg_ref) - self.assertTrue("test_deprecation.py" in c_m[0].filename, c_m[0].filename) - self.assertEqual(self._get_line_from_str("EnumTest.ONE"), c_m[0].lineno) - - # trying again should not emit deprecation - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - _ = EnumTest.TWO - self.assertListEqual(c_m, []) - - @data( - ( - "func1", - "The func1 function is deprecated as of version 0.1.1 " - "and will be removed no sooner than 3 months after the release. " - "Instead use the some_class class and more information.", - ), - ( - "func2", - "The func2 function is deprecated as of version 0.2.0 " - "and will be removed no sooner than 3 months after the release. " - "Instead use the some_function2 function.", - ), - ) - def test_function_deprecation(self, config): - """test function deprecation""" - - function_name, msg_ref = config - - # emit deprecation the first time it is used - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - self.assertEqual(2, globals()[function_name](2)) - msg = str(c_m[0].message) - self.assertEqual(msg, msg_ref) - self.assertTrue("test_deprecation.py" in c_m[0].filename, c_m[0].filename) - self.assertEqual(self._get_line_from_str("globals()[function_name](2)"), c_m[0].lineno) - - # trying again should not emit deprecation - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - globals()[function_name](None) - self.assertListEqual(c_m, []) - - def test_class_deprecation1(self): - """test class deprecation 1""" - - msg_ref = ( - "The DeprecatedClass1 class is deprecated as of version 0.3.0 " - "and will be removed no sooner than 3 months after the release. " - "Instead use the NewClass class." - ) - - # emit deprecation the first time it is used - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - obj = DeprecatedClass1() - self.assertEqual(obj.value, 10) - msg = str(c_m[0].message) - self.assertEqual(msg, msg_ref) - self.assertTrue("test_deprecation.py" in c_m[0].filename, c_m[0].filename) - self.assertEqual(self._get_line_from_str("DeprecatedClass1()"), c_m[0].lineno) - - # trying again should not emit deprecation - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - obj = DeprecatedClass1() - self.assertEqual(obj.value, 10) - self.assertListEqual(c_m, []) - - def test_class_deprecation2(self): - """test class deprecation 2""" - - msg_ref = ( - "The DeprecatedClass2 class is deprecated as of version 0.3.0 " - "and will be removed no sooner than 3 months after the release. " - "Instead use the DeprecatedClass2 class from package test2." - ) - - # emit deprecation the first time it is used - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - obj = DeprecatedClass2() - self.assertEqual(obj.value, 10) - msg = str(c_m[0].message) - self.assertEqual(msg, msg_ref) - self.assertTrue("test_deprecation.py" in c_m[0].filename, c_m[0].filename) - self.assertEqual(self._get_line_from_str("DeprecatedClass2()"), c_m[0].lineno) - - # trying again should not emit deprecation - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - obj = DeprecatedClass2() - self.assertEqual(obj.value, 10) - self.assertListEqual(c_m, []) - - @data( - ( - "l1", - 'The loss argument value "l1" is deprecated as of version 0.2.0 ' - "and will be removed no sooner than 3 months after the release. " - 'Instead use the "absolute_error" value.', - ), - ( - "l2", - 'The loss argument value "l2" is deprecated as of version 0.2.0 ' - "and will be removed no sooner than 3 months after the release. " - 'Instead use the "squared_error" value.', - ), - ) - def test_string_values_deprecation(self, config): - """test string values deprecation""" - - loss, msg_ref = config - - # emit deprecation the first time it is used - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - obj = DeprecatedClass3(10, loss=loss) - self.assertEqual(obj.value, 10) - msg = str(c_m[0].message) - self.assertEqual(msg, msg_ref) - self.assertTrue("test_deprecation.py" in c_m[0].filename, c_m[0].filename) - self.assertEqual( - self._get_line_from_str("DeprecatedClass3(10, loss=loss)"), c_m[0].lineno - ) - - # trying again should not emit deprecation - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - obj = DeprecatedClass3(10, loss=loss) - self.assertEqual(obj.value, 10) - self.assertListEqual(c_m, []) - - # emit deprecation the first time it is used - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - obj = DeprecatedClass3(5, loss=loss) - obj.method1(10, loss) - self.assertEqual(obj.value, 10) - msg = str(c_m[0].message) - self.assertEqual(msg, msg_ref) - self.assertTrue("test_deprecation.py" in c_m[0].filename, c_m[0].filename) - self.assertEqual(self._get_line_from_str("obj.method1(10, loss)"), c_m[0].lineno) - - # trying again should not emit deprecation - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - obj = DeprecatedClass3(5, loss=loss) - obj.method1(10, loss) - self.assertEqual(obj.value, 10) - self.assertListEqual(c_m, []) - - @data( - ( - 3, - 'The status argument value "3" is deprecated as of version 0.2.0 ' - "and will be removed no sooner than 3 months after the release. " - 'Instead use the "2" value.', - ), - ( - 4, - 'The status argument value "4" is deprecated as of version 0.2.0 ' - "and will be removed no sooner than 3 months after the release. " - 'Instead use the "5" value.', - ), - ) - def test_int_values_deprecation(self, config): - """test int values deprecation""" - - status, msg_ref = config - obj = DeprecatedClass4() - - # emit deprecation the first time it is used - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - obj.method1(status) - msg = str(c_m[0].message) - self.assertEqual(msg, msg_ref) - self.assertTrue("test_deprecation.py" in c_m[0].filename, c_m[0].filename) - self.assertEqual(self._get_line_from_str("obj.method1(status)"), c_m[0].lineno) - - # trying again should not emit deprecation - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - obj.method1(status) - self.assertEqual(obj.status, status) - self.assertListEqual(c_m, []) - - @data( - ( - "method1", - "The method1 method is deprecated as of version 0.1.0 " - "and will be removed no sooner than 3 months after the release. " - "Instead use the some_method1 method and additional information.", - ), - ( - "method2", - "The method2 method is deprecated as of version 0.2.0 " - "and will be removed no sooner than 3 months after the release. " - "Instead use the some_method2 method.", - ), - ) - def test_method_deprecation(self, config): - """test method deprecation""" - - method_name, msg_ref = config - method = getattr(TestClass(), method_name) - - # emit deprecation the first time it is used - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - self.assertEqual(3, method(3)) - msg = str(c_m[0].message) - self.assertEqual(msg, msg_ref) - self.assertTrue("test_deprecation.py" in c_m[0].filename, c_m[0].filename) - self.assertEqual(self._get_line_from_str("method(3)"), c_m[0].lineno) - - # trying again should not emit deprecation - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - self.assertEqual(4, method(4)) - self.assertListEqual(c_m, []) - - def test_function_arguments_deprecation(self): - """test function arguments deprecation""" - - msg_ref = ( - "func3: the old_arg argument is deprecated as of version 0.1.2 " - "and will be removed no sooner than 3 months after the release. " - "Instead use the new_arg argument." - ) - # both arguments at the same time should raise exception - with self.assertRaises(TypeError): - func3(new_arg="2222", old_arg="hello") - - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - self.assertEqual(("hello", None), func3(old_arg="hello")) - msg = str(c_m[0].message) - self.assertEqual(msg, msg_ref) - self.assertTrue("test_deprecation.py" in c_m[0].filename, c_m[0].filename) - self.assertEqual(self._get_line_from_str('func3(old_arg="hello")'), c_m[0].lineno) - - # trying again should not emit deprecation - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - self.assertEqual(("hello", None), func3(old_arg="hello")) - self.assertListEqual(c_m, []) - - def test_method_arguments_deprecation(self): - """test method arguments deprecation""" - - obj = TestClass() - - msg_ref = ( - "method3: the old_arg argument is deprecated as of version 0.1.2 " - "and will be removed no sooner than 3 months after the release. " - "Instead use the new_arg argument." - ) - # both arguments at the same time should raise exception - with self.assertRaises(TypeError): - obj.method3(new_arg="2222", old_arg="hello") - - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - self.assertEqual(("hello", None), obj.method3(old_arg="hello")) - msg = str(c_m[0].message) - self.assertEqual(msg, msg_ref) - self.assertTrue("test_deprecation.py" in c_m[0].filename, c_m[0].filename) - self.assertEqual(self._get_line_from_str('obj.method3(old_arg="hello")'), c_m[0].lineno) - - # trying again should not emit deprecation - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - self.assertEqual(("hello", None), obj.method3(old_arg="hello")) - self.assertListEqual(c_m, []) - - def test_property_deprecation(self): - """test property deprecation""" - - obj = TestClass() - - msg_ref = ( - "The property1 property is deprecated as of version 0.1.0 " - "and will be removed no sooner than 3 months after the release." - ) - # property get - # emit deprecation the first time it is used - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - self.assertEqual(20, obj.property1) - msg = str(c_m[0].message) - self.assertEqual(msg, msg_ref) - self.assertTrue("test_deprecation.py" in c_m[0].filename, c_m[0].filename) - self.assertEqual(self._get_line_from_str("obj.property1"), c_m[0].lineno) - - # trying again should not emit deprecation - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - self.assertEqual(20, obj.property1) - self.assertListEqual(c_m, []) - - msg_ref = ( - "The property1 property is deprecated as of version 0.1.0 " - "and will be removed no sooner than 3 months after the release. " - "Instead use the new_property property and some additional information." - ) - # property set - # emit deprecation the first time it is used - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - obj.property1 = 0 - self.assertEqual(0, obj.property1) - msg = str(c_m[0].message) - self.assertEqual(msg, msg_ref) - self.assertTrue("test_deprecation.py" in c_m[0].filename, c_m[0].filename) - self.assertEqual(self._get_line_from_str("obj.property1 = 0"), c_m[0].lineno) - - # trying again should not emit deprecation - with warnings.catch_warnings(record=True) as c_m: - warnings.simplefilter("always") - obj.property1 = 0 - self.assertEqual(0, obj.property1) - self.assertListEqual(c_m, []) - - -if __name__ == "__main__": - unittest.main()