Coverage for tests/test_func.py: 80%
107 statements
« prev ^ index » next coverage.py v7.6.7, created at 2024-11-22 15:39 -0800
« prev ^ index » next coverage.py v7.6.7, created at 2024-11-22 15:39 -0800
1from inspect import signature
3import pytest
5import appl
6from appl import as_func, need_ctx, partial, ppl, records
8GLOBAL_V = 123
11def test_docstring():
12 @ppl
13 def func():
14 "This is a docstring"
16 assert func.__doc__ == "This is a docstring"
19def test_signature():
20 @ppl
21 def add(x: int, y: int) -> int:
22 return x + y
24 def add2(x: int, y: int, *, config=None) -> int:
25 # config (langsmith_extra) is added by langsmith @traceable
26 return x + y
28 new_sig = signature(add)
29 assert new_sig == signature(add.__wrapped__) or new_sig == signature(add2)
32def test_functionality():
33 @ppl
34 def add(x: int, y: int) -> int:
35 return x + y
37 assert add(1, 2) == 3
40def test_decorator():
41 def extra(func):
42 @need_ctx
43 def inner(*args, **kwargs):
44 return func(*args, **kwargs) + 1
46 return inner
48 @extra
49 @ppl
50 def add(x: int, y: int) -> int:
51 return x + y
53 assert add(1, 2) == 4
56def test_classmethod():
57 class A:
58 @classmethod
59 @ppl(ctx="same")
60 def addon(cls):
61 "addon"
63 @classmethod
64 @ppl
65 def func(cls):
66 "start"
67 cls.addon()
68 return records()
70 assert str(A.func()) == "start\naddon"
73def test_super_in_class():
74 class A:
75 def func(self):
76 return 1
78 class B(A):
79 @ppl
80 def func(self):
81 return super(B, self).func()
83 # NOTE: super() is not supported in ppl decorator
84 # TODO: fix by filling the class name and self in the function during compiling.
85 assert B().func() == 1
88def test_nested_ppl_error():
89 with pytest.raises(SyntaxError) as excinfo:
91 @ppl
92 def func():
93 "Hello"
95 @ppl # nested ppl decorator is not supported yet.
96 def func2():
97 "World"
99 func2()
100 return records()
102 assert "Nested ppl decorator is not" in str(excinfo.value)
105def test_function_inside_ppl():
106 @ppl
107 def f1():
108 "Hello"
110 def f2():
111 "World"
113 f2()
114 return records()
116 assert str(f1()) == "Hello\nWorld"
118 @ppl
119 def f3():
120 "Hello"
122 def f4():
123 "World"
125 return records()
127 assert str(f3()) == "Hello"
130def test_closure():
131 a = 1
133 @ppl
134 def func():
135 return a
137 assert func() == a
138 a = 2
139 assert func() == a
140 f = as_func(func)
141 assert f() == a
143 b = 1
145 def f2():
146 @ppl
147 def f3():
148 return b
150 return f3()
152 assert f2() == b
155def test_wrapper():
156 a = 2
158 def wrapper():
159 a = 1
161 @ppl
162 def func(b):
163 f"{a}+{b}={a+b}"
164 return records()
166 return as_func(func) # use as_func to inject the locals of wrapper (a=1)
168 # if not use as_func, the caller's locals will be used, which is from test_wrapper's locals (a=2)
169 func = wrapper()
170 assert str(func(2)) == "1+2=3"
173def test_global():
174 @ppl
175 def func():
176 return GLOBAL_V
178 assert func() == GLOBAL_V