Please see attached test.

Returning True from __exit__ when type is None can break expected program
flow. So far, I've found that each of break/continue/return inside a with
block is affected. Both with and without '--jit off'

PyPy2 is unaffected.

Thanks!

-Nate
import unittest

# Platform
#	Ubuntu Xenial
# PyPy 3
# 	url:  https://bitbucket.org/pypy/pypy/downloads/pypy3-v6.0.0-linux64.tar.bz2
#	md5:  86db0d6e4c332043dd79d0ab5aac4c2b
#	sha1: 500637664748891bf0f82bcbc0a66f8866f56f1a
class ContrivedContext(object):
    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        # CPython 2.7, 3.4, 3.7 behave as expected
        # PyPy 2 is fine as well
        # For PyPy 3.5, however (with and without '--jit off'):
        #  returning True for non-error causes a break/continue/return not to work correctly
        if type is None:
            # tests pass if False is always returned when type is None
            return True

class Test_PyPy35_Context_Badness(unittest.TestCase):
    def test_break(self):
        while True:
            with ContrivedContext():
                break
                # should never reach this
                self.assertTrue(False)
            # or this
            # but in PyPy 3.5, the above 'break' failed to kick us out of the loop,
            # due to the context __exit__ returning True
            self.assertTrue(False)
        # should reach this
        self.assertTrue(True)

    def test_continue(self):
        go = True
        while go:
            go = False
            with ContrivedContext():
                continue
                # should never reach this
                self.assertTrue(False)
            # or this
            # but in PyPy 3.5, the above 'continue' failed to jump to the beginning of the loop,
            # due to the context __exit__ returning True
            self.assertTrue(False)
        # should reach this
        self.assertTrue(True)

    def test_return(self):
        with ContrivedContext():
            return
            # should never reach this
            self.assertTrue(False)
        # or this
        # but in PyPy 3.5, the above 'return' failed and did not exit the function,
        # due to the context __exit__ returning True
        self.assertTrue(False)

if __name__ == '__main__':
    unittest.main()
_______________________________________________
pypy-dev mailing list
pypy-dev@python.org
https://mail.python.org/mailman/listinfo/pypy-dev

Reply via email to