summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/ctypes/test/test_structures.py9
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/_ctypes/_ctypes.c15
3 files changed, 27 insertions, 0 deletions
diff --git a/Lib/ctypes/test/test_structures.py b/Lib/ctypes/test/test_structures.py
index f9a1109..3005e82 100644
--- a/Lib/ctypes/test/test_structures.py
+++ b/Lib/ctypes/test/test_structures.py
@@ -215,6 +215,15 @@ class StructureTestCase(unittest.TestCase):
# 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)
+
+ # Should this raise TypeError instead?
+ self.assertRaises(ValueError, POINT, 2, 3, 4)
def test_keyword_initializers(self):
class POINT(Structure):
diff --git a/Misc/NEWS b/Misc/NEWS
index 0a7d00c..29bd3dd 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -364,6 +364,9 @@ Core and builtins
Library
-------
+- Issue #1831: ctypes now raises a TypeError if conflicting positional
+ and named arguments are passed to a Structure or Union initializer.
+
- Convert the internal ctypes array type cache to a WeakValueDict so
that array types do not live longer than needed.
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 1ff8e12..8c66194 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -3578,6 +3578,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);