cython

Форк
0
/
pep448_test_extcall.pyx 
571 строка · 11.9 Кб
1
# mode: run
2
# tag: pep448
3

4
from __future__ import print_function
5

6
__doc__ = """
7
>>> def f(*, w): pass
8
>>> try: errors_call_no_args(f)
9
... except TypeError: pass
10
... else: print("FAILED!")
11

12
>>> def f(*, a, b, c, d, e): pass
13
>>> try: errors_call_no_args(f)
14
... except TypeError: pass
15
... else: print("FAILED!")
16

17
>>> def f(*, kw, b): pass
18
>>> try: errors_call_3args_2kwargs(f)
19
... except TypeError: pass
20
... else: print("FAILED!")
21

22
>>> def f(a, b=2, *, kw): pass
23
>>> try: errors_call_3args_1kwarg(f)
24
... except TypeError: pass
25
... else: print("FAILED!")
26

27
>>> def f(*, kw): pass
28
>>> try: errors_call_1arg_1kwarg(f)
29
... except TypeError: pass
30
... else: print("FAILED!")
31
"""
32

33
# test for method/function calls. adapted from CPython's "test_extcall.py".
34

35
def sortdict(d):
36
    return '{%s}' % ', '.join(['%r: %r' % item for item in sorted(d.items())])
37

38
# We're going the use these types for extra testing
39

40
try:
41
    from collections import UserList, UserDict
42
except ImportError:
43
    from UserList import UserList
44
    from UserDict import UserDict
45

46

47
# We're defining four helper functions
48

49
def e(a,b):
50
    print(a, b)
51

52
def f(*a, **k):
53
    print(a, sortdict(k))
54

55
def g(x, *y, **z):
56
    print(x, y, sortdict(z))
57

58
def h(j=1, a=2, h=3):
59
    print(j, a, h)
60

61

62
# Argument list examples
63

64
def call_f_positional():
65
    """
66
    >>> call_f_positional()
67
    () {}
68
    (1,) {}
69
    (1, 2) {}
70
    (1, 2, 3) {}
71
    (1, 2, 3, 4, 5) {}
72
    (1, 2, 3, 4, 5) {}
73
    (1, 2, 3, 4, 5) {}
74
    (1, 2, 3, 4, 5) {}
75
    (1, 2, 3, 4, 5, 6, 7) {}
76
    (1, 2, 3, 4, 5, 6, 7) {}
77
    (1, 2, 3, 4, 5, 6, 7) {}
78
    (1, 2) {}
79
    """
80
    f()
81
    f(1)
82
    f(1, 2)
83
    f(1, 2, 3)
84
    f(1, 2, 3, *(4, 5))
85
    f(1, 2, 3, *[4, 5])
86
    f(*[1, 2, 3], 4, 5)
87
    f(1, 2, 3, *UserList([4, 5]))
88
    f(1, 2, 3, *[4, 5], *[6, 7])
89
    f(1, *[2, 3], 4, *[5, 6], 7)
90
    f(*UserList([1, 2]), *UserList([3, 4]), 5, *UserList([6, 7]))
91
    f(1, *[] or () and {}, *() and [], *{} or [] and (), *{} and [] or (), 2)
92

93

94
# Here we add keyword arguments
95

96
def call_f_kwargs():
97
    """
98
    >>> call_f_kwargs()
99
    (1, 2, 3) {'a': 4, 'b': 5}
100
    (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
101
    (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
102
    (1, 2, 3, 4, 5) {'a': 6, 'b': 7, 'c': 8}
103
    (1, 2, 3, 4, 5) {'a': 8, 'b': 9, 'x': 6, 'y': 7}
104
    (1, 2, 3) {'a': 4, 'b': 5}
105
    (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
106
    (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
107
    (1, 2, 3, 4, 5) {'a': 8, 'b': 9, 'x': 6, 'y': 7}
108
    (1, 2) {'a': 3}
109
    """
110

111
    f(1, 2, 3, **{'a':4, 'b':5})
112
    f(1, 2, 3, *[4, 5], **{'a':6, 'b':7})
113
    f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b': 9})
114
    f(1, 2, 3, *[4, 5], **{'c': 8}, **{'a':6, 'b':7})
115
    f(1, 2, 3, *(4, 5), x=6, y=7, **{'a':8, 'b': 9})
116

117
    f(1, 2, 3, **UserDict(a=4, b=5))
