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
= 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_error_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
51 self
.formatted_message
= format_error(message
, position
)
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
)
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"
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):
90 message
= u
'\n' + message
93 self
.message_only
= message
95 message
= u
"Compiler crash in %s%s" % (context
, message
)
99 u
'\n\nCompiler crash traceback from this point on:\n' +
100 u
''.join(traceback
.format_tb(stacktrace
)))
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
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
124 listing_file
= open_new_file(path
)
128 echo_file
= sys
.stderr
133 def close_listing_file():
139 def report_error(err
):
141 error_stack
[-1].append(err
)
144 # See Main.py for why dual reporting occurs. Quick fix for now.
145 if err
.reported
: return
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'
153 try: listing_file
.write(line
)
154 except UnicodeEncodeError:
155 listing_file
.write(line
.encode('ASCII', 'replace'))
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) ###
167 raise InternalError(message
)
168 err
= CompileError(position
, message
)
169 if DebugFlags
.debug_exception_on_error
: raise Exception(err
) # debug
173 LEVEL
=1 # warn about all errors level 1 or higher
175 def message(position
, message
, level
=1):
178 warn
= CompileWarning(position
, message
)
179 line
= "note: %s\n" % warn
181 listing_file
.write(line
)
183 echo_file
.write(line
)
186 def warning(position
, message
, level
=0):
189 if Options
.warning_errors
and position
:
190 return error(position
, message
)
191 warn
= CompileWarning(position
, message
)
192 line
= "warning: %s\n" % warn
194 listing_file
.write(line
)
196 echo_file
.write(line
)
200 def warn_once(position
, message
, level
=0):
201 if level
< LEVEL
or message
in _warn_once_seen
:
203 warn
= CompileWarning(position
, message
)
204 line
= "warning: %s\n" % warn
206 listing_file
.write(line
)
208 echo_file
.write(line
)
209 _warn_once_seen
[message
] = True
213 # These functions can be used to momentarily suppress errors.
218 error_stack
.append([])
220 def release_errors(ignore
=False):
221 held_errors
= error_stack
.pop()
223 for err
in 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
234 _warn_once_seen
.clear()