Allow deprecated decorator to specify no plan for removal

Allow the @deprecated decorator to specify functionality as deprecated
but not slate any release for removal of the deprecated functionality.

Change-Id: Iff24553ec83c4a8b0faf4b6381b6fe1589a1c089
This commit is contained in:
Morgan Fainberg
2014-07-12 17:06:27 -07:00
committed by Doug Hellmann
parent 14d1d9eea8
commit 7f263be4b1
2 changed files with 70 additions and 5 deletions

View File

@@ -53,6 +53,14 @@ class deprecated(object):
>>> @deprecated(as_of=deprecated.ICEHOUSE, remove_in=+1)
... def c(): pass
4. Specifying the deprecated functionality will not be removed:
>>> @deprecated(as_of=deprecated.ICEHOUSE, remove_in=0)
... def d(): pass
5. Specifying a replacement, deprecated functionality will not be removed:
>>> @deprecated(as_of=deprecated.ICEHOUSE, in_favor_of='f()', remove_in=0)
... def e(): pass
"""
# NOTE(morganfainberg): Bexar is used for unit test purposes, it is
@@ -83,6 +91,12 @@ class deprecated(object):
'%(what)s is deprecated as of %(as_of)s and may be '
'removed in %(remove_in)s. It will not be superseded.')
_deprecated_msg_with_alternative_no_removal = _(
'%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s.')
_deprecated_msg_with_no_alternative_no_removal = _(
'%(what)s is deprecated as of %(as_of)s. It will not be superseded.')
def __init__(self, as_of, in_favor_of=None, remove_in=2, what=None):
"""Initialize decorator
@@ -128,9 +142,19 @@ class deprecated(object):
if self.in_favor_of:
details['in_favor_of'] = self.in_favor_of
msg = self._deprecated_msg_with_alternative
if self.remove_in > 0:
msg = self._deprecated_msg_with_alternative
else:
# There are no plans to remove this function, but it is
# now deprecated.
msg = self._deprecated_msg_with_alternative_no_removal
else:
msg = self._deprecated_msg_no_alternative
if self.remove_in > 0:
msg = self._deprecated_msg_no_alternative
else:
# There are no plans to remove this function, but it is
# now deprecated.
msg = self._deprecated_msg_with_no_alternative_no_removal
return msg, details

View File

@@ -21,12 +21,23 @@ from openstack.common import versionutils
class DeprecatedTestCase(test_base.BaseTestCase):
def assert_deprecated(self, mock_log, **expected_details):
def assert_deprecated(self, mock_log, no_removal=False,
**expected_details):
decorator = versionutils.deprecated
if 'in_favor_of' in expected_details:
expected_msg = decorator._deprecated_msg_with_alternative
if no_removal is False:
expected_msg = decorator._deprecated_msg_with_alternative
else:
expected_msg = getattr(
decorator,
'_deprecated_msg_with_alternative_no_removal')
else:
expected_msg = decorator._deprecated_msg_no_alternative
if no_removal is False:
expected_msg = decorator._deprecated_msg_no_alternative
else:
expected_msg = getattr(
decorator,
'_deprecated_msg_with_no_alternative_no_removal')
mock_log.deprecated.assert_called_with(expected_msg, expected_details)
@mock.patch('openstack.common.versionutils.LOG', mock.Mock())
@@ -146,6 +157,36 @@ class DeprecatedTestCase(test_base.BaseTestCase):
as_of='Grizzly',
remove_in='Juno')
@mock.patch('openstack.common.versionutils.LOG')
def test_deprecated_with_removed_zero(self, mock_log):
@versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
remove_in=0)
def do_outdated_stuff():
return
do_outdated_stuff()
self.assert_deprecated(mock_log,
no_removal=True,
what='do_outdated_stuff()',
as_of='Grizzly',
remove_in='Grizzly')
@mock.patch('openstack.common.versionutils.LOG')
def test_deprecated_with_removed_zero_and_alternative(self, mock_log):
@versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
in_favor_of='different_stuff()',
remove_in=0)
def do_outdated_stuff():
return
do_outdated_stuff()
self.assert_deprecated(mock_log,
no_removal=True,
what='do_outdated_stuff()',
as_of='Grizzly',
in_favor_of='different_stuff()',
remove_in='Grizzly')
class IsCompatibleTestCase(test_base.BaseTestCase):
def test_same_version(self):