From: W. Trevor King Date: Mon, 2 May 2011 22:53:05 +0000 (-0400) Subject: Partial merge of trunk progress. Some tests still fail. X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=refs%2Fheads%2Fminimal-visibility;p=cython.git Partial merge of trunk progress. Some tests still fail. Failing tests: publicapi_pxd_mix generators_py cppwrap cpp_overload_wrapper --- 488a242124d9d9018f70fa02595a5595b8f8711a diff --cc Cython/Compiler/Code.py index 9bb3927f,c4c766cb..2c23b21b --- a/Cython/Compiler/Code.py +++ b/Cython/Compiler/Code.py @@@ -1391,3 -1462,26 +1461,27 @@@ class PyrexCodeWriter(object) def dedent(self): self.level -= 1 + + class ClosureTempAllocator(object): + def __init__(self, klass): + self.klass = klass + self.temps_allocated = {} + self.temps_free = {} + self.temps_count = 0 + + def reset(self): + for type, cnames in self.temps_allocated.items(): + self.temps_free[type] = list(cnames) + + def allocate_temp(self, type): + if not type in self.temps_allocated: + self.temps_allocated[type] = [] + self.temps_free[type] = [] + elif self.temps_free[type]: + return self.temps_free[type].pop(0) + cname = '%s%d' % (Naming.codewriter_temp_prefix, self.temps_count) - self.klass.declare_var(pos=None, name=cname, cname=cname, type=type, is_cdef=True) ++ self.klass.declare_var(pos=None, name=cname, cname=cname, type=type, ++ visibility='private', is_cdef=True) + self.temps_allocated[type].append(cname) + self.temps_count += 1 + return cname diff --cc Cython/Compiler/ExprNodes.py index da7a76ac,27f0ccb9..d6669b5e --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@@ -1335,9 -1330,8 +1331,9 @@@ class NameNode(AtomicExprNode) if entry and entry.is_cfunction: var_entry = entry.as_variable if var_entry: - if var_entry.is_builtin and Options.cache_builtins: + if var_entry.is_builtin and var_entry.is_const: - var_entry = env.declare_builtin(var_entry.name, self.pos) + var_entry = env.declare_builtin( + name = var_entry.name, pos = self.pos) node = NameNode(self.pos, name = self.name) node.entry = var_entry node.analyse_rvalue_entry(env) diff --cc Cython/Compiler/ModuleNode.py index 7ccff3ed,a3d34b39..1e6f89cb --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@@ -96,10 -96,12 +96,12 @@@ class ModuleNode(Nodes.Node, Nodes.Bloc f.close() def generate_h_code(self, env, options, result): - def h_entries(entries, pxd = 0): + def h_entries(entries, api=0, pxd=0): return [entry for entry in entries - if entry.c_visibility == 'public' or pxd and entry.defined_in_pxd] - h_types = h_entries(env.type_entries) - if ((entry.visibility == 'public') or ++ if ((entry.c_visibility == 'public') or + (api and entry.api) or + (pxd and entry.defined_in_pxd))] + h_types = h_entries(env.type_entries, api=1) h_vars = h_entries(env.var_entries) h_funcs = h_entries(env.cfunc_entries) h_extension_types = h_entries(env.c_class_entries) @@@ -874,13 -895,15 +895,15 @@@ code.putln("") name = entry.type.typeobj_cname if name: - if entry.visibility == 'extern' and not entry.in_cinclude: + if entry.c_visibility == 'extern' and not entry.in_cinclude: - code.putln("%s DL_IMPORT(PyTypeObject) %s;" % ( + code.putln("%s %s %s;" % ( Naming.extern_c_macro, + PyrexTypes.public_decl("PyTypeObject", "DL_IMPORT"), name)) - elif entry.visibility == 'public': + elif entry.c_visibility == 'public': - code.putln("%s DL_EXPORT(PyTypeObject) %s;" % ( + code.putln("%s %s %s;" % ( Naming.extern_c_macro, + PyrexTypes.public_decl("PyTypeObject", "DL_EXPORT"), name)) # ??? Do we really need the rest of this? ??? #else: @@@ -962,25 -988,27 +988,33 @@@ def generate_cfunction_predeclarations(self, env, code, definition): for entry in env.cfunc_entries: if entry.inline_func_in_pxd or (not entry.in_cinclude and (definition - or entry.defined_in_pxd or entry.visibility == 'extern')): - if entry.visibility == 'public': + or entry.defined_in_pxd or entry.c_visibility == 'extern')): + if entry.c_visibility in ('extern', 'public'): + storage_class = "%s " % Naming.extern_c_macro dll_linkage = "DL_EXPORT" + elif entry.visibility == 'extern': + storage_class = "%s " % Naming.extern_c_macro + dll_linkage = "DL_IMPORT" + elif entry.visibility == 'private': + storage_class = "static " + dll_linkage = None else: + storage_class = "static " dll_linkage = None type = entry.type + if not definition and entry.defined_in_pxd: type = CPtrType(type) header = type.declaration_code(entry.cname, - dll_linkage = dll_linkage) + dll_linkage = dll_linkage) + if entry.c_visibility == 'private': + storage_class = "static " + elif entry.c_visibility == 'public': + storage_class = "" + else: + storage_class = "%s " % Naming.extern_c_macro if entry.func_modifiers: - modifiers = '%s ' % ' '.join([ - modifier.upper() for modifier in entry.func_modifiers]) + modifiers = "%s " % ' '.join(entry.func_modifiers).upper() else: modifiers = '' code.putln("%s%s%s; /*proto*/" % ( diff --cc Cython/Compiler/Nodes.py index f59986cf,4405fefa..4113d7c8 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@@ -945,14 -954,18 +958,17 @@@ class CVarDefNode(StatNode) need_property = True else: need_property = False - visibility = self.visibility for declarator in self.declarators: - name_declarator, type = declarator.analyse(base_type, env) + if isinstance(declarator, CFuncDeclaratorNode): + name_declarator, type = declarator.analyse(base_type, env, directive_locals=self.directive_locals) + else: + name_declarator, type = declarator.analyse(base_type, env) if not type.is_complete(): - if not (self.visibility == 'extern' and type.is_array): + if not (self.c_visibility == 'extern' and type.is_array): error(declarator.pos, "Variable type '%s' is incomplete" % type) - if self.visibility == 'extern' and type.is_pyobject: + if self.c_visibility == 'extern' and type.is_pyobject: error(declarator.pos, "Python object cannot be declared extern") name = name_declarator.name @@@ -961,11 -974,11 +977,11 @@@ error(declarator.pos, "Missing name in declaration.") return if type.is_cfunction: - entry = dest_scope.declare_cfunction(name, type, declarator.pos, - cname = cname, visibility = self.visibility, in_pxd = self.in_pxd, - api = self.api) + entry = dest_scope.declare_cfunction( + name = name, cname = cname, c_visibility = self.c_visibility, visibility = self.visibility, overridable = self.overridable, api = self.api, type = type, in_pxd = self.in_pxd, + pos = declarator.pos) if entry is not None: - entry.directive_locals = self.directive_locals + entry.directive_locals = copy.copy(self.directive_locals) else: if self.directive_locals: error(self.pos, "Decorators can only be followed by functions") @@@ -978,12 -991,12 +994,13 @@@ class CStructOrUnionDefNode(StatNode): - # name string - # cname string or None + # name (same as Entry.name) + # cname (same as Entry.cname) # kind "struct" or "union" # typedef_flag boolean - # visibility "public" or "private" - # api boolean + # c_visibility (same as Entry.c_visibility) + # visibility (same as Entry.visibility) ++ # api (same as Entry.api) # in_pxd boolean # attributes [CVarDefNode] or None # entry Entry @@@ -998,9 -1011,9 +1015,9 @@@ if self.attributes is not None: scope = StructOrUnionScope(self.name) self.entry = env.declare_struct_or_union( - name = self.name, cname = self.cname, c_visibility = self.c_visibility, visibility = self.visibility, overridable = self.overridable, kind = self.kind, scope = scope, - self.name, self.kind, scope, self.typedef_flag, self.pos, - self.cname, visibility = self.visibility, api = self.api, - packed = self.packed) ++ name = self.name, cname = self.cname, c_visibility = self.c_visibility, visibility = self.visibility, overridable = self.overridable, api = self.api, kind = self.kind, scope = scope, + typedef_flag = self.typedef_flag, packed = self.packed, + pos = self.pos) if self.attributes is not None: if self.in_pxd and not env.in_cinclude: self.entry.defined_in_pxd = 1 @@@ -1077,20 -1091,21 +1094,21 @@@ class CppClassNode(CStructOrUnionDefNod attr.analyse_declarations(scope) class CEnumDefNode(StatNode): - # name string or None - # cname string or None + # name (same as Entry.name) + # cname (same as Entry.cname) # items [CEnumDefItemNode] # typedef_flag boolean - # visibility "public" or "private" - # api boolean + # c_visibility (same as Entry.c_visibility) + # visibility (same as Entry.visibility) ++ # api (same as Entry.api) # in_pxd boolean # entry Entry child_attrs = ["items"] def analyse_declarations(self, env): - self.entry = env.declare_enum(self.name, self.pos, - cname = self.cname, typedef_flag = self.typedef_flag, - visibility = self.visibility, api = self.api) + self.entry = env.declare_enum( - name = self.name, cname = self.cname, c_visibility = self.c_visibility, visibility = self.visibility, typedef_flag = self.typedef_flag, pos = self.pos) ++ name = self.name, cname = self.cname, c_visibility = self.c_visibility, visibility = self.visibility, api = self.api, typedef_flag = self.typedef_flag, pos = self.pos) if self.items is not None: if self.in_pxd and not env.in_cinclude: self.entry.defined_in_pxd = 1 @@@ -1101,11 -1116,9 +1119,11 @@@ pass def generate_execution_code(self, code): - if self.visibility == 'public': + if self.visibility == 'public' or self.api: temp = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True) for item in self.entry.enum_values: + if item.visibility == 'private': + continue code.putln("%s = PyInt_FromLong(%s); %s" % ( temp, item.cname, @@@ -1133,9 -1146,9 +1151,9 @@@ class CEnumDefItemNode(StatNode) if not self.value.type.is_int: self.value = self.value.coerce_to(PyrexTypes.c_int_type, env) self.value.analyse_const_expression(env) - entry = env.declare_const(self.name, enum_entry.type, - self.value, self.pos, cname = self.cname, - visibility = enum_entry.visibility, api = enum_entry.api) + entry = env.declare_const( + name = self.name, cname = self.cname, c_visibility = self.c_visibility, visibility = self.visibility, type = enum_entry.type, - value = self.value, pos = self.pos) ++ api = enum_entry.api, value = self.value, pos = self.pos) enum_entry.enum_values.append(entry) @@@ -1143,6 -1156,7 +1161,7 @@@ class CTypeDefNode(StatNode) # base_type CBaseTypeNode # declarator CDeclaratorNode # visibility "public" or "private" - # api boolean ++ # api (same as Entry.api) # in_pxd boolean child_attrs = ["base_type", "declarator"] @@@ -1150,8 -1164,10 +1169,8 @@@ def analyse_declarations(self, env): base = self.base_type.analyse(env) name_declarator, type = self.declarator.analyse(base, env) - name = name_declarator.name - cname = name_declarator.cname - entry = env.declare_typedef(name, type, self.pos, - cname = cname, visibility = self.visibility, api = self.api) + entry = env.declare_typedef( - name = name_declarator.name, cname = name_declarator.cname, c_visibility = self.c_visibility, visibility = self.visibility, base_type = type, pos = self.pos) ++ name = name_declarator.name, cname = name_declarator.cname, c_visibility = self.c_visibility, visibility = self.visibility, api = self.api, base_type = type, pos = self.pos) if self.in_pxd and not env.in_cinclude: entry.defined_in_pxd = 1 @@@ -1760,24 -1805,20 +1811,20 @@@ class CFuncDefNode(FuncDefNode) if cname is None: cname = self.entry.func_cname entity = type.function_header_code(cname, ', '.join(arg_decls)) - if self.entry.c_visibility == 'public': - dll_linkage = "DL_EXPORT" - if self.entry.visibility == 'private': ++ if self.entry.c_visibility == 'private': + storage_class = "static " else: - dll_linkage = None - header = self.return_type.declaration_code(entity, - dll_linkage = dll_linkage) - if self.entry.c_visibility == 'extern': - storage_class = "%s " % Naming.extern_c_macro - elif self.entry.c_visibility == 'public': storage_class = "" - else: - storage_class = "static " + dll_linkage = None + modifiers = "" if 'inline' in self.modifiers: self.modifiers[self.modifiers.index('inline')] = 'cython_inline' - code.putln("%s%s %s {" % ( - storage_class, - ' '.join(self.modifiers).upper(), # macro forms - header)) + if self.modifiers: + modifiers = "%s " % ' '.join(self.modifiers).upper() + + header = self.return_type.declaration_code(entity, dll_linkage=dll_linkage) + #print (storage_class, modifiers, header) + code.putln("%s%s%s {" % (storage_class, modifiers, header)) def generate_argument_declarations(self, env, code): for arg in self.args: @@@ -2195,14 -2232,7 +2244,7 @@@ class DefNode(FuncDefNode) entry.doc = None def declare_lambda_function(self, env): - name = self.name - prefix = env.scope_prefix - func_cname = \ - Naming.lambda_func_prefix + u'funcdef' + prefix + self.lambda_name - entry = env.declare_lambda_function(cname = func_cname, pos = self.pos) - entry.pymethdef_cname = \ - Naming.lambda_func_prefix + u'methdef' + prefix + self.lambda_name - entry.qualified_name = env.qualify_name(self.lambda_name) - entry = env.declare_lambda_function(self.lambda_name, self.pos) ++ entry = env.declare_lambda_function(cname = self.lambda_name, pos = self.pos) entry.doc = None self.entry = entry @@@ -2916,6 -2956,146 +2969,148 @@@ def caller_will_check_exceptions(self): return 1 + + class GeneratorDefNode(DefNode): + # Generator DefNode. + # + # gbody GeneratorBodyDefNode + # + + is_generator = True + needs_closure = True + + child_attrs = DefNode.child_attrs + ["gbody"] + + def __init__(self, **kwargs): + # XXX: don't actually needs a body + kwargs['body'] = StatListNode(kwargs['pos'], stats=[]) + super(GeneratorDefNode, self).__init__(**kwargs) + + def analyse_declarations(self, env): + super(GeneratorDefNode, self).analyse_declarations(env) + self.gbody.local_scope = self.local_scope + self.gbody.analyse_declarations(env) + + def generate_function_body(self, env, code): + body_cname = self.gbody.entry.func_cname + generator_cname = '%s->%s' % (Naming.cur_scope_cname, Naming.obj_base_cname) + + code.putln('%s.resume_label = 0;' % generator_cname) + code.putln('%s.body = (__pyx_generator_body_t) %s;' % (generator_cname, body_cname)) + code.put_giveref(Naming.cur_scope_cname) + code.put_finish_refcount_context() + code.putln("return (PyObject *) %s;" % Naming.cur_scope_cname); + + def generate_function_definitions(self, env, code): + self.gbody.generate_function_header(code, proto=True) + super(GeneratorDefNode, self).generate_function_definitions(env, code) + self.gbody.generate_function_definitions(env, code) + + + class GeneratorBodyDefNode(DefNode): + # Generator body DefNode. + # + + is_generator_body = True + + def __init__(self, pos=None, name=None, body=None): + super(GeneratorBodyDefNode, self).__init__(pos=pos, body=body, name=name, doc=None, + args=[], + star_arg=None, starstar_arg=None) + + def declare_generator_body(self, env): + prefix = env.next_id(env.scope_prefix) + name = env.next_id('generator') - entry = env.declare_var(prefix + name, py_object_type, self.pos, visibility='private') ++ entry = env.declare_var( ++ name=prefix + name, type=py_object_type, c_visibility='private', ++ visibility='public', pos=self.pos) + entry.func_cname = Naming.genbody_prefix + prefix + name + entry.qualified_name = EncodedString(self.name) + self.entry = entry + + def analyse_declarations(self, env): + self.analyse_argument_types(env) + self.declare_generator_body(env) + + def generate_function_header(self, code, proto=False): + header = "static PyObject *%s(%s, PyObject *%s)" % ( + self.entry.func_cname, + self.local_scope.scope_class.type.declaration_code(Naming.cur_scope_cname), + Naming.sent_value_cname) + if proto: + code.putln('%s; /* proto */' % header) + else: + code.putln('%s /* generator body */\n{' % header); + + def generate_function_definitions(self, env, code): + lenv = self.local_scope + + # Generate closure function definitions + self.body.generate_function_definitions(lenv, code) + + # Generate C code for header and body of function + code.enter_cfunc_scope() + code.return_from_error_cleanup_label = code.new_label() + + # ----- Top-level constants used by this function + code.mark_pos(self.pos) + self.generate_cached_builtins_decls(lenv, code) + # ----- Function header + code.putln("") + self.generate_function_header(code) + # ----- Local variables + code.putln("PyObject *%s = NULL;" % Naming.retval_cname) + tempvardecl_code = code.insertion_point() + code.put_declare_refcount_context() + code.put_setup_refcount_context(self.entry.name) + + # ----- Resume switch point. + code.funcstate.init_closure_temps(lenv.scope_class.type.scope) + resume_code = code.insertion_point() + first_run_label = code.new_label('first_run') + code.use_label(first_run_label) + code.put_label(first_run_label) + code.putln('%s' % + (code.error_goto_if_null(Naming.sent_value_cname, self.pos))) + + # ----- Function body + self.generate_function_body(env, code) + code.putln('PyErr_SetNone(PyExc_StopIteration); %s' % code.error_goto(self.pos)) + # ----- Error cleanup + if code.error_label in code.labels_used: + code.put_goto(code.return_label) + code.put_label(code.error_label) + for cname, type in code.funcstate.all_managed_temps(): + code.put_xdecref(cname, type) + code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name) + + # ----- Non-error return cleanup + code.put_label(code.return_label) + code.put_xdecref(Naming.retval_cname, py_object_type) + code.putln('%s->%s.resume_label = -1;' % (Naming.cur_scope_cname, Naming.obj_base_cname)) + code.put_finish_refcount_context() + code.putln('return NULL;'); + code.putln("}") + + # ----- Go back and insert temp variable declarations + tempvardecl_code.put_temp_declarations(code.funcstate) + # ----- Generator resume code + resume_code.putln("switch (%s->%s.resume_label) {" % (Naming.cur_scope_cname, Naming.obj_base_cname)); + resume_code.putln("case 0: goto %s;" % first_run_label) + + from ParseTreeTransforms import YieldNodeCollector + collector = YieldNodeCollector() + collector.visitchildren(self) + for yield_expr in collector.yields: + resume_code.putln("case %d: goto %s;" % (yield_expr.label_num, yield_expr.label_name)); + resume_code.putln("default: /* CPython raises the right error here */"); + resume_code.put_finish_refcount_context() + resume_code.putln("return NULL;"); + resume_code.putln("}"); + + code.exit_cfunc_scope() + + class OverrideCheckNode(StatNode): # A Node for dispatching to the def method if it # is overriden. diff --cc Cython/Compiler/ParseTreeTransforms.py index 5626c4dc,00de70a3..a660db13 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@@ -1219,7 -1227,8 +1227,8 @@@ if VALUE is not None def visit_CNameDeclaratorNode(self, node): if node.name in self.seen_vars_stack[-1]: entry = self.env_stack[-1].lookup(node.name) - if entry is None or entry.c_visibility != 'extern': - if (entry is None or entry.visibility != 'extern' ++ if (entry is None or entry.c_visibility != 'extern' + and not entry.scope.is_c_class_scope): warning(node.pos, "cdef variable '%s' declared after it is used" % node.name, 2) self.visitchildren(node) return node @@@ -1446,7 -1511,57 +1515,61 @@@ class CreateClosureClasses(CythonTransf self.visitchildren(node) return node - def get_scope_use(self, node): + def create_generator_class(self, target_module_scope, pos): + if self.generator_class: + return self.generator_class + # XXX: make generator class creation cleaner + entry = target_module_scope.declare_c_class(name='__pyx_Generator', + objstruct_cname='__pyx_Generator_object', + typeobj_cname='__pyx_Generator_type', + pos=pos, defining=True, implementing=True) + klass = entry.type.scope + klass.is_internal = True + klass.directives = {'final': True} + + body_type = PyrexTypes.create_typedef_type('generator_body', + PyrexTypes.c_void_ptr_type, + '__pyx_generator_body_t') + klass.declare_var(pos=pos, name='body', cname='body', - type=body_type, is_cdef=True) ++ visibility='private', type=body_type, is_cdef=True) + klass.declare_var(pos=pos, name='is_running', cname='is_running', type=PyrexTypes.c_int_type, + is_cdef=True) + klass.declare_var(pos=pos, name='resume_label', cname='resume_label', type=PyrexTypes.c_int_type, + is_cdef=True) + klass.declare_var(pos=pos, name='exc_type', cname='exc_type', + type=PyrexTypes.py_object_type, is_cdef=True) + klass.declare_var(pos=pos, name='exc_value', cname='exc_value', + type=PyrexTypes.py_object_type, is_cdef=True) + klass.declare_var(pos=pos, name='exc_traceback', cname='exc_traceback', + type=PyrexTypes.py_object_type, is_cdef=True) + + import TypeSlots - e = klass.declare_pyfunction('send', pos) ++ e = klass.declare_pyfunction(name='send', pos=pos) + e.func_cname = '__Pyx_Generator_Send' + e.signature = TypeSlots.binaryfunc + - e = klass.declare_pyfunction('close', pos) ++ e = klass.declare_pyfunction(name='close', pos=pos) + e.func_cname = '__Pyx_Generator_Close' + e.signature = TypeSlots.unaryfunc + - e = klass.declare_pyfunction('throw', pos) ++ e = klass.declare_pyfunction(name='throw', pos=pos) + e.func_cname = '__Pyx_Generator_Throw' + e.signature = TypeSlots.pyfunction_signature + - e = klass.declare_var('__iter__', PyrexTypes.py_object_type, pos, visibility='public') ++ e = klass.declare_var( ++ name='__iter__', type=PyrexTypes.py_object_type, ++ c_visibility='public', pos=pos) + e.func_cname = 'PyObject_SelfIter' + - e = klass.declare_var('__next__', PyrexTypes.py_object_type, pos, visibility='public') ++ e = klass.declare_var( ++ name='__next__', type=PyrexTypes.py_object_type, ++ c_visibility='public', pos=pos) + e.func_cname = '__Pyx_Generator_Next' + + self.generator_class = entry.type + return self.generator_class + + def find_entries_used_in_closures(self, node): from_closure = [] in_closure = [] for name, entry in node.local_scope.entries.items(): diff --cc Cython/Compiler/Parsing.py index 4a822d5e,4e2c55ad..63ae5c0f --- a/Cython/Compiler/Parsing.py +++ b/Cython/Compiler/Parsing.py @@@ -2436,8 -2471,8 +2488,9 @@@ def p_c_enum_definition(s, pos, ctx) s.expect_dedent() return Nodes.CEnumDefNode( pos, name = name, cname = cname, items = items, - typedef_flag = ctx.typedef_flag, visibility = ctx.visibility, - api = ctx.api, in_pxd = ctx.level == 'module_pxd') + typedef_flag = ctx.typedef_flag, c_visibility = ctx.c_visibility, - visibility = ctx.visibility, in_pxd = ctx.level == 'module_pxd') ++ visibility = ctx.visibility, api = ctx.api, ++ in_pxd = ctx.level == 'module_pxd') def p_c_enum_line(s, ctx, items): if s.sy != 'pass': @@@ -2499,38 -2530,21 +2552,39 @@@ def p_c_struct_or_union_definition(s, p s.expect_dedent() else: s.expect_newline("Syntax error in struct or union definition") -- return Nodes.CStructOrUnionDefNode(pos, - name = name, cname = cname, kind = kind, attributes = attributes, - typedef_flag = ctx.typedef_flag, visibility = ctx.visibility, - api = ctx.api, in_pxd = ctx.level == 'module_pxd', packed = packed) ++ return Nodes.CStructOrUnionDefNode(pos = pos, + name = name, + cname = cname, + kind = kind, + attributes = attributes, + typedef_flag = ctx.typedef_flag, + cdef_flag = ctx.cdef_flag, + overridable = ctx.overridable, + c_visibility = ctx.c_visibility, + visibility = ctx.visibility, ++ api = ctx.api, + in_pxd = ctx.level == 'module_pxd', + packed = packed) -def p_visibility(s, prev_visibility): +def p_visibility(s, ctx): pos = s.position() - visibility = prev_visibility if s.sy == 'IDENT' and s.systring in ('extern', 'public', 'readonly'): visibility = s.systring - if prev_visibility != 'private' and visibility != prev_visibility: - s.error("Conflicting visibility options '%s' and '%s'" - % (prev_visibility, visibility)) + outer_scope = ctx.level in ('module', 'module_pxd') + if visibility == 'extern': + #if prev_visibility != 'private' and visibility != prev_visibility: + # s.error("Conflicting visibility options '%s' and '%s'" + # % (prev_visibility, visibility)) + ctx.c_visibility = 'extern' + # Need to restore/set default value for Python visibility? + elif outer_scope and visibility not in ('readonly',): + ctx.c_visibility = visibility + else: + ctx.visibility = visibility + if ctx.visibility != 'private': + ctx.c_visibility = 'public' s.next() - return visibility + return ctx def p_c_modifiers(s): if s.sy == 'IDENT' and s.systring in ('inline',): @@@ -2619,9 -2617,10 +2673,9 @@@ def p_ctypedef_statement(s, pos, ctx) declarator = p_c_declarator(s, ctx, is_type = 1, nonempty = 1) s.expect_newline("Syntax error in ctypedef statement") return Nodes.CTypeDefNode( - pos, base_type = base_type, - declarator = declarator, - visibility = visibility, api = api, - in_pxd = ctx.level == 'module_pxd') + pos, base_type = base_type, declarator = declarator, + c_visibility = ctx.c_visibility, visibility = ctx.visibility, - in_pxd = ctx.level == 'module_pxd') ++ api = ctx.api, in_pxd = ctx.level == 'module_pxd') def p_decorators(s): decorators = [] @@@ -2747,8 -2746,8 +2801,8 @@@ def p_c_class_definition(s, pos, ctx, base_class_module = ".".join(base_class_path[:-1]) base_class_name = base_class_path[-1] if s.sy == '[': - if ctx.c_visibility not in ('extern', 'public'): - error(s.position(), "Name options only allowed for 'public' or 'extern' C class") - if ctx.visibility not in ('public', 'extern') and not ctx.api: ++ if ctx.c_visibility not in ('public', 'extern') and not ctx.api: + error(s.position(), "Name options only allowed for 'public', 'api', or 'extern' C class") objstruct_name, typeobj_name = p_c_class_options(s) if s.sy == ':': if ctx.level == 'module_pxd': @@@ -2774,13 -2769,15 +2828,16 @@@ error(pos, "Object struct name specification required for 'public' C class") if not typeobj_name: error(pos, "Type object name specification required for 'public' C class") - elif ctx.visibility == 'private': + elif ctx.c_visibility == 'private': if ctx.api: - error(pos, "Only 'public' C class can be declared 'api'") + if not objstruct_name: + error(pos, "Object struct name specification required for 'api' C class") + if not typeobj_name: + error(pos, "Type object name specification required for 'api' C class") else: - error(pos, "Invalid class visibility '%s'" % ctx.visibility) + error(pos, "Invalid class visibility '%s'" % ctx.visibility_string()) return Nodes.CClassDefNode(pos, + c_visibility = ctx.c_visibility, visibility = ctx.visibility, typedef_flag = ctx.typedef_flag, api = ctx.api, diff --cc Cython/Compiler/PyrexTypes.py index d9093f3c,0870cf22..9f9bd3d0 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py @@@ -1968,12 -1977,12 +1973,8 @@@ class StructUtilityCode(object) code.putln("return NULL;") code.putln("}") -- # This is a bit of a hack, we need a forward declaration -- # due to the way things are ordered in the module... -- if self.forward_decl: -- proto.putln(self.type.declaration_code('') + ';') proto.putln(self.header + ";") - + class CStructOrUnionType(CType): # name string @@@ -2013,12 -2022,12 +2014,12 @@@ self.to_py_function = None self._convert_code = False return False - forward_decl = (self.entry.visibility != 'extern') + forward_decl = (self.entry.c_visibility != 'extern') self._convert_code = StructUtilityCode(self, forward_decl) - + env.use_utility_code(self._convert_code) return True - + def __repr__(self): return "" % (self.name, self.cname, ("", " typedef")[self.typedef_flag]) diff --cc Cython/Compiler/Symtab.py index 5ffcb0ca,6425a26d..c045de96 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@@ -365,10 -363,10 +367,10 @@@ class Scope(object) def qualify_name(self, name): return EncodedString("%s.%s" % (self.qualified_name, name)) - def declare_const(self, name, type, value, pos, cname = None, visibility = 'private', api = 0): + def declare_const(self, name, cname = None, namespace = None, c_visibility = 'private', visibility = 'public', overridable = 0, api = 0, type = None, value = None, pos = None): # Add an entry for a named constant. if not cname: - if self.in_cinclude or c_visibility == 'public': - if self.in_cinclude or (visibility == 'public' or api): ++ if self.in_cinclude or c_visibility == 'public' or api: cname = name else: cname = self.mangle(Naming.enum_prefix, name) @@@ -382,17 -380,18 +384,18 @@@ # Add an entry for a type definition. if not cname: cname = name - entry = self.declare(name, cname, type, pos, visibility, shadow) + entry = self.declare(name = name, cname = cname, namespace = namespace, c_visibility = c_visibility, visibility = visibility, overridable = overridable, api = api, type = type, shadow = shadow, pos = pos) entry.is_type = 1 + entry.api = api if defining: self.type_entries.append(entry) # here we would set as_variable to an object representing this type return entry - def declare_typedef(self, name, base_type, pos, cname = None, - visibility = 'private', api = 0): + def declare_typedef(self, name, cname = None, namespace = None, c_visibility = 'private', visibility = 'public', overridable = 0, api = 0, + base_type = None, pos = None): if not cname: - if self.in_cinclude or c_visibility == 'public': - if self.in_cinclude or (visibility == 'public' or api): ++ if self.in_cinclude or c_visibility == 'public' or api: cname = name else: cname = self.mangle(Naming.type_prefix, name) @@@ -407,11 -406,13 +410,11 @@@ type.qualified_name = entry.qualified_name return entry - def declare_struct_or_union(self, name, kind, scope, - typedef_flag, pos, cname = None, - visibility = 'private', api = 0, - packed = False): + def declare_struct_or_union(self, name, cname = None, namespace = None, c_visibility = 'private', visibility = 'public', overridable = 0, api = 0, kind = None, scope = None, typedef_flag=False, + packed=False, pos = None): # Add an entry for a struct or union definition. if not cname: - if self.in_cinclude or c_visibility == 'public': - if self.in_cinclude or (visibility == 'public' or api): ++ if self.in_cinclude or c_visibility == 'public' or api: cname = name else: cname = self.mangle(Naming.type_prefix, name) @@@ -483,34 -482,18 +486,31 @@@ def check_previous_typedef_flag(self, entry, typedef_flag, pos): if typedef_flag != entry.type.typedef_flag: error(pos, "'%s' previously declared using '%s'" % ( - entry.name, ("cdef", "ctypedef")[entry.type.typedef_flag])) - - def check_previous_visibility(self, entry, visibility, pos): - if entry.visibility != visibility: - error(pos, "'%s' previously declared as '%s'" % ( - entry.name, entry.visibility)) - - def declare_enum(self, name, pos, cname, typedef_flag, - visibility = 'private', api = 0): + entry.name, + ("cdef", "ctypedef")[entry.type.typedef_flag])) + - def _check_previous_visibility(self, entry, c_visibility = 'private', visibility = 'public'): ++ def check_previous_visibility(self, entry, name, cname = None, namespace = None, c_visibility = 'private', visibility = 'public', overridable = 0, api = 0, type_name=None, ++ pos = None): + # Compare the visibility of `entry` with a second + # `visibility`. If there is a difference, return a string + # representing the conflicting `entry` visibility, otherwise + # return an empty string. ++ ++ if not type_name: ++ type_name = type(entry) + if c_visibility != entry.c_visibility: - return entry.c_visibility ++ error(pos, "%s '%s' C visibility changed from '%s' to '%s'" % ( ++ type_name, entry.name, entry.c_visibility, c_visibility)) + if visibility != entry.visibility: - return entry.visibility - - def check_previous_visibility(self, entry, name, cname = None, namespace = None, c_visibility = 'private', visibility = 'public', overridable = 0, api = 0, type_name=None, - pos = None): ++ error(pos, "%s '%s' Python visibility changed from '%s' to %s" % ( ++ type_name, entry.name, entry.visibility, visibility)) + # WTK: check api? Previous code seems to allow you to set the + # api flag anywhere. - vis_diff = self._check_previous_visibility(entry, c_visibility = c_visibility, visibility = visibility) - if vis_diff: - if not type_name: - type_name = type(entry) - error(pos, "%s '%s' previously declared as '%s'" % ( - type_name, entry.name, vis_diff)) + + def declare_enum(self, name, cname = None, namespace = None, c_visibility = 'private', visibility = 'public', overridable = 0, api = 0, typedef_flag = None, pos = None): if name: if not cname: - if self.in_cinclude or c_visibility == 'public': - if self.in_cinclude or (visibility == 'public' or api): ++ if self.in_cinclude or c_visibility == 'public' or api: cname = name else: cname = self.mangle(Naming.type_prefix, name) @@@ -533,8 -518,9 +533,9 @@@ constructor = type.scope.lookup(u'') if constructor is not None and PyrexTypes.best_match([], constructor.all_alternatives()) is None: error(pos, "C++ class must have a default constructor to be stack allocated") - entry = self.declare(name, cname, type, pos, visibility) + entry = self.declare(name = name, cname = cname, namespace = namespace, c_visibility = c_visibility, visibility = visibility, overridable = overridable, api = api, type = type, pos = pos) entry.is_variable = 1 + entry.api = api self.control_flow.set_state((), (name, 'initialized'), False) return entry @@@ -576,11 -556,17 +577,19 @@@ entry.is_anonymous = True return entry - def declare_lambda_function(self, lambda_name, pos): + def declare_lambda_function(self, name = None, cname = None, namespace = None, c_visibility = 'private', visibility = 'public', overridable = 0, api = 0, pos = None): # Add an entry for an anonymous Python function. - func_cname = self.mangle(Naming.lambda_func_prefix + u'funcdef_', lambda_name) - pymethdef_cname = self.mangle(Naming.lambda_func_prefix + u'methdef_', lambda_name) - qualified_name = self.qualify_name(lambda_name) ++ if not cname: ++ cname = self.mangle(Naming.lambda_func_prefix + u'funcdef_', cname) ++ pymethdef_cname = self.mangle(Naming.lambda_func_prefix + u'methdef_', cname) ++ qualified_name = self.qualify_name(cname) + - entry = self.declare(None, func_cname, py_object_type, pos, 'private') - entry.name = lambda_name + entry = self.declare_var(name = name, cname = cname, namespace = namespace, c_visibility = c_visibility, visibility = visibility, overridable = overridable, api = api, type = py_object_type, pos = pos) ++ + entry.name = EncodedString(cname) + entry.qualified_name = qualified_name + entry.pymethdef_cname = pymethdef_cname - entry.func_cname = func_cname + entry.func_cname = cname entry.signature = pyfunction_signature entry.is_anonymous = True return entry @@@ -601,12 -588,10 +610,13 @@@ cname = self.mangle(Naming.func_prefix, name) entry = self.lookup_here(name) if entry: - vis_diff = self._check_previous_visibility(entry, c_visibility = c_visibility, visibility = visibility) - if vis_diff: - warning(pos, "Function '%s' previously declared as '%s'" % ( - name, vis_diff), 1) - if visibility != 'private' and visibility != entry.visibility: - warning(pos, "Function '%s' previously declared as '%s'" % (name, entry.visibility), 1) ++ self.check_previous_visibility( ++ entry, name = name, cname = cname, namespace = namespace, ++ c_visibility = c_visibility, visibility = visibility, ++ overridable = overridable, api = api, type_name = 'Function', ++ pos = pos) if not entry.type.same_as(type): - if visibility == 'extern' and entry.visibility == 'extern': + if c_visibility == 'extern' and entry.c_visibility == 'extern': can_override = False if self.is_cpp(): can_override = True @@@ -772,15 -760,18 +784,18 @@@ class BuiltinScope(Scope) name = 'unicode' return Scope.lookup(self, name) - def declare_builtin(self, name, pos): + def declare_builtin(self, name, cname = None, namespace = None, c_visibility = 'private', visibility = 'public', overridable = 0, api = 0, pos = None): if not hasattr(builtins, name): if self.outer_scope is not None: - return self.outer_scope.declare_builtin(name, pos) + return self.outer_scope.declare_builtin(name = name, cname = cname, namespace = namespace, c_visibility = c_visibility, visibility = visibility, overridable = overridable, api = api, pos = pos) else: - error(pos, "undeclared name not builtin: %s" % name) + if Options.error_on_unknown_names: + error(pos, "undeclared name not builtin: %s" % name) + else: + warning(pos, "undeclared name not builtin: %s" % name, 2) - def declare_builtin_cfunction(self, name, type, cname, python_equiv = None, - utility_code = None): + def declare_builtin_cfunction(self, name, cname = None, namespace = None, c_visibility = 'private', visibility = 'public', overridable = 0, api = 0, type = None, python_equiv = None, + utility_code = None): # If python_equiv == "*", the Python equivalent has the same name # as the entry, otherwise it has the name specified by python_equiv. name = EncodedString(name) @@@ -932,34 -920,40 +949,42 @@@ class ModuleScope(Scope) return entry return self.outer_scope.lookup(name, language_level = self.context.language_level) - def declare_builtin(self, name, pos): + def declare_builtin(self, name, cname = None, namespace = None, c_visibility = 'private', visibility = 'public', overridable = 0, api = 0, pos = None): - if (not hasattr(builtins, name) - and name != 'xrange'): - # 'xrange' is special cased in Code.py + if not hasattr(builtins, name) \ + and name not in Code.non_portable_builtins_map \ + and name not in Code.uncachable_builtins: if self.has_import_star: - entry = self.declare_var(name, py_object_type, pos) + entry = self.declare_var(name = name, cname = cname, namespace = namespace, c_visibility = c_visibility, visibility = visibility, overridable = overridable, api = api, type = py_object_type, pos = pos) return entry + elif self.outer_scope is not None: + return self.outer_scope.declare_builtin(name = name, cname = cname, namespace = namespace, c_visibility = c_visibility, visibility = visibility, overridable = overridable, api = api, pos = pos) else: - error(pos, "undeclared name not builtin: %s"%name) + if Options.error_on_unknown_names: + error(pos, "undeclared name not builtin: %s" % name) + else: + warning(pos, "undeclared name not builtin: %s" % name, 2) + # unknown - assume it's builtin and look it up at runtime + entry = self.declare(name, None, py_object_type, pos, 'private') + entry.is_builtin = 1 + return entry if Options.cache_builtins: for entry in self.cached_builtins: if entry.name == name: return entry - entry = self.declare(None, None, py_object_type, pos, 'private') + entry = self.declare(type = py_object_type, pos = pos) - if Options.cache_builtins: + if Options.cache_builtins and name not in Code.uncachable_builtins: entry.is_builtin = 1 - entry.is_const = 1 + entry.is_const = 1 # cached entry.name = name entry.cname = Naming.builtin_prefix + name self.cached_builtins.append(entry) self.undeclared_cached_builtins.append(entry) else: entry.is_builtin = 1 + entry.name = name return entry - def find_module(self, module_name, pos): + def find_module(self, module_name, pos = None): # Find a module in the import namespace, interpreting # relative imports relative to this module's parent. # Finds and parses the module's .pxd file if the module @@@ -1071,9 -1060,9 +1096,9 @@@ # If this is a non-extern typedef class, expose the typedef, but use # the non-typedef struct internally to avoid needing forward # declarations for anonymous structs. - if typedef_flag and visibility != 'extern': - if not (visibility == 'public' or api): + if typedef_flag and c_visibility != 'extern': - if c_visibility != 'public': - warning(pos, "ctypedef only valid for public and extern classes", 2) ++ if not (c_visibility == 'public' or api): + warning(pos, "ctypedef only valid for 'extern' , 'public', and 'api'", 2) objtypedef_cname = objstruct_cname typedef_flag = 0 else: @@@ -1387,9 -1388,10 +1423,9 @@@ class GeneratorExpressionScope(Scope) self.genexp_prefix = "%s%d%s" % (Naming.pyrex_prefix, len(name), name) def mangle(self, prefix, name): - return '%s%s' % (self.genexp_prefix, self.parent_scope.mangle(self, prefix, name)) + return '%s%s' % (self.genexp_prefix, self.parent_scope.mangle(prefix, name)) - def declare_var(self, name, type, pos, - cname = None, visibility = 'private', api = 0, is_cdef = True): + def declare_var(self, name, cname = None, namespace = None, c_visibility = 'private', visibility = 'public', overridable = 0, api = 0, type = None, is_cdef = 0, pos = None): if type is unspecified_type: # if the outer scope defines a type for this variable, inherit it outer_entry = self.outer_scope.lookup(name) @@@ -1404,6 -1406,12 +1440,15 @@@ self.entries[name] = entry return entry - def declare_lambda_function(self, func_cname, pos): - return self.outer_scope.declare_lambda_function(func_cname, pos) ++ def declare_lambda_function(self, name = None, cname = None, namespace = None, c_visibility = 'private', visibility = 'public', overridable = 0, api = 0, pos = None): ++ return self.outer_scope.declare_lambda_function( ++ name = name, cname = cname, namespace = namespace, ++ c_visibility = c_visibility, visibility = visibility, ++ overridable = overridable, api = api, pos = pos) + + def add_lambda_def(self, def_node): + return self.outer_scope.add_lambda_def(def_node) + class ClosureScope(LocalScope): @@@ -1497,9 -1511,9 +1542,9 @@@ class PyClassScope(ClassScope) if type is unspecified_type: type = py_object_type # Add an entry for a class attribute. - entry = Scope.declare_var(self, name, type, pos, - cname=cname, visibility=visibility, api=api, is_cdef=is_cdef) + entry = Scope.declare_var( + self, name, cname = None, namespace = None, c_visibility = 'private', visibility = 'public', overridable = 0, api = 0, type = type, is_cdef = is_cdef, pos = pos) - entry.is_pyglobal = 1 + entry.is_pyglobal = 1 # FIXME: WTF? entry.is_pyclass_attr = 1 return entry @@@ -1595,9 -1627,8 +1654,7 @@@ class CClassScope(ClassScope) if name == "__new__": error(pos, "__new__ method of extension type will change semantics " "in a future version of Pyrex and Cython. Use __cinit__ instead.") - if c_visibility != 'extern': - error(pos, "C class pyfunctions may only be extern") - entry = self.declare_var(name, py_object_type, pos, - visibility='extern') + entry = self.declare_var(name = name, cname = cname, namespace = namespace, c_visibility = c_visibility, visibility = visibility, overridable = overridable, api = api, type = py_object_type, pos = pos) special_sig = get_special_method_signature(name) if special_sig: # Special methods get put in the method table with a particular diff --cc runtests.py index 3436d473,d565aed1..b241fbc9 --- a/runtests.py +++ b/runtests.py @@@ -510,64 -601,70 +601,70 @@@ class CythonRunTestCase(CythonCompileTe self.run_doctests(self.module, result) def run_doctests(self, module_name, result): - if sys.version_info[0] >= 3 or not hasattr(os, 'fork') or not self.fork: - doctest.DocTestSuite(module_name).run(result) - gc.collect() - return - - # fork to make sure we do not keep the tested module loaded - result_handle, result_file = tempfile.mkstemp() - os.close(result_handle) - child_id = os.fork() - if not child_id: - result_code = 0 - try: - try: - tests = None - try: - partial_result = PartialTestResult(result) - tests = doctest.DocTestSuite(module_name) - tests.run(partial_result) - gc.collect() - except Exception: - if tests is None: - # importing failed, try to fake a test class - tests = _FakeClass( - failureException=sys.exc_info()[1], - _shortDescription=self.shortDescription(), - module_name=None) - partial_result.addError(tests, sys.exc_info()) - result_code = 1 - output = open(result_file, 'wb') - pickle.dump(partial_result.data(), output) - except: - traceback.print_exc() - finally: - try: output.close() - except: pass - os._exit(result_code) + def run_test(result): + tests = doctest.DocTestSuite(module_name) + tests.run(result) + run_forked_test(result, run_test, self.shortDescription(), self.fork) + + def run_forked_test(result, run_func, test_name, fork=True): + if not fork or sys.version_info[0] >= 3 or not hasattr(os, 'fork'): + run_func(result) + gc.collect() + return + + # fork to make sure we do not keep the tested module loaded + result_handle, result_file = tempfile.mkstemp() + os.close(result_handle) + child_id = os.fork() + if not child_id: + result_code = 0 try: - cid, result_code = os.waitpid(child_id, 0) - # os.waitpid returns the child's result code in the - # upper byte of result_code, and the signal it was - # killed by in the lower byte - if result_code & 255: - raise Exception("Tests in module '%s' were unexpectedly killed by signal %d"% - (module_name, result_code & 255)) - result_code = result_code >> 8 - if result_code in (0,1): - input = open(result_file, 'rb') + try: + tests = None try: - PartialTestResult.join_results(result, pickle.load(input)) - finally: - input.close() - if result_code: - raise Exception("Tests in module '%s' exited with status %d" % - (module_name, result_code)) + partial_result = PartialTestResult(result) + run_func(partial_result) + gc.collect() + except Exception: + if tests is None: + # importing failed, try to fake a test class + tests = _FakeClass( + failureException=sys.exc_info()[1], + _shortDescription=test_name, + module_name=None) + partial_result.addError(tests, sys.exc_info()) + result_code = 1 + output = open(result_file, 'wb') + pickle.dump(partial_result.data(), output) + except: + traceback.print_exc() finally: - try: os.unlink(result_file) + try: output.close() except: pass + os._exit(result_code) + + try: + cid, result_code = os.waitpid(child_id, 0) + # os.waitpid returns the child's result code in the + # upper byte of result_code, and the signal it was + # killed by in the lower byte + if result_code & 255: - raise Exception("Tests in module '%s' were unexpectedly killed by signal %d"% - (module_name, result_code & 255)) ++ raise Exception("Test '%s' was unexpectedly killed by signal %d"% ++ (test_name, result_code & 255)) + result_code = result_code >> 8 + if result_code in (0,1): + input = open(result_file, 'rb') + try: + PartialTestResult.join_results(result, pickle.load(input)) + finally: + input.close() + if result_code: - raise Exception("Tests in module '%s' exited with status %d" % - (module_name, result_code)) ++ raise Exception("Test '%s' exited with status %d" % ++ (test_name, result_code)) + finally: + try: os.unlink(result_file) + except: pass class PureDoctestTestCase(unittest.TestCase): def __init__(self, module_name, module_path): diff --cc tests/compile/cpdef.pyx index 5db6b3e0,7eec85f7..38654775 --- a/tests/compile/cpdef.pyx +++ b/tests/compile/cpdef.pyx @@@ -1,8 -1,6 +1,10 @@@ + # mode: compile + cdef class A: + cdef public int i + cdef readonly int j + cdef void *ptr + cpdef a(self): ma(self) diff --cc tests/errors/builtin_type_inheritance.pyx index 0d11207d,c7c02222..82f7e40c --- a/tests/errors/builtin_type_inheritance.pyx +++ b/tests/errors/builtin_type_inheritance.pyx @@@ -11,7 -12,7 +12,7 @@@ cdef class MyStr(str): # only in Py2, b pass _ERRORS = """ - 4:0: inheritance from PyVarObject types like 'tuple' is not currently supported - 7:0: inheritance from PyVarObject types like 'bytes' is not currently supported - 10:0: inheritance from PyVarObject types like 'str' is not currently supported -5:5: inheritance from PyVarObject types like 'tuple' is not currently supported -8:5: inheritance from PyVarObject types like 'bytes' is not currently supported -11:5: inheritance from PyVarObject types like 'str' is not currently supported ++5:0: inheritance from PyVarObject types like 'tuple' is not currently supported ++8:0: inheritance from PyVarObject types like 'bytes' is not currently supported ++11:0: inheritance from PyVarObject types like 'str' is not currently supported """ diff --cc tests/errors/cdef_members_T517.pyx index 9867aca6,0b7dfe38..2e5d54ad --- a/tests/errors/cdef_members_T517.pyx +++ b/tests/errors/cdef_members_T517.pyx @@@ -15,11 -18,12 +18,11 @@@ cdef class Bar pass _ERRORS = u""" - 5:24: C attribute of type 'VoidP' cannot be accessed from Python - 5:24: Cannot convert 'VoidP' to Python object - 6:24: C attribute of type 'VoidP' cannot be accessed from Python - 6:24: Cannot convert 'VoidP' to Python object - 6:24: Cannot convert Python object to 'VoidP' - 14:22: Cannot convert Python object to 'Foo' + 8:24: C attribute of type 'VoidP' cannot be accessed from Python + 8:24: Cannot convert 'VoidP' to Python object + 9:24: C attribute of type 'VoidP' cannot be accessed from Python + 9:24: Cannot convert 'VoidP' to Python object + 9:24: Cannot convert Python object to 'VoidP' -17:22: C attribute of type 'Foo' cannot be accessed from Python + 17:22: Cannot convert Python object to 'Foo' """ diff --cc tests/errors/cdef_visibility.pyx index ff3664ae,00000000..c7f49fb3 mode 100644,000000..100644 --- a/tests/errors/cdef_visibility.pyx +++ b/tests/errors/cdef_visibility.pyx @@@ -1,38 -1,0 +1,40 @@@ ++# mode: error ++ +# TODO: a way to keep going after parsing errors? + +cdef private int priv_global_variable + +cdef private priv_global_function(x): + return x*2 + + +cdef class bare_global_class: + cdef private int priv_attribute + + def __cinit__(self): + self.priv_attribute = 1 + + +cdef class public pub_global_class: + cpdef cp_method(self, x): + return x*2 + + +cdef class private priv_global_class: + cpdef cp_method(self, x): + return x*2 + + +cdef class readonly ro_global_class: + cpdef cp_method(self, x): + return x*2 + + +cpdef class cp_global_class: + cpdef cp_method(self, x): + return x*2 + + +_ERRORS = u""" - 3:17: Syntax error in C variable declaration ++5:17: Syntax error in C variable declaration +""" diff --cc tests/errors/cdefspecial.pyx index f942006c,0998856a..f0243b11 --- a/tests/errors/cdefspecial.pyx +++ b/tests/errors/cdefspecial.pyx @@@ -7,6 -8,6 +8,6 @@@ cdef class Test pass _ERRORS = u""" - 3:4: Special methods must be declared with 'def', not 'cdef' - 6:4: Special methods must be declared with 'def', not 'cdef' -4:9: Special methods must be declared with 'def', not 'cdef' -7:9: Special methods must be declared with 'def', not 'cdef' ++4:4: Special methods must be declared with 'def', not 'cdef' ++7:4: Special methods must be declared with 'def', not 'cdef' """ diff --cc tests/errors/cmethbasematch.pyx index fbbafe2d,9e309f16..c9be2782 --- a/tests/errors/cmethbasematch.pyx +++ b/tests/errors/cmethbasematch.pyx @@@ -7,6 -9,6 +9,6 @@@ cdef class D(C) pass _ERRORS = u""" - 6: 4: Signature not compatible with previous declaration - 2: 4: Previous declaration is here -8: 9: Signature not compatible with previous declaration -4: 9: Previous declaration is here ++8: 4: Signature not compatible with previous declaration ++4: 4: Previous declaration is here """ diff --cc tests/errors/cpdef_syntax.pyx index 569750d3,7c608813..c4e140bb --- a/tests/errors/cpdef_syntax.pyx +++ b/tests/errors/cpdef_syntax.pyx @@@ -3,7 -4,7 +4,7 @@@ cpdef nogil: pas cpdef nogil class test: pass _ERRORS = u""" - 2: 0: cdef blocks cannot be declared cpdef - 3: 0: cdef blocks cannot be declared cpdef - 3:12: Expected ':', found 'class' -3: 6: cdef blocks cannot be declared cpdef -4: 6: cdef blocks cannot be declared cpdef ++3: 0: cdef blocks cannot be declared cpdef ++4: 0: cdef blocks cannot be declared cpdef + 4:12: Expected ':', found 'class' """ diff --cc tests/errors/e_cdefemptysue.pyx index 5ed13497,f71370f4..22ec012a --- a/tests/errors/e_cdefemptysue.pyx +++ b/tests/errors/e_cdefemptysue.pyx @@@ -7,7 -9,7 +9,7 @@@ ctypedef union eggs cdef enum ham: pass _ERRORS = u""" - 1:0: Empty struct or union definition not allowed outside a 'cdef extern from' block - 4:0: Empty struct or union definition not allowed outside a 'cdef extern from' block - 7:0: Empty enum definition not allowed outside a 'cdef extern from' block -3:5: Empty struct or union definition not allowed outside a 'cdef extern from' block ++3:0: Empty struct or union definition not allowed outside a 'cdef extern from' block + 6:0: Empty struct or union definition not allowed outside a 'cdef extern from' block -9:5: Empty enum definition not allowed outside a 'cdef extern from' block ++9:0: Empty enum definition not allowed outside a 'cdef extern from' block """ diff --cc tests/errors/e_cmethbasematch.pyx index 271421dc,45651f90..24afed5c --- a/tests/errors/e_cmethbasematch.pyx +++ b/tests/errors/e_cmethbasematch.pyx @@@ -6,6 -8,6 +8,6 @@@ cdef class D(C) cdef void f(self, int x): pass _ERRORS = u""" - 6:1: Signature not compatible with previous declaration - 2:1: Previous declaration is here -8:6: Signature not compatible with previous declaration -4:6: Previous declaration is here ++8:1: Signature not compatible with previous declaration ++4:1: Previous declaration is here """ diff --cc tests/errors/e_ctypedefornot.pyx index 1d8396b4,67563099..bfe17cd5 --- a/tests/errors/e_ctypedefornot.pyx +++ b/tests/errors/e_ctypedefornot.pyx @@@ -12,6 -14,6 +14,6 @@@ cdef Foo cdef Blarg b _ERRORS = u""" - 3:0: 'Foo' previously declared using 'cdef' - 9:0: 'Blarg' previously declared using 'ctypedef' + 5:0: 'Foo' previously declared using 'cdef' -11:5: 'Blarg' previously declared using 'ctypedef' ++11:0: 'Blarg' previously declared using 'ctypedef' """ diff --cc tests/errors/e_nogilcmeth.pyx index 6f4cb6ee,02ab59b4..5708bc65 --- a/tests/errors/e_nogilcmeth.pyx +++ b/tests/errors/e_nogilcmeth.pyx @@@ -3,6 -5,6 +5,6 @@@ cdef class C pass _ERRORS = u""" - 2:1: Signature not compatible with previous declaration 2:12: Previous declaration is here -4: 6: Signature not compatible with previous declaration ++4: 1: Signature not compatible with previous declaration """ diff --cc tests/errors/e_packedstruct_T290.pyx index 8a3ef5e6,cf2df11f..078f6066 --- a/tests/errors/e_packedstruct_T290.pyx +++ b/tests/errors/e_packedstruct_T290.pyx @@@ -3,5 -6,5 +6,5 @@@ cdef extern char a _ERRORS = u""" - 2:4: Cannot declare extern struct as 'packed' -5:9: Cannot declare extern struct as 'packed' ++5:4: Cannot declare extern struct as 'packed' """ diff --cc tests/errors/e_undefexttype.pyx index 0a9f6a9b,3a68f8b3..9f732a09 --- a/tests/errors/e_undefexttype.pyx +++ b/tests/errors/e_undefexttype.pyx @@@ -1,6 -3,6 +3,6 @@@ cdef class Spam cdef extern class external.Eggs _ERRORS = u""" - 1:0: C class 'Spam' is declared but not defined - 2:0: C class 'Eggs' is declared but not defined -3:5: C class 'Spam' is declared but not defined -4:5: C class 'Eggs' is declared but not defined ++3:0: C class 'Spam' is declared but not defined ++4:0: C class 'Eggs' is declared but not defined """ diff --cc tests/errors/missing_self_in_cpdef_method_T156.pyx index 3fbb7f6d,21241a22..3b621b35 --- a/tests/errors/missing_self_in_cpdef_method_T156.pyx +++ b/tests/errors/missing_self_in_cpdef_method_T156.pyx @@@ -4,5 -6,5 +6,5 @@@ cdef class B pass _ERRORS = u""" - 3:4: C method has no self argument -5:10: C method has no self argument ++5:4: C method has no self argument """ diff --cc tests/errors/missing_self_in_cpdef_method_T165.pyx index 89fc1947,6a95922d..3a0223e9 --- a/tests/errors/missing_self_in_cpdef_method_T165.pyx +++ b/tests/errors/missing_self_in_cpdef_method_T165.pyx @@@ -4,5 -6,5 +6,5 @@@ cdef class A pass _ERRORS = u""" - 3:4: Self argument (int) of C method 'a' does not match parent type (A) -5:10: Self argument (int) of C method 'a' does not match parent type (A) ++5:4: Self argument (int) of C method 'a' does not match parent type (A) """ diff --cc tests/errors/nogil.pyx index 1e85d08d,512e1b67..e7bb672b --- a/tests/errors/nogil.pyx +++ b/tests/errors/nogil.pyx @@@ -90,71 -92,71 +92,72 @@@ def bare_pyvar_name(object x) # except these: 29, 34, 44, 56, 58, 60, 62-64 _ERRORS = u""" - 1:0: Function with Python return type cannot be declared nogil - 4:0: Function declared nogil has Python locals or temporaries - 6:6: Assignment of Python object not allowed without gil - 9:5: Discarding owned Python object not allowed without gil - 11:0: Function with Python return type cannot be declared nogil - 15:5: Calling gil-requiring function not allowed without gil - 24:9: Calling gil-requiring function not allowed without gil - 26:12: Assignment of Python object not allowed without gil - 28:8: Discarding owned Python object not allowed without gil - 28:16: Constructing complex number not allowed without gil - 30:8: Backquote expression not allowed without gil -3:5: Function with Python return type cannot be declared nogil -6:5: Function declared nogil has Python locals or temporaries ++<<<<<<< HEAD ++3:0: Function with Python return type cannot be declared nogil ++6:0: Function declared nogil has Python locals or temporaries + 8:6: Assignment of Python object not allowed without gil + 11:5: Discarding owned Python object not allowed without gil -13:5: Function with Python return type cannot be declared nogil ++13:0: Function with Python return type cannot be declared nogil + 17:5: Calling gil-requiring function not allowed without gil + 26:9: Calling gil-requiring function not allowed without gil + 28:12: Assignment of Python object not allowed without gil 30:8: Discarding owned Python object not allowed without gil - 30:9: Operation not allowed without gil - 31:15: Assignment of Python object not allowed without gil - 31:15: Operation not allowed without gil - 31:15: Python import not allowed without gil - 32:8: Operation not allowed without gil - 32:13: Python import not allowed without gil - 32:25: Constructing Python list not allowed without gil - 32:25: Operation not allowed without gil - 33:17: Iterating over Python object not allowed without gil - 35:11: Discarding owned Python object not allowed without gil - 35:11: Indexing Python object not allowed without gil - 36:11: Discarding owned Python object not allowed without gil - 36:11: Slicing Python object not allowed without gil - 37:11: Constructing Python slice object not allowed without gil + 30:16: Constructing complex number not allowed without gil + 32:8: Backquote expression not allowed without gil + 32:8: Discarding owned Python object not allowed without gil + 32:9: Operation not allowed without gil + 33:15: Assignment of Python object not allowed without gil + 33:15: Operation not allowed without gil + 33:15: Python import not allowed without gil + 34:8: Operation not allowed without gil + 34:13: Python import not allowed without gil + 34:25: Constructing Python list not allowed without gil + 34:25: Operation not allowed without gil + 35:17: Iterating over Python object not allowed without gil 37:11: Discarding owned Python object not allowed without gil 37:11: Indexing Python object not allowed without gil - 37:13: Converting to Python object not allowed without gil - 37:15: Converting to Python object not allowed without gil - 37:17: Converting to Python object not allowed without gil - 38:11: Accessing Python attribute not allowed without gil 38:11: Discarding owned Python object not allowed without gil - 39:9: Constructing Python tuple not allowed without gil - 39:9: Discarding owned Python object not allowed without gil - 40:8: Constructing Python list not allowed without gil - 40:8: Discarding owned Python object not allowed without gil - 41:8: Constructing Python dict not allowed without gil - 41:8: Discarding owned Python object not allowed without gil - 42:12: Discarding owned Python object not allowed without gil - 42:12: Truth-testing Python object not allowed without gil - 43:13: Python type test not allowed without gil - 45:10: Discarding owned Python object not allowed without gil - 45:10: Operation not allowed without gil - 46:8: Discarding owned Python object not allowed without gil - 46:8: Operation not allowed without gil - 47:10: Assignment of Python object not allowed without gil - 47:14: Assignment of Python object not allowed without gil - 48:9: Assignment of Python object not allowed without gil - 48:13: Assignment of Python object not allowed without gil - 48:16: Creating temporary Python reference not allowed without gil - 48:19: Creating temporary Python reference not allowed without gil - 49:11: Assignment of Python object not allowed without gil - 49:11: Indexing Python object not allowed without gil - 50:11: Accessing Python attribute not allowed without gil - 50:11: Assignment of Python object not allowed without gil - 51:8: Constructing Python tuple not allowed without gil - 51:8: Python print statement not allowed without gil - 52:8: Deleting Python object not allowed without gil - 53:8: Returning Python object not allowed without gil - 54:8: Raising exception not allowed without gil - 55:14: Truth-testing Python object not allowed without gil - 57:17: Truth-testing Python object not allowed without gil - 59:8: For-loop using object bounds or target not allowed without gil - 61:8: Try-except statement not allowed without gil - 65:8: Try-finally statement not allowed without gil - 82:8: For-loop using object bounds or target not allowed without gil + 38:11: Slicing Python object not allowed without gil + 39:11: Constructing Python slice object not allowed without gil + 39:11: Discarding owned Python object not allowed without gil + 39:11: Indexing Python object not allowed without gil + 39:13: Converting to Python object not allowed without gil + 39:15: Converting to Python object not allowed without gil + 39:17: Converting to Python object not allowed without gil + 40:11: Accessing Python attribute not allowed without gil + 40:11: Discarding owned Python object not allowed without gil + 41:9: Constructing Python tuple not allowed without gil + 41:9: Discarding owned Python object not allowed without gil + 42:8: Constructing Python list not allowed without gil + 42:8: Discarding owned Python object not allowed without gil + 43:8: Constructing Python dict not allowed without gil + 43:8: Discarding owned Python object not allowed without gil + 44:12: Discarding owned Python object not allowed without gil + 44:12: Truth-testing Python object not allowed without gil + 45:13: Python type test not allowed without gil + 47:10: Discarding owned Python object not allowed without gil + 47:10: Operation not allowed without gil + 48:8: Discarding owned Python object not allowed without gil + 48:8: Operation not allowed without gil + 49:10: Assignment of Python object not allowed without gil + 49:14: Assignment of Python object not allowed without gil + 50:9: Assignment of Python object not allowed without gil + 50:13: Assignment of Python object not allowed without gil + 50:16: Creating temporary Python reference not allowed without gil + 50:19: Creating temporary Python reference not allowed without gil + 51:11: Assignment of Python object not allowed without gil + 51:11: Indexing Python object not allowed without gil + 52:11: Accessing Python attribute not allowed without gil + 52:11: Assignment of Python object not allowed without gil + 53:8: Constructing Python tuple not allowed without gil + 53:8: Python print statement not allowed without gil + 54:8: Deleting Python object not allowed without gil + 55:8: Returning Python object not allowed without gil + 56:8: Raising exception not allowed without gil + 57:14: Truth-testing Python object not allowed without gil + 59:17: Truth-testing Python object not allowed without gil + 61:8: For-loop using object bounds or target not allowed without gil + 63:8: Try-except statement not allowed without gil + 67:8: Try-finally statement not allowed without gil + 84:8: For-loop using object bounds or target not allowed without gil """ diff --cc tests/errors/nogilcmeth.pyx index 77327b23,c2c2cc3c..4eb36f9b --- a/tests/errors/nogilcmeth.pyx +++ b/tests/errors/nogilcmeth.pyx @@@ -3,6 -5,6 +5,6 @@@ cdef class C pass _ERRORS = u""" - 2:4: Signature not compatible with previous declaration 2:15: Previous declaration is here -4:9: Signature not compatible with previous declaration ++4:4: Signature not compatible with previous declaration """ diff --cc tests/errors/subtyping_final_class.pyx index ac16fbe8,05c5a9e9..434de1b1 --- a/tests/errors/subtyping_final_class.pyx +++ b/tests/errors/subtyping_final_class.pyx @@@ -9,5 -10,5 +10,5 @@@ cdef class SubType(FinalClass) pass _ERRORS = """ - 8:0: Base class 'FinalClass' of type 'SubType' is final -9:5: Base class 'FinalClass' of type 'SubType' is final ++9:0: Base class 'FinalClass' of type 'SubType' is final """