Commit a88130ee authored by Robert Bradshaw's avatar Robert Bradshaw

merge

parents 8c9d947e bcf5b71e
...@@ -19,8 +19,6 @@ import Options ...@@ -19,8 +19,6 @@ import Options
import ControlFlow import ControlFlow
import DebugFlags import DebugFlags
from DebugFlags import debug_disposal_code
absolute_path_length = 0 absolute_path_length = 0
def relative_position(pos): def relative_position(pos):
...@@ -4228,7 +4226,6 @@ class ExceptClauseNode(Node): ...@@ -4228,7 +4226,6 @@ class ExceptClauseNode(Node):
exc_value = None exc_value = None
excinfo_target = None excinfo_target = None
empty_body = False
def analyse_declarations(self, env): def analyse_declarations(self, env):
if self.target: if self.target:
...@@ -4248,16 +4245,10 @@ class ExceptClauseNode(Node): ...@@ -4248,16 +4245,10 @@ class ExceptClauseNode(Node):
self.pattern.release_temp(env) self.pattern.release_temp(env)
env.release_temp(self.match_flag) env.release_temp(self.match_flag)
# most simple case: empty body (pass) if self.target or self.excinfo_target:
self.empty_body = not self.target and not self.excinfo_target and \
not getattr(self.body, 'stats', True)
if not self.empty_body:
self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)] self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
env.use_utility_code(get_exception_utility_code)
env.use_utility_code(restore_exception_utility_code)
else: else:
self.exc_vars = [] self.exc_vars = None
if self.target: if self.target:
self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1]) self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
...@@ -4275,8 +4266,10 @@ class ExceptClauseNode(Node): ...@@ -4275,8 +4266,10 @@ class ExceptClauseNode(Node):
self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple) self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
self.body.analyse_expressions(env) self.body.analyse_expressions(env)
for var in self.exc_vars:
env.release_temp(var) if self.exc_vars:
for var in self.exc_vars:
env.release_temp(var)
def generate_handling_code(self, code, end_label): def generate_handling_code(self, code, end_label):
code.mark_pos(self.pos) code.mark_pos(self.pos)
...@@ -4294,21 +4287,31 @@ class ExceptClauseNode(Node): ...@@ -4294,21 +4287,31 @@ class ExceptClauseNode(Node):
else: else:
code.putln("/*except:*/ {") code.putln("/*except:*/ {")
if self.empty_body: if self.exc_vars:
# most simple case: reset the exception state, done exc_vars = self.exc_vars
elif not getattr(self.body, 'stats', True):
# most simple case: no exception variable, empty body (pass)
# => reset the exception state, done
code.putln("PyErr_Restore(0,0,0);") code.putln("PyErr_Restore(0,0,0);")
code.put_goto(end_label) code.put_goto(end_label)
code.putln("}") code.putln("}")
return return
else:
# during type analysis, we didn't know if we need the
# exception value, but apparently, we do
exc_vars = [code.funcstate.allocate_temp(py_object_type,
manage_ref=True)
for i in xrange(3)]
code.putln('__Pyx_AddTraceback("%s");' % self.function_name) code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
# We always have to fetch the exception value even if # We always have to fetch the exception value even if
# there is no target, because this also normalises the # there is no target, because this also normalises the
# exception and stores it in the thread state. # exception and stores it in the thread state.
exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars) code.globalstate.use_utility_code(get_exception_utility_code)
exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args, code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
code.error_goto(self.pos))) code.error_goto(self.pos)))
for x in self.exc_vars: for x in exc_vars:
code.put_gotref(x) code.put_gotref(x)
if self.target: if self.target:
self.exc_value.generate_evaluation_code(code) self.exc_value.generate_evaluation_code(code)
...@@ -4323,27 +4326,32 @@ class ExceptClauseNode(Node): ...@@ -4323,27 +4326,32 @@ class ExceptClauseNode(Node):
code.continue_label = code.new_label('except_continue') code.continue_label = code.new_label('except_continue')
old_exc_vars = code.funcstate.exc_vars old_exc_vars = code.funcstate.exc_vars
code.funcstate.exc_vars = self.exc_vars code.funcstate.exc_vars = exc_vars
self.body.generate_execution_code(code) self.body.generate_execution_code(code)
code.funcstate.exc_vars = old_exc_vars code.funcstate.exc_vars = old_exc_vars
for var in self.exc_vars: for var in exc_vars:
code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var)) code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
code.put_goto(end_label) code.put_goto(end_label)
if code.label_used(code.break_label): if code.label_used(code.break_label):
code.put_label(code.break_label) code.put_label(code.break_label)
for var in self.exc_vars: for var in exc_vars:
code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var)) code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
code.put_goto(old_break_label) code.put_goto(old_break_label)
code.break_label = old_break_label code.break_label = old_break_label
if code.label_used(code.continue_label): if code.label_used(code.continue_label):
code.put_label(code.continue_label) code.put_label(code.continue_label)
for var in self.exc_vars: for var in exc_vars:
code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var)) code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
code.put_goto(old_continue_label) code.put_goto(old_continue_label)
code.continue_label = old_continue_label code.continue_label = old_continue_label
if not self.exc_vars:
# clean up locally allocated temps
for temp in exc_vars:
code.funcstate.release_temp(temp)
code.putln( code.putln(
"}") "}")
...@@ -5594,7 +5602,12 @@ impl = """ ...@@ -5594,7 +5602,12 @@ impl = """
static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) { static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
PyObject *tmp_type, *tmp_value, *tmp_tb; PyObject *tmp_type, *tmp_value, *tmp_tb;
PyThreadState *tstate = PyThreadState_GET(); PyThreadState *tstate = PyThreadState_GET();
__Pyx_ErrFetch(type, value, tb); *type = tstate->curexc_type;
*value = tstate->curexc_value;
*tb = tstate->curexc_traceback;
tstate->curexc_type = 0;
tstate->curexc_value = 0;
tstate->curexc_traceback = 0;
PyErr_NormalizeException(type, value, tb); PyErr_NormalizeException(type, value, tb);
if (PyErr_Occurred()) if (PyErr_Occurred())
goto bad; goto bad;
......
...@@ -561,6 +561,8 @@ if __name__ == '__main__': ...@@ -561,6 +561,8 @@ if __name__ == '__main__':
if WITH_CYTHON: if WITH_CYTHON:
from Cython.Compiler.Version import version from Cython.Compiler.Version import version
sys.stderr.write("Running tests against Cython %s\n" % version) sys.stderr.write("Running tests against Cython %s\n" % version)
from Cython.Compiler import DebugFlags
DebugFlags.debug_temp_code_comments = 1
else: else:
sys.stderr.write("Running tests without Cython.\n") sys.stderr.write("Running tests without Cython.\n")
sys.stderr.write("Python %s\n" % sys.version) sys.stderr.write("Python %s\n" % sys.version)
......
return 'bar'
class A:
return None
cdef class B:
return None
try: return None
except: pass
try: return None
finally: pass
for i in (1,2):
return None
while True:
return None
if True:
return None
else:
return None
_ERRORS = u'''
2:0: Return not inside a function body
5:4: Return not inside a function body
8:4: Return not inside a function body
10:5: Return not inside a function body
13:5: Return not inside a function body
17:4: Return not inside a function body
20:4: Return not inside a function body
23:4: Return not inside a function body
25:4: Return not inside a function body
'''
break
class A:
break
cdef class B:
break
def test():
break
try: break
except: pass
try: break
finally: pass
if True:
break
else:
break
_ERRORS = u'''
2:0: break statement not inside loop
5:4: break statement not inside loop
8:4: break statement not inside loop
11:4: break statement not inside loop
16:5: break statement not inside loop
20:4: break statement not inside loop
22:4: break statement not inside loop
'''
continue
class A:
continue
cdef class B:
continue
def test():
continue
try: continue
except: pass
try: continue
finally: pass
if True:
continue
else:
continue
_ERRORS = u'''
2:0: continue statement not inside loop
5:4: continue statement not inside loop
8:4: continue statement not inside loop
11:4: continue statement not inside loop
16:5: continue statement not inside loop
20:4: continue statement not inside loop
22:4: continue statement not inside loop
'''
...@@ -8,7 +8,13 @@ __doc__ = u""" ...@@ -8,7 +8,13 @@ __doc__ = u"""
... except AttributeError: ... except AttributeError:
... print(sys.exc_info()[0] is AttributeError or sys.exc_info()[0]) ... print(sys.exc_info()[0] is AttributeError or sys.exc_info()[0])
... try: raise KeyError ... try: raise KeyError
... except: print(sys.exc_info()[0] is KeyError or sys.exc_info()[0]) ... except:
... print(sys.exc_info()[0] is KeyError or sys.exc_info()[0])
... if IS_PY3:
... print(isinstance(sys.exc_info()[1].__context__, AttributeError)
... or sys.exc_info()[1].__context__)
... else:
... print(True)
... print((IS_PY3 and sys.exc_info()[0] is AttributeError) or ... print((IS_PY3 and sys.exc_info()[0] is AttributeError) or
... (not IS_PY3 and sys.exc_info()[0] is KeyError) or ... (not IS_PY3 and sys.exc_info()[0] is KeyError) or
... sys.exc_info()[0]) ... sys.exc_info()[0])
...@@ -24,6 +30,7 @@ True ...@@ -24,6 +30,7 @@ True
True True
True True
True True
True
>>> print(sys.exc_info()[0]) # test_py() >>> print(sys.exc_info()[0]) # test_py()
None None
...@@ -32,6 +39,7 @@ True ...@@ -32,6 +39,7 @@ True
True True
True True
True True
True
>>> print(sys.exc_info()[0]) # test_c() >>> print(sys.exc_info()[0]) # test_c()
None None
...@@ -52,6 +60,7 @@ True ...@@ -52,6 +60,7 @@ True
True True
True True
True True
True
>>> print(sys.exc_info()[0]) # test_py2() >>> print(sys.exc_info()[0]) # test_py2()
None None
...@@ -62,6 +71,7 @@ True ...@@ -62,6 +71,7 @@ True
True True
True True
True True
True
>>> print(sys.exc_info()[0]) # test_c2() >>> print(sys.exc_info()[0]) # test_c2()
None None
""" """
...@@ -76,7 +86,13 @@ def test_c(outer_exc): ...@@ -76,7 +86,13 @@ def test_c(outer_exc):
except AttributeError: except AttributeError:
print(sys.exc_info()[0] is AttributeError or sys.exc_info()[0]) print(sys.exc_info()[0] is AttributeError or sys.exc_info()[0])
try: raise KeyError try: raise KeyError
except: print(sys.exc_info()[0] is KeyError or sys.exc_info()[0]) except:
print(sys.exc_info()[0] is KeyError or sys.exc_info()[0])
if IS_PY3:
print(isinstance(sys.exc_info()[1].__context__, AttributeError)
or sys.exc_info()[1].__context__)
else:
print(True)
print(sys.exc_info()[0] is AttributeError or sys.exc_info()[0]) print(sys.exc_info()[0] is AttributeError or sys.exc_info()[0])
print(sys.exc_info()[0] is outer_exc or sys.exc_info()[0]) print(sys.exc_info()[0] is outer_exc or sys.exc_info()[0])
......
__doc__ = u"""
>>> try: exc()
... except IndexError:
... if IS_PY3:
... print(isinstance(sys.exc_info()[1].__context__, ValueError))
... else:
... print(True)
True
"""
import sys
IS_PY3 = sys.version_info[0] >= 3
def exc():
try:
raise ValueError
except ValueError:
raise IndexError
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment