From 55ae33d77d2d7985c3545c75d5b7b019da902aa6 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Sat, 30 Oct 2010 20:59:13 +0200 Subject: [PATCH] support 'internal' cdef classes that do not show up in the module dict --- Cython/Compiler/ModuleNode.py | 16 ++++++++++------ Cython/Compiler/Nodes.py | 2 +- Cython/Compiler/Options.py | 4 ++++ Cython/Compiler/TypeSlots.py | 2 +- tests/run/internal_cdef_class.pyx | 29 +++++++++++++++++++++++++++++ 5 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 tests/run/internal_cdef_class.pyx diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index 27188d3d..a3650396 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -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: diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index e109b507..92536a7a 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -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: diff --git a/Cython/Compiler/Options.py b/Cython/Compiler/Options.py index fd7666ac..f36a33a0 100644 --- a/Cython/Compiler/Options.py +++ b/Cython/Compiler/Options.py @@ -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',), diff --git a/Cython/Compiler/TypeSlots.py b/Cython/Compiler/TypeSlots.py index 6e1b1131..a85bbae1 100644 --- a/Cython/Compiler/TypeSlots.py +++ b/Cython/Compiler/TypeSlots.py @@ -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 index 00000000..e532cc62 --- /dev/null +++ b/tests/run/internal_cdef_class.pyx @@ -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 -- 2.26.2