118
    f(1, 2, 3, *(4, 5), **UserDict(a=6, b=7))
119
    f(1, 2, 3, x=4, y=5, *(6, 7), **UserDict(a=8, b=9))
120
    f(1, 2, 3, *(4, 5), x=6, y=7, **UserDict(a=8, b=9))
121

122
    f(1, *[] or () and {}, *() and [], *{} or [] and (), *{} and [] or (), 2,
123
      **{} and {} or {}, **{} or {} and {}, **{} and {}, a=3)
124

125

126
# Examples with invalid arguments (TypeErrors). We're also testing the function
127
# names in the exception messages.
128
#
129
# Verify clearing of SF bug #733667
130

131
def errors_f1():
132
    """
133
    >>> errors_f1()  # doctest: +ELLIPSIS
134
    Traceback (most recent call last):
135
        ...
136
    TypeError: ...got multiple values for keyword argument 'a'
137
    """
138
    f(1, 2, **{'a': -1, 'b': 5}, **{'a': 4, 'c': 6})
139

140

141
def errors_f2():
142
    """
143
    >>> errors_f2()  # doctest: +ELLIPSIS
144
    Traceback (most recent call last):
145
        ...
146
    TypeError: ...multiple values for keyword argument 'a'
147
    """
148
    f(1, 2, **{'a': -1, 'b': 5}, a=4, c=6)
149

150

151
def errors_e1():
152
    """
153
    >>> try: errors_e1()
154
    ... except TypeError: pass
155
    ... else: print("FAILED!")
156
    """
157
    e(c=4)
158

159

160
def errors_e2():
161
    """
162
    >>> try: errors_e2()
163
    ... except TypeError: pass
164
    ... else: print("FAILED!")
165
    """
166
    e(a=1, b=2, c=4)
167

168

169
def errors_g1():
170
    """
171
    >>> errors_g1()
172
    Traceback (most recent call last):
173
      ...
174
    TypeError: g() takes at least 1 positional argument (0 given)
175

176
    # TypeError: g() missing 1 required positional argument: 'x'
177
    """
178
    g()
179

180

181
def errors_g2():
182
    """
183
    >>> errors_g2()
184
    Traceback (most recent call last):
185
      ...
186
    TypeError: g() takes at least 1 positional argument (0 given)
187

188
    # TypeError: g() missing 1 required positional argument: 'x'
189
    """
190
    g(*())
191

192

193
def errors_g3():
194
    """
195
    >>> errors_g3()
196
    Traceback (most recent call last):
197
      ...
198
    TypeError: g() takes at least 1 positional argument (0 given)
199

200
    # TypeError: g() missing 1 required positional argument: 'x'
201
    """
202
    g(*(), **{})
203

204

205
def call_g_positional():
206
    """
207
    >>> call_g_positional()
208
    1 () {}
209
    1 (2,) {}
210
    1 (2, 3) {}
211
    1 (2, 3, 4, 5) {}
212
    """
213
    g(1)
214
    g(1, 2)
215
    g(1, 2, 3)
216
    g(1, 2, 3, *(4, 5))
217

218

219

220
def call_nonseq_positional1():
221
    """
222
    >>> call_nonseq_positional1()  # doctest: +ELLIPSIS
223
    Traceback (most recent call last):
224
      ...
225
    TypeError: ...Nothing...
226

227
    # TypeError: g() argument after * must be a sequence, not Nothing
228
    """
229
    class Nothing(object): pass
230
    g(*Nothing())
231

232

233
def call_nonseq_positional2():
234
    """
235
    >>> call_nonseq_positional2()  # doctest: +ELLIPSIS
236
    Traceback (most recent call last):
237
      ...
238
    TypeError: ...Nothing...
239

240
    # TypeError: g() argument after * must be a sequence, not Nothing
241
    """
242
    class Nothing(object):
243
        def __len__(self): return 5
244
    g(*Nothing())
245

246

247
def call_seqlike_positional1():
248
    """
249
    >>> call_seqlike_positional1()
250
    0 (1, 2) {}
251
    """
252
    class Nothing(object):
253
        def __len__(self): return 5
254
        def __getitem__(self, i):
255
            if i<3: return i
256
            else: raise IndexError(i)
257

258
    g(*Nothing())
259

260

261
def call_seqlike_positional2():
262
    """
263
    >>> call_seqlike_positional2()
264
    0 (1, 2, 3) {}
265
    """
266
    class Nothing:
267
        def __init__(self): self.c = 0
268
        def __iter__(self): return self
269
        def __next__(self):
270
            if self.c == 4:
271
                raise StopIteration
272
            c = self.c
273
            self.c += 1
274
            return c
275
        next = __next__
276

277
    g(*Nothing())
278

279

280
# Make sure that the function doesn't stomp the dictionary
281

282
def call_kwargs_unmodified1():
283
    """
284
    >>> call_kwargs_unmodified1()
285
    1 () {'a': 1, 'b': 2, 'c': 3, 'd': 4}
286
    True
287
    """
288
    d = {'a': 1, 'b': 2, 'c': 3}
289
    d2 = d.copy()
290
    g(1, d=4, **d)
291
    return d == d2
292

293

294
# What about willful misconduct?
295

296
def call_kwargs_unmodified2():
297
    """
298
    >>> call_kwargs_unmodified2()
299
    {}
300
    """
301
    def saboteur(**kw):
302
        kw['x'] = 'm'
303
        return kw
304

305
    d = {}
306
    kw = saboteur(a=1, **d)
307
    return d
308

309

310
def errors_args_kwargs_overlap():
311
    """
312
    >>> errors_args_kwargs_overlap()  # doctest: +ELLIPSIS
313
    Traceback (most recent call last):
314
      ...
315
    TypeError: ...got multiple values for... argument 'x'
316
    """
317
    g(1, 2, 3, **{'x': 4, 'y': 5})
318

319

320
def errors_non_string_kwarg():
321
    """
322
    >>> errors_non_string_kwarg()  # doctest: +ELLIPSIS
323
    Traceback (most recent call last):
324
    TypeError: ...keywords must be strings...
325
    """
326
    f(**{1:2})
327

328

329
def errors_unexpected_kwarg():
330
    """
331
    >>> errors_unexpected_kwarg()
332
    Traceback (most recent call last):
333
      ...
334
    TypeError: h() got an unexpected keyword argument 'e'
335
    """
336
    h(**{'e': 2})
337

338

339
def errors_call_nonseq():
340
    """
341
    >>> try: errors_call_nonseq()
342
    ... except TypeError: pass
343
    ... else: print("FAILED!")
344
    """
345
    h(*h)
346

347

348
def errors_call_builtin_nonseq():
349
    """
350
    >>> try: errors_call_builtin_nonseq()
351
    ... except TypeError: pass
352
    ... else: print("FAILED!")
353
    """
354
    dir(*h)
355

356

357
def errors_call_none_nonseq():
358
    """
359
    >>> try: errors_call_none_nonseq()
360
    ... except TypeError: pass
361
    ... else: print("FAILED!")
362
    """
363
    None(*h)
364

365

366
def errors_call_nonmapping_kwargs():
367
    """
368
    >>> try: errors_call_nonmapping_kwargs()
369
    ... except TypeError: pass
370
    ... else: print("FAILED!")
371
    """
372
    h(**h)
373

374

375
def errors_call_builtin_nonmapping_kwargs():
376
    """
377
    >>> try: errors_call_builtin_nonmapping_kwargs()
378
    ... except TypeError: pass
379
    ... else: print("FAILED!")
380
    """
381
    dir(**h)
382

383

384
def errors_call_none_nonmapping_kwargs():
385
    """
386
    >>> try: errors_call_none_nonmapping_kwargs()
387
    ... except TypeError: pass
388
    ... else: print("FAILED!")
389
    """
390
    None(**h)
391

392

393
'''  # compile time error in Cython
394
def errors_call_builtin_duplicate_kwarg():
395
    """
396
    >>> errors_call_builtin_duplicate_kwarg()  # doctest: +ELLIPSIS
397
    Traceback (most recent call last):
398
      ...
399
    TypeError: ...got multiple values for keyword argument 'b'
400
    """
401
    dir(b=1, **{'b': 1})
402
'''
403

404

405
# Another helper function
406

407
def f2(*a, **b):
408
    return a, b
409

410

411
def call_many_kwargs():
412
    """
413
    call_many_kwargs()
414
    (3, 512, True)
415
    """
416
    d = {}
417
    for i in range(512):
418
        key = 'k%d' % i
419
        d[key] = i
420
    a, b = f2(1, *(2,3), **d)
