mirror of
https://github.com/python/cpython
synced 2024-09-16 02:19:59 +00:00
Merged revisions 60001,60003-60004,60008 via svnmerge from
svn+ssh://pythondev@svn.python.org/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. ........
This commit is contained in:
parent
9893de1b83
commit
ff72122184
|
@ -182,7 +182,7 @@ class c_double(_SimpleCData):
|
|||
_check_size(c_double)
|
||||
|
||||
class c_longdouble(_SimpleCData):
|
||||
_type_ = "D"
|
||||
_type_ = "g"
|
||||
if sizeof(c_longdouble) == sizeof(c_double):
|
||||
c_longdouble = c_double
|
||||
|
||||
|
|
|
@ -116,5 +116,19 @@ def test_from_addressW(self):
|
|||
self.failUnlessEqual(sz[1:4:2], "o")
|
||||
self.failUnlessEqual(sz.value, "foo")
|
||||
|
||||
def test_cache(self):
|
||||
# Array types are cached internally in the _ctypes extension,
|
||||
# in a WeakValueDictionary. Make sure the array type is
|
||||
# removed from the cache when the itemtype goes away. This
|
||||
# test will not fail, but will show a leak in the testsuite.
|
||||
|
||||
# Create a new type:
|
||||
class my_int(c_int):
|
||||
pass
|
||||
# Create a new array type based on it:
|
||||
t1 = my_int * 1
|
||||
t2 = my_int * 1
|
||||
self.failUnless(t1 is t2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -215,6 +215,15 @@ class Person(Structure):
|
|||
# too long
|
||||
self.assertRaises(ValueError, Person, "1234567", 5)
|
||||
|
||||
def test_conflicting_initializers(self):
|
||||
class POINT(Structure):
|
||||
_fields_ = [("x", c_int), ("y", c_int)]
|
||||
# conflicting positional and keyword args
|
||||
self.assertRaises(TypeError, POINT, 2, 3, x=4)
|
||||
self.assertRaises(TypeError, POINT, 2, 3, y=4)
|
||||
|
||||
# too many initializers
|
||||
self.assertRaises(TypeError, POINT, 2, 3, 4)
|
||||
|
||||
def test_keyword_initializers(self):
|
||||
class POINT(Structure):
|
||||
|
@ -305,9 +314,9 @@ class Person(Structure):
|
|||
self.failUnlessEqual(cls, RuntimeError)
|
||||
if issubclass(Exception, object):
|
||||
self.failUnlessEqual(msg,
|
||||
"(Phone) <type 'ValueError'>: too many initializers")
|
||||
"(Phone) <type 'TypeError'>: too many initializers")
|
||||
else:
|
||||
self.failUnlessEqual(msg, "(Phone) ValueError: too many initializers")
|
||||
self.failUnlessEqual(msg, "(Phone) TypeError: too many initializers")
|
||||
|
||||
|
||||
def get_except(self, func, *args):
|
||||
|
|
|
@ -122,6 +122,7 @@ bytes(cdata)
|
|||
|
||||
PyObject *PyExc_ArgError;
|
||||
static PyTypeObject Simple_Type;
|
||||
PyObject *array_types_cache;
|
||||
|
||||
char *conversion_mode_encoding = NULL;
|
||||
char *conversion_mode_errors = NULL;
|
||||
|
@ -1112,7 +1113,7 @@ _type_ attribute.
|
|||
|
||||
*/
|
||||
|
||||
static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOvtD";
|
||||
static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOvtg";
|
||||
|
||||
static PyObject *
|
||||
c_wchar_p_from_param(PyObject *type, PyObject *value)
|
||||
|
@ -3535,7 +3536,7 @@ Struct_init(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
|
||||
if (PyTuple_GET_SIZE(args) > PySequence_Length(fields)) {
|
||||
Py_DECREF(fields);
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"too many initializers");
|
||||
return -1;
|
||||
}
|
||||
|
@ -3556,6 +3557,21 @@ Struct_init(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
return IBUG("_fields_[i][0] failed");
|
||||
}
|
||||
|
||||
if (kwds && PyDict_GetItem(kwds, name)) {
|
||||
char *field = PyString_AsString(name);
|
||||
if (field == NULL) {
|
||||
PyErr_Clear();
|
||||
field = "???";
|
||||
}
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"duplicate values for field %s",
|
||||
field);
|
||||
Py_DECREF(pair);
|
||||
Py_DECREF(name);
|
||||
Py_DECREF(fields);
|
||||
return -1;
|
||||
}
|
||||
|
||||
val = PyTuple_GET_ITEM(args, i);
|
||||
if (-1 == PyObject_SetAttr(self, name, val)) {
|
||||
Py_DECREF(pair);
|
||||
|
@ -3977,25 +3993,19 @@ PyTypeObject Array_Type = {
|
|||
PyObject *
|
||||
CreateArrayType(PyObject *itemtype, Py_ssize_t length)
|
||||
{
|
||||
static PyObject *cache;
|
||||
PyObject *key;
|
||||
PyObject *result;
|
||||
char name[256];
|
||||
|
||||
if (cache == NULL) {
|
||||
cache = PyDict_New();
|
||||
if (cache == NULL)
|
||||
return NULL;
|
||||
}
|
||||
key = Py_BuildValue("(On)", itemtype, length);
|
||||
if (!key)
|
||||
return NULL;
|
||||
result = PyDict_GetItem(cache, key);
|
||||
result = PyObject_GetItem(array_types_cache, key);
|
||||
if (result) {
|
||||
Py_INCREF(result);
|
||||
Py_DECREF(key);
|
||||
return result;
|
||||
}
|
||||
} else
|
||||
PyErr_Clear();
|
||||
|
||||
if (!PyType_Check(itemtype)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
|
@ -4021,7 +4031,11 @@ CreateArrayType(PyObject *itemtype, Py_ssize_t length)
|
|||
);
|
||||
if (!result)
|
||||
return NULL;
|
||||
PyDict_SetItem(cache, key, result);
|
||||
if (-1 == PyObject_SetItem(array_types_cache, key, result)) {
|
||||
Py_DECREF(key);
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
Py_DECREF(key);
|
||||
return result;
|
||||
}
|
||||
|
@ -4778,6 +4792,7 @@ PyMODINIT_FUNC
|
|||
init_ctypes(void)
|
||||
{
|
||||
PyObject *m;
|
||||
PyObject *weakref;
|
||||
|
||||
/* Note:
|
||||
ob_type is the metatype (the 'type'), defaults to PyType_Type,
|
||||
|
@ -4790,6 +4805,16 @@ init_ctypes(void)
|
|||
if (!m)
|
||||
return;
|
||||
|
||||
weakref = PyImport_ImportModule("weakref");
|
||||
if (weakref == NULL)
|
||||
return;
|
||||
array_types_cache = PyObject_CallMethod(weakref,
|
||||
"WeakValueDictionary",
|
||||
NULL);
|
||||
if (array_types_cache == NULL)
|
||||
return;
|
||||
Py_DECREF(weakref);
|
||||
|
||||
if (PyType_Ready(&PyCArg_Type) < 0)
|
||||
return;
|
||||
|
||||
|
|
|
@ -983,7 +983,7 @@ Q_get_sw(void *ptr, Py_ssize_t size)
|
|||
|
||||
|
||||
static PyObject *
|
||||
D_set(void *ptr, PyObject *value, Py_ssize_t size)
|
||||
g_set(void *ptr, PyObject *value, Py_ssize_t size)
|
||||
{
|
||||
long double x;
|
||||
|
||||
|
@ -999,7 +999,7 @@ D_set(void *ptr, PyObject *value, Py_ssize_t size)
|
|||
}
|
||||
|
||||
static PyObject *
|
||||
D_get(void *ptr, Py_ssize_t size)
|
||||
g_get(void *ptr, Py_ssize_t size)
|
||||
{
|
||||
long double val;
|
||||
memcpy(&val, ptr, sizeof(long double));
|
||||
|
@ -1630,7 +1630,7 @@ static struct fielddesc formattable[] = {
|
|||
{ 'B', B_set, B_get, &ffi_type_uchar},
|
||||
{ 'c', c_set, c_get, &ffi_type_schar},
|
||||
{ 'd', d_set, d_get, &ffi_type_double, d_set_sw, d_get_sw},
|
||||
{ 'D', D_set, D_get, &ffi_type_longdouble},
|
||||
{ 'g', g_set, g_get, &ffi_type_longdouble},
|
||||
{ 'f', f_set, f_get, &ffi_type_float, f_set_sw, f_get_sw},
|
||||
{ 'h', h_set, h_get, &ffi_type_sshort, h_set_sw, h_get_sw},
|
||||
{ 'H', H_set, H_get, &ffi_type_ushort, H_set_sw, H_get_sw},
|
||||
|
|
Loading…
Reference in a new issue