6 from Cython.Utils import open_new_file
9 class PyrexError(Exception):
12 class PyrexWarning(Exception):
16 def context(position):
18 assert not (isinstance(source, unicode) or isinstance(source, str)), (
19 "Please replace filename strings with Scanning.FileSourceDescriptor instances %r" % source)
21 F = list(source.get_lines())
22 except UnicodeDecodeError:
23 # file has an encoding problem
24 s = u"[unprintable code]\n"
26 s = u''.join(F[max(0, position[1]-6):position[1]])
27 s = u'...\n%s%s^\n' % (s, u' '*(position[2]-1))
28 s = u'%s\n%s%s\n' % (u'-'*60, s, u'-'*60)
31 def format_position(position):
33 return u"%s:%d:%d: " % (position[0].get_description(),
34 position[1], position[2])
37 def format_error(message, position):
39 pos_str = format_position(position)
40 cont = context(position)
41 message = u'\nError converting Pyrex file to C:\n%s\n%s%s' % (cont, pos_str, message or u'')
44 class CompileError(PyrexError):
46 def __init__(self, position = None, message = u""):
47 self.position = position
48 self.message_only = message
50 # Deprecated and withdrawn in 2.6:
51 # self.message = message
52 Exception.__init__(self, format_error(message, position))
54 class CompileWarning(PyrexWarning):
56 def __init__(self, position = None, message = ""):
57 self.position = position
58 # Deprecated and withdrawn in 2.6:
59 # self.message = message
60 Exception.__init__(self, format_position(position) + message)
63 class InternalError(Exception):
64 # If this is ever raised, there is a bug in the compiler.
66 def __init__(self, message):
67 self.message_only = message
68 Exception.__init__(self, u"Internal compiler error: %s"
72 class CompilerCrash(CompileError):
73 # raised when an unexpected exception occurs in a transform
74 def __init__(self, pos, context, message, cause, stacktrace=None):
76 message = u'\n' + message
79 self.message_only = message
81 message = u"Compiler crash in %s%s" % (context, message)
85 u'\n\nCompiler crash traceback from this point on:\n' +
86 u''.join(traceback.format_tb(stacktrace)))
90 message += u'%s: %s' % (cause.__class__.__name__, cause)
91 CompileError.__init__(self, pos, message)
98 def open_listing_file(path, echo_to_stderr = 1):
99 # Begin a new error listing. If path is None, no file
100 # is opened, the error counter is just reset.
101 global listing_file, num_errors, echo_file
103 listing_file = open_new_file(path)
107 echo_file = sys.stderr
112 def close_listing_file():
118 def report_error(err):
120 error_stack[-1].append(err)
123 # See Main.py for why dual reporting occurs. Quick fix for now.
124 if err.reported: return
126 try: line = u"%s\n" % err
127 except UnicodeEncodeError:
128 # Python <= 2.5 does this for non-ASCII Unicode exceptions
129 line = format_error(getattr(err, 'message_only', "[unprintable exception message]"),
130 getattr(err, 'position', None)) + u'\n'
132 try: listing_file.write(line)
133 except UnicodeEncodeError:
134 listing_file.write(line.encode('ASCII', 'replace'))
136 try: echo_file.write(line)
137 except UnicodeEncodeError:
138 echo_file.write(line.encode('ASCII', 'replace'))
139 num_errors = num_errors + 1
141 def error(position, message):
142 #print "Errors.error:", repr(position), repr(message) ###
144 raise InternalError(message)
145 err = CompileError(position, message)
146 #if position is not None: raise Exception(err) # debug
150 LEVEL=1 # warn about all errors level 1 or higher
152 def message(position, message, level=1):
155 warn = CompileWarning(position, message)
156 line = "note: %s\n" % warn
158 listing_file.write(line)
160 echo_file.write(line)
163 def warning(position, message, level=0):
166 warn = CompileWarning(position, message)
167 line = "warning: %s\n" % warn
169 listing_file.write(line)
171 echo_file.write(line)
175 def warn_once(position, message, level=0):
176 if level < LEVEL or message in _warn_once_seen:
178 warn = CompileWarning(position, message)
179 line = "warning: %s\n" % warn
181 listing_file.write(line)
183 echo_file.write(line)
184 _warn_once_seen[message] = True
188 # These functions can be used to momentarily suppress errors.
193 error_stack.append([])
195 def release_errors(ignore=False):
196 held_errors = error_stack.pop()
198 for err in held_errors:
202 return error_stack[-1]