1# cython: always_allow_keywords=True
2# mode: run
3# tag: posonly, pure3.8
4
5import cython
6import sys
7import pickle
8
9def test_optional_posonly_args1(a, b=10, /, c=100):
10    """
11    >>> test_optional_posonly_args1(1, 2, 3)
12    6
13    >>> test_optional_posonly_args1(1, 2, c=3)
14    6
15    >>> test_optional_posonly_args1(1, b=2, c=3)  # doctest: +ELLIPSIS
16    Traceback (most recent call last):
17    TypeError: test_optional_posonly_args1() got ... keyword argument... 'b'
18    >>> test_optional_posonly_args1(1, 2)
19    103
20    >>> test_optional_posonly_args1(1, b=2)  # doctest: +ELLIPSIS
21    Traceback (most recent call last):
22    TypeError: test_optional_posonly_args1() got ... keyword argument... 'b'
23    """
24    return a + b + c
25
26def test_optional_posonly_args2(a=1, b=10, /, c=100):
27    """
28    >>> test_optional_posonly_args2(1, 2, 3)
29    6
30    >>> test_optional_posonly_args2(1, 2, c=3)
31    6
32    >>> test_optional_posonly_args2(1, b=2, c=3)  # doctest: +ELLIPSIS
33    Traceback (most recent call last):
34    TypeError: test_optional_posonly_args2() got ... keyword argument... 'b'
35    >>> test_optional_posonly_args2(1, 2)
36    103
37    >>> test_optional_posonly_args2(1, b=2)  # doctest: +ELLIPSIS
38    Traceback (most recent call last):
39    TypeError: test_optional_posonly_args2() got ... keyword argument... 'b'
40    >>> test_optional_posonly_args2(1, c=2)
41    13
42    """
43    return a + b + c
44
45# TODO: this causes a line that is too long for old versions of Clang
46#def many_args(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,
47#              a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32,a33,a34,a35,a36,a37,a38,a39,a40,
48#              a41,a42,a43,a44,a45,a46,a47,a48,a49,a50,a51,a52,a53,a54,a55,a56,a57,a58,a59,
49#              a60,a61,a62,a63,a64,a65,a66,a67,a68,a69,a70,a71,a72,a73,a74,a75,a76,a77,a78,
50#              a79,a80,a81,a82,a83,a84,a85,a86,a87,a88,a89,a90,a91,a92,a93,a94,a95,a96,a97,
51#              a98,a99,a100,a101,a102,a103,a104,a105,a106,a107,a108,a109,a110,a111,a112,
52#              a113,a114,a115,a116,a117,a118,a119,a120,a121,a122,a123,a124,a125,a126,a127,
53#              a128,a129,a130,a131,a132,a133,a134,a135,a136,a137,a138,a139,a140,a141,a142,
54#              a143,a144,a145,a146,a147,a148,a149,a150,a151,a152,a153,a154,a155,a156,a157,
55#              a158,a159,a160,a161,a162,a163,a164,a165,a166,a167,a168,a169,a170,a171,a172,
56#              a173,a174,a175,a176,a177,a178,a179,a180,a181,a182,a183,a184,a185,a186,a187,
57#              a188,a189,a190,a191,a192,a193,a194,a195,a196,a197,a198,a199,a200,a201,a202,
58#              a203,a204,a205,a206,a207,a208,a209,a210,a211,a212,a213,a214,a215,a216,a217,
59#              a218,a219,a220,a221,a222,a223,a224,a225,a226,a227,a228,a229,a230,a231,a232,
60#              a233,a234,a235,a236,a237,a238,a239,a240,a241,a242,a243,a244,a245,a246,a247,
61#              a248,a249,a250,a251,a252,a253,a254,a255,a256,a257,a258,a259,a260,a261,a262,
62#              a263,a264,a265,a266,a267,a268,a269,a270,a271,a272,a273,a274,a275,a276,a277,
63#              a278,a279,a280,a281,a282,a283,a284,a285,a286,a287,a288,a289,a290,a291,a292,
64#              a293,a294,a295,a296,a297,a298,a299,/,b,c=42,*,d):
65#    """
66#    >>> many_args(*range(299),b=1,c=2,d=3)
67#    (298, 1, 2, 3)
68#    >>> many_args(*range(299),b=1,d=3)
69#    (298, 1, 42, 3)
70#    >>> many_args(*range(300),d=3)
71#    (298, 299, 42, 3)
72#    """
73#    return (a299, b, c, d)
74
75#TODO: update this test for Python 3.8 final
76@cython.binding(True)
77def func_introspection1(a, b, c, /, d, e=1, *, f, g=2):
78    """
79    >>> if sys.version_info[0] < 3:
80    ...     assert func_introspection2.__code__.co_argcount == 7, func_introspection2.__code__.co_argcount
81    ... else:
82    ...     assert func_introspection2.__code__.co_argcount == 5, func_introspection2.__code__.co_argcount
83    >>> func_introspection1.__defaults__
84    (1,)
85    """
86
87@cython.binding(True)
88def func_introspection2(a, b, c=1, /, d=2, e=3, *, f, g=4):
89    """
90    >>> if sys.version_info[0] < 3:
91    ...     assert func_introspection2.__code__.co_argcount == 7, func_introspection2.__code__.co_argcount
92    ... else:
93    ...     assert func_introspection2.__code__.co_argcount == 5, func_introspection2.__code__.co_argcount
94    >>> func_introspection2.__defaults__
95    (1, 2, 3)
96    """
97
98def test_pos_only_call_via_unpacking(a, b, /):
99    """
100    >>> test_pos_only_call_via_unpacking(*[1,2])
101    3
102    """
103    return a + b
104
105def test_use_positional_as_keyword1(a, /):
106    """
107    >>> test_use_positional_as_keyword1(1)
108    >>> test_use_positional_as_keyword1(a=1)  # doctest: +ELLIPSIS
109    Traceback (most recent call last):
110    TypeError: test_use_positional_as_keyword1() ... keyword arguments...
111    """
112
113def test_use_positional_as_keyword2(a, /, b):
114    """
115    >>> test_use_positional_as_keyword2(1, 2)
116    >>> test_use_positional_as_keyword2(1, b=2)
117    >>> test_use_positional_as_keyword2(a=1, b=2)  # doctest: +ELLIPSIS
118    Traceback (most recent call last):
119    TypeError: test_use_positional_as_keyword2() ... positional...arguments...
120    """
121
122def test_use_positional_as_keyword3(a, b, /):
123    """
124    >>> test_use_positional_as_keyword3(1, 2)
125    >>> test_use_positional_as_keyword3(a=1, b=2) # doctest:+ELLIPSIS
126    Traceback (most recent call last):
127    TypeError: test_use_positional_as_keyword3() got ... keyword argument...
128    """
129
130def test_positional_only_and_arg_invalid_calls(a, b, /, c):
131    """
132    >>> test_positional_only_and_arg_invalid_calls(1, 2, 3)
133    >>> test_positional_only_and_arg_invalid_calls(1, 2, c=3)
134    >>> test_positional_only_and_arg_invalid_calls(1, 2)  # doctest: +ELLIPSIS
135    Traceback (most recent call last):
136    TypeError: test_positional_only_and_arg_invalid_calls() ... positional argument...
137    >>> test_positional_only_and_arg_invalid_calls(1)  # doctest: +ELLIPSIS
138    Traceback (most recent call last):
139    TypeError: test_positional_only_and_arg_invalid_calls() ... positional arguments...
140    >>> test_positional_only_and_arg_invalid_calls(1,2,3,4)  # doctest: +ELLIPSIS
141    Traceback (most recent call last):
142    TypeError: test_positional_only_and_arg_invalid_calls() takes ... positional arguments ...4 ...given...
143    """
144
145def test_positional_only_and_optional_arg_invalid_calls(a, b, /, c=3):
146    """
147    >>> test_positional_only_and_optional_arg_invalid_calls(1, 2)
148    >>> test_positional_only_and_optional_arg_invalid_calls(1)  # doctest: +ELLIPSIS
149    Traceback (most recent call last):
150    TypeError: test_positional_only_and_optional_arg_invalid_calls() ... positional argument...
151    >>> test_positional_only_and_optional_arg_invalid_calls()  # doctest: +ELLIPSIS
152    Traceback (most recent call last):
153    TypeError: test_positional_only_and_optional_arg_invalid_calls() ... positional arguments...
154    >>> test_positional_only_and_optional_arg_invalid_calls(1, 2, 3, 4)  # doctest: +ELLIPSIS
155    Traceback (most recent call last):
156    TypeError: test_positional_only_and_optional_arg_invalid_calls() takes ... positional arguments ...4 ...given...
157    """
158
159def test_positional_only_and_kwonlyargs_invalid_calls(a, b, /, c, *, d, e):
160    """
161    >>> test_positional_only_and_kwonlyargs_invalid_calls(1, 2, 3, d=1, e=2)
162    >>> test_positional_only_and_kwonlyargs_invalid_calls(1, 2, 3, e=2)  # doctest: +ELLIPSIS
163    Traceback (most recent call last):
164    TypeError: test_positional_only_and_kwonlyargs_invalid_calls() ... keyword-only argument...d...
165    >>> test_positional_only_and_kwonlyargs_invalid_calls(1, 2, 3)  # doctest: +ELLIPSIS
166    Traceback (most recent call last):
167    TypeError: test_positional_only_and_kwonlyargs_invalid_calls() ... keyword-only argument...d...
168    >>> test_positional_only_and_kwonlyargs_invalid_calls(1, 2)  # doctest: +ELLIPSIS
169    Traceback (most recent call last):
170    TypeError: test_positional_only_and_kwonlyargs_invalid_calls() ... positional argument...
171    >>> test_positional_only_and_kwonlyargs_invalid_calls(1)  # doctest: +ELLIPSIS
172    Traceback (most recent call last):
173    TypeError: test_positional_only_and_kwonlyargs_invalid_calls() ... positional arguments...
174    >>> test_positional_only_and_kwonlyargs_invalid_calls()  # doctest: +ELLIPSIS
175    Traceback (most recent call last):
176    TypeError: test_positional_only_and_kwonlyargs_invalid_calls() ... positional arguments...
177    >>> test_positional_only_and_kwonlyargs_invalid_calls(1, 2, 3, 4, 5, 6, d=7, e=8)  # doctest: +ELLIPSIS
178    Traceback (most recent call last):
179    TypeError: test_positional_only_and_kwonlyargs_invalid_calls() takes ... positional arguments ...
180    >>> test_positional_only_and_kwonlyargs_invalid_calls(1, 2, 3, d=1, e=4, f=56)  # doctest: +ELLIPSIS
181    Traceback (most recent call last):
182    TypeError: test_positional_only_and_kwonlyargs_invalid_calls() got an unexpected keyword argument 'f'
183    """
184
185def test_positional_only_invalid_calls(a, b, /):
186    """
187    >>> test_positional_only_invalid_calls(1, 2)
188    >>> test_positional_only_invalid_calls(1)  # doctest: +ELLIPSIS
189    Traceback (most recent call last):
190    TypeError: test_positional_only_invalid_calls() ... positional argument...
191    >>> test_positional_only_invalid_calls()  # doctest: +ELLIPSIS
192    Traceback (most recent call last):
193    TypeError: test_positional_only_invalid_calls() ... positional arguments...
194    >>> test_positional_only_invalid_calls(1, 2, 3)  # doctest: +ELLIPSIS
195    Traceback (most recent call last):
196    TypeError: test_positional_only_invalid_calls() takes ... positional arguments ...3 ...given...
197    """
198
199def test_positional_only_with_optional_invalid_calls(a, b=2, /):
200    """
201    >>> test_positional_only_with_optional_invalid_calls(1)
202    >>> test_positional_only_with_optional_invalid_calls()  # doctest: +ELLIPSIS
203    Traceback (most recent call last):
204    TypeError: test_positional_only_with_optional_invalid_calls() ... positional argument...
205    >>> test_positional_only_with_optional_invalid_calls(1, 2, 3)  # doctest: +ELLIPSIS
206    Traceback (most recent call last):
207    TypeError: test_positional_only_with_optional_invalid_calls() takes ... positional arguments ...3 ...given...
208    """
209
210def test_no_standard_args_usage(a, b, /, *, c):
211    """
212    >>> test_no_standard_args_usage(1, 2, c=3)
213    >>> test_no_standard_args_usage(1, b=2, c=3)  # doctest: +ELLIPSIS
214    Traceback (most recent call last):
215    TypeError: test_no_standard_args_usage() ... positional... arguments...
216    """
217
218#def test_change_default_pos_only():
219# TODO: probably remove this, since  __defaults__ is not writable in Cython?
220#    """
221#    >>> test_change_default_pos_only()
222#    True
223#    True
224#    """
225#    def f(a, b=2, /, c=3):
226#        return a + b + c
227#
228#    print((2,3) == f.__defaults__)
229#    f.__defaults__ = (1, 2, 3)
230#    print(f(1, 2, 3) == 6)
231
232def test_lambdas():
233    """
234    >>> test_lambdas()
235    3
236    3
237    3
238    3
239    3
240    """
241    x = lambda a, /, b: a + b
242    print(x(1,2))
243    print(x(1,b=2))
244
245    x = lambda a, /, b=2: a + b
246    print(x(1))
247
248    x = lambda a, b, /: a + b
249    print(x(1, 2))
250
251    x = lambda a, b, /, : a + b
252    print(x(1, 2))
253
254class TestPosonlyMethods(object):
255    """
256    >>> TestPosonlyMethods().f(1,2)
257    (1, 2)
258    >>> TestPosonlyMethods.f(TestPosonlyMethods(), 1, 2)
259    (1, 2)
260    >>> try:
261    ...     TestPosonlyMethods.f(1,2)
262    ... except TypeError:
263    ...    print("Got type error")
264    Got type error
265    >>> TestPosonlyMethods().f(1, b=2)  # doctest: +ELLIPSIS
266    Traceback (most recent call last):
267    TypeError: ...f() got ... keyword argument... 'b'
268    """
269    def f(self, a, b, /):
270        return a, b
271
272class TestMangling(object):
273    """
274    >>> TestMangling().f()
275    42
276    >>> TestMangling().f2()
277    42
278
279    #>>> TestMangling().f3()
280    #(42, 43)
281    #>>> TestMangling().f4()
282    #(42, 43, 44)
283
284    >>> TestMangling().f2(1)
285    1
286
287    #>>> TestMangling().f3(1, _TestMangling__b=2)
288    #(1, 2)
289    #>>> TestMangling().f4(1, _TestMangling__b=2, _TestMangling__c=3)
290    #(1, 2, 3)
291    """
292    def f(self, *, __a=42):
293        return __a
294
295    def f2(self, __a=42, /):
296        return __a
297
298# FIXME: https://github.com/cython/cython/issues/1382
299#    def f3(self, __a=42, /, __b=43):
300#        return (__a, __b)
301
302#    def f4(self, __a=42, /, __b=43, *, __c=44):
303#        return (__a, __b, __c)
304
305def test_module_function(a, b, /):
306    """
307    >>> test_module_function(1, 2)
308    >>> test_module_function()  # doctest: +ELLIPSIS
309    Traceback (most recent call last):
310    TypeError: test_module_function() ... positional arguments...
311    """
312
313def test_closures1(x,y):
314    """
315    >>> test_closures1(1,2)(3,4)
316    10
317    >>> test_closures1(1,2)(3)  # doctest: +ELLIPSIS
318    Traceback (most recent call last):
319    TypeError: ...g() ... positional argument...
320    >>> test_closures1(1,2)(3,4,5)  # doctest: +ELLIPSIS
321    Traceback (most recent call last):
322    TypeError: ...g() ... positional argument...
323    """
324    def g(x2, /, y2):
325        return x + y + x2 + y2
326    return g
327
328def test_closures2(x, /, y):
329    """
330    >>> test_closures2(1,2)(3,4)
331    10
332    """
333    def g(x2,y2):
334        return x + y + x2 + y2
335    return g
336
337
338def test_closures3(x, /, y):
339    """
340    >>> test_closures3(1,2)(3,4)
341    10
342    >>> test_closures3(1,2)(3)  # doctest: +ELLIPSIS
343    Traceback (most recent call last):
344    TypeError: ...g() ... positional argument...
345    >>> test_closures3(1,2)(3,4,5)  # doctest: +ELLIPSIS
346    Traceback (most recent call last):
347    TypeError: ...g() ... positional argument...
348    """
349    def g(x2, /, y2):
350        return x + y + x2 + y2
351    return g
352
353
354def test_same_keyword_as_positional_with_kwargs(something, /, **kwargs):
355    """
356    >>> test_same_keyword_as_positional_with_kwargs(42, something=42)
357    (42, {'something': 42})
358    >>> test_same_keyword_as_positional_with_kwargs(something=42)  # doctest: +ELLIPSIS
359    Traceback (most recent call last):
360    TypeError: test_same_keyword_as_positional_with_kwargs() ... positional argument...
361    >>> test_same_keyword_as_positional_with_kwargs(42)
362    (42, {})
363    """
364    return (something, kwargs)
365
366def test_serialization1(a, b, /):
367    """
368    >>> pickled_posonly = pickle.dumps(test_serialization1)
369    >>> unpickled_posonly = pickle.loads(pickled_posonly)
370    >>> unpickled_posonly(1, 2)
371    (1, 2)
372    >>> unpickled_posonly(a=1, b=2)  # doctest: +ELLIPSIS
373    Traceback (most recent call last):
374    TypeError: test_serialization1() got ... keyword argument...
375    """
376    return (a, b)
377
378def test_serialization2(a, /, b):
379    """
380    >>> pickled_optional = pickle.dumps(test_serialization2)
381    >>> unpickled_optional = pickle.loads(pickled_optional)
382    >>> unpickled_optional(1, 2)
383    (1, 2)
384    >>> unpickled_optional(a=1, b=2)  # doctest: +ELLIPSIS
385    Traceback (most recent call last):
386    TypeError: test_serialization2() ... positional... arguments...
387    """
388    return (a, b)
389
390def test_serialization3(a=1, /, b=2):
391    """
392    >>> pickled_defaults = pickle.dumps(test_serialization3)
393    >>> unpickled_defaults = pickle.loads(pickled_defaults)
394    >>> unpickled_defaults(1, 2)
395    (1, 2)
396    >>> unpickled_defaults(a=1, b=2)  # doctest: +ELLIPSIS
397    Traceback (most recent call last):
398    TypeError: test_serialization3() got ... keyword argument... 'a'
399    """
400    return (a, b)
401
402
403async def test_async(a=1, /, b=2):
404    """
405    >>> test_async(a=1, b=2)  # doctest: +ELLIPSIS
406    Traceback (most recent call last):
407    TypeError: test_async() got ... keyword argument... 'a'
408    """
409    return a, b
410
411
412def test_async_call(*args, **kwargs):
413    """
414    >>> test_async_call(1, 2)
415    >>> test_async_call(1, b=2)
416    >>> test_async_call(1)
417    >>> test_async_call()
418    """
419    if sys.version_info < (3, 6):
420        return
421    try:
422        coro = test_async(*args, **kwargs)
423        coro.send(None)
424    except StopIteration as e:
425        result = e.value
426    assert result == (1, 2), result
427
428
429def test_generator(a=1, /, b=2):
430    """
431    >>> test_generator(a=1, b=2)  # doctest: +ELLIPSIS
432    Traceback (most recent call last):
433    TypeError: test_generator() got ... keyword argument... 'a'
434    >>> gen = test_generator(1, 2)
435    >>> next(gen)
436    (1, 2)
437    >>> gen = test_generator(1, b=2)
438    >>> next(gen)
439    (1, 2)
440    >>> gen = test_generator(1)
441    >>> next(gen)
442    (1, 2)
443    >>> gen = test_generator()
444    >>> next(gen)
445    (1, 2)
446    """
447    yield a, b
448
449def f_call_1_0_0(a,/):
450    """
451    >>> f_call_1_0_0(1)
452    (1,)
453    """
454    return (a,)
455
456def f_call_1_1_0(a, /, b):
457    """
458    >>> f_call_1_1_0(1,2)
459    (1, 2)
460    """
461    return (a,b)
462
463def f_call_1_1_1(a, /, b, *, c):
464    """
465    >>> f_call_1_1_1(1,2,c=3)
466    (1, 2, 3)
467    """
468    return (a,b,c)
469
470def f_call_1_1_1_star(a, /, b, *args, c):
471    """
472    >>> f_call_1_1_1_star(1,2,c=3)
473    (1, 2, (), 3)
474    >>> f_call_1_1_1_star(1,2,3,4,5,6,7,8,c=9)
475    (1, 2, (3, 4, 5, 6, 7, 8), 9)
476    """
477    return (a,b,args,c)
478
479def f_call_1_1_1_kwds(a, /, b, *, c, **kwds):
480    """
481    >>> f_call_1_1_1_kwds(1,2,c=3)
482    (1, 2, 3, {})
483    >>> f_call_1_1_1_kwds(1,2,c=3,d=4,e=5) == (1, 2, 3, {'d': 4, 'e': 5})
484    True
485    """
486    return (a,b,c,kwds)
487
488def f_call_1_1_1_star_kwds(a, /, b, *args, c, **kwds):
489    """
490    >>> f_call_1_1_1_star_kwds(1,2,c=3,d=4,e=5) == (1, 2, (), 3, {'d': 4, 'e': 5})
491    True
492    >>> f_call_1_1_1_star_kwds(1,2,3,4,c=5,d=6,e=7) == (1, 2, (3, 4), 5, {'d': 6, 'e': 7})
493    True
494    """
495    return (a,b,args,c,kwds)
496
497def f_call_one_optional_kwd(a, /, *, b=2):
498    """
499    >>> f_call_one_optional_kwd(1)
500    (1, 2)
501    >>> f_call_one_optional_kwd(1, b=3)
502    (1, 3)
503    """
504    return (a,b)
505
506def f_call_posonly_stararg(a, /, *args):
507    """
508    >>> f_call_posonly_stararg(1)
509    (1, ())
510    >>> f_call_posonly_stararg(1, 2, 3, 4)
511    (1, (2, 3, 4))
512    """
513    return (a,args)
514
515def f_call_posonly_kwarg(a, /, **kw):
516    """
517    >>> f_call_posonly_kwarg(1)
518    (1, {})
519    >>> all_args = f_call_posonly_kwarg(1, b=2, c=3, d=4)
520    >>> all_args == (1, {'b': 2, 'c': 3, 'd': 4}) or all_args
521    True
522    """
523    return (a,kw)
524
525def f_call_posonly_stararg_kwarg(a, /, *args, **kw):
526    """
527    >>> f_call_posonly_stararg_kwarg(1)
528    (1, (), {})
529    >>> f_call_posonly_stararg_kwarg(1, 2)
530    (1, (2,), {})
531    >>> all_args = f_call_posonly_stararg_kwarg(1, b=3, c=4)
532    >>> all_args == (1, (), {'b': 3, 'c': 4}) or all_args
533    True
534    >>> all_args = f_call_posonly_stararg_kwarg(1, 2, b=3, c=4)
535    >>> all_args == (1, (2,), {'b': 3, 'c': 4}) or all_args
536    True
537    """
538    return (a,args,kw)
539
540def test_empty_kwargs(a, b, /):
541    """
542    >>> test_empty_kwargs(1, 2)
543    (1, 2)
544    >>> test_empty_kwargs(1, 2, **{})
545    (1, 2)
546    >>> test_empty_kwargs(1, 2, **{'c': 3})
547    Traceback (most recent call last):
548    TypeError: test_empty_kwargs() got an unexpected keyword argument 'c'
549    """
550    return (a,b)
551
552
553@cython.cclass
554class TestExtensionClass:
555    """
556    >>> t = TestExtensionClass()
557    >>> t.f(1,2)
558    (1, 2, 3)
559    >>> t.f(1,2,4)
560    (1, 2, 4)
561    >>> t.f(1, 2, c=4)
562    (1, 2, 4)
563    >>> t.f(1, 2, 5, c=6)  # doctest: +ELLIPSIS
564    Traceback (most recent call last):
565    TypeError: ...f() got multiple values for ...argument 'c'
566    """
567    def f(self, a, b, /, c=3):
568        return (a,b,c)
569