6 from Cython.Utils import open_new_file
11 class PyrexError(Exception):
14 class PyrexWarning(Exception):
18 def context(position):
20 assert not (isinstance(source, unicode) or isinstance(source, str)), (
21 "Please replace filename strings with Scanning.FileSourceDescriptor instances %r" % source)
23 F = list(source.get_lines())
24 except UnicodeDecodeError:
25 # file has an encoding problem
26 s = u"[unprintable code]\n"
28 s = u''.join(F[max(0, position[1]-6):position[1]])
29 s = u'...\n%s%s^\n' % (s, u' '*(position[2]-1))
30 s = u'%s\n%s%s\n' % (u'-'*60, s, u'-'*60)
33 def format_position(position):
35 return u"%s:%d:%d: " % (position[0].get_description(),
36 position[1], position[2])
39 def format_error(message, position):
41 pos_str = format_position(position)
42 cont = context(position)
43 message = u'\nError compiling Cython file:\n%s\n%s%s' % (cont, pos_str, message or u'')
46 class CompileError(PyrexError):
48 def __init__(self, position = None, message = u""):
49 self.position = position
50 self.message_only = message
52 # Deprecated and withdrawn in 2.6:
53 # self.message = message
54 Exception.__init__(self, format_error(message, position))
56 class CompileWarning(PyrexWarning):
58 def __init__(self, position = None, message = ""):
59 self.position = position
60 # Deprecated and withdrawn in 2.6:
61 # self.message = message
62 Exception.__init__(self, format_position(position) + message)
64 class InternalError(Exception):
65 # If this is ever raised, there is a bug in the compiler.
67 def __init__(self, message):
68 self.message_only = message
69 Exception.__init__(self, u"Internal compiler error: %s"
72 class AbortError(Exception):
73 # Throw this to stop the compilation immediately.
75 def __init__(self, message):
76 self.message_only = message
77 Exception.__init__(self, u"Abort error: %s" % message)
79 class CompilerCrash(CompileError):
80 # raised when an unexpected exception occurs in a transform
81 def __init__(self, pos, context, message, cause, stacktrace=None):
83 message = u'\n' + message
86 self.message_only = message
88 message = u"Compiler crash in %s%s" % (context, message)
92 u'\n\nCompiler crash traceback from this point on:\n' +
93 u''.join(traceback.format_tb(stacktrace)))
97 message += u'%s: %s' % (cause.__class__.__name__, cause)
98 CompileError.__init__(self, pos, message)
100 class NoElementTreeInstalledException(PyrexError):
101 """raised when the user enabled options.gdb_debug but no ElementTree
102 implementation was found
109 def open_listing_file(path, echo_to_stderr = 1):
110 # Begin a new error listing. If path is None, no file
111 # is opened, the error counter is just reset.
112 global listing_file, num_errors, echo_file
114 listing_file = open_new_file(path)
118 echo_file = sys.stderr
123 def close_listing_file():
129 def report_error(err):
131 error_stack[-1].append(err)
134 # See Main.py for why dual reporting occurs. Quick fix for now.
135 if err.reported: return
137 try: line = u"%s\n" % err
138 except UnicodeEncodeError:
139 # Python <= 2.5 does this for non-ASCII Unicode exceptions
140 line = format_error(getattr(err, 'message_only', "[unprintable exception message]"),
141 getattr(err, 'position', None)) + u'\n'
143 try: listing_file.write(line)
144 except UnicodeEncodeError:
145 listing_file.write(line.encode('ASCII', 'replace'))
147 try: echo_file.write(line)
148 except UnicodeEncodeError:
149 echo_file.write(line.encode('ASCII', 'replace'))
150 num_errors = num_errors + 1
151 if Options.fast_fail:
152 raise AbortError, "fatal errors"
154 def error(position, message):
155 #print "Errors.error:", repr(position), repr(message) ###
157 raise InternalError(message)
158 err = CompileError(position, message)
159 if DebugFlags.debug_exception_on_error: raise Exception(err) # debug
163 LEVEL=1 # warn about all errors level 1 or higher
165 def message(position, message, level=1):
168 warn = CompileWarning(position, message)
169 line = "note: %s\n" % warn
171 listing_file.write(line)
173 echo_file.write(line)
176 def warning(position, message, level=0):
179 if Options.warning_errors and position:
180 return error(position, message)
181 warn = CompileWarning(position, message)
182 line = "warning: %s\n" % warn
184 listing_file.write(line)
186 echo_file.write(line)
190 def warn_once(position, message, level=0):
191 if level < LEVEL or message in _warn_once_seen:
193 warn = CompileWarning(position, message)
194 line = "warning: %s\n" % warn
196 listing_file.write(line)
198 echo_file.write(line)
199 _warn_once_seen[message] = True
203 # These functions can be used to momentarily suppress errors.
208 error_stack.append([])
210 def release_errors(ignore=False):
211 held_errors = error_stack.pop()
213 for err in held_errors:
217 return error_stack[-1]
220 # this module needs a redesign to support parallel cythonisation, but
221 # for now, the following works at least in sequential compiler runs
224 _warn_once_seen.clear()