Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/python-wasm
Path: blob/main/python/pylang/test/starargs.py
1396 views
1
# vim:fileencoding=utf-8
2
# globals: assrt
3
4
eq = assrt.equal
5
de = assrt.deepEqual
6
7
def get(obj, name):
8
return obj[name] if obj else undefined
9
10
# Test the parsing of function definitions {{{
11
12
def basic_test(code, arglen, starargs, kwargs, defaults):
13
func = PyLang.parse('def func(' + code + '): pass\n', {'filename':code}).body[0]
14
eq(func.argnames.length, arglen)
15
eq(get(func.argnames.starargs, 'name'), starargs)
16
eq(get(func.argnames.kwargs, 'name'), kwargs)
17
eq(func.argnames.is_simple_func, bool(not starargs and not kwargs and not defaults))
18
if defaults:
19
fd = {}
20
for key in Object.keys(func.argnames.defaults):
21
fd[key] = func.argnames.defaults[key].value
22
de(fd, defaults)
23
return func
24
25
def throw_test(code):
26
assrt.throws(def():
27
PyLang.parse('def func(' + code + '): pass\n', {'filename':code}).body[0]
28
, PyLang.SyntaxError)
29
30
basic_test('a, b, c', 3)
31
basic_test('*args', 0, 'args')
32
basic_test('a, b, *args', 2, 'args')
33
throw_test('*args, a')
34
throw_test('*args, *a')
35
basic_test('**kwargs', 0, undefined, 'kwargs')
36
basic_test('*args, **kwargs', 0, 'args', 'kwargs')
37
basic_test('a, b, *args, **kwargs', 2, 'args', 'kwargs')
38
throw_test('**kw, *a')
39
throw_test('**kw, **a')
40
basic_test('a=1, b="2"', 2, None, None, {'a':1, 'b':"2"})
41
basic_test('x, a=1, b="2", *args, **kw', 3, 'args', 'kw', {'a':1, 'b':"2"})
42
throw_test('a=1, b')
43
throw_test('**k, a=1')
44
throw_test('a, a')
45
throw_test('a, a=1')
46
throw_test('*a, **a')
47
# }}}
48
49
# Test parsing of function calls {{{
50
51
def parse_call_test(code, arglen, opts):
52
func = PyLang.parse('f(' + code + ')', {'filename':code}).body[0].body
53
opts = opts or {}
54
eq(func.args.length, arglen, 'Incorrect len for: ' + code)
55
if (opts.starargs != undefined):
56
si = [[i, x.name] for i, x in enumerate(func.args) if x.is_array]
57
de(opts.starargs, si, 'starargs wrong for: ' + code + ': ' + si + ' != ' + opts.starargs)
58
if (opts.kwargs != undefined):
59
de(opts.kwargs, [x[0].name for x in func.args.kwargs])
60
61
62
parse_call_test('a, b, c', 3)
63
parse_call_test('*args', 1, {'starargs':[[0, 'args']]})
64
parse_call_test('a, b, *args', 3, {'starargs':[[2, 'args']]})
65
parse_call_test('a, *args, b, *a2', 4, {'starargs':[[1, 'args'], [3, 'a2']]})
66
parse_call_test('a=1', 0, {'kwargs':['a']})
67
parse_call_test('a=1, b', 1, {'kwargs':['a']})
68
parse_call_test('a=1, b, **kwargs, *args, **k2', 2, {'kwargs':['a'], 'kw':['kwargs', 'k2'], 'starargs':[[1,'args']]})
69
# }}}
70
71
# Test calling {{{
72
73
def f():
74
return Array.prototype.slice.call(arguments)
75
76
77
de(f(1, 2, 3), [1, 2, 3])
78
args1, args2 = [4, 5, 6], [7, 8, 9]
79
kw1, kw2 = {'a':4, 'b':5, 'c':6}, {'a':7, 'x':8, 'y':9}
80
81
de(f(*args1), [4, 5, 6])
82
de(f(1, *args1), [1, 4, 5, 6])
83
de(f(*args1, 2), [4, 5, 6, 2])
84
de(f(1, *args1, 2), [1, 4, 5, 6, 2])
85
de(f(*args1, *args2), args1.concat(args2))
86
de(f(*args1, 1, 2, *args2, 3), [4, 5, 6, 1, 2, 7, 8, 9, 3])
87
88
de(f(1, a=2), [1, {'a':2}])
89
de(f(1, a=2, 3), [1, 3, {'a':2}])
90
de(f(**kw1), [kw1])
91
de(f(1, a=2, 3, **kw1), [1, 3, {'a':2, 'b':5, 'c':6}])
92
de(f(**kw2, 1, 3, **kw1, 2), [1, 3, 2, {'a':4, 'b':5, 'c':6, 'x':8, 'y':9}])
93
94
# }}}
95
96
# Test calling with definitions {{{
97
98
def f1(a, b, c):
99
return a, b, c
100
de(f1(1, 2, 3), [1, 2, 3])
101
de(f1(), [undefined, undefined, undefined])
102
103
def f2(a, b=1):
104
return a, b
105
106
de(f2(), [undefined, 1])
107
de(f2(1), [1, 1])
108
de(f2(1, 2), [1, 2])
109
de(f2(b=2), [undefined, 2])
110
de(f2(1, b=2), [1, 2])
111
de(f2({'b':3}), [{'b':3}, 1], 'a normal object is being treated as an options object')
112
113
def f3(*args):
114
return args
115
116
de(f3(), [])
117
de(f3(1, 2), [1, 2])
118
119
def f4(**kwargs):
120
return kwargs
121
122
de(f4(), {})
123
de(f4(a=1, b=2), {'a':1, 'b':2})
124
125
def f5(*args, **kwargs):
126
return [args, kwargs]
127
128
de(f5(), [[], {}])
129
de(f5(1, 2, a=1, b=2), [[1,2], {'a':1, 'b':2}])
130
131
def f6(a, *args):
132
return [a, args]
133
134
de(f6(), [undefined, []])
135
de(f6(1), [1, []])
136
de(f6(1, 2, 3), [1, [2, 3]])
137
138
def f7(a=1, **kw):
139
return [a, kw]
140
141
de(f7(), [1, {}])
142
de(f7(a=3, b=4), [3, {'b':4}])
143
144
def f8(a, b=2, *args, **kwargs):
145
return [a, b, args, kwargs]
146
147
de(f8(), [undefined, 2, [], {}])
148
de(f8(1), [1, 2, [], {}])
149
de(f8(1, 3, 4, 5, b=8, c=9), [1, 8, [4, 5], {'c':9}])
150
151
def f9(*args, **kwargs):
152
return [args, kwargs]
153
154
de(f9(), [[], {}])
155
de(f9(1, 2, a=1, b=2), [[1,2], {'a':1, 'b':2}])
156
157
def f10(a, b=2, c=3):
158
return [a, b, c]
159
160
de(f10(1, c=6), [1, 2, 6])
161
162
def f11(a, b, x=1):
163
return [a, b, x]
164
165
de(f11(x=3), [undefined, undefined, 3])
166
# }}}
167
168
acc = []
169
def mutable_defaults(a=acc):
170
a.append(1)
171
172
mutable_defaults(), mutable_defaults()
173
de([1, 1], acc)
174
175
def identity(f):
176
return def():
177
return f()
178
179
@identity
180
def wrapped(x=1):
181
return x
182
183
eq(wrapped(), 1)
184
185
class W:
186
@identity
187
def wrapped(self, x=1):
188
return x
189
eq(W().wrapped(), 1)
190
eq(1, (def(x=1): return x;)())
191
192
class Simple:
193
194
def __init__(self, a, b):
195
self.q = [a, b]
196
de(Simple(b=2, a=1).q, [1, 2])
197
198
class Other:
199
def func(self, **kw):
200
if self:
201
return kw
202
203
class Test:
204
205
def __init__(self, a, b=2, *args, **kwargs):
206
self.q = [a, b, args, kwargs]
207
self.other = Other()
208
209
def forwarded(self, **kw):
210
return self.other.func(**kw)
211
212
def simple(self, a, b):
213
return [a, b]
214
215
de(Test().q, [undefined, 2, [], {}])
216
de(Test(a=1).q, [1, 2, [], {}])
217
de(Test(1, 3, 4, 5, b=8, c=9).q, [1, 8, [4, 5], {'c':9}])
218
args = [1, 2]
219
de(Test(*args).q, [1, 2, [], {}])
220
t = Test()
221
de(t.simple(b=2, a=1), [1, 2])
222
223
@options_object
224
def callback(a, b=1, c=2):
225
return [a, b, c]
226
227
de(callback(0, {'c':4}), [0, 1, 4])
228
229
def afunc(a=1):
230
return a
231
232
def a2func(*args):
233
return args[0]
234
235
eq(afunc(None), None)
236
eq(a2func(None), None)
237
de(Test().forwarded(a=1), {'a':1})
238
239
def norm(a, b):
240
return [a, b]
241
242
de(norm(b=2, a=1), [1, 2])
243
244
call_counter = 0
245
246
def cc():
247
nonlocal call_counter
248
call_counter += 1
249
return def():
250
pass
251
252
cc()(a=1)
253
eq(call_counter, 1)
254
cc(o=1)(a=1)
255
eq(call_counter, 2)
256
call_counter = 0
257
258
def cc2():
259
nonlocal call_counter
260
call_counter += 1
261
return {'val':3, 'x':def():return this.val;}
262
eq(3, cc2().x(a=1))
263
eq(call_counter, 1)
264
call_counter = 0
265
266
def cc3():
267
nonlocal call_counter
268
call_counter += 1
269
this.num = call_counter
270
this.c = def():
271
return call_counter
272
eq(new cc3(a=1).num, 1)
273
eq(new cc3(a=1).c(b=9), 2)
274
275
class Pr:
276
def __init__(self, a=1):
277
self.a = a
278
279
def add(self, val=0):
280
self.a += val
281
282
class Pr2(Pr):
283
284
def __init__(self):
285
Pr.__init__(self, a=2)
286
287
def add(self):
288
Pr.add(self, val=1)
289
290
p = Pr(a=2)
291
p.add(val=3)
292
eq(p.a, 5)
293
p = Pr2()
294
p.add()
295
eq(p.a, 3)
296
p1, p2 = Pr(), Pr(a=1)
297
eq(p1.prototype, p2.prototype)
298
de(dir(p1), dir(p2))
299
300
class Prn:
301
302
def __init__(self, x):
303
self.x = x
304
305
class Prn1(Prn):
306
307
def __init__(self, x, *a):
308
Prn.__init__(self, [x, a])
309
310
class Prn2(Prn):
311
312
def __init__(self, *a):
313
Prn.__init__(self, a)
314
315
316
class Prn3(Prn):
317
318
def __init__(self, *a):
319
Prn.__init__(self, *a)
320
321
p = Prn1(1, 2, 3)
322
eq(p.x[0], 1)
323
de(p.x[1], [2, 3])
324
p = Prn2(1, 2)
325
de(p.x, [1, 2])
326
p = Prn3(1, 2)
327
eq(p.x, 1)
328
329
330
class Prnb:
331
332
def __init__(self, a, k):
333
self.a, self.k = a, k
334
335
class Prnb1(Prnb):
336
337
def __init__(self, *a, **kw):
338
Prnb.__init__(self, a, kw)
339
340
p = Prnb1(1, 2, x=1, y=2)
341
de(p.a, [1, 2])
342
de(p.k, {'x': 1, 'y':2})
343
344