aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/cython/Cython/Utility/CConvert.pyx
blob: 5969f6a5826e5671f3d7508ec7c8f832762247ea (plain) (blame)
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
#################### FromPyStructUtility ####################

cdef extern from *:
    ctypedef struct PyTypeObject:
        char* tp_name
    PyTypeObject *Py_TYPE(obj)
    bint PyMapping_Check(obj)
    object PyErr_Format(exc, const char *format, ...)

@cname("{{funcname}}")
cdef {{struct_type}} {{funcname}}(obj) except *:
    cdef {{struct_type}} result
    if not PyMapping_Check(obj):
        PyErr_Format(TypeError, b"Expected %.16s, got %.200s", b"a mapping", Py_TYPE(obj).tp_name)

    {{for member in var_entries:}}
    try:
        value = obj['{{member.name}}']
    except KeyError:
        raise ValueError("No value specified for struct attribute '{{member.name}}'")
    result.{{member.cname}} = value
    {{endfor}}
    return result


#################### FromPyUnionUtility ####################

cdef extern from *:
    ctypedef struct PyTypeObject:
        char* tp_name
    PyTypeObject *Py_TYPE(obj)
    bint PyMapping_Check(obj)
    object PyErr_Format(exc, const char *format, ...)

@cname("{{funcname}}")
cdef {{struct_type}} {{funcname}}(obj) except *:
    cdef {{struct_type}} result
    cdef Py_ssize_t length
    if not PyMapping_Check(obj):
        PyErr_Format(TypeError, b"Expected %.16s, got %.200s", b"a mapping", Py_TYPE(obj).tp_name)

    last_found = None
    length = len(obj)
    if length:
        {{for member in var_entries:}}
        if '{{member.name}}' in obj:
            if last_found is not None:
                raise ValueError("More than one union attribute passed: '%s' and '%s'" % (last_found, '{{member.name}}'))
            last_found = '{{member.name}}'
            result.{{member.cname}} = obj['{{member.name}}']
            length -= 1
            if not length:
                return result
        {{endfor}}
    if last_found is None:
        raise ValueError("No value specified for any of the union attributes (%s)" %
                         '{{", ".join(member.name for member in var_entries)}}')
    return result


#################### cfunc.to_py ####################

@cname("{{cname}}")
cdef object {{cname}}({{return_type.ctype}} (*f)({{ ', '.join(arg.type_cname for arg in args) }}) {{except_clause}}):
    def wrap({{ ', '.join('{arg.ctype} {arg.name}'.format(arg=arg) for arg in args) }}):
        """wrap({{', '.join(('{arg.name}: {arg.type_displayname}'.format(arg=arg) if arg.type_displayname else arg.name) for arg in args)}}){{if return_type.type_displayname}} -> {{return_type.type_displayname}}{{endif}}"""
        {{'' if return_type.type.is_void else 'return '}}f({{ ', '.join(arg.name for arg in args) }})
    return wrap


#################### carray.from_py ####################

cdef extern from *:
    object PyErr_Format(exc, const char *format, ...)

@cname("{{cname}}")
cdef int {{cname}}(object o, {{base_type}} *v, Py_ssize_t length) except -1:
    cdef Py_ssize_t i = length
    try:
        i = len(o)
    except (TypeError, OverflowError):
        pass
    if i == length:
        for i, item in enumerate(o):
            if i >= length:
                break
            v[i] = item
        else:
            i += 1  # convert index to length
            if i == length:
                return 0

    PyErr_Format(
        IndexError,
        ("too many values found during array assignment, expected %zd"
         if i >= length else
         "not enough values found during array assignment, expected %zd, got %zd"),
        length, i)


#################### carray.to_py ####################

cdef extern from *:
    void Py_INCREF(object o)
    tuple PyTuple_New(Py_ssize_t size)
    list PyList_New(Py_ssize_t size)
    void PyTuple_SET_ITEM(object  p, Py_ssize_t pos, object o)
    void PyList_SET_ITEM(object  p, Py_ssize_t pos, object o)


@cname("{{cname}}")
cdef inline list {{cname}}({{base_type}} *v, Py_ssize_t length):
    cdef size_t i
    cdef object value
    l = PyList_New(length)
    for i in range(<size_t>length):
        value = v[i]
        Py_INCREF(value)
        PyList_SET_ITEM(l, i, value)
    return l


@cname("{{to_tuple_cname}}")
cdef inline tuple {{to_tuple_cname}}({{base_type}} *v, Py_ssize_t length):
    cdef size_t i
    cdef object value
    t = PyTuple_New(length)
    for i in range(<size_t>length):
        value = v[i]
        Py_INCREF(value)
        PyTuple_SET_ITEM(t, i, value)
    return t