[pypy-commit] pypy py3.6: Move app-level tests from test_generator.py to apptest_generator.py and simplify them
rlamy
pypy.commits at gmail.com
Wed Dec 4 21:16:56 EST 2019
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py3.6
Changeset: r98233:17dfad3241f2
Date: 2019-12-05 01:48 +0000
http://bitbucket.org/pypy/pypy/changeset/17dfad3241f2/
Log: Move app-level tests from test_generator.py to apptest_generator.py
and simplify them
diff too long, truncating to 2000 out of 2660 lines
diff --git a/pypy/interpreter/test/test_generator.py b/pypy/interpreter/test/apptest_generator.py
copy from pypy/interpreter/test/test_generator.py
copy to pypy/interpreter/test/apptest_generator.py
--- a/pypy/interpreter/test/test_generator.py
+++ b/pypy/interpreter/test/apptest_generator.py
@@ -1,929 +1,857 @@
-class AppTestGenerator:
+from pytest import raises, skip
- def test_generator(self):
- def f():
+def test_generator():
+ def f():
+ yield 1
+ assert next(f()) == 1
+
+def test_generator2():
+ def f():
+ yield 1
+ g = f()
+ assert next(g) == 1
+ with raises(StopIteration):
+ next(g)
+
+def test_attributes():
+ def f():
+ yield 1
+ assert g.gi_running
+ g = f()
+ assert g.gi_code is f.__code__
+ assert g.__name__ == 'f'
+ assert g.gi_frame is not None
+ assert not g.gi_running
+ next(g)
+ assert not g.gi_running
+ with raises(StopIteration):
+ next(g)
+ assert not g.gi_running
+ assert g.gi_frame is None
+ assert g.gi_code is f.__code__
+ assert g.__name__ == 'f'
+
+def test_generator3():
+ def f():
+ yield 1
+ g = f()
+ assert list(g) == [1]
+
+def test_generator4():
+ def f():
+ yield 1
+ g = f()
+ assert [x for x in g] == [1]
+
+def test_generator5():
+ def f():
+ v = (yield)
+ yield v
+ g = f()
+ next(g)
+ assert g.send(42) == 42
+
+def test_throw1():
+ def f():
+ yield 2
+ g = f()
+ # two arguments version
+ with raises(NameError):
+ g.throw(NameError, "Error")
+
+def test_throw2():
+ def f():
+ yield 2
+ g = f()
+ # single argument version
+ with raises(NameError):
+ g.throw(NameError("Error"))
+
+def test_throw3():
+ def f():
+ try:
yield 1
- assert next(f()) == 1
+ yield 2
+ except NameError:
+ yield 3
+ g = f()
+ assert next(g) == 1
+ assert g.throw(NameError("Error")) == 3
+ with raises(StopIteration):
+ next(g)
- def test_generator2(self):
- def f():
+def test_throw4():
+ def f():
+ try:
yield 1
- g = f()
- assert next(g) == 1
- with raises(StopIteration):
- next(g)
+ v = (yield 2)
+ except NameError:
+ yield 3
+ g = f()
+ assert next(g) == 1
+ assert next(g) == 2
+ assert g.throw(NameError("Error")) == 3
+ with raises(StopIteration):
+ next(g)
- def test_attributes(self):
- def f():
+def test_throw5():
+ def f():
+ try:
yield 1
- assert g.gi_running
- g = f()
- assert g.gi_code is f.__code__
- assert g.__name__ == 'f'
- assert g.gi_frame is not None
- assert not g.gi_running
+ except Exception:
+ x = 3
+ try:
+ yield x
+ except Exception:
+ pass
+ g = f()
+ next(g)
+ # String exceptions are not allowed anymore
+ with raises(TypeError):
+ g.throw("Error")
+ assert g.throw(Exception) == 3
+ with raises(StopIteration):
+ g.throw(Exception)
+
+def test_throw6():
+ def f():
+ yield 2
+ g = f()
+ with raises(NameError):
+ g.throw(NameError, "Error", None)
+
+
+def test_throw_fail():
+ def f():
+ yield 1
+ g = f()
+ with raises(TypeError):
+ g.throw(NameError("Error"), "error")
+
+def test_throw_fail2():
+ def f():
+ yield 1
+ g = f()
+ with raises(TypeError):
+ g.throw(list())
+
+def test_throw_fail3():
+ def f():
+ yield 1
+ g = f()
+ with raises(TypeError):
+ g.throw(NameError("Error"), None, "not tb object")
+
+def test_throw_finishes_generator():
+ def f():
+ yield 1
+ g = f()
+ assert g.gi_frame is not None
+ with raises(ValueError):
+ g.throw(ValueError)
+ assert g.gi_frame is None
+
+def test_throw_bug():
+ def f():
+ try:
+ x.throw(IndexError) # => "generator already executing"
+ except ValueError:
+ yield 1
+ x = f()
+ res = list(x)
+ assert res == [1]
+
+def test_throw_on_finished_generator():
+ def f():
+ yield 1
+ g = f()
+ res = next(g)
+ assert res == 1
+ with raises(StopIteration):
next(g)
- assert not g.gi_running
- with raises(StopIteration):
- next(g)
- assert not g.gi_running
- assert g.gi_frame is None
- assert g.gi_code is f.__code__
- assert g.__name__ == 'f'
+ with raises(NameError):
+ g.throw(NameError)
- def test_generator3(self):
- def f():
+def test_throw_tb():
+ def f():
+ try:
+ yield
+ except ZeroDivisionError:
+ raise
+ g = f()
+ try:
+ 1 / 0
+ except ZeroDivisionError as v:
+ try:
+ g.throw(v)
+ except Exception as w:
+ tb = w.__traceback__
+ levels = 0
+ while tb:
+ levels += 1
+ tb = tb.tb_next
+ assert levels == 3
+
+def test_throw_context():
+ # gen.throw(exc) must not modify exc.__context__
+ def gen():
+ try:
+ yield
+ except Exception:
+ raise ValueError
+
+ try:
+ raise KeyError
+ except KeyError:
+ g = gen()
+ next(g)
+ exc1 = Exception(1)
+ exc2 = Exception(2)
+ exc2.__context__ = exc1
+ try:
+ g.throw(exc2)
+ except ValueError:
+ assert exc2.__context__ is exc1
+
+def test_close():
+ def f():
+ yield 1
+ g = f()
+ assert g.close() is None
+
+def test_close2():
+ def f():
+ try:
yield 1
- g = f()
- assert list(g) == [1]
+ except GeneratorExit:
+ raise StopIteration
+ g = f()
+ next(g)
+ assert g.close() is None
- def test_generator4(self):
- def f():
+def test_close3():
+ def f():
+ try:
yield 1
- g = f()
- assert [x for x in g] == [1]
+ except GeneratorExit:
+ raise NameError
+ g = f()
+ next(g)
+ with raises(NameError):
+ g.close()
- def test_generator5(self):
- d = {}
- exec("""if 1:
- def f():
- v = (yield )
- yield v
- g = f()
+def test_close_fail():
+ def f():
+ try:
+ yield 1
+ except GeneratorExit:
+ yield 2
+ g = f()
+ next(g)
+ with raises(RuntimeError):
+ g.close()
+
+def test_close_on_collect():
+ import gc
+ def f():
+ try:
+ yield
+ finally:
+ f.x = 42
+ g = f()
+ next(g)
+ del g
+ gc.collect()
+ assert f.x == 42
+
+def test_generator_raises_typeerror():
+ def f():
+ yield 1
+ g = f()
+ with raises(TypeError):
+ g.send() # one argument required
+ with raises(TypeError):
+ g.send(1) # not started, must send None
+
+def test_generator_explicit_stopiteration():
+ def f():
+ yield 1
+ raise StopIteration
+ g = f()
+ assert [x for x in g] == [1]
+
+def test_generator_propagate_stopiteration():
+ def f():
+ it = iter([1])
+ while 1:
+ yield next(it)
+ g = f()
+ assert [x for x in g] == [1]
+
+def test_generator_restart():
+ def g():
+ i = next(me)
+ yield i
+ me = g()
+ with raises(ValueError):
+ next(me)
+
+def test_generator_expression():
+ d = {}
+ exec("res = sum(i*i for i in range(5))", d, d)
+ assert d['res'] == 30
+
+def test_generator_expression_2():
+ def f():
+ total = sum(i for i in [x for x in z])
+ return total
+ z = [1, 2, 7]
+ assert f() == 10
+
+def test_repr():
+ def myFunc():
+ yield 1
+ g = myFunc()
+ r = repr(g)
+ assert r.startswith("<generator object test_repr.<locals>.myFunc at 0x")
+ assert list(g) == [1]
+ assert repr(g) == r
+
+def test_unpackiterable_gen():
+ g = (i * i for i in range(-5, 3))
+ assert set(g) == set([0, 1, 4, 9, 16, 25])
+ assert set(g) == set()
+ assert set(i for i in range(0)) == set()
+
+def test_explicit_stop_iteration_unpackiterable():
+ def f():
+ yield 1
+ raise StopIteration
+ assert tuple(f()) == (1,)
+
+def test_exception_is_cleared_by_yield():
+ def f():
+ try:
+ foobar
+ except NameError:
+ yield 5
+ raise
+ gen = f()
+ next(gen) # --> 5
+ try:
+ next(gen)
+ except NameError:
+ pass
+
+def test_yield_return():
+ def f():
+ yield 1
+ return 2
+ g = f()
+ assert next(g) == 1
+ try:
next(g)
- """, d, d)
- g = d['g']
- assert g.send(42) == 42
+ except StopIteration as e:
+ assert e.value == 2
+ else:
+ assert False, 'Expected StopIteration'
- def test_throw1(self):
- def f():
- yield 2
- g = f()
- # two arguments version
- with raises(NameError):
- g.throw(NameError, "Error")
+def test_yield_from_basic():
+ def f1():
+ yield from []
+ yield from [1, 2, 3]
+ yield from f2()
+ def f2():
+ yield 4
+ yield 5
+ gen = f1()
+ assert next(gen) == 1
+ assert next(gen) == 2
+ assert next(gen) == 3
+ assert next(gen) == 4
+ assert next(gen) == 5
+ assert list(gen) == []
- def test_throw2(self):
- def f():
- yield 2
- g = f()
- # single argument version
- with raises(NameError):
- g.throw(NameError("Error"))
+def test_yield_from_return():
+ def f1():
+ result = yield from f2()
+ return result
+ def f2():
+ yield 1
+ return 2
+ g = f1()
+ assert next(g) == 1
+ try:
+ next(g)
+ except StopIteration as e:
+ assert e.value == 2
+ else:
+ assert False, 'Expected StopIteration'
- def test_throw3(self):
- def f():
- try:
- yield 1
- yield 2
- except:
- yield 3
- g = f()
- assert next(g) == 1
- assert g.throw(NameError("Error")) == 3
- with raises(StopIteration):
- next(g)
+def test_yield_from_return_tuple():
+ def f1():
+ result = yield from f2()
+ return result
+ def f2():
+ yield 1
+ return (1, 2)
+ g = f1()
+ assert next(g) == 1
+ try:
+ next(g)
+ except StopIteration as e:
+ assert e.value == (1, 2)
+ else:
+ assert False, 'Expected StopIteration'
- def test_throw4(self):
- d = {}
- exec("""if 1:
- def f():
- try:
- yield 1
- v = (yield 2)
- except:
- yield 3
- g = f()
- """, d, d)
- g = d['g']
- assert next(g) == 1
- assert next(g) == 2
- assert g.throw(NameError("Error")) == 3
- with raises(StopIteration):
- next(g)
+def test_set_name_qualname():
+ class A:
+ def f(self):
+ yield 5
+ g = A().f()
+ assert g.__name__ == "f"
+ assert g.__qualname__ == "test_set_name_qualname.<locals>.A.f"
+ g.__name__ = "h.i"
+ g.__qualname__ = "j.k"
+ assert g.__name__ == "h.i"
+ assert g.__qualname__ == "j.k"
+ with raises(TypeError):
+ g.__name__ = 42
+ with raises(TypeError):
+ g.__qualname__ = 42
+ with raises((TypeError, AttributeError)):
+ del g.__name__
+ with raises((TypeError, AttributeError)):
+ del g.__qualname__
- def test_throw5(self):
- def f():
- try:
- yield 1
- except:
- x = 3
- try:
- yield x
- except:
- pass
- g = f()
- next(g)
- # String exceptions are not allowed anymore
- with raises(TypeError):
- g.throw("Error")
- assert g.throw(Exception) == 3
- with raises(StopIteration):
- g.throw(Exception)
+def test_gi_yieldfrom():
+ def g(x):
+ assert gen.gi_yieldfrom is None
+ yield x
+ assert gen.gi_yieldfrom is None
+ def f(x):
+ assert gen.gi_yieldfrom is None
+ yield from g(x)
+ assert gen.gi_yieldfrom is None
+ yield 42
+ assert gen.gi_yieldfrom is None
+ gen = f(5)
+ assert gen.gi_yieldfrom is None
+ assert next(gen) == 5
+ assert gen.gi_yieldfrom.__name__ == 'g'
+ assert next(gen) == 42
+ assert gen.gi_yieldfrom is None
- def test_throw6(self):
- def f():
- yield 2
- g = f()
- with raises(NameError):
- g.throw(NameError, "Error", None)
+def test_gi_running_in_throw_generatorexit():
+ # We must force gi_running to be True on the outer generators
+ # when running an inner custom close() method.
+ class A:
+ def __iter__(self):
+ return self
+ def __next__(self):
+ return 42
+ def close(self):
+ closed.append(gen.gi_running)
+ def g():
+ yield from A()
+ gen = g()
+ assert next(gen) == 42
+ closed = []
+ with raises(GeneratorExit):
+ gen.throw(GeneratorExit)
+ assert closed == [True]
-
- def test_throw_fail(self):
- def f():
- yield 1
- g = f()
- with raises(TypeError):
- g.throw(NameError("Error"), "error")
-
- def test_throw_fail2(self):
- def f():
- yield 1
- g = f()
- with raises(TypeError):
- g.throw(list())
-
- def test_throw_fail3(self):
- def f():
- yield 1
- g = f()
- with raises(TypeError):
- g.throw(NameError("Error"), None, "not tb object")
-
- def test_throw_finishes_generator(self):
- def f():
- yield 1
- g = f()
- assert g.gi_frame is not None
- with raises(ValueError):
- g.throw(ValueError)
- assert g.gi_frame is None
-
- def test_throw_bug(self):
- def f():
- try:
- x.throw(IndexError) # => "generator already executing"
- except ValueError:
- yield 1
- x = f()
- res = list(x)
- assert res == [1]
-
- def test_throw_on_finished_generator(self):
- def f():
- yield 1
- g = f()
- res = next(g)
- assert res == 1
- with raises(StopIteration):
- next(g)
- with raises(NameError):
- g.throw(NameError)
-
- def test_throw_tb(self):
- def f():
- try:
- yield
- except:
- raise
- g = f()
- try:
- 1/0
- except ZeroDivisionError as v:
- try:
- g.throw(v)
- except Exception as w:
- tb = w.__traceback__
- levels = 0
- while tb:
- levels += 1
- tb = tb.tb_next
- assert levels == 3
-
- def test_throw_context(self):
- # gen.throw(exc) must not modify exc.__context__
- def gen():
- try:
- yield
- except:
- raise ValueError
-
- try:
- raise KeyError
- except KeyError:
- g = gen()
- next(g)
- exc1 = Exception(1)
- exc2 = Exception(2)
- exc2.__context__ = exc1
- try:
- g.throw(exc2)
- except ValueError:
- assert exc2.__context__ is exc1
-
- def test_close(self):
- def f():
- yield 1
- g = f()
- assert g.close() is None
-
- def test_close2(self):
- def f():
- try:
- yield 1
- except GeneratorExit:
- raise StopIteration
- g = f()
- next(g)
- assert g.close() is None
-
- def test_close3(self):
- def f():
- try:
- yield 1
- except GeneratorExit:
- raise NameError
- g = f()
- next(g)
- with raises(NameError):
- g.close()
-
- def test_close_fail(self):
- def f():
- try:
- yield 1
- except GeneratorExit:
- yield 2
- g = f()
- next(g)
- with raises(RuntimeError):
- g.close()
-
- def test_close_on_collect(self):
- import gc
- def f():
- try:
- yield
- finally:
- f.x = 42
- g = f()
- next(g)
- del g
- gc.collect()
- assert f.x == 42
-
- def test_generator_raises_typeerror(self):
- def f():
- yield 1
- g = f()
- with raises(TypeError):
- g.send() # one argument required
- with raises(TypeError):
- g.send(1) # not started, must send None
-
- def test_generator_explicit_stopiteration(self):
- def f():
- yield 1
- raise StopIteration
- g = f()
- assert [x for x in g] == [1]
-
- def test_generator_propagate_stopiteration(self):
- def f():
- it = iter([1])
- while 1: yield next(it)
- g = f()
- assert [x for x in g] == [1]
-
- def test_generator_restart(self):
- def g():
- i = next(me)
- yield i
- me = g()
- with raises(ValueError):
- next(me)
-
- def test_generator_expression(self):
- d = {}
- exec("res = sum(i*i for i in range(5))", d, d)
- assert d['res'] == 30
-
- def test_generator_expression_2(self):
- d = {}
- exec("""
-def f():
- total = sum(i for i in [x for x in z])
- return total
-z = [1, 2, 7]
-res = f()
-""", d, d)
- assert d['res'] == 10
-
- def test_repr(self):
- def myFunc():
- yield 1
- g = myFunc()
- r = repr(g)
- assert r.startswith("<generator object test_repr.<locals>.myFunc at 0x")
- assert list(g) == [1]
- assert repr(g) == r
-
- def test_unpackiterable_gen(self):
- g = (i*i for i in range(-5, 3))
- assert set(g) == set([0, 1, 4, 9, 16, 25])
- assert set(g) == set()
- assert set(i for i in range(0)) == set()
-
- def test_explicit_stop_iteration_unpackiterable(self):
- def f():
- yield 1
- raise StopIteration
- assert tuple(f()) == (1,)
-
- def test_exception_is_cleared_by_yield(self):
- def f():
- try:
- foobar
- except NameError:
- yield 5
- raise
- gen = f()
- next(gen) # --> 5
- try:
- next(gen)
- except NameError:
- pass
-
- def test_yield_return(self):
- """
- def f():
- yield 1
- return 2
- g = f()
- assert next(g) == 1
- try:
- next(g)
- except StopIteration as e:
- assert e.value == 2
- else:
- assert False, 'Expected StopIteration'
- """
-
- def test_yield_from_basic(self):
- """
- def f1():
- yield from []
- yield from [1, 2, 3]
- yield from f2()
- def f2():
- yield 4
- yield 5
- gen = f1()
- assert next(gen) == 1
- assert next(gen) == 2
- assert next(gen) == 3
- assert next(gen) == 4
- assert next(gen) == 5
- assert list(gen) == []
- """
-
- def test_yield_from_return(self):
- """
- def f1():
- result = yield from f2()
- return result
- def f2():
- yield 1
- return 2
- g = f1()
- assert next(g) == 1
- try:
- next(g)
- except StopIteration as e:
- assert e.value == 2
- else:
- assert False, 'Expected StopIteration'
- """
-
- def test_yield_from_return_tuple(self):
- """
- def f1():
- result = yield from f2()
- return result
- def f2():
- yield 1
- return (1, 2)
- g = f1()
- assert next(g) == 1
- try:
- next(g)
- except StopIteration as e:
- assert e.value == (1, 2)
- else:
- assert False, 'Expected StopIteration'
- """
-
- def test_set_name_qualname(self):
- class A:
- def f(self):
- yield 5
- g = A().f()
- assert g.__name__ == "f"
- assert g.__qualname__ == "test_set_name_qualname.<locals>.A.f"
- g.__name__ = "h.i"
- g.__qualname__ = "j.k"
- assert g.__name__ == "h.i"
- assert g.__qualname__ == "j.k"
- with raises(TypeError):
- g.__name__ = 42
- with raises(TypeError):
- g.__qualname__ = 42
- with raises((TypeError, AttributeError)):
- del g.__name__
- with raises((TypeError, AttributeError)):
- del g.__qualname__
-
- def test_gi_yieldfrom(self): """
- def g(x):
- assert gen.gi_yieldfrom is None
- yield x
- assert gen.gi_yieldfrom is None
- def f(x):
- assert gen.gi_yieldfrom is None
- yield from g(x)
- assert gen.gi_yieldfrom is None
- yield 42
- assert gen.gi_yieldfrom is None
- gen = f(5)
- assert gen.gi_yieldfrom is None
- assert next(gen) == 5
- assert gen.gi_yieldfrom.__name__ == 'g'
- assert next(gen) == 42
- assert gen.gi_yieldfrom is None
- """
-
- def test_gi_running_in_throw_generatorexit(self): """
- # We must force gi_running to be True on the outer generators
- # when running an inner custom close() method.
- class A:
- def __iter__(self):
- return self
- def __next__(self):
- return 42
- def close(self):
- closed.append(gen.gi_running)
- def g():
- yield from A()
- gen = g()
- assert next(gen) == 42
- closed = []
- with raises(GeneratorExit):
- gen.throw(GeneratorExit)
- assert closed == [True]
- """
-
- def test_exc_info_in_generator(self):
- import sys
- def g():
- try:
- raise ValueError
- except ValueError:
- yield sys.exc_info()[0]
- yield sys.exc_info()[0]
- try:
- raise IndexError
- except IndexError:
- gen = g()
- assert sys.exc_info()[0] is IndexError
- assert next(gen) is ValueError
- assert sys.exc_info()[0] is IndexError
- assert next(gen) is ValueError
- assert sys.exc_info()[0] is IndexError
- with raises(StopIteration):
- next(gen)
- assert sys.exc_info()[0] is IndexError
-
- def test_exc_info_in_generator_2(self):
- import sys
- def g():
- yield sys.exc_info()[0]
- try:
- raise LookupError
- except LookupError:
- yield sys.exc_info()[0]
- yield sys.exc_info()[0]
- try:
- raise IndexError
- except IndexError:
- gen = g() # the IndexError is not captured at all
+def test_exc_info_in_generator():
+ import sys
+ def g():
try:
raise ValueError
except ValueError:
- assert next(gen) is ValueError
- assert next(gen) is LookupError
- assert next(gen) is ValueError
+ yield sys.exc_info()[0]
+ yield sys.exc_info()[0]
+ try:
+ raise IndexError
+ except IndexError:
+ gen = g()
+ assert sys.exc_info()[0] is IndexError
+ assert next(gen) is ValueError
+ assert sys.exc_info()[0] is IndexError
+ assert next(gen) is ValueError
+ assert sys.exc_info()[0] is IndexError
+ with raises(StopIteration):
+ next(gen)
+ assert sys.exc_info()[0] is IndexError
- def test_exc_info_in_generator_3(self):
- import sys
- def g():
+def test_exc_info_in_generator_2():
+ import sys
+ def g():
+ yield sys.exc_info()[0]
+ try:
+ raise LookupError
+ except LookupError:
yield sys.exc_info()[0]
- yield sys.exc_info()[0]
- yield sys.exc_info()[0]
- gen = g()
- try:
- raise IndexError
- except IndexError:
- assert next(gen) is IndexError
- assert next(gen) is None
+ yield sys.exc_info()[0]
+ try:
+ raise IndexError
+ except IndexError:
+ gen = g() # the IndexError is not captured at all
+ try:
+ raise ValueError
+ except ValueError:
+ assert next(gen) is ValueError
+ assert next(gen) is LookupError
+ assert next(gen) is ValueError
+
+def test_exc_info_in_generator_3():
+ import sys
+ def g():
+ yield sys.exc_info()[0]
+ yield sys.exc_info()[0]
+ yield sys.exc_info()[0]
+ gen = g()
+ try:
+ raise IndexError
+ except IndexError:
+ assert next(gen) is IndexError
+ assert next(gen) is None
+ try:
+ raise ValueError
+ except ValueError:
+ assert next(gen) is ValueError
+
+def test_exc_info_in_generator_4():
+ skip("buggy behavior, both in CPython and in PyPy")
+ import sys
+ def g():
try:
raise ValueError
except ValueError:
- assert next(gen) is ValueError
+ yield 1
+ assert sys.exc_info() == (None, None, None)
+ yield 2
+ gen = g()
+ try:
+ raise IndexError
+ except IndexError:
+ assert next(gen) is 1
+ assert next(gen) is 2
- def test_exc_info_in_generator_4(self):
- skip("buggy behavior, both in CPython and in PyPy")
- import sys
- def g():
- try:
- raise ValueError
- except ValueError:
- yield 1
- assert sys.exc_info() == (None, None, None)
- yield 2
- gen = g()
+def test_multiple_invalid_sends():
+ def mygen():
+ yield 42
+ g = mygen()
+ with raises(TypeError):
+ g.send(2)
+ with raises(TypeError):
+ g.send(2)
+
+def test_delegating_close():
+ """
+ Test delegating 'close'
+ """
+ trace = []
+ def g1():
try:
- raise IndexError
- except IndexError:
- assert next(gen) is 1
- assert next(gen) is 2
+ trace.append("Starting g1")
+ yield "g1 ham"
+ yield from g2()
+ yield "g1 eggs"
+ finally:
+ trace.append("Finishing g1")
+ def g2():
+ try:
+ trace.append("Starting g2")
+ yield "g2 spam"
+ yield "g2 more spam"
+ finally:
+ trace.append("Finishing g2")
+ g = g1()
+ for i in range(2):
+ x = next(g)
+ trace.append("Yielded %s" % (x,))
+ g.close()
+ assert trace == [
+ "Starting g1",
+ "Yielded g1 ham",
+ "Starting g2",
+ "Yielded g2 spam",
+ "Finishing g2",
+ "Finishing g1"
+ ]
- def test_multiple_invalid_sends(self):
- def mygen():
- yield 42
- g = mygen()
- with raises(TypeError):
- g.send(2)
- with raises(TypeError):
- g.send(2)
+def test_handing_exception_while_delegating_close():
+ """
+ Test handling exception while delegating 'close'
+ """
+ trace = []
+ def g1():
+ try:
+ trace.append("Starting g1")
+ yield "g1 ham"
+ yield from g2()
+ yield "g1 eggs"
+ finally:
+ trace.append("Finishing g1")
+ def g2():
+ try:
+ trace.append("Starting g2")
+ yield "g2 spam"
+ yield "g2 more spam"
+ finally:
+ trace.append("Finishing g2")
+ raise ValueError("nybbles have exploded with delight")
+ g = g1()
+ for i in range(2):
+ x = next(g)
+ trace.append("Yielded %s" % (x,))
+ with raises(ValueError) as excinfo:
+ g.close()
+ assert excinfo.value.args[0] == "nybbles have exploded with delight"
+ assert isinstance(excinfo.value.__context__, GeneratorExit)
+ assert trace == [
+ "Starting g1",
+ "Yielded g1 ham",
+ "Starting g2",
+ "Yielded g2 spam",
+ "Finishing g2",
+ "Finishing g1",
+ ]
+def test_delegating_throw():
+ """
+ Test delegating 'throw'
+ """
+ trace = []
+ def g1():
+ try:
+ trace.append("Starting g1")
+ yield "g1 ham"
+ yield from g2()
+ yield "g1 eggs"
+ finally:
+ trace.append("Finishing g1")
+ def g2():
+ try:
+ trace.append("Starting g2")
+ yield "g2 spam"
+ yield "g2 more spam"
+ finally:
+ trace.append("Finishing g2")
+ g = g1()
+ for i in range(2):
+ x = next(g)
+ trace.append("Yielded %s" % (x,))
+ e = ValueError("tomato ejected")
+ with raises(ValueError) as excinfo:
+ g.throw(e)
+ assert excinfo.value.args[0] == "tomato ejected"
+ assert trace == [
+ "Starting g1",
+ "Yielded g1 ham",
+ "Starting g2",
+ "Yielded g2 spam",
+ "Finishing g2",
+ "Finishing g1",
+ ]
-def test_should_not_inline(space):
- from pypy.interpreter.generator import should_not_inline
- w_co = space.appexec([], '''():
- def g(x):
- yield x + 5
- return g.__code__
- ''')
- assert should_not_inline(w_co) == False
- w_co = space.appexec([], '''():
- def g(x):
- yield x + 5
- yield x + 6
- return g.__code__
- ''')
- assert should_not_inline(w_co) == True
+def test_delegating_throw_to_non_generator():
+ """
+ Test delegating 'throw' to non-generator
+ """
+ trace = []
+ def g():
+ try:
+ trace.append("Starting g")
+ yield from range(10)
+ finally:
+ trace.append("Finishing g")
+ gi = g()
+ for i in range(5):
+ x = next(gi)
+ trace.append("Yielded %s" % (x,))
+ with raises(ValueError) as excinfo:
+ gi.throw(ValueError("tomato ejected"))
+ assert excinfo.value.args[0] == "tomato ejected"
+ assert trace == [
+ "Starting g",
+ "Yielded 0",
+ "Yielded 1",
+ "Yielded 2",
+ "Yielded 3",
+ "Yielded 4",
+ "Finishing g",
+ ]
-class AppTestYieldFrom:
- def test_delegating_close(self):
- """
- Test delegating 'close'
- """
- trace = []
- d = dict(trace=trace)
- exec('''if 1:
- def g1():
- try:
- trace.append("Starting g1")
- yield "g1 ham"
- yield from g2()
- yield "g1 eggs"
- finally:
- trace.append("Finishing g1")
- def g2():
- try:
- trace.append("Starting g2")
- yield "g2 spam"
- yield "g2 more spam"
- finally:
- trace.append("Finishing g2")
- ''', d)
- g1, g2 = d['g1'], d['g2']
- g = g1()
- for i in range(2):
- x = next(g)
- trace.append("Yielded %s" % (x,))
- g.close()
- assert trace == [
- "Starting g1",
- "Yielded g1 ham",
- "Starting g2",
- "Yielded g2 spam",
- "Finishing g2",
- "Finishing g1"
- ]
+def test_broken_getattr_handling():
+ """
+ Test subiterator with a broken getattr implementation
+ """
+ import _io, sys
+ class Broken:
+ def __iter__(self):
+ return self
+ def __next__(self):
+ return 1
+ def __getattr__(self, attr):
+ 1 / 0
- def test_handing_exception_while_delegating_close(self):
- """
- Test handling exception while delegating 'close'
- """
- trace = []
- d = dict(trace=trace)
- exec('''if 1:
- def g1():
- try:
- trace.append("Starting g1")
- yield "g1 ham"
- yield from g2()
- yield "g1 eggs"
- finally:
- trace.append("Finishing g1")
- def g2():
- try:
- trace.append("Starting g2")
- yield "g2 spam"
- yield "g2 more spam"
- finally:
- trace.append("Finishing g2")
- raise ValueError("nybbles have exploded with delight")
- ''', d)
- g1, g2 = d['g1'], d['g2']
- g = g1()
- for i in range(2):
- x = next(g)
- trace.append("Yielded %s" % (x,))
- with raises(ValueError) as excinfo:
- g.close()
- assert excinfo.value.args[0] == "nybbles have exploded with delight"
- assert isinstance(excinfo.value.__context__, GeneratorExit)
- assert trace == [
- "Starting g1",
- "Yielded g1 ham",
- "Starting g2",
- "Yielded g2 spam",
- "Finishing g2",
- "Finishing g1",
- ]
+ def g():
+ yield from Broken()
- def test_delegating_throw(self):
- """
- Test delegating 'throw'
- """
- trace = []
- d = dict(trace=trace)
- exec('''if 1:
- def g1():
- try:
- trace.append("Starting g1")
- yield "g1 ham"
- yield from g2()
- yield "g1 eggs"
- finally:
- trace.append("Finishing g1")
- def g2():
- try:
- trace.append("Starting g2")
- yield "g2 spam"
- yield "g2 more spam"
- finally:
- trace.append("Finishing g2")
- ''', d)
- g1, g2 = d['g1'], d['g2']
- g = g1()
- for i in range(2):
- x = next(g)
- trace.append("Yielded %s" % (x,))
- e = ValueError("tomato ejected")
- with raises(ValueError) as excinfo:
- g.throw(e)
- assert excinfo.value.args[0] == "tomato ejected"
- assert trace == [
- "Starting g1",
- "Yielded g1 ham",
- "Starting g2",
- "Yielded g2 spam",
- "Finishing g2",
- "Finishing g1",
- ]
+ gi = g()
+ assert next(gi) == 1
+ with raises(ZeroDivisionError):
+ gi.send(1)
- def test_delegating_throw_to_non_generator(self):
- """
- Test delegating 'throw' to non-generator
- """
- trace = []
- d = dict(trace=trace)
- exec('''if 1:
- def g():
- try:
- trace.append("Starting g")
- yield from range(10)
- finally:
- trace.append("Finishing g")
- ''', d)
- g = d['g']
- gi = g()
- for i in range(5):
- x = next(gi)
- trace.append("Yielded %s" % (x,))
- with raises(ValueError) as excinfo:
- gi.throw(ValueError("tomato ejected"))
- assert excinfo.value.args[0] == "tomato ejected"
- assert trace == [
- "Starting g",
- "Yielded 0",
- "Yielded 1",
- "Yielded 2",
- "Yielded 3",
- "Yielded 4",
- "Finishing g",
- ]
+ gi = g()
+ assert next(gi) == 1
+ with raises(ZeroDivisionError):
+ gi.throw(RuntimeError)
- def test_broken_getattr_handling(self):
- """
- Test subiterator with a broken getattr implementation
- """
- class Broken:
- def __iter__(self):
- return self
- def __next__(self):
- return 1
- def __getattr__(self, attr):
- 1/0
+ gi = g()
+ assert next(gi) == 1
+ sys.stderr = _io.StringIO()
+ gi.close()
+ assert 'ZeroDivisionError' in sys.stderr.getvalue()
- d = dict(Broken=Broken)
- exec('''if 1:
- def g():
- yield from Broken()
- ''', d)
- g = d['g']
+def test_returning_value_from_delegated_throw():
+ """
+ Test returning value from delegated 'throw'
+ """
+ trace = []
+ class LunchError(Exception):
+ pass
+ def g1():
+ try:
+ trace.append("Starting g1")
+ yield "g1 ham"
+ yield from g2()
+ yield "g1 eggs"
+ finally:
+ trace.append("Finishing g1")
+ def g2():
+ try:
+ trace.append("Starting g2")
+ yield "g2 spam"
+ yield "g2 more spam"
+ except LunchError:
+ trace.append("Caught LunchError in g2")
+ yield "g2 lunch saved"
+ yield "g2 yet more spam"
+ g = g1()
+ for i in range(2):
+ x = next(g)
+ trace.append("Yielded %s" % (x,))
+ e = LunchError("tomato ejected")
+ g.throw(e)
+ for x in g:
+ trace.append("Yielded %s" % (x,))
+ assert trace == [
+ "Starting g1",
+ "Yielded g1 ham",
+ "Starting g2",
+ "Yielded g2 spam",
+ "Caught LunchError in g2",
+ "Yielded g2 yet more spam",
+ "Yielded g1 eggs",
+ "Finishing g1",
+ ]
- gi = g()
- assert next(gi) == 1
- with raises(ZeroDivisionError):
- gi.send(1)
+def test_catching_exception_from_subgen_and_returning():
+ """
+ Test catching an exception thrown into a
+ subgenerator and returning a value
+ """
+ trace = []
+ def inner():
+ try:
+ yield 1
+ except ValueError:
+ trace.append("inner caught ValueError")
+ return 2
- gi = g()
- assert next(gi) == 1
- with raises(ZeroDivisionError):
- gi.throw(RuntimeError)
+ def outer():
+ v = yield from inner()
+ trace.append("inner returned %r to outer" % v)
+ yield v
+ g = outer()
+ trace.append(next(g))
+ trace.append(g.throw(ValueError))
+ assert trace == [
+ 1,
+ "inner caught ValueError",
+ "inner returned 2 to outer",
+ 2,
+ ]
- gi = g()
- assert next(gi) == 1
- import _io, sys
- sys.stderr = _io.StringIO()
- gi.close()
- assert 'ZeroDivisionError' in sys.stderr.getvalue()
+def test_exception_context():
+ import operator
+ def f():
+ try:
+ raise ValueError
+ except ValueError:
+ yield from map(operator.truediv, [2, 3], [4, 0])
+ gen = f()
+ assert next(gen) == 0.5
+ try:
+ next(gen)
+ except ZeroDivisionError as e:
+ assert e.__context__ is not None
+ assert isinstance(e.__context__, ValueError)
+ else:
+ assert False, "should have raised"
- def test_returning_value_from_delegated_throw(self):
- """
- Test returning value from delegated 'throw'
- """
- trace = []
- class LunchError(Exception):
- pass
- d = dict(trace=trace, LunchError=LunchError)
- exec('''if 1:
- def g1():
- try:
- trace.append("Starting g1")
- yield "g1 ham"
- yield from g2()
- yield "g1 eggs"
- finally:
- trace.append("Finishing g1")
- def g2():
- try:
- trace.append("Starting g2")
- yield "g2 spam"
- yield "g2 more spam"
- except LunchError:
- trace.append("Caught LunchError in g2")
- yield "g2 lunch saved"
- yield "g2 yet more spam"
- ''', d)
- g1, g2 = d['g1'], d['g2']
- g = g1()
- for i in range(2):
- x = next(g)
- trace.append("Yielded %s" % (x,))
- e = LunchError("tomato ejected")
- g.throw(e)
- for x in g:
- trace.append("Yielded %s" % (x,))
- assert trace == [
- "Starting g1",
- "Yielded g1 ham",
- "Starting g2",
- "Yielded g2 spam",
- "Caught LunchError in g2",
- "Yielded g2 yet more spam",
- "Yielded g1 eggs",
- "Finishing g1",
- ]
- def test_catching_exception_from_subgen_and_returning(self):
- """
- Test catching an exception thrown into a
- subgenerator and returning a value
- """
- trace = []
- d = dict(trace=trace)
- exec('''if 1:
- def inner():
- try:
- yield 1
- except ValueError:
- trace.append("inner caught ValueError")
- return 2
+def test_past_generator_stop():
+ # how it works without 'from __future__' import generator_stop
+ def f(x):
+ raise StopIteration
+ yield x
+ with raises(StopIteration):
+ next(f(5))
- def outer():
- v = yield from inner()
- trace.append("inner returned %r to outer" % v)
- yield v
- ''', d)
- inner, outer = d['inner'], d['outer']
- g = outer()
- trace.append(next(g))
- trace.append(g.throw(ValueError))
- assert trace == [
- 1,
- "inner caught ValueError",
- "inner returned 2 to outer",
- 2,
- ]
-
- def test_exception_context(self): """
- import operator
- def f():
- try:
- raise ValueError
- except ValueError:
- yield from map(operator.truediv, [2, 3], [4, 0])
- gen = f()
- assert next(gen) == 0.5
- try:
- next(gen)
- except ZeroDivisionError as e:
- assert e.__context__ is not None
- assert isinstance(e.__context__, ValueError)
- else:
- assert False, "should have raised"
- """
-
-
-class AppTestGeneratorStop:
-
- def test_past_generator_stop(self):
- # how it works without 'from __future__' import generator_stop
- def f(x):
- raise StopIteration
- yield x
- with raises(StopIteration):
- next(f(5))
-
- def test_future_generator_stop(self):
- d = {}
- exec("""from __future__ import generator_stop
+def test_future_generator_stop():
+ d = {}
+ exec("""from __future__ import generator_stop
def f(x):
raise StopIteration
yield x
""", d)
- f = d['f']
- with raises(RuntimeError):
- next(f(5))
+ f = d['f']
+ with raises(RuntimeError):
+ next(f(5))
- def test_generator_stop_cause(self):
- d = {}
- exec("""from __future__ import generator_stop
+def test_generator_stop_cause():
+ d = {}
+ exec("""from __future__ import generator_stop
def gen1():
yield 42
""", d)
- my_gen = d['gen1']()
- assert next(my_gen) == 42
- stop_exc = StopIteration('spam')
- with raises(RuntimeError) as e:
- my_gen.throw(StopIteration, stop_exc, None)
- assert e.value.__cause__ is stop_exc
- assert e.value.__context__ is stop_exc
+ my_gen = d['gen1']()
+ assert next(my_gen) == 42
+ stop_exc = StopIteration('spam')
+ with raises(RuntimeError) as e:
+ my_gen.throw(StopIteration, stop_exc, None)
+ assert e.value.__cause__ is stop_exc
+ assert e.value.__context__ is stop_exc
- def test_return_tuple(self):
- d = {}
- exec("def gen1(): return (yield 1)", d)
+def test_return_tuple():
+ def gen1():
+ return (yield 1)
+ gen = gen1()
+ assert next(gen) == 1
+ with raises(StopIteration) as excinfo:
+ gen.send((2,))
+ assert excinfo.value.value == (2,)
- gen = d['gen1']()
- assert next(gen) == 1
- with raises(StopIteration) as excinfo:
- gen.send((2,))
- assert excinfo.value.value == (2,)
-
- def test_return_stopiteration(self):
- d = {}
- exec("def gen1(): return (yield 1)", d)
-
- gen = d['gen1']()
- assert next(gen) == 1
- with raises(StopIteration) as excinfo:
- gen.send(StopIteration(2))
- assert isinstance(excinfo.value, StopIteration)
- assert excinfo.value.value.value == 2
+def test_return_stopiteration():
+ def gen1():
+ return (yield 1)
+ gen = gen1()
+ assert next(gen) == 1
+ with raises(StopIteration) as excinfo:
+ gen.send(StopIteration(2))
+ assert isinstance(excinfo.value, StopIteration)
+ assert excinfo.value.value.value == 2
diff --git a/pypy/interpreter/test/test_generator.py b/pypy/interpreter/test/test_generator.py
--- a/pypy/interpreter/test/test_generator.py
+++ b/pypy/interpreter/test/test_generator.py
@@ -1,572 +1,3 @@
-class AppTestGenerator:
-
- def test_generator(self):
- def f():
- yield 1
- assert next(f()) == 1
-
- def test_generator2(self):
- def f():
- yield 1
- g = f()
- assert next(g) == 1
- with raises(StopIteration):
- next(g)
-
- def test_attributes(self):
- def f():
- yield 1
- assert g.gi_running
- g = f()
- assert g.gi_code is f.__code__
- assert g.__name__ == 'f'
- assert g.gi_frame is not None
- assert not g.gi_running
- next(g)
- assert not g.gi_running
- with raises(StopIteration):
- next(g)
- assert not g.gi_running
- assert g.gi_frame is None
- assert g.gi_code is f.__code__
- assert g.__name__ == 'f'
-
- def test_generator3(self):
- def f():
- yield 1
- g = f()
- assert list(g) == [1]
-
- def test_generator4(self):
- def f():
- yield 1
- g = f()
- assert [x for x in g] == [1]
-
- def test_generator5(self):
- d = {}
- exec("""if 1:
- def f():
- v = (yield )
- yield v
- g = f()
- next(g)
- """, d, d)
- g = d['g']
- assert g.send(42) == 42
-
- def test_throw1(self):
- def f():
- yield 2
- g = f()
- # two arguments version
- with raises(NameError):
- g.throw(NameError, "Error")
-
- def test_throw2(self):
- def f():
- yield 2
- g = f()
- # single argument version
- with raises(NameError):
- g.throw(NameError("Error"))
-
- def test_throw3(self):
- def f():
- try:
- yield 1
- yield 2
- except:
- yield 3
- g = f()
- assert next(g) == 1
- assert g.throw(NameError("Error")) == 3
- with raises(StopIteration):
- next(g)
-
- def test_throw4(self):
- d = {}
- exec("""if 1:
- def f():
- try:
- yield 1
- v = (yield 2)
- except:
- yield 3
- g = f()
- """, d, d)
- g = d['g']
- assert next(g) == 1
- assert next(g) == 2
- assert g.throw(NameError("Error")) == 3
- with raises(StopIteration):
- next(g)
-
- def test_throw5(self):
- def f():
- try:
- yield 1
- except:
- x = 3
- try:
- yield x
- except:
- pass
- g = f()
- next(g)
- # String exceptions are not allowed anymore
- with raises(TypeError):
- g.throw("Error")
- assert g.throw(Exception) == 3
- with raises(StopIteration):
- g.throw(Exception)
-
- def test_throw6(self):
- def f():
- yield 2
- g = f()
- with raises(NameError):
- g.throw(NameError, "Error", None)
-
-
- def test_throw_fail(self):
- def f():
- yield 1
- g = f()
- with raises(TypeError):
- g.throw(NameError("Error"), "error")
-
- def test_throw_fail2(self):
- def f():
- yield 1
- g = f()
- with raises(TypeError):
- g.throw(list())
-
- def test_throw_fail3(self):
- def f():
- yield 1
- g = f()
- with raises(TypeError):
- g.throw(NameError("Error"), None, "not tb object")
-
- def test_throw_finishes_generator(self):
- def f():
- yield 1
- g = f()
- assert g.gi_frame is not None
- with raises(ValueError):
- g.throw(ValueError)
- assert g.gi_frame is None
-
- def test_throw_bug(self):
- def f():
- try:
- x.throw(IndexError) # => "generator already executing"
- except ValueError:
- yield 1
- x = f()
- res = list(x)
- assert res == [1]
-
- def test_throw_on_finished_generator(self):
- def f():
- yield 1
- g = f()
- res = next(g)
- assert res == 1
- with raises(StopIteration):
- next(g)
- with raises(NameError):
- g.throw(NameError)
-
- def test_throw_tb(self):
- def f():
- try:
- yield
- except:
- raise
- g = f()
- try:
- 1/0
- except ZeroDivisionError as v:
- try:
- g.throw(v)
- except Exception as w:
- tb = w.__traceback__
- levels = 0
- while tb:
- levels += 1
- tb = tb.tb_next
- assert levels == 3
-
- def test_throw_context(self):
- # gen.throw(exc) must not modify exc.__context__
- def gen():
- try:
- yield
- except:
- raise ValueError
-
- try:
- raise KeyError
- except KeyError:
- g = gen()
- next(g)
- exc1 = Exception(1)
- exc2 = Exception(2)
- exc2.__context__ = exc1
- try:
- g.throw(exc2)
- except ValueError:
- assert exc2.__context__ is exc1
-
- def test_close(self):
- def f():
- yield 1
- g = f()
- assert g.close() is None
-
- def test_close2(self):
- def f():
- try:
- yield 1
- except GeneratorExit:
- raise StopIteration
- g = f()
- next(g)
- assert g.close() is None
-
- def test_close3(self):
- def f():
- try:
- yield 1
- except GeneratorExit:
- raise NameError
- g = f()
- next(g)
- with raises(NameError):
- g.close()
-
- def test_close_fail(self):
- def f():
- try:
- yield 1
- except GeneratorExit:
- yield 2
- g = f()
- next(g)
- with raises(RuntimeError):
- g.close()
-
More information about the pypy-commit
mailing list