mirror of https://github.com/scrapy/scrapy.git
warn when the deprecated class is instanciated
This commit is contained in:
parent
8c4e1db5fe
commit
b41ad38fab
|
|
@ -42,6 +42,27 @@ class WarnWhenSubclassedTest(unittest.TestCase):
|
|||
)
|
||||
self.assertEqual(msg.lineno, inspect.getsourcelines(UserClass)[1])
|
||||
|
||||
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()
|
||||
|
||||
self.assertEqual(len(w), 2)
|
||||
msg = w[1]
|
||||
assert issubclass(msg.category, MyWarning)
|
||||
self.assertEqual(
|
||||
str(msg.message),
|
||||
"scrapy.tests.test_utils_deprecate.Deprecated is deprecated, "
|
||||
"instanciate scrapy.tests.test_utils_deprecate.NewName instead."
|
||||
)
|
||||
self.assertEqual(msg.lineno, lineno)
|
||||
|
||||
def test_warning_auto_message(self):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
Deprecated = create_deprecated_class('Deprecated', NewName)
|
||||
|
|
|
|||
|
|
@ -14,11 +14,16 @@ def attribute(obj, oldattr, newattr, version='0.12'):
|
|||
|
||||
def create_deprecated_class(name, new_class, clsdict=None,
|
||||
warn_category=ScrapyDeprecationWarning,
|
||||
warn_message="{cls} inherits from deprecated class {old}, "\
|
||||
"please inherit from {new}."):
|
||||
subclass_warn_message="{cls} inherits from "\
|
||||
"deprecated class {old}, please inherit "\
|
||||
"from {new}.",
|
||||
instance_warn_message="{cls} is deprecated, "\
|
||||
"instanciate {new} instead."):
|
||||
"""
|
||||
Return a "deprecated" class that causes its subclasses to issue a warning.
|
||||
Subclasses of ``new_class`` are considered subclasses of this class.
|
||||
It also warns when the deprecated class is instanciated, but do not when
|
||||
its subclasses are instanciated.
|
||||
|
||||
It can be used to rename a base class in a library. For example, if we
|
||||
have
|
||||
|
|
@ -50,10 +55,11 @@ def create_deprecated_class(name, new_class, clsdict=None,
|
|||
return cls
|
||||
|
||||
def __init__(cls, name, bases, clsdict_):
|
||||
if cls is not cls.__class__.deprecated_class:
|
||||
msg = warn_message.format(cls=_clspath(cls),
|
||||
old=_clspath(cls.__class__.deprecated_class),
|
||||
new=_clspath(new_class))
|
||||
old = cls.__class__.deprecated_class
|
||||
if cls is not old:
|
||||
msg = subclass_warn_message.format(cls=_clspath(cls),
|
||||
old=_clspath(old),
|
||||
new=_clspath(new_class))
|
||||
warnings.warn(msg, warn_category, stacklevel=2)
|
||||
super(DeprecatedClass, cls).__init__(name, bases, clsdict_)
|
||||
|
||||
|
|
@ -72,6 +78,13 @@ def create_deprecated_class(name, new_class, clsdict=None,
|
|||
candidates = {cls, new_class}
|
||||
return any(c in candidates for c in mro)
|
||||
|
||||
def __call__(cls, *args, **kwargs):
|
||||
if cls is cls.__class__.deprecated_class:
|
||||
msg = instance_warn_message.format(cls=_clspath(cls),
|
||||
new=_clspath(new_class))
|
||||
warnings.warn(msg, warn_category, stacklevel=2)
|
||||
return super(DeprecatedClass, cls).__call__(*args, **kwargs)
|
||||
|
||||
deprecated_cls = DeprecatedClass(name, (new_class,), clsdict or {})
|
||||
frm = inspect.stack()[1]
|
||||
parent_module = inspect.getmodule(frm[0])
|
||||
|
|
|
|||
Loading…
Reference in New Issue