aboutsummaryrefslogtreecommitdiff
path: root/tests/unittest_brain_ctypes.py
blob: ee0213d4f16a1eadce2fab8fc6c2a734d9407fb3 (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
import sys

import pytest

from astroid import extract_node, nodes

pytestmark = pytest.mark.skipif(
    hasattr(sys, "pypy_version_info"),
    reason="pypy has its own implementation of _ctypes module which is different from the one of cpython",
)


# The parameters of the test define a mapping between the ctypes redefined types
# and the builtin types that the "value" member holds
@pytest.mark.parametrize(
    "c_type,builtin_type,type_code",
    [
        ("c_bool", "bool", "?"),
        ("c_byte", "int", "b"),
        ("c_char", "bytes", "c"),
        ("c_double", "float", "d"),
        pytest.param(
            "c_buffer",
            "bytes",
            "<class 'ctypes.c_char'>",
            marks=pytest.mark.xfail(
                reason="c_buffer is Uninferable but for now we do not know why"
            ),
        ),
        ("c_float", "float", "f"),
        ("c_int", "int", "i"),
        ("c_int16", "int", "h"),
        ("c_int32", "int", "i"),
        ("c_int64", "int", "l"),
        ("c_int8", "int", "b"),
        ("c_long", "int", "l"),
        ("c_longdouble", "float", "g"),
        ("c_longlong", "int", "l"),
        ("c_short", "int", "h"),
        ("c_size_t", "int", "L"),
        ("c_ssize_t", "int", "l"),
        ("c_ubyte", "int", "B"),
        ("c_uint", "int", "I"),
        ("c_uint16", "int", "H"),
        ("c_uint32", "int", "I"),
        ("c_uint64", "int", "L"),
        ("c_uint8", "int", "B"),
        ("c_ulong", "int", "L"),
        ("c_ulonglong", "int", "L"),
        ("c_ushort", "int", "H"),
        ("c_wchar", "str", "u"),
    ],
)
def test_ctypes_redefined_types_members(c_type, builtin_type, type_code):
    """
    Test that the "value" and "_type_" member of each redefined types are correct
    """
    src = f"""
    import ctypes
    x=ctypes.{c_type}("toto")
    x.value
    """
    node = extract_node(src)
    assert isinstance(node, nodes.NodeNG)
    node_inf = node.inferred()[0]
    assert node_inf.pytype() == f"builtins.{builtin_type}"

    src = f"""
    import ctypes
    x=ctypes.{c_type}("toto")
    x._type_
    """
    node = extract_node(src)
    assert isinstance(node, nodes.NodeNG)
    node_inf = node.inferred()[0]
    assert isinstance(node_inf, nodes.Const)
    assert node_inf.value == type_code


def test_cdata_member_access() -> None:
    """
    Test that the base members are still accessible. Each redefined ctypes type inherits from _SimpleCData which itself
    inherits from _CData. Checks that _CData members are accessibles
    """
    src = """
    import ctypes
    x=ctypes.c_float(1.0)
    x._objects
    """
    node = extract_node(src)
    assert isinstance(node, nodes.NodeNG)
    node_inf = node.inferred()[0]
    assert node_inf.display_type() == "Class"
    assert node_inf.qname() == "_ctypes._SimpleCData._objects"


def test_other_ctypes_member_untouched() -> None:
    """
    Test that other ctypes members, which are not touched by the brain, are correctly inferred
    """
    src = """
    import ctypes
    ctypes.ARRAY(3, 2)
    """
    node = extract_node(src)
    assert isinstance(node, nodes.NodeNG)
    node_inf = node.inferred()[0]
    assert isinstance(node_inf, nodes.Const)
    assert node_inf.value == 6