summaryrefslogtreecommitdiff
path: root/tests/run/extra_walrus.py
blob: 151a48ed5c5e5da2d11e9cc91e918b7b1a2af5c5 (plain)
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) ]