Kaydet (Commit) ff721221 authored tarafından Thomas Heller's avatar Thomas Heller

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.
........
üst 9893de1b
...@@ -182,7 +182,7 @@ class c_double(_SimpleCData): ...@@ -182,7 +182,7 @@ class c_double(_SimpleCData):
_check_size(c_double) _check_size(c_double)
class c_longdouble(_SimpleCData): class c_longdouble(_SimpleCData):
_type_ = "D" _type_ = "g"
if sizeof(c_longdouble) == sizeof(c_double): if sizeof(c_longdouble) == sizeof(c_double):
c_longdouble = c_double c_longdouble = c_double
......
...@@ -116,5 +116,19 @@ class ArrayTestCase(unittest.TestCase): ...@@ -116,5 +116,19 @@ class ArrayTestCase(unittest.TestCase):
self.failUnlessEqual(sz[1:4:2], "o") self.failUnlessEqual(sz[1:4:2], "o")
self.failUnlessEqual(sz.value, "foo") 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__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -215,6 +215,15 @@ class StructureTestCase(unittest.TestCase): ...@@ -215,6 +215,15 @@ class StructureTestCase(unittest.TestCase):
# too long # too long
self.assertRaises(ValueError, Person, "1234567", 5) 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): def test_keyword_initializers(self):
class POINT(Structure): class POINT(Structure):
...@@ -305,9 +314,9 @@ class StructureTestCase(unittest.TestCase): ...@@ -305,9 +314,9 @@ class StructureTestCase(unittest.TestCase):
self.failUnlessEqual(cls, RuntimeError) self.failUnlessEqual(cls, RuntimeError)
if issubclass(Exception, object): if issubclass(Exception, object):
self.failUnlessEqual(msg, self.failUnlessEqual(msg,
"(Phone) <type 'ValueError'>: too many initializers") "(Phone) <type 'TypeError'>: too many initializers")
else: else:
self.failUnlessEqual(msg, "(Phone) ValueError: too many initializers") self.failUnlessEqual(msg, "(Phone) TypeError: too many initializers")
def get_except(self, func, *args): def get_except(self, func, *args):
......
...@@ -122,6 +122,7 @@ bytes(cdata) ...@@ -122,6 +122,7 @@ bytes(cdata)
PyObject *PyExc_ArgError; PyObject *PyExc_ArgError;
static PyTypeObject Simple_Type; static PyTypeObject Simple_Type;
PyObject *array_types_cache;
char *conversion_mode_encoding = NULL; char *conversion_mode_encoding = NULL;
char *conversion_mode_errors = NULL; char *conversion_mode_errors = NULL;
...@@ -1112,7 +1113,7 @@ _type_ attribute. ...@@ -1112,7 +1113,7 @@ _type_ attribute.
*/ */
static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOvtD"; static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOvtg";
static PyObject * static PyObject *
c_wchar_p_from_param(PyObject *type, PyObject *value) c_wchar_p_from_param(PyObject *type, PyObject *value)
...@@ -3535,7 +3536,7 @@ Struct_init(PyObject *self, PyObject *args, PyObject *kwds) ...@@ -3535,7 +3536,7 @@ Struct_init(PyObject *self, PyObject *args, PyObject *kwds)
if (PyTuple_GET_SIZE(args) > PySequence_Length(fields)) { if (PyTuple_GET_SIZE(args) > PySequence_Length(fields)) {
Py_DECREF(fields); Py_DECREF(fields);
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_TypeError,
"too many initializers"); "too many initializers");
return -1; return -1;
} }
...@@ -3556,6 +3557,21 @@ Struct_init(PyObject *self, PyObject *args, PyObject *kwds) ...@@ -3556,6 +3557,21 @@ Struct_init(PyObject *self, PyObject *args, PyObject *kwds)
return IBUG("_fields_[i][0] failed"); 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); val = PyTuple_GET_ITEM(args, i);
if (-1 == PyObject_SetAttr(self, name, val)) { if (-1 == PyObject_SetAttr(self, name, val)) {
Py_DECREF(pair); Py_DECREF(pair);
...@@ -3977,25 +3993,19 @@ PyTypeObject Array_Type = { ...@@ -3977,25 +3993,19 @@ PyTypeObject Array_Type = {
PyObject * PyObject *
CreateArrayType(PyObject *itemtype, Py_ssize_t length) CreateArrayType(PyObject *itemtype, Py_ssize_t length)
{ {
static PyObject *cache;
PyObject *key; PyObject *key;
PyObject *result; PyObject *result;
char name[256]; char name[256];
if (cache == NULL) {
cache = PyDict_New();
if (cache == NULL)
return NULL;
}
key = Py_BuildValue("(On)", itemtype, length); key = Py_BuildValue("(On)", itemtype, length);
if (!key) if (!key)
return NULL; return NULL;
result = PyDict_GetItem(cache, key); result = PyObject_GetItem(array_types_cache, key);
if (result) { if (result) {
Py_INCREF(result);
Py_DECREF(key); Py_DECREF(key);
return result; return result;
} } else
PyErr_Clear();
if (!PyType_Check(itemtype)) { if (!PyType_Check(itemtype)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
...@@ -4021,7 +4031,11 @@ CreateArrayType(PyObject *itemtype, Py_ssize_t length) ...@@ -4021,7 +4031,11 @@ CreateArrayType(PyObject *itemtype, Py_ssize_t length)
); );
if (!result) if (!result)
return NULL; 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); Py_DECREF(key);
return result; return result;
} }
...@@ -4778,6 +4792,7 @@ PyMODINIT_FUNC ...@@ -4778,6 +4792,7 @@ PyMODINIT_FUNC
init_ctypes(void) init_ctypes(void)
{ {
PyObject *m; PyObject *m;
PyObject *weakref;
/* Note: /* Note:
ob_type is the metatype (the 'type'), defaults to PyType_Type, ob_type is the metatype (the 'type'), defaults to PyType_Type,
...@@ -4790,6 +4805,16 @@ init_ctypes(void) ...@@ -4790,6 +4805,16 @@ init_ctypes(void)
if (!m) if (!m)
return; 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) if (PyType_Ready(&PyCArg_Type) < 0)
return; return;
......
...@@ -983,7 +983,7 @@ Q_get_sw(void *ptr, Py_ssize_t size) ...@@ -983,7 +983,7 @@ Q_get_sw(void *ptr, Py_ssize_t size)
static PyObject * 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; long double x;
...@@ -999,7 +999,7 @@ D_set(void *ptr, PyObject *value, Py_ssize_t size) ...@@ -999,7 +999,7 @@ D_set(void *ptr, PyObject *value, Py_ssize_t size)
} }
static PyObject * static PyObject *
D_get(void *ptr, Py_ssize_t size) g_get(void *ptr, Py_ssize_t size)
{ {
long double val; long double val;
memcpy(&val, ptr, sizeof(long double)); memcpy(&val, ptr, sizeof(long double));
...@@ -1630,7 +1630,7 @@ static struct fielddesc formattable[] = { ...@@ -1630,7 +1630,7 @@ static struct fielddesc formattable[] = {
{ 'B', B_set, B_get, &ffi_type_uchar}, { 'B', B_set, B_get, &ffi_type_uchar},
{ 'c', c_set, c_get, &ffi_type_schar}, { '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_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}, { '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_sshort, h_set_sw, h_get_sw},
{ 'H', H_set, H_get, &ffi_type_ushort, H_set_sw, H_get_sw}, { 'H', H_set, H_get, &ffi_type_ushort, H_set_sw, H_get_sw},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment