cython

Форк
0
/
fused_def.pyx 
463 строки · 11.7 Кб
1
# mode: run
2

3
"""
4
Test Python def functions without extern types
5
"""
6

7
cy = __import__("cython")
8
cimport cython
9

10
cdef extern from *:
11
    int __Pyx_CyFunction_Check(object)
12

13
cdef class Base(object):
14
    def __repr__(self):
15
        return type(self).__name__
16

17

18
cdef class ExtClassA(Base):
19
    pass
20

21
cdef class ExtClassB(Base):
22
    pass
23

24
cdef enum MyEnum:
25
    entry0
26
    entry1
27
    entry2
28
    entry3
29
    entry4
30

31
ctypedef fused fused_t:
32
    str
33
    int
34
    long
35
    complex
36
    ExtClassA
37
    ExtClassB
38
    MyEnum
39

40

41
ctypedef ExtClassA xxxlast
42
ctypedef ExtClassB aaafirst
43

44

45
ctypedef fused fused_with_object:
46
    aaafirst
47
    object
48
    xxxlast
49
    int
50
    long
51

52

53
f = 5.6
54
i = 9
55

56

57
def opt_func(fused_t obj, cython.floating myf = 1.2, cython.integral myi = 7,
58
             another_opt = 2, yet_another_opt=3):
59
    """
60
    Test runtime dispatch, indexing of various kinds and optional arguments.
61
    Use 5 arguments because at one point the optional argument from the
62
    5th argument was overwriting that of the __pyx_fused dispatcher.
63
    https://github.com/cython/cython/issues/3511
64

65
    >>> opt_func("spam", f, i)
66
    str object double long
67
    spam 5.60 9 5.60 9
68
    >>> opt_func("spam", f, myi=i)
69
    str object double long
70
    spam 5.60 9 5.60 9
71
    >>> opt_func("spam", myf=f, myi=i)
72
    str object double long
73
    spam 5.60 9 5.60 9
74
    >>> opt_func[str, float, int]("spam", f, i)
75
    str object float int
76
    spam 5.60 9 5.60 9
77
    >>> opt_func[str, cy.double, cy.long]("spam", f, i)
78
    str object double long
79
    spam 5.60 9 5.60 9
80
    >>> opt_func[str, cy.double, cy.long]("spam", f, myi=i)
81
    str object double long
82
    spam 5.60 9 5.60 9
83
    >>> opt_func[str, float, cy.int]("spam", f, i)
84
    str object float int
85
    spam 5.60 9 5.60 9
86

87

88
    >>> opt_func(ExtClassA(), f, i)
89
    ExtClassA double long
90
    ExtClassA 5.60 9 5.60 9
91
    >>> opt_func[ExtClassA, float, int](ExtClassA(), f, i)
92
    ExtClassA float int
93
    ExtClassA 5.60 9 5.60 9
94
    >>> opt_func[ExtClassA, cy.double, cy.long](ExtClassA(), f, i)
95
    ExtClassA double long
96
    ExtClassA 5.60 9 5.60 9
97

98
    >>> opt_func(ExtClassB(), f, i)
99
    ExtClassB double long
100
    ExtClassB 5.60 9 5.60 9
101
    >>> opt_func[ExtClassB, cy.double, cy.long](ExtClassB(), f, i)
102
    ExtClassB double long
103
    ExtClassB 5.60 9 5.60 9
104

105
    >>> opt_func(10, f)
106
    long double long
107
    10 5.60 7 5.60 9
108
    >>> opt_func[int, float, int](10, f)
109
    int float int
110
    10 5.60 7 5.60 9
111

112
    >>> opt_func(10 + 2j, myf = 2.6)
113
    double complex double long
114
    (10+2j) 2.60 7 5.60 9
115
    >>> opt_func[cy.py_complex, float, int](10 + 2j, myf = 2.6)
116
    double complex float int
117
    (10+2j) 2.60 7 5.60 9
118
    >>> opt_func[cy.doublecomplex, cy.float, cy.int](10 + 2j, myf = 2.6)
119
    double complex float int
120
    (10+2j) 2.60 7 5.60 9
121

122
    >>> opt_func(object(), f)
123
    Traceback (most recent call last):
124
    TypeError: Function call with ambiguous argument types
125
    >>> opt_func()
126
    Traceback (most recent call last):
127
    TypeError: Expected at least 1 argument, got 0
128
    >>> opt_func("abc", f, i, 5, 5, 5)  # doctest: +ELLIPSIS
129
    Traceback (most recent call last):
130
    TypeError: ...at most 5...
131
    >>> opt_func[ExtClassA, cy.float, cy.long](object(), f)
132
    Traceback (most recent call last):
133
    TypeError: Argument 'obj' has incorrect type (expected fused_def.ExtClassA, got object)
134
    """
135
    print cython.typeof(obj), cython.typeof(myf), cython.typeof(myi)
136
    print obj, "%.2f" % myf, myi, "%.2f" % f, i
137

138
def non_fused_opt(fused_t obj, value=5):
139
    """
140
    PyObject constants as parts of fused functions weren't being created correctly
141
    which would lead this to crash
142
    >>> non_fused_opt(0)
143
    5
144
    >>> non_fused_opt("str", 10)
145
    10
146
    """
147
    print value
148

149
def run_cyfunction_check():
150
    """
151
    tp_base of the fused function was being set incorrectly meaning
152
    it wasn't being identified as a CyFunction
153
    >>> run_cyfunction_check()
154
    fused_cython_function
155
    1
156
    """
157
    print(type(opt_func).__name__.rsplit('.', 1)[-1])
158
    print(__Pyx_CyFunction_Check(opt_func))  # should be True
159

160
def test_opt_func():
161
    """
162
    >>> test_opt_func()
163
    str object double long
164
    ham 5.60 4 5.60 9
165
    """
166
    opt_func("ham", f, entry4)
167

168

169
def test_opt_func_introspection():
170
    """
171
    >>> opt_func.__defaults__
172
    (1.2, 7, 2, 3)
173
    >>> opt_func.__kwdefaults__
174
    >>> opt_func.__annotations__
175
    {}
176

177
    >>> opt_func[str, float, int].__defaults__
178
    (1.2, 7, 2, 3)
179
    >>> opt_func[str, float, int].__kwdefaults__
180
    >>> opt_func[str, float, int].__annotations__
181
    {}
182

183
    >>> opt_func[str, cy.double, cy.long].__defaults__
184
    (1.2, 7, 2, 3)
185
    >>> opt_func[str, cy.double, cy.long].__kwdefaults__
186
    >>> opt_func[str, cy.double, cy.long].__annotations__
187
    {}
188
    """
189

190

191
def func_with_object(fused_with_object obj, cython.integral myi = 7):
192
    """
193
    >>> func_with_object(1)
194
    long long
195
    1 7
196
    >>> func_with_object(1, 3)
197
    long long
198
    1 3
199
    >>> func_with_object['int', 'int'](1, 3)
200
    int int
201
    1 3
202
    >>> func_with_object(1j, 3)
203
    Python object long
204
    1j 3
205
    >>> func_with_object('abc', 3)
206
    Python object long
207
    abc 3
208
    >>> func_with_object(ExtClassA(), 3)
209
    xxxlast long
210
    ExtClassA 3
211
    >>> func_with_object(ExtClassB(), 3)
212
    aaafirst long
213
    ExtClassB 3
214
    >>> func_with_object['object', 'long'](ExtClassA(), 3)
215
    Python object long
216
    ExtClassA 3
217
    >>> func_with_object['object', 'long'](ExtClassB(), 3)
218
    Python object long
219
    ExtClassB 3
220
    """
221
    print cython.typeof(obj), cython.typeof(myi)
222
    print obj, myi
223

224

225

226
def args_kwargs(fused_t obj, cython.floating myf = 1.2, *args, **kwargs):
227
    """
228
    >>> args_kwargs("foo")
229
    str object double
230
    foo 1.20 5.60 () {}
231

232
    >>> args_kwargs("eggs", f, 1, 2, [], d={})
233
    str object double
234
    eggs 5.60 5.60 (1, 2, []) {'d': {}}
235

236
    >>> args_kwargs[str, float]("eggs", f, 1, 2, [], d={})
237
    str object float
238
    eggs 5.60 5.60 (1, 2, []) {'d': {}}
239

240
    """
241
    print cython.typeof(obj), cython.typeof(myf)
242
    print obj, "%.2f" % myf, "%.2f" % f, args, kwargs
243

244

245
class BaseClass(object):
246
    """
247
    Test fused class/static/normal methods and super() without args
248
    """
249

250
    @staticmethod
251
    def mystaticmethod(cython.integral arg1):
252
        print cython.typeof(arg1), arg1
253

254
    @classmethod
255
    def myclassmethod(cls, cython.integral arg1):
256
        print cls, cython.typeof(arg1), arg1
257

258
    def normalmethod(self, cython.integral arg1):
259
        print self, cython.typeof(arg1), arg1
260

261
    def __repr__(self):
262
        return "<%s.%s object>" % (__name__, type(self).__name__)
263

264
class SubClass(BaseClass):
265

266
    @staticmethod
267
    def mystaticmethod(self, cython.integral arg1):
268
        print cython.typeof(arg1), arg1
269
        super().mystaticmethod(arg1 + 1)
270

271
    @classmethod
272
    def myclassmethod(cls, cython.integral arg1):
273
        print cls, cython.typeof(arg1), arg1
274
        super().myclassmethod(arg1 + 1)
275

276
    def normalmethod(self, cython.integral arg1):
277
        print self, cython.typeof(arg1), arg1
278
        super().normalmethod(arg1 + 1)
279

280
class SubSubClass(SubClass):
281
    pass
282

283
def test_fused_def_super():
284
    """
285
    >>> test_fused_def_super()
286
    long 10
287
    long 11
288
    long 11
289
    long 12
290
    short 12
291
    long 13
292
    short 13
293
    long 14
294
    <class 'fused_def.SubClass'> long 14
295
    <class 'fused_def.SubClass'> long 15
296
    <class 'fused_def.SubClass'> long 15
297
    <class 'fused_def.SubClass'> long 16
298
    <class 'fused_def.SubClass'> short 16
299
    <class 'fused_def.SubClass'> long 17
300
    <class 'fused_def.SubClass'> short 17
301
    <class 'fused_def.SubClass'> long 18
302
    <fused_def.SubClass object> long 18
303
    <fused_def.SubClass object> long 19
304
    <fused_def.SubClass object> long 19
305
    <fused_def.SubClass object> long 20
306
    <fused_def.SubClass object> short 20
307
    <fused_def.SubClass object> long 21
308
    <fused_def.SubClass object> short 21
309
    <fused_def.SubClass object> long 22
310
    """
311
    obj = SubClass()
312
    cls = SubClass
313

314
    obj.mystaticmethod(obj, 10)
315
    cls.mystaticmethod(obj, 11)
316
    obj.mystaticmethod[cy.short](obj, 12)
317
    cls.mystaticmethod[cy.short](obj, 13)
318

319
    obj.myclassmethod(14)
320
    cls.myclassmethod(15)
321
    obj.myclassmethod[cy.short](16)
322
    cls.myclassmethod[cy.short](17)
323

324
    obj.normalmethod(18)
325
    cls.normalmethod(obj, 19)
326
    obj.normalmethod[cy.short](20)
327
    cls.normalmethod[cy.short](obj, 21)
328

329
def test_fused_def_classmethod():
330
    """
331
    >>> test_fused_def_classmethod()
332
    <class 'fused_def.SubSubClass'> long 10
333
    <class 'fused_def.SubSubClass'> long 11
334
    <class 'fused_def.SubSubClass'> long 11
335
    <class 'fused_def.SubSubClass'> long 12
336
    <class 'fused_def.SubSubClass'> short 12
337
    <class 'fused_def.SubSubClass'> long 13
338
    <class 'fused_def.SubSubClass'> short 13
339
    <class 'fused_def.SubSubClass'> long 14
340
    """
341
    SubSubClass().myclassmethod(10)
342
    SubSubClass.myclassmethod(11)
343

344
    SubSubClass().myclassmethod[cy.short](12)
345
    SubSubClass.myclassmethod[cy.short](13)
346

