From 02ec289f3e16ee6b00ecf7ec8f8e0f2a3e1ad152 Mon Sep 17 00:00:00 2001 From: Thomas Heller Date: Wed, 16 Jan 2008 19:37:33 +0000 Subject: [PATCH] Raise a TypeError if conflicting positional and named arguments are passed to a Structure or Union constructor. --- Lib/ctypes/test/test_structures.py | 9 +++++++++ Misc/NEWS | 3 +++ Modules/_ctypes/_ctypes.c | 15 +++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/Lib/ctypes/test/test_structures.py b/Lib/ctypes/test/test_structures.py index f9a11096938..3005e829b3a 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 0a7d00c8031..29bd3dd9397 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 1ff8e12ce5c..8c6619489f7 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);