Author: thomas.heller
Date: Thu Jan 17 19:46:55 2008
New Revision: 60023

Modified:
   python/branches/py3k/   (props changed)
   python/branches/py3k/Lib/ctypes/__init__.py
   python/branches/py3k/Lib/ctypes/test/test_arrays.py
   python/branches/py3k/Lib/ctypes/test/test_structures.py
   python/branches/py3k/Modules/_ctypes/_ctypes.c
   python/branches/py3k/Modules/_ctypes/cfield.c
Log:
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.
........


Modified: python/branches/py3k/Lib/ctypes/__init__.py
==============================================================================
--- python/branches/py3k/Lib/ctypes/__init__.py (original)
+++ python/branches/py3k/Lib/ctypes/__init__.py Thu Jan 17 19:46:55 2008
@@ -182,7 +182,7 @@
 _check_size(c_double)
 
 class c_longdouble(_SimpleCData):
-    _type_ = "D"
+    _type_ = "g"
 if sizeof(c_longdouble) == sizeof(c_double):
     c_longdouble = c_double
 

Modified: python/branches/py3k/Lib/ctypes/test/test_arrays.py
==============================================================================
--- python/branches/py3k/Lib/ctypes/test/test_arrays.py (original)
+++ python/branches/py3k/Lib/ctypes/test/test_arrays.py Thu Jan 17 19:46:55 2008
@@ -116,5 +116,19 @@
             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()

Modified: python/branches/py3k/Lib/ctypes/test/test_structures.py
==============================================================================
--- python/branches/py3k/Lib/ctypes/test/test_structures.py     (original)
+++ python/branches/py3k/Lib/ctypes/test/test_structures.py     Thu Jan 17 
19:46:55 2008
@@ -215,6 +215,15 @@
         # 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 @@
         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):

Modified: python/branches/py3k/Modules/_ctypes/_ctypes.c
==============================================================================
--- python/branches/py3k/Modules/_ctypes/_ctypes.c      (original)
+++ python/branches/py3k/Modules/_ctypes/_ctypes.c      Thu Jan 17 19:46:55 2008
@@ -122,6 +122,7 @@
 
 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 @@
 
 */
 
-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 @@
 
                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 @@
                                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 @@
 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 @@
                );
        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 @@
 init_ctypes(void)
 {
        PyObject *m;
+       PyObject *weakref;
 
 /* Note:
    ob_type is the metatype (the 'type'), defaults to PyType_Type,
@@ -4790,6 +4805,16 @@
        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;
 

Modified: python/branches/py3k/Modules/_ctypes/cfield.c
==============================================================================
--- python/branches/py3k/Modules/_ctypes/cfield.c       (original)
+++ python/branches/py3k/Modules/_ctypes/cfield.c       Thu Jan 17 19:46:55 2008
@@ -983,7 +983,7 @@
 
 
 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 @@
 }
 
 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 @@
        { '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},
_______________________________________________
Python-3000-checkins mailing list
Python-3000-checkins@python.org
http://mail.python.org/mailman/listinfo/python-3000-checkins

Reply via email to