Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / third_party / cython / src / Cython / Compiler / Errors.py
blob046ab531196ac25656d1c25039e586d6b342e695
2 # Errors
5 import sys
6 from Cython.Utils import open_new_file
7 import DebugFlags
8 import Options
11 class PyrexError(Exception):
12 pass
14 class PyrexWarning(Exception):
15 pass
18 def context(position):
19 source = position[0]
20 assert not (isinstance(source, unicode) or isinstance(source, str)), (
21 "Please replace filename strings with Scanning.FileSourceDescriptor instances %r" % source)
22 try:
23 F = source.get_lines()
24 except UnicodeDecodeError:
25 # file has an encoding problem
26 s = u"[unprintable code]\n"
27 else:
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)
31 return s
33 def format_position(position):
34 if position:
35 return u"%s:%d:%d: " % (position[0].get_error_description(),
36 position[1], position[2])
37 return u''
39 def format_error(message, position):
40 if 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'')
44 return message
46 class CompileError(PyrexError):
48 def __init__(self, position = None, message = u""):
49 self.position = position
50 self.message_only = message
51 self.formatted_message = format_error(message, position)
52 self.reported = False
53 # Deprecated and withdrawn in 2.6:
54 # self.message = message
55 Exception.__init__(self, self.formatted_message)
56 # Python Exception subclass pickling is broken,
57 # see http://bugs.python.org/issue1692335
58 self.args = (position, message)
60 def __str__(self):
61 return self.formatted_message
63 class CompileWarning(PyrexWarning):
65 def __init__(self, position = None, message = ""):
66 self.position = position
67 # Deprecated and withdrawn in 2.6:
68 # self.message = message
69 Exception.__init__(self, format_position(position) + message)
71 class InternalError(Exception):
72 # If this is ever raised, there is a bug in the compiler.
74 def __init__(self, message):
75 self.message_only = message
76 Exception.__init__(self, u"Internal compiler error: %s"
77 % message)
79 class AbortError(Exception):
80 # Throw this to stop the compilation immediately.
82 def __init__(self, message):
83 self.message_only = message
84 Exception.__init__(self, u"Abort error: %s" % message)
86 class CompilerCrash(CompileError):
87 # raised when an unexpected exception occurs in a transform
88 def __init__(self, pos, context, message, cause, stacktrace=None):
89 if message:
90 message = u'\n' + message
91 else:
92 message = u'\n'
93 self.message_only = message
94 if context:
95 message = u"Compiler crash in %s%s" % (context, message)
96 if stacktrace:
97 import traceback
98 message += (
99 u'\n\nCompiler crash traceback from this point on:\n' +
100 u''.join(traceback.format_tb(stacktrace)))
101 if cause:
102 if not stacktrace:
103 message += u'\n'
104 message += u'%s: %s' % (cause.__class__.__name__, cause)
105 CompileError.__init__(self, pos, message)
106 # Python Exception subclass pickling is broken,
107 # see http://bugs.python.org/issue1692335
108 self.args = (pos, context, message, cause, stacktrace)
110 class NoElementTreeInstalledException(PyrexError):
111 """raised when the user enabled options.gdb_debug but no ElementTree
112 implementation was found
115 listing_file = None
116 num_errors = 0
117 echo_file = None
119 def open_listing_file(path, echo_to_stderr = 1):
120 # Begin a new error listing. If path is None, no file
121 # is opened, the error counter is just reset.
122 global listing_file, num_errors, echo_file
123 if path is not None:
124 listing_file = open_new_file(path)
125 else:
126 listing_file = None
127 if echo_to_stderr:
128 echo_file = sys.stderr
129 else:
130 echo_file = None
131 num_errors = 0
133 def close_listing_file():
134 global listing_file
135 if listing_file:
136 listing_file.close()
137 listing_file = None
139 def report_error(err):
140 if error_stack:
141 error_stack[-1].append(err)
142 else:
143 global num_errors
144 # See Main.py for why dual reporting occurs. Quick fix for now.
145 if err.reported: return
146 err.reported = True
147 try: line = u"%s\n" % err
148 except UnicodeEncodeError:
149 # Python <= 2.5 does this for non-ASCII Unicode exceptions
150 line = format_error(getattr(err, 'message_only', "[unprintable exception message]"),
151 getattr(err, 'position', None)) + u'\n'
152 if listing_file:
153 try: listing_file.write(line)
154 except UnicodeEncodeError:
155 listing_file.write(line.encode('ASCII', 'replace'))
156 if echo_file:
157 try: echo_file.write(line)
158 except UnicodeEncodeError:
159 echo_file.write(line.encode('ASCII', 'replace'))
160 num_errors = num_errors + 1
161 if Options.fast_fail:
162 raise AbortError("fatal errors")
164 def error(position, message):
165 #print "Errors.error:", repr(position), repr(message) ###
166 if position is None:
167 raise InternalError(message)
168 err = CompileError(position, message)
169 if DebugFlags.debug_exception_on_error: raise Exception(err) # debug
170 report_error(err)
171 return err
173 LEVEL=1 # warn about all errors level 1 or higher
175 def message(position, message, level=1):
176 if level < LEVEL:
177 return
178 warn = CompileWarning(position, message)
179 line = "note: %s\n" % warn
180 if listing_file:
181 listing_file.write(line)
182 if echo_file:
183 echo_file.write(line)
184 return warn
186 def warning(position, message, level=0):
187 if level < LEVEL:
188 return
189 if Options.warning_errors and position:
190 return error(position, message)
191 warn = CompileWarning(position, message)
192 line = "warning: %s\n" % warn
193 if listing_file:
194 listing_file.write(line)
195 if echo_file:
196 echo_file.write(line)
197 return warn
199 _warn_once_seen = {}
200 def warn_once(position, message, level=0):
201 if level < LEVEL or message in _warn_once_seen:
202 return
203 warn = CompileWarning(position, message)
204 line = "warning: %s\n" % warn
205 if listing_file:
206 listing_file.write(line)
207 if echo_file:
208 echo_file.write(line)
209 _warn_once_seen[message] = True
210 return warn
213 # These functions can be used to momentarily suppress errors.
215 error_stack = []
217 def hold_errors():
218 error_stack.append([])
220 def release_errors(ignore=False):
221 held_errors = error_stack.pop()
222 if not ignore:
223 for err in held_errors:
224 report_error(err)
226 def held_errors():
227 return error_stack[-1]
230 # this module needs a redesign to support parallel cythonisation, but
231 # for now, the following works at least in sequential compiler runs
233 def reset():
234 _warn_once_seen.clear()
235 del error_stack[:]