support 'internal' cdef classes that do not show up in the module dict
authorStefan Behnel <scoder@users.berlios.de>
Sat, 30 Oct 2010 18:59:13 +0000 (20:59 +0200)
committerStefan Behnel <scoder@users.berlios.de>
Sat, 30 Oct 2010 18:59:13 +0000 (20:59 +0200)
Cython/Compiler/ModuleNode.py
Cython/Compiler/Nodes.py
Cython/Compiler/Options.py
Cython/Compiler/TypeSlots.py
tests/run/internal_cdef_class.pyx [new file with mode: 0644]

index 27188d3d4b443e448d584be8dc4b9c29702eb0f4..a3650396d5ef2048755b08ab13b4b0dec6839fbd 100644 (file)
@@ -2075,12 +2075,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                             type.vtabptr_cname,
                             code.error_goto(entry.pos)))
                     env.use_utility_code(Nodes.set_vtable_utility_code)
-                code.putln(
-                    'if (__Pyx_SetAttrString(%s, "%s", (PyObject *)&%s) < 0) %s' % (
-                        Naming.module_cname,
-                        scope.class_name,
-                        typeobj_cname,
-                        code.error_goto(entry.pos)))
+                if not type.scope.is_internal and not type.scope.directives['internal']:
+                    # scope.is_internal is set for types defined by
+                    # Cython (such as closures), the 'internal'
+                    # directive is set by users
+                    code.putln(
+                        'if (__Pyx_SetAttrString(%s, "%s", (PyObject *)&%s) < 0) %s' % (
+                            Naming.module_cname,
+                            scope.class_name,
+                            typeobj_cname,
+                            code.error_goto(entry.pos)))
                 weakref_entry = scope.lookup_here("__weakref__")
                 if weakref_entry:
                     if weakref_entry.type is py_object_type:
index e109b5071ba5a7b04038d4cd1c3dc27fa2a40bf4..92536a7a3aac4c96299bf8d27aca0ef2000084b6 100644 (file)
@@ -3107,7 +3107,7 @@ class CClassDefNode(ClassDefNode):
                         error(self.pos, "Base class '%s' of type '%s' is incomplete" % (
                             self.base_class_name, self.class_name))
                     elif base_class_entry.type.scope and base_class_entry.type.scope.directives and \
-                             base_class_entry.type.scope.directives.get('final', False):
+                             base_class_entry.type.scope.directives['final']:
                         error(self.pos, "Base class '%s' of type '%s' is final" % (
                             self.base_class_name, self.class_name))
                     else:
index fd7666ac9c840d4b91b3445a6aab574493ac42d2..f36a33a05ceb82a1dc8d84b809db8c687127237c 100644 (file)
@@ -62,6 +62,8 @@ directive_defaults = {
     'wraparound' : True,
     'ccomplex' : False, # use C99/C++ for complex types and arith
     'callspec' : "",
+    'final' : False,
+    'internal' : False,
     'profile': False,
     'infer_types': None,
     'infer_types.verbose': False,
@@ -82,6 +84,7 @@ directive_defaults = {
 # Override types possibilities above, if needed
 directive_types = {
     'final' : bool,  # final cdef classes and methods
+    'internal' : bool,  # cdef class visibility in the module dict
     'infer_types' : bool, # values can be True/None/False
     }
 
@@ -92,6 +95,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
+    'internal' : ('cclass',),
     'autotestdict' : ('module',),
     'test_assert_path_exists' : ('function',),
     'test_fail_if_path_exists' : ('function',),
index 6e1b1131834072a773f8232e735b1b4aefd3b5ff..a85bbae1effb0a2e97cfa37e41630b4c5184d9e9 100644 (file)
@@ -324,7 +324,7 @@ class TypeFlagsSlot(SlotDescriptor):
     
     def slot_code(self, scope):
         value = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER"
-        if not scope.directives.get('final', False):
+        if not scope.directives['final']:
             value += "|Py_TPFLAGS_BASETYPE"
         if scope.needs_gc():
             value += "|Py_TPFLAGS_HAVE_GC"
diff --git a/tests/run/internal_cdef_class.pyx b/tests/run/internal_cdef_class.pyx
new file mode 100644 (file)
index 0000000..e532cc6
--- /dev/null
@@ -0,0 +1,29 @@
+
+cimport cython
+
+
+@cython.internal
+cdef class InternalType:
+    """
+    NOTE: this doesn't fail because it is never tested !
+    >>> i = InternalType
+    """
+
+cdef class PublicType:
+    """
+    >>> p = PublicType
+    """
+
+def test():
+    """
+    >>> p,i = test()
+
+    >>> p = PublicType
+
+    >>> i = InternalType
+    Traceback (most recent call last):
+    NameError: name 'InternalType' is not defined
+    """
+    p = PublicType
+    i = InternalType
+    return p,i