Commit c506034b authored by Robert Bradshaw's avatar Robert Bradshaw

Fix builtin Exception type checking.

Closes #1496
parent d8c54671
......@@ -2129,7 +2129,7 @@ class FuncDefNode(StatNode, BlockNode):
typeptr_cname,
arg.accept_none,
arg.name,
arg.type.is_builtin_type,
arg.type.is_builtin_type and arg.type.require_exact,
code.error_goto(arg.pos)))
else:
error(arg.pos, "Cannot test type of extern C class without type object name specification")
......
......@@ -1138,6 +1138,7 @@ class BuiltinObjectType(PyObjectType):
has_attributes = 1
base_type = None
module_name = '__builtin__'
require_exact = 1
# fields that let it look like an extension type
vtabslot_cname = None
......@@ -1157,6 +1158,8 @@ class BuiltinObjectType(PyObjectType):
# Special case the type type, as many C API calls (and other
# libraries) actually expect a PyTypeObject* for type arguments.
self.decl_type = objstruct_cname
if name == 'Exception':
self.require_exact = 0
def set_scope(self, scope):
self.scope = scope
......@@ -1210,13 +1213,15 @@ class BuiltinObjectType(PyObjectType):
type_check = 'PyString_Check'
elif type_name == 'basestring':
type_check = '__Pyx_PyBaseString_Check'
elif type_name == 'Exception':
type_check = '__Pyx_PyException_Check'
elif type_name == 'bytearray':
type_check = 'PyByteArray_Check'
elif type_name == 'frozenset':
type_check = 'PyFrozenSet_Check'
else:
type_check = 'Py%s_Check' % type_name.capitalize()
if exact and type_name not in ('bool', 'slice'):
if exact and type_name not in ('bool', 'slice', 'Exception'):
type_check += 'Exact'
return type_check
......
......@@ -308,6 +308,7 @@
#endif
#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type)
#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception)
#if PY_MAJOR_VERSION >= 3
#define PyIntObject PyLongObject
......
......@@ -125,3 +125,26 @@ cdef class MyException(Exception):
cdef readonly int value
def __cinit__(self, value):
self.value = value
def test_exception_isinstance(maybe_exn):
"""
>>> test_exception_isinstance(Exception())
True
>>> test_exception_isinstance(MyException(3))
True
>>> test_exception_isinstance(3)
False
"""
return isinstance(maybe_exn, Exception)
def test_exception_type_cast(Exception maybe_exn):
"""
>>> test_exception_type_cast(Exception())
>>> test_exception_type_cast(MyException(3))
>>> test_exception_type_cast(3) # doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError: Argument 'maybe_exn' has incorrect type (expected ...Exception, got int)
"""
cdef object o = maybe_exn
cdef Exception e = o
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment