summaryrefslogtreecommitdiff
path: root/tests/run/fused_bound_functions.py
blob: 650bc51ffe04191aff976d4ff748c73a105db17e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# mode: run
# tag: pure3.0
# cython: binding=True

"""
Test that fused functions can be used in the same way as CyFunctions with respect to
assigning them to class attributes. Previously they enforced extra type/argument checks
beyond those which CyFunctions did.
"""

import cython

MyFusedClass = cython.fused_type(
    float,
    'Cdef',
    object)

def fused_func(x: MyFusedClass):
    return (type(x).__name__, cython.typeof(x))

IntOrFloat = cython.fused_type(int, float)

def fused_func_0(x: IntOrFloat = 0):
    """
    Fused functions can legitimately take 0 arguments
    >>> fused_func_0()
    ('int', 'int')

    # subscripted in module __doc__ conditionally
    """
    return (type(x).__name__, cython.typeof(x))

def regular_func(x):
    return (type(x).__name__, cython.typeof(x))

def regular_func_0():
    return

@cython.cclass
class Cdef:
    __doc__ = """
    >>> c = Cdef()

    # functions are callable with an instance of c
    >>> c.fused_func()
    ('Cdef', 'Cdef')
    >>> c.regular_func()
    ('Cdef', '{typeofCdef}')
    >>> c.fused_in_class(1.5)
    ('float', 'float')

    # Fused functions are callable without an instance
    # (This applies to everything in Py3 - see __doc__ below)
    >>> Cdef.fused_func(1.5)
    ('float', 'float')
    >>> Cdef.fused_in_class(c, 1.5)
    ('float', 'float')
    >>> Cdef.fused_func_0()
    ('int', 'int')

    # Functions not expecting an argument don't work with an instance
    >>> c.regular_func_0()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: regular_func_0() takes ... arguments ...1... given...
    """.format(typeofCdef = 'Python object' if cython.compiled else 'Cdef')

    if cython.compiled:
        __doc__ += """

    # fused_func_0 does not accept a "Cdef" instance
    >>> c.fused_func_0()
    Traceback (most recent call last):
    TypeError: No matching signature found

    # subscripting requires fused methods (so  not pure Python)
    >>> Cdef.fused_func_0['float']()
    ('float', 'float')
    >>> c.fused_func_0['float']()  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    TypeError: (Exception looks quite different in Python2 and 3 so no way to match both)
    """
    fused_func = fused_func
    fused_func_0 = fused_func_0
    regular_func = regular_func
    regular_func_0 = regular_func_0

    def fused_in_class(self, x: MyFusedClass):
        return (type(x).__name__, cython.typeof(x))

    def regular_in_class(self):
        return type(self).__name__

class Regular(object):
    __doc__ = """
    >>> c = Regular()

    # Functions are callable with an instance of C
    >>> c.fused_func()
    ('Regular', '{typeofRegular}')
    >>> c.regular_func()
    ('Regular', '{typeofRegular}')

    # Fused functions are callable without an instance
    # (This applies to everything in Py3 - see __doc__ below)
    >>> Regular.fused_func(1.5)
    ('float', 'float')
    >>> Regular.fused_func_0()
    ('int', 'int')

    # Functions not expecting an argument don't work with an instance
    >>> c.regular_func_0()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: regular_func_0() takes ... arguments ...1... given...
    """.format(typeofRegular = "Python object" if cython.compiled else 'Regular')
    if cython.compiled:
        __doc__ += """
    # fused_func_0 does not accept a "Regular" instance
    >>> c.fused_func_0()
    Traceback (most recent call last):
    TypeError: No matching signature found

    # subscripting requires fused methods (so  not pure Python)
    >>> c.fused_func_0['float']()  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    TypeError: (Exception looks quite different in Python2 and 3 so no way to match both)
    >>> Regular.fused_func_0['float']()
    ('float', 'float')
    """

    fused_func = fused_func
    fused_func_0 = fused_func_0
    regular_func = regular_func
    regular_func_0 = regular_func_0

import sys
if sys.version_info[0] > 2:
    # extra Py3 only tests - shows that functions added to a class can be called
    # with an type as the first argument
    __doc__ = """
    >>> Cdef.regular_func(1.5)
    ('float', '{typeoffloat}')
    >>> Regular.regular_func(1.5)
    ('float', '{typeoffloat}')
    >>> Cdef.regular_func_0()
    >>> Regular.regular_func_0()
    """.format(typeoffloat='Python object' if cython.compiled else 'float')
if cython.compiled:
    __doc__ += """
    >>> fused_func_0['float']()
    ('float', 'float')
    """