support for 'final' cdef types using a directive decorator
authorStefan Behnel <scoder@users.berlios.de>
Sat, 30 Oct 2010 17:04:39 +0000 (19:04 +0200)
committerStefan Behnel <scoder@users.berlios.de>
Sat, 30 Oct 2010 17:04:39 +0000 (19:04 +0200)
Cython/Compiler/Options.py
Cython/Compiler/TypeSlots.py
tests/run/final_cdef_class.pyx [new file with mode: 0644]

index ccc5c0f9e8a87982af91c1012a7e5e1ad43b177b..fd7666ac9c840d4b91b3445a6aab574493ac42d2 100644 (file)
@@ -81,6 +81,7 @@ directive_defaults = {
 
 # Override types possibilities above, if needed
 directive_types = {
+    'final' : bool,  # final cdef classes and methods
     'infer_types' : bool, # values can be True/None/False
     }
 
@@ -90,6 +91,7 @@ for key, val in directive_defaults.items():
 
 directive_scopes = { # defaults to available everywhere
     # 'module', 'function', 'class', 'with statement'
+    'final' : ('cclass',),   # add 'method' in the future
     'autotestdict' : ('module',),
     'test_assert_path_exists' : ('function',),
     'test_fail_if_path_exists' : ('function',),
index b4dbdda99f2bb607a97fe79797f114e505ce0e85..6e1b1131834072a773f8232e735b1b4aefd3b5ff 100644 (file)
@@ -323,7 +323,9 @@ class TypeFlagsSlot(SlotDescriptor):
     #  Descriptor for the type flags slot.
     
     def slot_code(self, scope):
-        value = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_NEWBUFFER"
+        value = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER"
+        if not scope.directives.get('final', False):
+            value += "|Py_TPFLAGS_BASETYPE"
         if scope.needs_gc():
             value += "|Py_TPFLAGS_HAVE_GC"
         return value
diff --git a/tests/run/final_cdef_class.pyx b/tests/run/final_cdef_class.pyx
new file mode 100644 (file)
index 0000000..6845c71
--- /dev/null
@@ -0,0 +1,43 @@
+
+cimport cython
+
+@cython.final
+cdef class FinalClass:
+    """
+    >>> f = FinalClass()
+    >>> test_final_class(f)
+    Type tested
+
+    >>> try:
+    ...     class SubType(FinalClass): pass
+    ... except TypeError:
+    ...     print 'PASSED!'
+    PASSED!
+    """
+
+cdef class NonFinalClass:
+    """
+    >>> class SubType(NonFinalClass): pass
+    >>> s = SubType()
+    """
+
+@cython.final
+cdef class FinalSubClass(NonFinalClass):
+    """
+    >>> f = FinalSubClass()
+    >>> test_non_final_class(f)
+    Type tested
+
+    >>> try:
+    ...     class SubType(FinalSubClass): pass
+    ... except TypeError:
+    ...     print 'PASSED!'
+    PASSED!
+    """
+
+
+def test_final_class(FinalClass c):
+    print u"Type tested"
+
+def test_non_final_class(NonFinalClass c):
+    print u"Type tested"