OILS / opy / byterun / test_functions.py View on Github | oilshell.org

393 lines, 99 significant
1#!/usr/bin/env python2
2from __future__ import print_function
3"""Test functions etc, for Byterun."""
4
5import unittest
6
7import six
8
9import vmtest
10
11PY3 = six.PY3
12
13
14class TestFunctions(vmtest.VmTestCase):
15 def test_functions(self):
16 self.assert_ok("""\
17 def fn(a, b=17, c="Hello", d=[]):
18 d.append(99)
19 print(a, b, c, d)
20 fn(1)
21 fn(2, 3)
22 fn(3, c="Bye")
23 fn(4, d=["What?"])
24 fn(5, "b", "c")
25 """)
26
27 def test_recursion(self):
28 self.assert_ok("""\
29 def fact(n):
30 if n <= 1:
31 return 1
32 else:
33 return n * fact(n-1)
34 f6 = fact(6)
35 print(f6)
36 assert f6 == 720
37 """)
38
39 def test_nested_names(self):
40 self.assert_ok("""\
41 def one():
42 x = 1
43 def two():
44 x = 2
45 print(x)
46 two()
47 print(x)
48 one()
49 """)
50
51 def test_calling_functions_with_args_kwargs(self):
52 self.assert_ok("""\
53 def fn(a, b=17, c="Hello", d=[]):
54 d.append(99)
55 print(a, b, c, d)
56 fn(6, *[77, 88])
57 fn(**{'c': 23, 'a': 7})
58 fn(6, *[77], **{'c': 23, 'd': [123]})
59 """)
60
61 def test_defining_functions_with_args_kwargs(self):
62 self.assert_ok("""\
63 def fn(*args):
64 print("args is %r" % (args,))
65 fn(1, 2)
66 """)
67 self.assert_ok("""\
68 def fn(**kwargs):
69 print("kwargs is %r" % (kwargs,))
70 fn(red=True, blue=False)
71 """)
72 self.assert_ok("""\
73 def fn(*args, **kwargs):
74 print("args is %r" % (args,))
75 print("kwargs is %r" % (kwargs,))
76 fn(1, 2, red=True, blue=False)
77 """)
78 self.assert_ok("""\
79 def fn(x, y, *args, **kwargs):
80 print("x is %r, y is %r" % (x, y))
81 print("args is %r" % (args,))
82 print("kwargs is %r" % (kwargs,))
83 fn('a', 'b', 1, 2, red=True, blue=False)
84 """)
85
86 def test_defining_functions_with_empty_args_kwargs(self):
87 self.assert_ok("""\
88 def fn(*args):
89 print("args is %r" % (args,))
90 fn()
91 """)
92 self.assert_ok("""\
93 def fn(**kwargs):
94 print("kwargs is %r" % (kwargs,))
95 fn()
96 """)
97 self.assert_ok("""\
98 def fn(*args, **kwargs):
99 print("args is %r, kwargs is %r" % (args, kwargs))
100 fn()
101 """)
102
103 def test_partial(self):
104 self.assert_ok("""\
105 from _functools import partial
106
107 def f(a,b):
108 return a-b
109
110 f7 = partial(f, 7)
111 four = f7(3)
112 assert four == 4
113 """)
114
115 def test_partial_with_kwargs(self):
116 self.assert_ok("""\
117 from _functools import partial
118
119 def f(a,b,c=0,d=0):
120 return (a,b,c,d)
121
122 f7 = partial(f, b=7, c=1)
123 them = f7(10)
124 assert them == (10,7,1,0)
125 """)
126
127 def test_wraps(self):
128 self.assert_ok("""\
129 from functools import wraps
130 def my_decorator(f):
131 dec = wraps(f)
132 def wrapper(*args, **kwds):
133 print('Calling decorated function')
134 return f(*args, **kwds)
135 wrapper = dec(wrapper)
136 return wrapper
137
138 @my_decorator
139 def example():
140 '''Docstring'''
141 return 17
142
143 assert example() == 17
144 """)
145
146
147class TestClosures(vmtest.VmTestCase):
148 def test_closures(self):
149 self.assert_ok("""\
150 def make_adder(x):
151 def add(y):
152 return x+y
153 return add
154 a = make_adder(10)
155 print(a(7))
156 assert a(7) == 17
157 """)
158
159 def test_closures_store_deref(self):
160 self.assert_ok("""\
161 def make_adder(x):
162 z = x+1
163 def add(y):
164 return x+y+z
165 return add
166 a = make_adder(10)
167 print(a(7))
168 assert a(7) == 28
169 """)
170
171 def test_closures_in_loop(self):
172 self.assert_ok("""\
173 def make_fns(x):
174 fns = []
175 for i in range(x):
176 fns.append(lambda i=i: i)
177 return fns
178 fns = make_fns(3)
179 for f in fns:
180 print(f())
181 assert (fns[0](), fns[1](), fns[2]()) == (0, 1, 2)
182 """)
183
184 def test_closures_with_defaults(self):
185 self.assert_ok("""\
186 def make_adder(x, y=13, z=43):
187 def add(q, r=11):
188 return x+y+z+q+r
189 return add
190 a = make_adder(10, 17)
191 print(a(7))
192 assert a(7) == 88
193 """)
194
195 def test_deep_closures(self):
196 self.assert_ok("""\
197 def f1(a):
198 b = 2*a
199 def f2(c):
200 d = 2*c
201 def f3(e):
202 f = 2*e
203 def f4(g):
204 h = 2*g
205 return a+b+c+d+e+f+g+h
206 return f4
207 return f3
208 return f2
209 answer = f1(3)(4)(5)(6)
210 print(answer)
211 assert answer == 54
212 """)
213
214
215class TestGenerators(vmtest.VmTestCase):
216 def test_first(self):
217 self.assert_ok("""\
218 def two():
219 yield 1
220 yield 2
221 for i in two():
222 print(i)
223 """)
224
225 def test_partial_generator(self):
226 self.assert_ok("""\
227 from _functools import partial
228
229 def f(a,b):
230 num = a+b
231 while num:
232 yield num
233 num -= 1
234
235 f2 = partial(f, 2)
236 three = f2(1)
237 assert list(three) == [3,2,1]
238 """)
239
240 def test_yield_multiple_values(self):
241 self.assert_ok("""\
242 def triples():
243 yield 1, 2, 3
244 yield 4, 5, 6
245
246 for a, b, c in triples():
247 print(a, b, c)
248 """)
249
250 def test_simple_generator(self):
251 self.assert_ok("""\
252 g = (x for x in [0,1,2])
253 print(list(g))
254 """)
255
256 def test_generator_from_generator(self):
257 self.assert_ok("""\
258 g = (x*x for x in range(5))
259 h = (y+1 for y in g)
260 print(list(h))
261 """)
262
263 def test_generator_from_generator2(self):
264 self.assert_ok("""\
265 class Thing(object):
266 RESOURCES = ('abc', 'def')
267 def get_abc(self):
268 return "ABC"
269 def get_def(self):
270 return "DEF"
271 def resource_info(self):
272 for name in self.RESOURCES:
273 get_name = 'get_' + name
274 yield name, getattr(self, get_name)
275
276 def boom(self):
277 #d = list((name, get()) for name, get in self.resource_info())
278 d = [(name, get()) for name, get in self.resource_info()]
279 return d
280
281 print(Thing().boom())
282 """)
283
284 if PY3: # PY3.3+ only
285 def test_yield_from(self):
286 self.assert_ok("""\
287 def main():
288 x = outer()
289 next(x)
290 y = x.send("Hello, World")
291 print(y)
292
293 def outer():
294 yield from inner()
295
296 def inner():
297 y = yield
298 yield y
299
300 main()
301 """)
302
303 def test_yield_from_tuple(self):
304 self.assert_ok("""\
305 def main():
306 for x in outer():
307 print(x)
308
309 def outer():
310 yield from (1, 2, 3, 4)
311
312 main()
313 """)
314
315 def test_distinguish_iterators_and_generators(self):
316 self.assert_ok("""\
317 class Foo(object):
318 def __iter__(self):
319 return FooIter()
320
321 class FooIter(object):
322 def __init__(self):
323 self.state = 0
324
325 def __next__(self):
326 if self.state >= 10:
327 raise StopIteration
328 self.state += 1
329 return self.state
330
331 def send(self, n):
332 print("sending")
333
334 def outer():
335 yield from Foo()
336
337 for x in outer():
338 print(x)
339 """)
340
341 def test_nested_yield_from(self):
342 self.assert_ok("""\
343 def main():
344 x = outer()
345 next(x)
346 y = x.send("Hello, World")
347 print(y)
348
349 def outer():
350 yield from middle()
351
352 def middle():
353 yield from inner()
354
355 def inner():
356 y = yield
357 yield y
358
359 main()
360 """)
361
362 def test_return_from_generator(self):
363 self.assert_ok("""\
364 def gen():
365 yield 1
366 return 2
367
368 x = gen()
369 while True:
370 try:
371 print(next(x))
372 except StopIteration as e:
373 print(e.value)
374 break
375 """)
376
377 def test_return_from_generator_with_yield_from(self):
378 self.assert_ok("""\
379 def returner():
380 if False:
381 yield
382 return 1
383
384 def main():
385 y = yield from returner()
386 print(y)
387
388 list(main())
389 """)
390
391
392if __name__ == '__main__':
393 unittest.main()