diff --git a/Cython/Compiler/Errors.py b/Cython/Compiler/Errors.py index a8ad03aff4dfeb8d89abcec68802fb2a4988a473..db0572ebac9b8490947c2dfd2da3f6ea0173fc53 100644 --- a/Cython/Compiler/Errors.py +++ b/Cython/Compiler/Errors.py @@ -63,11 +63,16 @@ class InternalError(Exception): def __init__(self, message): Exception.__init__(self, "Internal compiler error: %s" % message) - + +class AbortCompilationError(Exception): + """ + Raised in order to abort compilation. + """ listing_file = None num_errors = 0 echo_file = None +last_error = None def open_listing_file(path, echo_to_stderr = 1): # Begin a new error listing. If path is None, no file @@ -90,7 +95,7 @@ def close_listing_file(): listing_file = None def report_error(err): - global num_errors + global num_errors, last_error # See Main.py for why dual reporting occurs. Quick fix for now. if err.reported: return err.reported = True @@ -100,6 +105,7 @@ def report_error(err): if echo_file: echo_file.write(line) num_errors = num_errors + 1 + last_error = err def error(position, message): #print "Errors.error:", repr(position), repr(message) ### diff --git a/Cython/Compiler/Main.py b/Cython/Compiler/Main.py index 2d8c3dd60380d61aad90acf8c7abfe80b8d0fddf..10e9049e5d03ada37ef5b9c1a5568cff3f3d00a4 100644 --- a/Cython/Compiler/Main.py +++ b/Cython/Compiler/Main.py @@ -84,6 +84,11 @@ class Context: from Buffer import IntroduceBufferAuxiliaryVars from ModuleNode import check_c_classes + def abort_if_errors(t): + if Errors.num_errors > 0: + raise Errors.AbortCompilationError() + return t + if pxd: _check_c_classes = None _specific_post_parse = PxdPostParse(self) @@ -123,10 +128,10 @@ class Context: # (this seems strange -- I believe the right concept is to split # ModuleNode into a ModuleNode and a CodeGenerator, and tell that # CodeGenerator to generate code both from the pyx and pxd ModuleNodes. - stats.append(statlistnode) - # Until utility code is moved to code generation phase everywhere, - # we need to copy it over to the main scope - module_node.scope.utility_code_list.extend(scope.utility_code_list) + stats.append(statlistnode) + # Until utility code is moved to code generation phase everywhere, + # we need to copy it over to the main scope + module_node.scope.utility_code_list.extend(scope.utility_code_list) return module_node return ([ @@ -167,10 +172,16 @@ class Context: for phase in pipeline: if phase is not None: data = phase(data) + print Errors.num_errors except CompileError, err: - # err is set + print "hello", err Errors.report_error(err) - return (err, data) + raise err + except Errors.AbortCompilationError: + print "abort", Errors.num_errors + pass + print "normal" + return data def find_module(self, module_name, relative_to = None, pos = None, need_pxd = 1): @@ -227,10 +238,7 @@ class Context: if debug_find_module: print("Context.find_module: Parsing %s" % pxd_pathname) source_desc = FileSourceDescriptor(pxd_pathname) - err, result = self.process_pxd(source_desc, scope, module_name) - if err: - raise err - (pxd_codenodes, pxd_scope) = result + pxd_codenodes, pxd_scope = self.process_pxd(source_desc, scope, module_name) self.pxds[module_name] = (pxd_codenodes, pxd_scope) except CompileError: pass @@ -399,7 +407,7 @@ class Context: except UnicodeDecodeError, msg: error((source_desc, 0, 0), "Decoding error, missing or incorrect coding=<encoding-name> at top of source (%s)" % msg) if Errors.num_errors > 0: - raise CompileError + raise Errors.AbortCompilationError() return tree def extract_module_name(self, path, options): @@ -429,15 +437,13 @@ class Context: else: Errors.open_listing_file(None) - def teardown_errors(self, err, options, result): + def teardown_errors(self, options, result): source_desc = result.compilation_source.source_desc if not isinstance(source_desc, FileSourceDescriptor): raise RuntimeError("Only file sources for code supported") Errors.close_listing_file() result.num_errors = Errors.num_errors - if result.num_errors > 0: - err = True - if err and result.c_file: + if result.num_errors > 0 and result.c_file: try: Utils.castrate_file(result.c_file, os.stat(source_desc.filename)) except EnvironmentError: @@ -498,8 +504,13 @@ def run_pipeline(source, options, full_module_name = None): pipeline = context.create_pyx_pipeline(options, result) context.setup_errors(options) - err, enddata = context.run_pipeline(pipeline, source) - context.teardown_errors(err, options, result) + try: + enddata = context.run_pipeline(pipeline, source) + except Errors.CompileError: + pass + except Errors.AbortCompilationError: + pass + context.teardown_errors(options, result) return result #------------------------------------------------------------------------ diff --git a/tests/errors/e_switch.pyx b/tests/errors/e_switch.pyx index 405fd0109761d25e3274ab615111732b79c57733..9d0b4453d1b8f5da6ddfeb8e1a901edf85944a65 100644 --- a/tests/errors/e_switch.pyx +++ b/tests/errors/e_switch.pyx @@ -8,5 +8,5 @@ elif x == 4: print 34 _ERRORS = """ -4:23: undeclared name not builtin: NONEXISTING +3:19: undeclared name not builtin: NONEXISTING """