make the NULL-instead-of-None change in tp_clear() optional and off by default -...
authorStefan Behnel <stefan_ml@behnel.de>
Thu, 8 Aug 2013 17:49:11 +0000 (19:49 +0200)
committerStefan Behnel <stefan_ml@behnel.de>
Thu, 8 Aug 2013 17:49:11 +0000 (19:49 +0200)
Cython/Compiler/ModuleNode.py
Cython/Compiler/Options.py
runtests.py

index d1cc241..d4a9833 100644 (file)
@@ -1366,6 +1366,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln("")
         code.putln("static int %s(%sPyObject *o) {" % (slot_func, unused))
 
+        if py_attrs and Options.clear_to_none:
+            code.putln("PyObject* tmp;")
+
         if py_attrs or py_buffers:
             self.generate_self_cast(scope, code)
 
@@ -1389,8 +1392,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 code.globalstate.use_utility_code(
                     UtilityCode.load_cached("CallNextTpClear", "ExtensionTypes.c"))
 
-        for entry in py_attrs:
-            code.putln("Py_CLEAR(p->%s);" % entry.cname)
+        if Options.clear_to_none:
+            for entry in py_attrs:
+                name = "p->%s" % entry.cname
+                code.putln("tmp = ((PyObject*)%s);" % name)
+                if entry.is_declared_generic:
+                    code.put_init_to_py_none(name, py_object_type, nanny=False)
+                else:
+                    code.put_init_to_py_none(name, entry.type, nanny=False)
+                code.putln("Py_XDECREF(tmp);")
+        else:
+            for entry in py_attrs:
+                code.putln("Py_CLEAR(p->%s);" % entry.cname)
 
         for entry in py_buffers:
             # Note: shouldn't this call __Pyx_ReleaseBuffer ??
index 64f845a..472dfdc 100644 (file)
@@ -68,7 +68,6 @@ old_style_globals = False
 # Allows cimporting from a pyx file without a pxd file.
 cimport_from_pyx = False
 
-
 # max # of dims for buffers -- set lower than number of dimensions in numpy, as
 # slices are passed by value and involve a lot of copying
 buffer_max_dims = 8
@@ -76,6 +75,10 @@ buffer_max_dims = 8
 # Number of function closure instances to keep in a freelist (0: no freelists)
 closure_freelist_size = 8
 
+# Should tp_clear() set object fields to None instead of clearing them to NULL?
+clear_to_none = True
+
+
 # Declare compiler directives
 directive_defaults = {
     'boundscheck' : True,
index 2a60844..e2eeab0 100755 (executable)
@@ -523,6 +523,7 @@ class CythonCompileTestCase(unittest.TestCase):
         from Cython.Compiler import Options
         self._saved_options = [ (name, getattr(Options, name))
                                 for name in ('warning_errors',
+                                             'clear_to_none',
                                              'error_on_unknown_names',
                                              'error_on_uninitialized') ]
         self._saved_default_directives = Options.directive_defaults.items()
@@ -784,6 +785,11 @@ class CythonCompileTestCase(unittest.TestCase):
         return so_path
 
 class CythonRunTestCase(CythonCompileTestCase):
+    def setUp(self):
+        CythonCompileTestCase.setUp(self)
+        from Cython.Compiler import Options
+        Options.clear_to_none = False
+
     def shortDescription(self):
         if self.cython_only:
             return CythonCompileTestCase.shortDescription(self)