Cython has moved to github.

cython-devel

view Cython/Compiler/Errors.py @ 1598:7110f62bc826

provide more context on compiler crashes during transforms
author Stefan Behnel <scoder@users.berlios.de>
date Sat Jan 10 15:32:22 2009 +0100 (3 years ago)
parents fd38efcd7236
children 3bf246dd7f44
line source
1 #
2 # Pyrex - Errors
3 #
5 import sys
6 from Cython.Utils import open_new_file
9 class PyrexError(Exception):
10 pass
12 class PyrexWarning(Exception):
13 pass
16 def context(position):
17 source = position[0]
18 assert not (isinstance(source, unicode) or isinstance(source, str)), (
19 "Please replace filename strings with Scanning.FileSourceDescriptor instances %r" % source)
20 try:
21 F = list(source.get_lines())
22 except UnicodeDecodeError:
23 # file has an encoding problem
24 s = "[unprintable code]\n"
25 else:
26 s =''.join(F[max(0, position[1]-6):position[1]])
27 s = '...\n' + s + ' '*(position[2]-1) + '^\n'
28 s = '-'*60 + '\n' + s + '-'*60 + '\n'
29 return s
31 class CompileError(PyrexError):
33 def __init__(self, position = None, message = ""):
34 self.position = position
35 self.message_only = message
36 self.reported = False
37 # Deprecated and withdrawn in 2.6:
38 # self.message = message
39 if position:
40 pos_str = "%s:%d:%d: " % (position[0].get_description(), position[1], position[2])
41 cont = context(position)
42 else:
43 pos_str = ""
44 cont = ''
45 Exception.__init__(self, '\nError converting Pyrex file to C:\n' + cont + '\n' + pos_str + message )
47 class CompileWarning(PyrexWarning):
49 def __init__(self, position = None, message = ""):
50 self.position = position
51 # Deprecated and withdrawn in 2.6:
52 # self.message = message
53 if position:
54 pos_str = "%s:%d:%d: " % (position[0].get_description(), position[1], position[2])
55 else:
56 pos_str = ""
57 Exception.__init__(self, pos_str + message)
60 class InternalError(Exception):
61 # If this is ever raised, there is a bug in the compiler.
63 def __init__(self, message):
64 Exception.__init__(self, "Internal compiler error: %s"
65 % message)
68 class CompilerCrash(CompileError):
69 # raised when an unexpected exception occurs in a transform
70 def __init__(self, pos, context, message, cause, stacktrace=None):
71 if message:
72 message = u'\n' + message
73 else:
74 message = u'\n'
75 if context:
76 message = "Compiler crash in " + context + message
77 if stacktrace:
78 import traceback, sys
79 message += (
80 u'\n\nCompiler crash traceback up to this point:\n' +
81 u''.join(traceback.format_tb(stacktrace)))
82 if cause:
83 if not stacktrace:
84 message += u'\n'
85 message += u'%s: %s' % (cause.__class__.__name__, cause)
86 CompileError.__init__(self, pos, message)
89 listing_file = None
90 num_errors = 0
91 echo_file = None
93 def open_listing_file(path, echo_to_stderr = 1):
94 # Begin a new error listing. If path is None, no file
95 # is opened, the error counter is just reset.
96 global listing_file, num_errors, echo_file
97 if path is not None:
98 listing_file = open_new_file(path)
99 else:
100 listing_file = None
101 if echo_to_stderr:
102 echo_file = sys.stderr
103 else:
104 echo_file = None
105 num_errors = 0
107 def close_listing_file():
108 global listing_file
109 if listing_file:
110 listing_file.close()
111 listing_file = None
113 def report_error(err):
114 if error_stack:
115 error_stack[-1].append(err)
116 else:
117 global num_errors
118 # See Main.py for why dual reporting occurs. Quick fix for now.
119 if err.reported: return
120 err.reported = True
121 line = "%s\n" % err
122 if listing_file:
123 listing_file.write(line)
124 if echo_file:
125 echo_file.write(line)
126 num_errors = num_errors + 1
128 def error(position, message):
129 #print "Errors.error:", repr(position), repr(message) ###
130 err = CompileError(position, message)
131 #if position is not None: raise Exception(err) # debug
132 report_error(err)
133 return err
135 LEVEL=1 # warn about all errors level 1 or higher
137 def warning(position, message, level=0):
138 if level < LEVEL:
139 return
140 warn = CompileWarning(position, message)
141 line = "warning: %s\n" % warn
142 if listing_file:
143 listing_file.write(line)
144 if echo_file:
145 echo_file.write(line)
146 return warn
148 # These functions can be used to momentarily suppress errors.
150 error_stack = []
152 def hold_errors():
153 error_stack.append([])
155 def release_errors(ignore=False):
156 held_errors = error_stack.pop()
157 if not ignore:
158 for err in held_errors:
159 report_error(err)
161 def held_errors():
162 return error_stack[-1]