Issue 24237: Raise PendingDeprecationWarning per PEP 479

Raise PendingDeprecationWarning when generator raises StopIteration
and no __future__ import is used.  Fix offenders in the stdlib
and tests.

See also issue 22906.
Thanks to Nick Coghlan and Berker Peksag for reviews.
This commit is contained in:
Yury Selivanov 2015-05-22 11:16:47 -04:00
parent e79ec70801
commit 683333955a
5 changed files with 78 additions and 29 deletions

View file

@ -1,6 +1,7 @@
import gc
import sys
import unittest
import warnings
import weakref
from test import support
@ -217,6 +218,46 @@ class ExceptionTest(unittest.TestCase):
self.assertEqual(next(g), "done")
self.assertEqual(sys.exc_info(), (None, None, None))
def test_stopiteration_warning(self):
# See also PEP 479.
def gen():
raise StopIteration
yield
with self.assertRaises(StopIteration), \
self.assertWarnsRegex(PendingDeprecationWarning, "StopIteration"):
next(gen())
with self.assertRaisesRegex(PendingDeprecationWarning,
"generator .* raised StopIteration"), \
warnings.catch_warnings():
warnings.simplefilter('error')
next(gen())
def test_tutorial_stopiteration(self):
# Raise StopIteration" stops the generator too:
def f():
yield 1
raise StopIteration
yield 2 # never reached
g = f()
self.assertEqual(next(g), 1)
with self.assertWarnsRegex(PendingDeprecationWarning, "StopIteration"):
with self.assertRaises(StopIteration):
next(g)
with self.assertRaises(StopIteration):
# This time StopIteration isn't raised from the generator's body,
# hence no warning.
next(g)
tutorial_tests = """
Let's try a simple generator:
@ -263,26 +304,7 @@ Let's try a simple generator:
File "<stdin>", line 1, in ?
StopIteration
"raise StopIteration" stops the generator too:
>>> def f():
... yield 1
... raise StopIteration
... yield 2 # never reached
...
>>> g = f()
>>> next(g)
1
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
StopIteration
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
StopIteration
However, they are not exactly equivalent:
However, "return" and StopIteration are not exactly equivalent:
>>> def g1():
... try: