Fix #632 isinstance bugs.
authorRobert Bradshaw <robertwb@math.washington.edu>
Tue, 21 Dec 2010 09:45:27 +0000 (01:45 -0800)
committerRobert Bradshaw <robertwb@math.washington.edu>
Tue, 21 Dec 2010 09:45:27 +0000 (01:45 -0800)
Cython/Compiler/ModuleNode.py
Cython/Compiler/Optimize.py
tests/run/isinstance.pyx

index e7e652ef0e1d987909908676e2e7fba89b237ebd..6cb0d5feb34c654742e2cad2cbb0a1c448107d80 100644 (file)
@@ -579,6 +579,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
   #define PySet_CheckExact(obj)        (Py_TYPE(obj) == &PySet_Type)
 #endif
 
+#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type)
+
 #if PY_MAJOR_VERSION >= 3
   #define PyIntObject                  PyLongObject
   #define PyInt_Type                   PyLong_Type
index 28ed19ff47d27498c9204f274d041c31b066b360..77fdaac10d43e7ee502e509244aa5b2d6e661443 100644 (file)
@@ -1986,20 +1986,26 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
         test_nodes = []
         env = self.current_env()
         for test_type_node in types:
-            if not test_type_node.entry:
-                return node
-            entry = env.lookup(test_type_node.entry.name)
-            if not entry or not entry.type or not entry.type.is_builtin_type:
-                return node
-            type_check_function = entry.type.type_check_function(exact=False)
-            if not type_check_function:
+            builtin_type = None
+            if isinstance(test_type_node, ExprNodes.NameNode):
+                if test_type_node.entry:
+                    entry = env.lookup(test_type_node.entry.name)
+                    if entry and entry.type and entry.type.is_builtin_type:
+                        builtin_type = entry.type
+            if builtin_type and builtin_type is not Builtin.type_type:
+                type_check_function = entry.type.type_check_function(exact=False)
+                type_check_args = [arg]
+            elif test_type_node.type is Builtin.type_type:
+                type_check_function = '__Pyx_TypeCheck'
+                type_check_args = [arg, test_type_node]
+            else:
                 return node
             if type_check_function not in tests:
                 tests.append(type_check_function)
                 test_nodes.append(
                     ExprNodes.PythonCapiCallNode(
                         test_type_node.pos, type_check_function, self.Py_type_check_func_type,
-                        args = [arg],
+                        args = type_check_args,
                         is_temp = True,
                         ))
 
index db54a9de3c2ccb274aee46031571cd0e961b4367..d11b3771c4d1c9de98975d98733fecdaabfd4010 100644 (file)
@@ -5,8 +5,6 @@ from cpython.bool cimport bool
 cdef class A:
     pass
 
-cdef an_A = A()
-
 @cython.test_assert_path_exists('//SimpleCallNode//SimpleCallNode')
 @cython.test_fail_if_path_exists('//SimpleCallNode//PythonCapiCallNode',
                                  '//PythonCapiCallNode//SimpleCallNode')
@@ -50,11 +48,11 @@ def test_optimised():
     assert isinstance(complex(), complex)
     assert not isinstance(u"foo", int)
     assert isinstance(A, type)
-    assert isinstance(an_A, A)
+    assert isinstance(A(), A)
     cdef type typed_type = A
-    assert isinstance(an_A, typed_type)
+    assert isinstance(A(), typed_type)
     cdef object untyped_type = A
-    assert isinstance(an_A, <type>untyped_type)
+    assert isinstance(A(), <type>untyped_type)
     return True
 
 @cython.test_assert_path_exists('//PythonCapiCallNode')
@@ -66,13 +64,11 @@ def test_optimised_tuple():
     >>> test_optimised_tuple()
     True
     """
-    assert isinstance(int(),   (int, long, float, bytes, str, unicode, tuple, list, dict, set, slice))
-    assert isinstance(list(),  (int, long, float, bytes, str, unicode, tuple, list, dict, set, slice))
+    assert isinstance(int(),   (int, long, float, bytes, str, unicode, tuple, list, dict, set, slice, A))
+    assert isinstance(list(),  (int, long, float, bytes, str, unicode, tuple, list, dict, set, slice, A))
+    assert isinstance(A(),  (int, long, float, bytes, str, unicode, tuple, list, dict, set, slice, A))
     return True
 
-@cython.test_assert_path_exists('//SimpleCallNode//SimpleCallNode')
-@cython.test_fail_if_path_exists('//SimpleCallNode//PythonCapiCallNode',
-                                 '//PythonCapiCallNode//SimpleCallNode')
 def test_custom():
     """
     >>> test_custom()