enable Py_TPFLAGS_HAVE_VERSION_TAG on extension types by default (also in Py2) and...
authorStefan Behnel <stefan_ml@behnel.de>
Sat, 6 Apr 2013 20:30:13 +0000 (22:30 +0200)
committerStefan Behnel <stefan_ml@behnel.de>
Sat, 6 Apr 2013 20:30:13 +0000 (22:30 +0200)
CHANGES.rst
Cython/Compiler/Options.py
Cython/Compiler/TypeSlots.py
Cython/Shadow.py
Cython/Utility/ModuleSetupCode.c
docs/src/reference/compilation.rst
tests/compile/ext_attribute_cache.pyx [new file with mode: 0644]

index b465371..6d4bc2a 100644 (file)
@@ -8,6 +8,10 @@ Cython Changelog
 Features added
 --------------
 
+* The extension type flag ``Py_TPFLAGS_HAVE_VERSION_TAG`` is enabled by default
+  on extension types and can be disabled using the ``type_version_tag`` compiler
+  directive.
+
 * EXPERIMENTAL support for simple Cython code level line tracing.  Enabled by
   the "linetrace" compiler directive.
 
index 04a1579..50fa18c 100644 (file)
@@ -101,6 +101,7 @@ directive_defaults = {
     'py2_import': False, # For backward compatibility of Cython's source code in Py3 source mode
     'c_string_type': 'bytes',
     'c_string_encoding': '',
+    'type_version_tag': True,   # enables Py_TPFLAGS_HAVE_VERSION_TAG on extension types
 
     # set __file__ and/or __path__ to known source/target path at import time (instead of not having them available)
     'set_initial_path' : None,  # SOURCEFILE or "/full/path/to/module"
@@ -218,6 +219,7 @@ directive_scopes = { # defaults to available everywhere
     # Avoid scope-specific to/from_py_functions for c_string.
     'c_string_type': ('module',),
     'c_string_encoding': ('module',),
+    'type_version_tag': ('module', 'cclass'),
 }
 
 def parse_directive_value(name, value, relaxed_bool=False):
index 9ff876b..3a3fc9c 100644 (file)
@@ -377,7 +377,14 @@ class TypeFlagsSlot(SlotDescriptor):
     #  Descriptor for the type flags slot.
 
     def slot_code(self, scope):
-        value = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER"
+        value = "Py_TPFLAGS_DEFAULT"
+        if scope.directives['type_version_tag']:
+            # it's not in 'Py_TPFLAGS_DEFAULT' in Py2
+            value += "|Py_TPFLAGS_HAVE_VERSION_TAG"
+        else:
+            # it's enabled in 'Py_TPFLAGS_DEFAULT' in Py3
+            value = "(%s^Py_TPFLAGS_HAVE_VERSION_TAG)" % value
+        value += "|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER"
         if not scope.parent_type.is_final_type:
             value += "|Py_TPFLAGS_BASETYPE"
         if scope.needs_gc():
index b5c6fcd..e1a6401 100644 (file)
@@ -97,7 +97,7 @@ cclass = ccall = cfunc = _EmptyDecoratorAndManager()
 
 returns = lambda type_arg: _EmptyDecoratorAndManager()
 
-final = internal = _empty_decorator
+final = internal = type_version_tag = _empty_decorator
 
 def inline(f, *args, **kwds):
   if isinstance(f, basestring):
index 58e761f..e28844c 100644 (file)
   #define Py_TPFLAGS_HAVE_NEWBUFFER 0
 #endif
 
+#if PY_VERSION_HEX < 0x02060000
+  #define Py_TPFLAGS_HAVE_VERSION_TAG 0
+#endif
+
 /* new Py3.3 unicode type (PEP 393) */
 #if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND)
   #define CYTHON_PEP393_ENABLED 1
index 4053f9e..604305c 100644 (file)
@@ -224,6 +224,15 @@ Cython code.  Here is the list of currently supported directives:
     when set to ``ascii`` or ``default``, the latter being utf-8 in Python 3 and
     nearly-always ascii in Python 2.
 
+``type_version_tag`` (True / False)
+    Enables the attribute cache for extension types in CPython by setting the
+    type flag ``Py_TPFLAGS_HAVE_VERSION_TAG``.  Default is True, meaning that
+    the cache is enabled for Cython implemented types.  To disable it
+    explicitly in the rare cases where a type needs to juggle with its ``tp_dict``
+    internally without paying attention to cache consistency, this option can
+    be set to False.
+
+
 How to set directives
 ---------------------
 
diff --git a/tests/compile/ext_attribute_cache.pyx b/tests/compile/ext_attribute_cache.pyx
new file mode 100644 (file)
index 0000000..bcc43f5
--- /dev/null
@@ -0,0 +1,13 @@
+# mode: compile
+
+cimport cython
+
+cdef class AttrCache(object):
+    cdef public int x
+    cdef object y
+
+@cython.type_version_tag(False)
+cdef class NoAttrCache(object):
+    cdef public int x
+    cdef object y
+