-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathtest_autoret.py
More file actions
130 lines (115 loc) · 4.64 KB
/
test_autoret.py
File metadata and controls
130 lines (115 loc) · 4.64 KB
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
# -*- coding: utf-8 -*-
"""Implicit return statements."""
from ...syntax import macros, test, test_raises # noqa: F401
from ...test.fixtures import session, testset
from ...syntax import macros, autoreturn # noqa: F401, F811
from ...env import env
def runtests():
# - in a function body, any expression "expr" in tail position
# (along any code path) is transformed to "return expr".
# - if/elif/else, try/except/else/finally and "with" blocks are supported.
# - a loop (for/else, while) in tail position is considered to always return None.
# - if you need a loop in tail position to have a return value,
# use an explicit return, or the constructs from unpythonic.fploop.
# - any explicit return statements are left alone, so "return" can be used normally.
with testset("basic usage"):
with autoreturn:
def f():
"I'll just return this"
test[f() == "I'll just return this"]
def f2():
return "I'll just return this" # explicit return, not transformed
test[f2() == "I'll just return this"]
with testset("if, elif, else"):
with autoreturn:
def g(x):
if x == 1:
"one"
elif x == 2:
"two"
else:
"something else"
test[g(1) == "one"]
test[g(2) == "two"]
test[g(42) == "something else"]
with testset("except, else"):
with autoreturn:
def h(x):
try:
if x == 1:
raise ValueError("h doesn't like the number 'one'")
except ValueError:
"error" # there's a tail position in each "except" clause
else: # if an "else" clause is present in a try, the tail position of the main path is there
2 * x
test[h(10) == 20]
test[h(1) == "error"]
with testset("except, body of the try"):
with autoreturn:
def h2(x):
try:
if x == 1:
raise ValueError("h doesn't like the number 'one'")
x # no else clause, the tail position of the main path is in the "try"
except ValueError:
"error" # also in this case there's a tail position in each "except" clause
test[h2(10) == 10]
test[h2(1) == "error"]
with testset("with block"):
with autoreturn:
def ctx():
with env(x="hi") as e: # just need some context manager for testing, doesn't matter which
e.x # tail position in a with block
test[ctx() == "hi"]
with testset("function definition"): # v0.15.0+
with autoreturn:
def outer():
def inner():
"inner function"
test[callable(outer())] # returned a function
test[outer()() == "inner function"]
with testset("class definition"): # v0.15.0+
with autoreturn:
def classdefiner():
class InnerClassDefinition:
pass
test[isinstance(classdefiner(), type)] # returned a class
test[classdefiner().__name__ == "InnerClassDefinition"]
with testset("match/case"): # Python 3.10+
with autoreturn:
def classify(x):
match x:
case 1:
"one"
case 2:
"two"
case _:
"other"
test[classify(1) == "one"]
test[classify(2) == "two"]
test[classify(42) == "other"]
def classify_nested(x):
match x:
case (a, b):
a + b
case [a, b, *rest]:
a + b + sum(rest)
case _:
0
test[classify_nested((3, 4)) == 7]
test[classify_nested([1, 2, 3, 4]) == 10]
test[classify_nested("nope") == 0]
def classify_with_guard(x):
match x:
case n if n < 0:
"negative"
case 0:
"zero"
case n if n > 0:
"positive"
test[classify_with_guard(-5) == "negative"]
test[classify_with_guard(0) == "zero"]
test[classify_with_guard(7) == "positive"]
if __name__ == '__main__': # pragma: no cover
with session(__file__):
runtests()