421
    return len(a), len(b), b == d
422

423

424
def call_method(Foo):
425
    """
426
    >>> class Foo(object):
427
    ...     def method(self, arg1, arg2):
428
    ...         print(arg1+arg2)
429

430
    >>> call_method(Foo)
431
    3
432
    3
433
    5
434
    5
435
    """
436
    x = Foo()
437
    Foo.method(*(x, 1, 2))
438
    Foo.method(x, *(1, 2))
439
    Foo.method(*(1, 2, 3))
440
    Foo.method(1, *[2, 3])
441

442

443
# A PyCFunction that takes only positional parameters should allow an
444
# empty keyword dictionary to pass without a complaint, but raise a
445
# TypeError if the dictionary is not empty
446

447
def call_builtin_empty_dict():
448
    """
449
    >>> call_builtin_empty_dict()
450
    """
451
    silence = id(1, *{})
452
    silence = id(1, **{})
453

454

455
def call_builtin_nonempty_dict():
456
    """
457
    >>> call_builtin_nonempty_dict() # doctest: +ELLIPSIS
458
    Traceback (most recent call last):
459
      ...
460
    TypeError: id() ... keyword argument...
461
    """
462
    return id(1, **{'foo': 1})
463

464

465
''' Cython: currently just passes empty kwargs into f() while CPython keeps the content
466

467
# A corner case of keyword dictionary items being deleted during
468
# the function call setup. See <https://bugs.python.org/issue2016>.
469

470
def call_kwargs_modified_while_building():
471
    """
472
    >>> call_kwargs_modified_while_building()
473
    1 2
474
    """
475
    class Name(str):
476
        def __eq__(self, other):
477
            try:
478
                 del x[self]
479
            except KeyError:
480
                 pass
481
            return str.__eq__(self, other)
482
        def __hash__(self):
483
            return str.__hash__(self)
484

485
    x = {Name("a"):1, Name("b"):2}
486
    def f(a, b):
487
        print(a,b)
488
    f(**x)
489
'''
490

491

492
# Too many arguments:
493

494
def errors_call_one_arg(f):
495
    """
496
    >>> def f(): pass
497
    >>> try: errors_call_one_arg(f)
498
    ... except TypeError: pass
499
    ... else: print("FAILED!")
500
    """
501
    f(1)
502

503
def errors_call_2args(f):
504
    """
505
    >>> def f(a): pass
506
    >>> try: errors_call_2args(f)
507
    ... except TypeError: pass
508
    ... else: print("FAILED!")
509
    """
510
    f(1, 2)
511

512
def errors_call_3args(f):
513
    """
514
    >>> def f(a, b=1): pass
515
    >>> try: errors_call_3args(f)
516
    ... except TypeError: pass
517
    ... else: print("FAILED!")
518
    """
519
    f(1, 2, 3)
520

521

522
def errors_call_1arg_1kwarg(f):
523
    # Py3 only
524
    f(1, kw=3)
525

526

527
def errors_call_3args_2kwargs(f):
528
    # Py3 only
529
    f(1, 2, 3, b=3, kw=3)
530

531

532
def errors_call_3args_1kwarg(f):
533
    # Py3 only
534
    f(2, 3, 4, kw=4)
535

536

537
# Too few and missing arguments:
538

539
def errors_call_no_args(f):
540
    """
541
    >>> def f(a): pass
542
    >>> try: errors_call_no_args(f)
543
    ... except TypeError: pass
544
    ... else: print("FAILED!")
545

546
    >>> def f(a, b): pass
547
    >>> try: errors_call_no_args(f)
548
    ... except TypeError: pass
549
    ... else: print("FAILED!")
550

551
    >>> def f(a, b, c): pass
552
    >>> try: errors_call_no_args(f)
553
    ... except TypeError: pass
554
    ... else: print("FAILED!")
555

556
    >>> def f(a, b, c, d, e): pass
557
    >>> try: errors_call_no_args(f)
558
    ... except TypeError: pass
559
    ... else: print("FAILED!")
560
    """
561
    f()
562

563

564
def errors_call_one_missing_kwarg(f):
565
    """
566
    >>> def f(a, b=4, c=5, d=5): pass
567
    >>> try: errors_call_one_missing_kwarg(f)
568
    ... except TypeError: pass
569
    ... else: print("FAILED!")
570
    """
571
    f(c=12, b=9)
572

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.