split subclassing tests and default to warning only once per deprecated class

This commit is contained in:
Daniel Graña 2014-01-10 13:40:54 -02:00
parent a97b4aa633
commit 1e37b64ecd
2 changed files with 65 additions and 70 deletions

View File

@ -17,99 +17,92 @@ class NewName(SomeBaseClass):
class WarnWhenSubclassedTest(unittest.TestCase):
def _mywarnings(self, w, category=MyWarning):
return [x for x in w if x.category is MyWarning]
def test_no_warning_on_definition(self):
with warnings.catch_warnings(record=True) as w:
Deprecated = create_deprecated_class('Deprecated', NewName)
w = self._mywarnings(w)
self.assertEqual(w, [])
def test_warning_on_subclassing(self):
with warnings.catch_warnings(record=True) as w:
Deprecated = create_deprecated_class('Deprecated', NewName,
warn_category=MyWarning)
def test_subclassing_warning_message(self):
Deprecated = create_deprecated_class('Deprecated', NewName,
warn_category=MyWarning)
with warnings.catch_warnings(record=True) as w:
class UserClass(Deprecated):
pass
w = self._mywarnings(w)
self.assertEqual(len(w), 1)
self.assertEqual(
str(w[0].message),
"scrapy.tests.test_utils_deprecate.UserClass inherits from "
"deprecated class scrapy.tests.test_utils_deprecate.Deprecated, "
"please inherit from scrapy.tests.test_utils_deprecate.NewName."
" (warning only on first subclass, there may be others)"
)
self.assertEqual(w[0].lineno, inspect.getsourcelines(UserClass)[1])
def test_subclassing_warns_only_on_direct_childs(self):
Deprecated = create_deprecated_class('Deprecated', NewName,
warn_once=False,
warn_category=MyWarning)
with warnings.catch_warnings(record=True) as w:
class UserClass(Deprecated):
pass
class NoWarnOnMe(UserClass):
pass
w = self._mywarnings(w)
self.assertEqual(len(w), 1)
msg = w[0]
assert issubclass(msg.category, MyWarning)
self.assertEqual(
str(msg.message),
"scrapy.tests.test_utils_deprecate.UserClass inherits from "
"deprecated class scrapy.tests.test_utils_deprecate.Deprecated, "
"please inherit from scrapy.tests.test_utils_deprecate.NewName."
)
self.assertEqual(msg.lineno, inspect.getsourcelines(UserClass)[1])
self.assertIn('UserClass', str(w[0].message))
def test_subclassing_warns_once_by_default(self):
Deprecated = create_deprecated_class('Deprecated', NewName,
warn_category=MyWarning)
def test_warning_on_instance(self):
with warnings.catch_warnings(record=True) as w:
Deprecated = create_deprecated_class('Deprecated', NewName,
warn_category=MyWarning)
class UserClass(Deprecated):
pass
_, lineno = Deprecated(), inspect.getlineno(inspect.currentframe())
_ = UserClass()
class FooClass(Deprecated):
pass
self.assertEqual(len(w), 2)
msg = w[1]
assert issubclass(msg.category, MyWarning)
class BarClass(Deprecated):
pass
w = self._mywarnings(w)
self.assertEqual(len(w), 1)
self.assertIn('UserClass', str(w[0].message))
def test_warning_on_instance(self):
Deprecated = create_deprecated_class('Deprecated', NewName,
warn_category=MyWarning)
# ignore subclassing warnings
with warnings.catch_warnings(record=True):
class UserClass(Deprecated):
pass
with warnings.catch_warnings(record=True) as w:
# warns only once on instantations in the same lineno
for _ in range(10):
_, lineno = Deprecated(), inspect.getlineno(inspect.currentframe())
_ = UserClass() # subclass instances don't warn
w = self._mywarnings(w)
self.assertEqual(len(w), 1)
self.assertEqual(
str(msg.message),
str(w[0].message),
"scrapy.tests.test_utils_deprecate.Deprecated is deprecated, "
"instantiate scrapy.tests.test_utils_deprecate.NewName instead."
)
self.assertEqual(msg.lineno, lineno)
def test_warning_shown_everytime(self):
Deprecated = create_deprecated_class('Deprecated', NewName,
warn_category=MyWarning)
with warnings.catch_warnings(record=True) as w:
class U1(Deprecated):
pass
class U2(Deprecated):
pass
self.assertEqual(len(w), 2)
assert issubclass(w[0].category, MyWarning)
assert issubclass(w[1].category, MyWarning)
with warnings.catch_warnings(record=True) as w:
_i1 = Deprecated()
_i2 = Deprecated()
self.assertEqual(len(w), 2)
assert issubclass(w[0].category, MyWarning)
assert issubclass(w[1].category, MyWarning)
def test_warning_shown_once(self):
Deprecated = create_deprecated_class('Deprecated', NewName,
warn_once=True,
warn_category=MyWarning)
with warnings.catch_warnings(record=True) as w:
class U1(Deprecated):
pass
class U2(Deprecated):
pass
self.assertEqual(len(w), 1)
assert issubclass(w[0].category, MyWarning)
# warns once instantations in the same lineno
with warnings.catch_warnings(record=True) as w:
for _ in range(10):
_i1 = Deprecated()
_i2 = Deprecated()
self.assertEqual(len(w), 2)
assert issubclass(w[0].category, MyWarning)
self.assertEqual(w[0].lineno, lineno)
def test_warning_auto_message(self):
with warnings.catch_warnings(record=True) as w:

View File

@ -14,7 +14,7 @@ def attribute(obj, oldattr, newattr, version='0.12'):
def create_deprecated_class(name, new_class, clsdict=None,
warn_category=ScrapyDeprecationWarning,
warn_once=False,
warn_once=True,
subclass_warn_message="{cls} inherits from "\
"deprecated class {old}, please inherit "\
"from {new}.",
@ -64,6 +64,8 @@ def create_deprecated_class(name, new_class, clsdict=None,
msg = subclass_warn_message.format(cls=_clspath(cls),
old=_clspath(old),
new=_clspath(new_class))
if warn_once:
msg += ' (warning only on first subclass, there may be others)'
warnings.warn(msg, warn_category, stacklevel=2)
super(DeprecatedClass, cls).__init__(name, bases, clsdict_)