Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ff72122

Browse files
author
Thomas Heller
committed
Merged revisions 60001,60003-60004,60008 via svnmerge from
svn+ssh://[email protected]/python/trunk ........ r60001 | thomas.heller | 2008-01-16 20:16:27 +0100 (Mi, 16 Jan 2008) | 3 lines Convert the internal ctypes array type cache to a WeakValueDict so that array types do not live longer than needed. ........ r60003 | thomas.heller | 2008-01-16 20:37:33 +0100 (Mi, 16 Jan 2008) | 3 lines Raise a TypeError if conflicting positional and named arguments are passed to a Structure or Union constructor. ........ r60004 | thomas.heller | 2008-01-16 20:45:51 +0100 (Mi, 16 Jan 2008) | 3 lines Raise a TypeError instead of a ValueError when too many initializers are used in a Structure or Union constructor. ........ r60008 | thomas.heller | 2008-01-16 21:34:37 +0100 (Mi, 16 Jan 2008) | 3 lines Use 'g' instead of 'D' as the ctypes typecode for c_longdouble, for compliance with PEP 3118. ........
1 parent 9893de1 commit ff72122

5 files changed

Lines changed: 66 additions & 18 deletions

File tree

Lib/ctypes/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ class c_double(_SimpleCData):
182182
_check_size(c_double)
183183

184184
class c_longdouble(_SimpleCData):
185-
_type_ = "D"
185+
_type_ = "g"
186186
if sizeof(c_longdouble) == sizeof(c_double):
187187
c_longdouble = c_double
188188

Lib/ctypes/test/test_arrays.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,5 +116,19 @@ def test_from_addressW(self):
116116
self.failUnlessEqual(sz[1:4:2], "o")
117117
self.failUnlessEqual(sz.value, "foo")
118118

119+
def test_cache(self):
120+
# Array types are cached internally in the _ctypes extension,
121+
# in a WeakValueDictionary. Make sure the array type is
122+
# removed from the cache when the itemtype goes away. This
123+
# test will not fail, but will show a leak in the testsuite.
124+
125+
# Create a new type:
126+
class my_int(c_int):
127+
pass
128+
# Create a new array type based on it:
129+
t1 = my_int * 1
130+
t2 = my_int * 1
131+
self.failUnless(t1 is t2)
132+
119133
if __name__ == '__main__':
120134
unittest.main()

Lib/ctypes/test/test_structures.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,15 @@ class Person(Structure):
215215
# too long
216216
self.assertRaises(ValueError, Person, "1234567", 5)
217217

218+
def test_conflicting_initializers(self):
219+
class POINT(Structure):
220+
_fields_ = [("x", c_int), ("y", c_int)]
221+
# conflicting positional and keyword args
222+
self.assertRaises(TypeError, POINT, 2, 3, x=4)
223+
self.assertRaises(TypeError, POINT, 2, 3, y=4)
224+
225+
# too many initializers
226+
self.assertRaises(TypeError, POINT, 2, 3, 4)
218227

219228
def test_keyword_initializers(self):
220229
class POINT(Structure):
@@ -305,9 +314,9 @@ class Person(Structure):
305314
self.failUnlessEqual(cls, RuntimeError)
306315
if issubclass(Exception, object):
307316
self.failUnlessEqual(msg,
308-
"(Phone) <type 'ValueError'>: too many initializers")
317+
"(Phone) <type 'TypeError'>: too many initializers")
309318
else:
310-
self.failUnlessEqual(msg, "(Phone) ValueError: too many initializers")
319+
self.failUnlessEqual(msg, "(Phone) TypeError: too many initializers")
311320

312321

313322
def get_except(self, func, *args):

Modules/_ctypes/_ctypes.c

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ bytes(cdata)
122122

123123
PyObject *PyExc_ArgError;
124124
static PyTypeObject Simple_Type;
125+
PyObject *array_types_cache;
125126

126127
char *conversion_mode_encoding = NULL;
127128
char *conversion_mode_errors = NULL;
@@ -1112,7 +1113,7 @@ _type_ attribute.
11121113
11131114
*/
11141115

1115-
static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOvtD";
1116+
static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOvtg";
11161117

11171118
static PyObject *
11181119
c_wchar_p_from_param(PyObject *type, PyObject *value)
@@ -3535,7 +3536,7 @@ Struct_init(PyObject *self, PyObject *args, PyObject *kwds)
35353536

35363537
if (PyTuple_GET_SIZE(args) > PySequence_Length(fields)) {
35373538
Py_DECREF(fields);
3538-
PyErr_SetString(PyExc_ValueError,
3539+
PyErr_SetString(PyExc_TypeError,
35393540
"too many initializers");
35403541
return -1;
35413542
}
@@ -3556,6 +3557,21 @@ Struct_init(PyObject *self, PyObject *args, PyObject *kwds)
35563557
return IBUG("_fields_[i][0] failed");
35573558
}
35583559

