Merge pull request #202 from hongweipeng/support-isinstance-check

Add support for isinstance() checks. #201.
develop
Graham Dumpleton 7 months ago committed by GitHub
commit a81b675ec3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 32
      src/wrapt/_wrappers.c
  2. 5
      src/wrapt/wrappers.py
  3. 28
      tests/test_inheritance_py37.py

@ -2544,6 +2544,36 @@ static PyObject *WraptFunctionWrapperBase_set_name(
/* ------------------------------------------------------------------------- */
static PyObject *WraptFunctionWrapperBase_instancecheck(
WraptFunctionWrapperObject *self, PyObject *instance)
{
PyObject *object = NULL;
PyObject *result = NULL;
int check = 0;
if (!self->object_proxy.wrapped) {
PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized");
return NULL;
}
object = PyObject_GetAttrString(self, "__wrapped__");
if (!object) {
PyErr_Clear();
}
check = PyObject_IsInstance(instance, object);
Py_XDECREF(object);
if (check < 0) {
return NULL;
}
result = check ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
/* ------------------------------------------------------------------------- */
static PyObject *WraptFunctionWrapperBase_subclasscheck(
WraptFunctionWrapperObject *self, PyObject *args)
{
@ -2656,6 +2686,8 @@ static PyObject *WraptFunctionWrapperBase_get_self_parent(
static PyMethodDef WraptFunctionWrapperBase_methods[] = {
{ "__set_name__", (PyCFunction)WraptFunctionWrapperBase_set_name,
METH_VARARGS | METH_KEYWORDS, 0 },
{ "__instancecheck__", (PyCFunction)WraptFunctionWrapperBase_instancecheck,
METH_O, 0},
{ "__subclasscheck__", (PyCFunction)WraptFunctionWrapperBase_subclasscheck,
METH_VARARGS, 0 },
{ NULL, NULL },

@ -588,6 +588,11 @@ class _FunctionWrapperBase(ObjectProxy):
if hasattr(self.__wrapped__, "__set_name__"):
self.__wrapped__.__set_name__(owner, name)
def __instancecheck__(self, instance):
# This is a special method used by isinstance() to make checks
# instance of the `__wrapped__`.
return isinstance(instance, self.__wrapped__)
def __subclasscheck__(self, subclass):
# This is a special method used by issubclass() to make checks
# about inheritance of classes. We need to upwrap any object

@ -12,7 +12,7 @@ class TestClassInheritance(unittest.TestCase):
def test_basic_inheritance(self):
@wrapt.decorator
def wrapper(wrapped, instance, args, kwargs):
return wrapped(args, kwargs)
return wrapped(*args, **kwargs)
class B1:
def method(self):
@ -43,6 +43,18 @@ class TestClassInheritance(unittest.TestCase):
self.assertTrue(issubclass(C1, (B1, C1, D1)))
self.assertTrue(issubclass(D1, (B1, C1, D1)))
self.assertTrue(isinstance(C1(), B1))
self.assertTrue(isinstance(C1(), C1))
self.assertTrue(isinstance(D1(), B1))
self.assertTrue(isinstance(D1(), C1))
def function():
pass
class F(wrapt.FunctionWrapper):
pass
instance = F(function, wrapper)
self.assertTrue(isinstance(instance, wrapt.FunctionWrapper))
def test_abc_inheritance(self):
# XXX The checks commented out below all fail because the
# helpers for issubclass() via __subclasscheck__() in ABCMeta
@ -58,7 +70,7 @@ class TestClassInheritance(unittest.TestCase):
@wrapt.decorator
def wrapper(wrapped, instance, args, kwargs):
return wrapped(args, kwargs)
return wrapped(*args, **kwargs)
class A1(metaclass=abc.ABCMeta):
@abc.abstractmethod
@ -103,6 +115,11 @@ class TestClassInheritance(unittest.TestCase):
# self.assertTrue(issubclass(C1, (A1, B1, C1, D1)))
self.assertTrue(issubclass(D1, (A1, B1, C1, D1)))
self.assertTrue(isinstance(C1(), B1))
self.assertTrue(isinstance(C1(), C1))
self.assertTrue(isinstance(D1(), B1))
self.assertTrue(isinstance(D1(), C1))
def test_py_abc_inheritance(self):
# In contrast to above when C implementation for ABCMeta helpers
# are used, these all pass as have use the Python implementation
@ -110,7 +127,7 @@ class TestClassInheritance(unittest.TestCase):
@wrapt.decorator
def wrapper(wrapped, instance, args, kwargs):
return wrapped(args, kwargs)
return wrapped(*args, **kwargs)
class A1(metaclass=_py_abc.ABCMeta):
@abc.abstractmethod
@ -155,5 +172,10 @@ class TestClassInheritance(unittest.TestCase):
self.assertTrue(issubclass(C1, (A1, B1, C1, D1)))
self.assertTrue(issubclass(D1, (A1, B1, C1, D1)))
self.assertTrue(isinstance(C1(), B1))
self.assertTrue(isinstance(C1(), C1))
self.assertTrue(isinstance(D1(), B1))
self.assertTrue(isinstance(D1(), C1))
if __name__ == '__main__':
unittest.main()

Loading…
Cancel
Save