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
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/main/LICENSE
# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt
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 accessible.
"""
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
|