1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
# mode: run
# tag: pure3.8
# These are extra tests for the assignment expression/walrus operator/named expression that cover things
# additional to the standard Python test-suite in tests/run/test_named_expressions.pyx
import cython
import sys
@cython.test_assert_path_exists("//PythonCapiCallNode")
def optimized(x):
"""
x*2 is optimized to a PythonCapiCallNode. The test fails unless the CloneNode is kept up-to-date
(in the event that the optimization changes and test_assert_path_exists fails, the thing to do
is to find another case that's similarly optimized - the test isn't specifically interested in
multiplication)
>>> optimized(5)
10
"""
return (x:=x*2)
# FIXME: currently broken; GH-4146
# Changing x in the assignment expression should not affect the value used on the right-hand side
#def order(x):
# """
# >>> order(5)
# 15
# """
# return x+(x:=x*2)
@cython.test_fail_if_path_exists("//CloneNode")
def optimize_literals1():
"""
There's a small optimization for literals to avoid creating unnecessary temps
>>> optimize_literals1()
10
"""
x = 5
return (x := 10)
@cython.test_fail_if_path_exists("//CloneNode")
def optimize_literals2():
"""
There's a small optimization for literals to avoid creating unnecessary temps
Test is in __doc__ (for Py2 string formatting reasons)
"""
x = 5
return (x := u"a string")
@cython.test_fail_if_path_exists("//CloneNode")
def optimize_literals3():
"""
There's a small optimization for literals to avoid creating unnecessary temps
Test is in __doc__ (for Py2 string formatting reasons)
"""
x = 5
return (x := b"a bytes")
@cython.test_fail_if_path_exists("//CloneNode")
def optimize_literals4():
"""
There's a small optimization for literals to avoid creating unnecessary temps
Test is in __doc__ (for Py2 string formatting reasons)
"""
x = 5
return (x := (u"tuple", 1, 1.0, b"stuff"))
if sys.version_info[0] != 2:
__doc__ = """
>>> optimize_literals2()
'a string'
>>> optimize_literals3()
b'a bytes'
>>> optimize_literals4()
('tuple', 1, 1.0, b'stuff')
"""
else:
__doc__ = """
>>> optimize_literals2()
u'a string'
>>> optimize_literals3()
'a bytes'
>>> optimize_literals4()
(u'tuple', 1, 1.0, 'stuff')
"""
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode//AssignmentExpressionNode")
def avoid_extra_coercion(x : cython.double):
"""
The assignment expression and x are both coerced to PyObject - this should happen only once
rather than to both separately
>>> avoid_extra_coercion(5.)
5.0
"""
y : object = "I'm an object"
return (y := x)
async def async_func():
"""
DW doesn't understand async functions well enough to make it a runtime test, but it was causing
a compile-time failure at one point
"""
if variable := 1:
pass
y_global = 6
class InLambdaInClass:
"""
>>> InLambdaInClass.x1
12
>>> InLambdaInClass.x2
[12, 12]
"""
x1 = (lambda y_global: (y_global := y_global + 1) + y_global)(2) + y_global
x2 = [(lambda y_global: (y_global := y_global + 1) + y_global)(2) + y_global for _ in range(2) ]
def in_lambda_in_list_comprehension1():
"""
>>> in_lambda_in_list_comprehension1()
[[0, 2, 4, 6], [0, 2, 4, 6], [0, 2, 4, 6], [0, 2, 4, 6], [0, 2, 4, 6]]
"""
return [ (lambda x: [(x := y) + x for y in range(4)])(x) for x in range(5) ]
def in_lambda_in_list_comprehension2():
"""
>>> in_lambda_in_list_comprehension2()
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7]]
"""
return [ (lambda z: [(x := y) + z for y in range(4)])(x) for x in range(5) ]
def in_lambda_in_generator_expression1():
"""
>>> in_lambda_in_generator_expression1()
[(0, 2, 4, 6), (0, 2, 4, 6), (0, 2, 4, 6), (0, 2, 4, 6), (0, 2, 4, 6)]
"""
return [ (lambda x: tuple((x := y) + x for y in range(4)))(x) for x in range(5) ]
def in_lambda_in_generator_expression2():
"""
>>> in_lambda_in_generator_expression2()
[(0, 1, 2, 3), (1, 2, 3, 4), (2, 3, 4, 5), (3, 4, 5, 6), (4, 5, 6, 7)]
"""
return [ (lambda z: tuple((x := y) + z for y in range(4)))(x) for x in range(5) ]
|