-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtest_placeholder.py
145 lines (106 loc) · 3.6 KB
/
test_placeholder.py
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
import pytest
import sidekick.api as sk
from sidekick.api import placeholder as _, fn, record, lazy, M, F, X, Y
from sidekick.functions.fn_placeholders import simplify_ast, Cte, Expr
from types import SimpleNamespace
func = lambda x: x.__inner_function__
class TestPlaceholder:
def test_basic_properties(self):
assert str(+(_.method(42 + _))) == "(+_.method(42 + _))"
def test_with_math_operators(self):
inc = fn(_ + 1)
assert inc(1) == 2
assert inc(2) == 3
half = fn(_ / 2)
assert half(2) == 1.0
assert half(4) == 2.0
inv = fn(1 / _)
assert inv(2) == 0.5
assert inv(0.5) == 2.0
expr = fn(+(2 * _) + 1)
assert expr(0) == 1.0
assert expr(1) == 3.0
def test_multiple_args(self):
double = fn(_ + _)
assert double(2) == 4
poly = fn(_ ** 2 + 2 * _ + 1)
assert poly(0) == 1
assert poly(1) == 4
def test_attr_access(self):
imag = fn(_.imag)
assert imag(1) == 0
assert imag(1j) == 1
def test_method_call(self):
bit = fn(_.bit_length())
assert bit(2) == 2
assert bit(42) == 6
def test_function_application(self):
f = fn(F(abs, _))
assert f(-1) == 1
f = fn(F(dict, [], foo=_))
assert f("bar") == {"foo": "bar"}
f = fn(F[dict]([], foo=_))
assert f("bar") == {"foo": "bar"}
def test_nested_attribute_access(self):
x = record(foo=record(bar=42))
assert fn(_.foo.bar == 42)(x) is True
assert fn(_.foo.bar == 40)(x) is False
assert fn(_.foo.bar.bit_length())(x) == 6
def test_nested_algebraic_expresions(self):
f = fn(_.real + _.imag)
assert f(42) == 42
assert f(21 + 21j) == 42
f = fn(_.real / (_.real + _.imag))
assert f(42) == 1.0
assert f(21 + 21j) == 0.5
f = fn(_.real / (_.real * _.real))
assert f(2) == 0.5
assert f(2 + 2j) == 0.5
f = fn(-_)
assert f(2) == -2
f = fn(-(2 * _))
assert f(2) == -4
f = fn((2 * _).imag)
assert f(2) == 0
class TestPlaceholderCompiler:
def test_compiler_simplifications(self):
assert simplify_ast(Expr(Cte(42)).imag._ast) == Cte(0)
class TestThisPlaceholder:
@pytest.fixture(scope="class")
def cls(self):
class Cls:
sum = lazy(_.x + _.y)
def __init__(self, x, y):
self.x, self.y = x, y
return Cls
@pytest.fixture
def instance(self, cls):
return cls(1, 2)
def test_this_descriptor_works(self, instance):
assert instance.sum == 3
# noinspection PyPep8Naming
class TestInstantPlaceholders:
def test_repr(self):
assert repr(X) == "X"
assert repr(Y) == "Y"
def test_expressions_with_X(self):
assert (X - 1)(1) == 0
def test_expressions_with_Y(self):
assert (X - Y)(1, 2) == -1
assert (Y - X)(1, 2) == +1
assert (Y - 1)(1, 2) == +1
assert (1 - Y)(1, 2) == -1
assert (Y + Y)(1, 2) == +4
def test_XY_are_identity_functions(self, arg=42):
assert X(arg) == arg
assert Y(..., arg) == arg
assert sk.to_callable(X)(arg) == arg
assert sk.to_callable(Y)(None, arg) == arg
def test_XY_getattr(self, value=42):
arg = SimpleNamespace(attr=value)
assert X.attr(arg) == value
assert Y.attr(..., arg) == value
def test_method_caller(self, value=42):
arg = SimpleNamespace(method=lambda: value)
assert M.method()(arg) == value
assert M(1)(X + 1) == 2