Do not report deprecations in subclasses
Upgrading to mock 1.1.0 somehow exposed the logic error in deprecated() that was causing subclasses of deprecated exceptions to be reported as deprecated when they should not be. The problem makes sense because we were indiscriminately reporting the case in the constructor, and if the subclass initialized the base class the deprecation reporting function would be called. Change the logic to only report the deprecation if the class being instantiated matches one of the deprecated classes. Add a warning, and skip the test, for catching deprecated exceptions under Python 3, since this feature does not always work there. Also explicitly declare the versions of mock supported in the unit tests, since we need different versions for python 2.6 vs. 2.7 and later. Change-Id: Ib60413a0e45901902382c3ae547be0e24df4e50c
This commit is contained in:
@@ -15,7 +15,9 @@
|
||||
|
||||
import mock
|
||||
from oslotest import base as test_base
|
||||
import six
|
||||
from testtools import matchers
|
||||
import unittest2
|
||||
|
||||
from oslo_log import versionutils
|
||||
|
||||
@@ -246,6 +248,9 @@ class DeprecatedTestCase(test_base.BaseTestCase):
|
||||
as_of='Juno',
|
||||
remove_in='Kilo')
|
||||
|
||||
@unittest2.skipIf(
|
||||
six.PY3,
|
||||
'Deprecated exception detection does not work for Python 3')
|
||||
@mock.patch('oslo_log.versionutils.report_deprecated_feature')
|
||||
def test_deprecated_exception(self, mock_log):
|
||||
@versionutils.deprecated(as_of=versionutils.deprecated.ICEHOUSE,
|
||||
|
||||
@@ -77,6 +77,12 @@ class deprecated(object):
|
||||
... remove_in=None)
|
||||
... def e(): pass
|
||||
|
||||
.. warning::
|
||||
|
||||
The hook used to detect when a deprecated exception is being
|
||||
*caught* does not work under Python 3. Deprecated exceptions
|
||||
are still logged if they are thrown.
|
||||
|
||||
"""
|
||||
|
||||
# NOTE(morganfainberg): Bexar is used for unit test purposes, it is
|
||||
@@ -155,11 +161,23 @@ class deprecated(object):
|
||||
# and added to the oslo-incubator requrements
|
||||
@functools.wraps(orig_init, assigned=('__name__', '__doc__'))
|
||||
def new_init(self, *args, **kwargs):
|
||||
report_deprecated_feature(LOG, msg, details)
|
||||
if self.__class__ in _DEPRECATED_EXCEPTIONS:
|
||||
report_deprecated_feature(LOG, msg, details)
|
||||
orig_init(self, *args, **kwargs)
|
||||
func_or_cls.__init__ = new_init
|
||||
_DEPRECATED_EXCEPTIONS.add(func_or_cls)
|
||||
|
||||
if issubclass(func_or_cls, Exception):
|
||||
# NOTE(dhellmann): The subclasscheck is called,
|
||||
# sometimes, to test whether a class matches the type
|
||||
# being caught in an exception. This lets us warn
|
||||
# folks that they are trying to catch an exception
|
||||
# that has been deprecated. However, under Python 3
|
||||
# the test for whether one class is a subclass of
|
||||
# another has been optimized so that the abstract
|
||||
# check is only invoked in some cases. (See
|
||||
# PyObject_IsSubclass in cpython/Objects/abstract.c
|
||||
# for the short-cut.)
|
||||
class ExceptionMeta(type):
|
||||
def __subclasscheck__(self, subclass):
|
||||
if self in _DEPRECATED_EXCEPTIONS:
|
||||
@@ -168,6 +186,7 @@ class deprecated(object):
|
||||
self).__subclasscheck__(subclass)
|
||||
func_or_cls = six.add_metaclass(ExceptionMeta)(func_or_cls)
|
||||
_DEPRECATED_EXCEPTIONS.add(func_or_cls)
|
||||
|
||||
return func_or_cls
|
||||
else:
|
||||
raise TypeError('deprecated can be used only with functions or '
|
||||
|
||||
@@ -10,6 +10,8 @@ python-subunit>=0.0.18
|
||||
testrepository>=0.0.18
|
||||
testscenarios>=0.4
|
||||
testtools>=1.4.0
|
||||
mock>=1.1;python_version!='2.6'
|
||||
mock==1.0.1;python_version=='2.6'
|
||||
oslotest>=1.5.1 # Apache-2.0
|
||||
|
||||
# when we can require tox>= 1.4, this can go into tox.ini:
|
||||
@@ -20,6 +22,3 @@ coverage>=3.6
|
||||
# this is required for the docs build jobs
|
||||
sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2
|
||||
oslosphinx>=2.5.0 # Apache-2.0
|
||||
|
||||
# mocking framework
|
||||
mock>=1.0
|
||||
|
||||
Reference in New Issue
Block a user