347
cdef class CBaseClass(object):
348
    """
349
    Test fused def and cpdef methods in cdef classes.
350

351
    >>> import cython as cy
352
    >>> obj = CBaseClass()
353
    >>> cls = CBaseClass
354

355
    >>> obj.mystaticmethod(10)
356
    long 10
357
    >>> obj.mystaticmethod[cy.short](10)
358
    short 10
359
    >>> cls.mystaticmethod(10)
360
    long 10
361
    >>> cls.mystaticmethod[cy.short](10)
362
    short 10
363

364
    >>> obj.myclassmethod(10)
365
    CBaseClass long 10
366
    >>> obj.myclassmethod[cy.short](10)
367
    CBaseClass short 10
368
    >>> cls.myclassmethod(10)
369
    CBaseClass long 10
370
    >>> cls.myclassmethod[cy.short](10)
371
    CBaseClass short 10
372

373
    >>> obj.normalmethod(10, 11, 12)
374
    <fused_def.CBaseClass object> long 10 11 12
375
    >>> obj.normalmethod[cy.short](10, 11, 12)
376
    <fused_def.CBaseClass object> short 10 11 12
377
    >>> cls.normalmethod(obj, 10, 11, 12)
378
    <fused_def.CBaseClass object> long 10 11 12
379
    >>> cls.normalmethod[cy.short](obj, 10, 11, 12)
380
    <fused_def.CBaseClass object> short 10 11 12
381

382
    >>> obj.cpdefmethod(10)
383
    <fused_def.CBaseClass object> long 10
384
    >>> obj.cpdefmethod[cy.short](10)
385
    <fused_def.CBaseClass object> short 10
386
    >>> cls.cpdefmethod(obj, 10)
387
    <fused_def.CBaseClass object> long 10
388
    >>> cls.cpdefmethod[cy.short](obj, 10)
389
    <fused_def.CBaseClass object> short 10
390
    """
391

392
    @staticmethod
393
    def mystaticmethod(cython.integral arg1):
394
        print cython.typeof(arg1), arg1
395

396
    @classmethod
397
    def myclassmethod(cls, cython.integral arg1):
398
        print cls.__name__, cython.typeof(arg1), arg1
399

400
    def normalmethod(self, cython.integral arg1, arg2, arg3):
401
        print self, cython.typeof(arg1), arg1, arg2, arg3
402

403
    cpdef cpdefmethod(self, cython.integral arg1):
404
        print self, cython.typeof(arg1), arg1
405

406
    def __repr__(self):
407
        return "<%s.%s object>" % (__name__, type(self).__name__)
408

409
def getcode(func):
410
    return getattr(func, '__code__', None) or func.func_code
411

412
def test_code_object(cython.floating dummy = 2.0):
413
    """
414
    A test for default arguments is in cyfunction_defaults
415

416
    >>> test_code_object.__code__ is not test_code_object[float].__code__
417
    True
418
    """
419

420
def create_dec(value):
421
    def dec(f):
422
        if not hasattr(f, 'order'):
423
            f.order = []
424
        f.order.append(value)
425
        return f
426
    return dec
427

428
@create_dec(1)
429
@create_dec(2)
430
@create_dec(3)
431
def test_decorators(cython.floating arg):
432
    """
433
    >>> test_decorators.order
434
    [3, 2, 1]
435
    """
436

437
@cython.binding(True)
438
def bind_me(self, cython.floating a=1.):
439
    return a
440

441
cdef class HasBound:
442
    """
443
    Using default arguments of bound specialized fused functions used to cause a segfault
444
    https://github.com/cython/cython/issues/3370
445
    >>> inst = HasBound()
446
    >>> inst.func()
447
    1.0
448
    >>> inst.func(2)
449
    2.0
450
    >>> inst.func_fused()
451
    1.0
452
    >>> inst.func_fused(2.)
453
    2.0
454
    >>> bind_me.__defaults__
455
    (1.0,)
456
    >>> inst.func.__defaults__
457
    (1.0,)
458
    >>> inst.func_fused.__defaults__
459
    (1.0,)
460
    """
461
    func = bind_me[float]
462

463
    func_fused = bind_me
464

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

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

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

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