Commit e7a92df0 authored by Stefan Behnel's avatar Stefan Behnel

avoid setting explicit "None" as StopIteration exception value in generators...

avoid setting explicit "None" as StopIteration exception value in generators and directly return NULL instead
parent e5fc5239
......@@ -5501,10 +5501,10 @@ class ReturnStatNode(StatNode):
have_gil=self.in_nogil_context)
elif self.in_generator:
# return value == raise StopIteration(value), but uncatchable
code.putln(
"%s = NULL; PyErr_SetObject(PyExc_StopIteration, %s);" % (
Naming.retval_cname,
self.value.result_as(self.return_type)))
code.putln("%s = NULL;" % Naming.retval_cname)
if not self.value.is_none:
code.putln("PyErr_SetObject(PyExc_StopIteration, %s);" %
self.value.result_as(self.return_type))
self.value.generate_disposal_code(code)
else:
self.value.make_owned_reference(code)
......@@ -5516,7 +5516,10 @@ class ReturnStatNode(StatNode):
self.value.free_temps(code)
else:
if self.return_type.is_pyobject:
code.put_init_to_py_none(Naming.retval_cname, self.return_type)
if self.in_generator:
code.putln("%s = NULL;" % Naming.retval_cname)
else:
code.put_init_to_py_none(Naming.retval_cname, self.return_type)
elif self.return_type.is_returncode:
self.put_return(code, self.return_type.default_value)
......
......@@ -293,6 +293,7 @@ def test_decorated(*args):
for i in args:
yield i
def test_return(a):
"""
>>> d = dict()
......@@ -309,6 +310,59 @@ def test_return(a):
a['i_was_here'] = True
return
def test_return_in_finally(a):
"""
>>> d = dict()
>>> obj = test_return_in_finally(d)
>>> next(obj)
1
>>> next(obj)
Traceback (most recent call last):
StopIteration
>>> d['i_was_here']
True
>>> obj = test_return_in_finally(None)
>>> next(obj)
1
>>> next(obj)
Traceback (most recent call last):
StopIteration
"""
yield 1
try:
a['i_was_here'] = True
finally:
return
def test_return_none_in_finally(a):
"""
>>> d = dict()
>>> obj = test_return_none_in_finally(d)
>>> next(obj)
1
>>> next(obj)
Traceback (most recent call last):
StopIteration
>>> d['i_was_here']
True
>>> obj = test_return_none_in_finally(None)
>>> next(obj)
1
>>> next(obj)
Traceback (most recent call last):
StopIteration
"""
yield 1
try:
a['i_was_here'] = True
finally:
return None
def test_copied_yield(foo):
"""
>>> class Manager(object):
......
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