Skip to content
Browse files

Fix wrong checks on subclassing of deprecated classes. closes #581

  • Loading branch information
dangra committed Feb 5, 2014
1 parent 13846de commit 46d98d625af4c72537b5dc588d6224146c440706
Showing with 19 additions and 2 deletions.
  1. +11 −0 scrapy/tests/
  2. +8 −2 scrapy/utils/
@@ -145,6 +145,9 @@ class UpdatedUserClass1a(NewName):
class OutdatedUserClass1(DeprecatedName):

class OutdatedUserClass1a(DeprecatedName):

class UnrelatedClass(object):

@@ -159,6 +162,8 @@ class OldStyleClass:
assert not issubclass(UnrelatedClass, DeprecatedName)
assert not issubclass(OldStyleClass, DeprecatedName)
assert not issubclass(OldStyleClass, DeprecatedName)
assert not issubclass(OutdatedUserClass1, OutdatedUserClass1a)
assert not issubclass(OutdatedUserClass1a, OutdatedUserClass1)

self.assertRaises(TypeError, issubclass, object(), DeprecatedName)

@@ -175,6 +180,9 @@ class UpdatedUserClass2a(NewName):
class OutdatedUserClass2(DeprecatedName):

class OutdatedUserClass2a(DeprecatedName):

class UnrelatedClass(object):

@@ -186,6 +194,9 @@ class OldStyleClass:
assert isinstance(UpdatedUserClass2(), DeprecatedName)
assert isinstance(UpdatedUserClass2a(), DeprecatedName)
assert isinstance(OutdatedUserClass2(), DeprecatedName)
assert isinstance(OutdatedUserClass2a(), DeprecatedName)
assert not isinstance(OutdatedUserClass2a(), OutdatedUserClass2)
assert not isinstance(OutdatedUserClass2(), OutdatedUserClass2a)
assert not isinstance(UnrelatedClass(), DeprecatedName)
assert not isinstance(OldStyleClass(), DeprecatedName)

@@ -79,12 +79,18 @@ def __instancecheck__(cls, inst):
for c in {type(inst), inst.__class__})

def __subclasscheck__(cls, sub):
if cls is not DeprecatedClass.deprecated_class:
# we should do the magic only if second `issubclass` argument
# is the deprecated class itself - subclasses of the
# deprecated class should not use custom `__subclasscheck__`
# method.
return super(DeprecatedClass, cls).__subclasscheck__(sub)

if not inspect.isclass(sub):
raise TypeError("issubclass() arg 1 must be a class")

mro = getattr(sub, '__mro__', ())
candidates = {cls, new_class}
return any(c in candidates for c in mro)
return any(c in {cls, new_class} for c in mro)

def __call__(cls, *args, **kwargs):
old = DeprecatedClass.deprecated_class

0 comments on commit 46d98d6

Please sign in to comment.
You can’t perform that action at this time.