3560+
if (kwds && PyDict_GetItem(kwds, name)) {
3561+
char *field = PyString_AsString(name);
3562+
if (field == NULL) {
3563+
PyErr_Clear();
3564+
field = "???";
3565+
}
3566+
PyErr_Format(PyExc_TypeError,
3567+
"duplicate values for field %s",
3568+
field);
3569+
Py_DECREF(pair);
3570+
Py_DECREF(name);
3571+
Py_DECREF(fields);
3572+
return -1;
3573+
}
3574+
35593575
val = PyTuple_GET_ITEM(args, i);
35603576
if (-1 == PyObject_SetAttr(self, name, val)) {
35613577
Py_DECREF(pair);
@@ -3977,25 +3993,19 @@ PyTypeObject Array_Type = {
39773993
PyObject *
39783994
CreateArrayType(PyObject *itemtype, Py_ssize_t length)
39793995
{
3980-
static PyObject *cache;
39813996
PyObject *key;
39823997
PyObject *result;
39833998
char name[256];
39843999

3985-
if (cache == NULL) {
3986-
cache = PyDict_New();
3987-
if (cache == NULL)
3988-
return NULL;
3989-
}
39904000
key = Py_BuildValue("(On)", itemtype, length);
39914001
if (!key)
39924002
return NULL;
3993-
result = PyDict_GetItem(cache, key);
4003+
result = PyObject_GetItem(array_types_cache, key);
39944004
if (result) {
3995-
Py_INCREF(result);
39964005
Py_DECREF(key);
39974006
return result;
3998-
}
4007+
} else
4008+
PyErr_Clear();
39994009

40004010
if (!PyType_Check(itemtype)) {
40014011
PyErr_SetString(PyExc_TypeError,
@@ -4021,7 +4031,11 @@ CreateArrayType(PyObject *itemtype, Py_ssize_t length)
40214031
);
40224032
if (!result)
40234033
return NULL;
4024-
PyDict_SetItem(cache, key, result);
4034+
if (-1 == PyObject_SetItem(array_types_cache, key, result)) {
4035+
Py_DECREF(key);
4036+
Py_DECREF(result);
4037+
return NULL;
4038+
}
40254039
Py_DECREF(key);
40264040
return result;
40274041
}
@@ -4778,6 +4792,7 @@ PyMODINIT_FUNC
47784792
init_ctypes(void)
47794793
{
47804794
PyObject *m;
4795+
PyObject *weakref;
47814796

47824797
/* Note:
47834798
ob_type is the metatype (the 'type'), defaults to PyType_Type,
@@ -4790,6 +4805,16 @@ init_ctypes(void)
47904805
if (!m)
47914806
return;
47924807

4808+
weakref = PyImport_ImportModule("weakref");
4809+
if (weakref == NULL)
4810+
return;
4811+
array_types_cache = PyObject_CallMethod(weakref,
4812+
"WeakValueDictionary",
4813+
NULL);
4814+
if (array_types_cache == NULL)
4815+
return;
4816+
Py_DECREF(weakref);
4817+
47934818
if (PyType_Ready(&PyCArg_Type) < 0)
47944819
return;
47954820

Modules/_ctypes/cfield.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@ Q_get_sw(void *ptr, Py_ssize_t size)
983983

984984

985985
static PyObject *
986-
D_set(void *ptr, PyObject *value, Py_ssize_t size)
986+
g_set(void *ptr, PyObject *value, Py_ssize_t size)
987987
{
988988
long double x;
989989

@@ -999,7 +999,7 @@ D_set(void *ptr, PyObject *value, Py_ssize_t size)
999999
}
10001000

10011001
static PyObject *
1002-
D_get(void *ptr, Py_ssize_t size)
1002+
g_get(void *ptr, Py_ssize_t size)
10031003
{
10041004
long double val;
10051005
memcpy(&val, ptr, sizeof(long double));
@@ -1630,7 +1630,7 @@ static struct fielddesc formattable[] = {
16301630
{ 'B', B_set, B_get, &ffi_type_uchar},
16311631
{ 'c', c_set, c_get, &ffi_type_schar},
16321632
{ 'd', d_set, d_get, &ffi_type_double, d_set_sw, d_get_sw},
1633-
{ 'D', D_set, D_get, &ffi_type_longdouble},
1633+
{ 'g', g_set, g_get, &ffi_type_longdouble},
16341634
{ 'f', f_set, f_get, &ffi_type_float, f_set_sw, f_get_sw},
16351635
{ 'h', h_set, h_get, &ffi_type_sshort, h_set_sw, h_get_sw},
16361636
{ 'H', H_set, H_get, &ffi_type_ushort, H_set_sw, H_get_sw},

0 commit comments

Comments
 (0)