summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2012-01-13 11:43:40 (GMT)
committerNick Coghlan <ncoghlan@gmail.com>2012-01-13 11:43:40 (GMT)
commit1f7ce62bd61488d5d721896a36a1b43befab88b5 (patch)
treee7c92d4429ce431c78d0b7816c93862629590223 /Lib
parente51757f6de9db71b7ee0a6cbf7dde62e9f146804 (diff)
downloadcpython-1f7ce62bd61488d5d721896a36a1b43befab88b5.zip
cpython-1f7ce62bd61488d5d721896a36a1b43befab88b5.tar.gz
cpython-1f7ce62bd61488d5d721896a36a1b43befab88b5.tar.bz2
Implement PEP 380 - 'yield from' (closes #11682)
Diffstat (limited to 'Lib')
-rw-r--r--Lib/opcode.py1
-rw-r--r--Lib/test/test_ast.py3
-rw-r--r--Lib/test/test_generators.py42
-rw-r--r--Lib/test/test_grammar.py32
-rw-r--r--Lib/test/test_parser.py5
-rw-r--r--Lib/test/test_sys.py2
6 files changed, 40 insertions, 45 deletions
diff --git a/Lib/opcode.py b/Lib/opcode.py
index b631b25..6fe20c7 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -87,6 +87,7 @@ def_op('STORE_LOCALS', 69)
def_op('PRINT_EXPR', 70)
def_op('LOAD_BUILD_CLASS', 71)
+def_op('YIELD_FROM', 72)
def_op('INPLACE_LSHIFT', 75)
def_op('INPLACE_RSHIFT', 76)
diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py
index b1656bc..2022ee2 100644
--- a/Lib/test/test_ast.py
+++ b/Lib/test/test_ast.py
@@ -813,7 +813,8 @@ class ASTValidatorTests(unittest.TestCase):
self._check_comprehension(factory)
def test_yield(self):
- self.expr(ast.Yield(ast.Name("x", ast.Store())), "must have Load")
+ self.expr(ast.Yield(0, ast.Name("x", ast.Store())), "must have Load")
+ self.expr(ast.Yield(1, ast.Name("x", ast.Store())), "must have Load")
def test_compare(self):
left = ast.Name("x", ast.Load())
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index 5f47b3e..06f67c2 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -728,29 +728,6 @@ Ye olde Fibonacci generator, tee style.
syntax_tests = """
->>> def f():
-... return 22
-... yield 1
-Traceback (most recent call last):
- ..
-SyntaxError: 'return' with argument inside generator
-
->>> def f():
-... yield 1
-... return 22
-Traceback (most recent call last):
- ..
-SyntaxError: 'return' with argument inside generator
-
-"return None" is not the same as "return" in a generator:
-
->>> def f():
-... yield 1
-... return None
-Traceback (most recent call last):
- ..
-SyntaxError: 'return' with argument inside generator
-
These are fine:
>>> def f():
@@ -866,20 +843,6 @@ These are fine:
>>> type(f())
<class 'generator'>
-
->>> def f():
-... if 0:
-... lambda x: x # shouldn't trigger here
-... return # or here
-... def f(i):
-... return 2*i # or here
-... if 0:
-... return 3 # but *this* sucks (line 8)
-... if 0:
-... yield 2 # because it's a generator (line 10)
-Traceback (most recent call last):
-SyntaxError: 'return' with argument inside generator
-
This one caused a crash (see SF bug 567538):
>>> def f():
@@ -1566,11 +1529,6 @@ Traceback (most recent call last):
...
SyntaxError: 'yield' outside function
->>> def f(): return lambda x=(yield): 1
-Traceback (most recent call last):
- ...
-SyntaxError: 'return' with argument inside generator
-
>>> def f(): x = yield = y
Traceback (most recent call last):
...
diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py
index eff763e..6b326bd 100644
--- a/Lib/test/test_grammar.py
+++ b/Lib/test/test_grammar.py
@@ -458,7 +458,39 @@ class GrammarTests(unittest.TestCase):
check_syntax_error(self, "class foo:return 1")
def test_yield(self):
+ # Allowed as standalone statement
+ def g(): yield 1
+ def g(): yield from ()
+ # Allowed as RHS of assignment
+ def g(): x = yield 1
+ def g(): x = yield from ()
+ # Ordinary yield accepts implicit tuples
+ def g(): yield 1, 1
+ def g(): x = yield 1, 1
+ # 'yield from' does not
+ check_syntax_error(self, "def g(): yield from (), 1")
+ check_syntax_error(self, "def g(): x = yield from (), 1")
+ # Requires parentheses as subexpression
+ def g(): 1, (yield 1)
+ def g(): 1, (yield from ())
+ check_syntax_error(self, "def g(): 1, yield 1")
+ check_syntax_error(self, "def g(): 1, yield from ()")
+ # Requires parentheses as call argument
+ def g(): f((yield 1))
+ def g(): f((yield 1), 1)
+ def g(): f((yield from ()))
+ def g(): f((yield from ()), 1)
+ check_syntax_error(self, "def g(): f(yield 1)")
+ check_syntax_error(self, "def g(): f(yield 1, 1)")
+ check_syntax_error(self, "def g(): f(yield from ())")
+ check_syntax_error(self, "def g(): f(yield from (), 1)")
+ # Not allowed at top level
+ check_syntax_error(self, "yield")
+ check_syntax_error(self, "yield from")
+ # Not allowed at class scope
check_syntax_error(self, "class foo:yield 1")
+ check_syntax_error(self, "class foo:yield from ()")
+
def test_raise(self):
# 'raise' test [',' test]
diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py
index 2b50fca..b6f81fb 100644
--- a/Lib/test/test_parser.py
+++ b/Lib/test/test_parser.py
@@ -50,6 +50,10 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase):
self.check_suite("def f(): (yield 1)*2")
self.check_suite("def f(): return; yield 1")
self.check_suite("def f(): yield 1; return")
+ self.check_suite("def f(): yield from 1")
+ self.check_suite("def f(): x = yield from 1")
+ self.check_suite("def f(): f((yield from 1))")
+ self.check_suite("def f(): yield 1; return 1")
self.check_suite("def f():\n"
" for x in range(30):\n"
" yield x\n")
@@ -621,7 +625,6 @@ class OtherParserCase(unittest.TestCase):
with self.assertRaises(TypeError):
parser.expr("a", "b")
-
def test_main():
support.run_unittest(
RoundtripLegalSyntaxTestCase,
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index f89514f..6dc0e42 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -727,7 +727,7 @@ class SizeofTest(unittest.TestCase):
nfrees = len(x.f_code.co_freevars)
extras = x.f_code.co_stacksize + x.f_code.co_nlocals +\
ncells + nfrees - 1
- check(x, size(vh + '12P3i' + CO_MAXBLOCKS*'3i' + 'P' + extras*'P'))
+ check(x, size(vh + '13P3i' + CO_MAXBLOCKS*'3i' + 'P' + extras*'P'))
# function
def func(): pass
check(func, size(h + '12P'))