From dd3705db37b5a5d3abe2a48b33a34b883f78b961 Mon Sep 17 00:00:00 2001 From: Dag Sverre Seljebotn Date: Fri, 15 Aug 2008 14:12:51 +0200 Subject: [PATCH] Abort compilation prior to code generation transforms if errors were recorded --- Cython/Compiler/Errors.py | 10 +++++++-- Cython/Compiler/Main.py | 45 ++++++++++++++++++++++++--------------- tests/errors/e_switch.pyx | 2 +- 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/Cython/Compiler/Errors.py b/Cython/Compiler/Errors.py index a8ad03af..db0572eb 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 2d8c3dd6..10e9049e 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= 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 405fd010..9d0b4453 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 """ -- 2.26.2