Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d7cb1b9

Browse files
author
Thomas Heller
committed
Merged revisions 74917 via svnmerge from
svn+ssh://[email protected]/python/trunk ........ r74917 | thomas.heller | 2009-09-18 20:55:17 +0200 (Fr, 18 Sep 2009) | 3 lines Issue #5042: Structure sub-subclass does now initialize correctly with base class positional arguments. ........ Also made small stylistic changes.
1 parent a91ded2 commit d7cb1b9

3 files changed

Lines changed: 95 additions & 58 deletions

File tree

Lib/ctypes/test/test_structures.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,25 @@ def test_methods(self):
349349
self.assertTrue("from_address" in dir(type(Structure)))
350350
self.assertTrue("in_dll" in dir(type(Structure)))
351351

352+
def test_positional_args(self):
353+
# see also http://bugs.python.org/issue5042
354+
class W(Structure):
355+
_fields_ = [("a", c_int), ("b", c_int)]
356+
class X(W):
357+
_fields_ = [("c", c_int)]
358+
class Y(X):
359+
pass
360+
class Z(Y):
361+
_fields_ = [("d", c_int), ("e", c_int), ("f", c_int)]
362+
363+
z = Z(1, 2, 3, 4, 5, 6)
364+
self.assertEqual((z.a, z.b, z.c, z.d, z.e, z.f),
365+
(1, 2, 3, 4, 5, 6))
366+
z = Z(1)
367+
self.assertEqual((z.a, z.b, z.c, z.d, z.e, z.f),
368+
(1, 0, 0, 0, 0, 0))
369+
self.assertRaises(TypeError, lambda: Z(1, 2, 3, 4, 5, 6, 7))
370+
352371
class PointerMemberTestCase(unittest.TestCase):
353372

354373
def test(self):

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ C-API
7272
Library
7373
-------
7474

75+
- Issue #5042: Structure sub-subclass does now initialize correctly
76+
with base class positional arguments.
77+
7578
- Issue #6882: Import uuid creates zombies processes.
7679

7780
- Issue #6635: Fix profiler printing usage message.

Modules/_ctypes/_ctypes.c

Lines changed: 73 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3936,82 +3936,97 @@ IBUG(char *msg)
39363936
return -1;
39373937
}
39383938

3939+
/*
3940+
This function is called to initialize a Structure or Union with positional
3941+
arguments. It calls itself recursively for all Structure or Union base
3942+
classes, then retrieves the _fields_ member to associate the argument
3943+
position with the correct field name.
3944+
3945+
Returns -1 on error, or the index of next argument on success.
3946+
*/
39393947
static int
3940-
Struct_init(PyObject *self, PyObject *args, PyObject *kwds)
3948+
_init_pos_args(PyObject *self, PyTypeObject *type,
3949+
PyObject *args, PyObject *kwds,
3950+
int index)
39413951
{
3942-
int i;
3952+
StgDictObject *dict;
39433953
PyObject *fields;
3954+
int i;
3955+
3956+
if (PyType_stgdict((PyObject *)type->tp_base)) {
3957+
index = _init_pos_args(self, type->tp_base,
3958+
args, kwds,
3959+
index);
3960+
if (index == -1)
3961+
return -1;
3962+
}
3963+
3964+
dict = PyType_stgdict((PyObject *)type);
3965+
fields = PyDict_GetItemString((PyObject *)dict, "_fields_");
3966+
if (fields == NULL)
3967+
return index;
3968+
3969+
for (i = 0;
3970+
i < dict->length && (i+index) < PyTuple_GET_SIZE(args);
3971+
++i) {
3972+
PyObject *pair = PySequence_GetItem(fields, i);
3973+
PyObject *name, *val;
3974+
int res;
3975+
if (!pair)
3976+
return -1;
3977+
name = PySequence_GetItem(pair, 0);
3978+
if (!name) {
3979+
Py_DECREF(pair);
3980+
return -1;
3981+
}
3982+
val = PyTuple_GET_ITEM(args, i + index);
3983+
if (kwds && PyDict_GetItem(kwds, name)) {
3984+
char *field = PyBytes_AsString(name);
3985+
if (field == NULL) {
3986+
PyErr_Clear();
3987+
field = "???";
3988+
}
3989+
PyErr_Format(PyExc_TypeError,
3990+
"duplicate values for field '%s'",
3991+
field);
3992+
Py_DECREF(pair);
3993+
Py_DECREF(name);
3994+
return -1;
3995+
}
3996+
3997+
res = PyObject_SetAttr(self, name, val);
3998+
Py_DECREF(pair);
3999+
Py_DECREF(name);
4000+
if (res == -1)
4001+
return -1;
4002+
}
4003+
return index + dict->length;
4004+
}
4005+
4006+
static int
4007+
Struct_init(PyObject *self, PyObject *args, PyObject *kwds)
4008+
{
4009+
StgDictObject *stgdict = PyObject_stgdict(self);
39444010

39454011
/* Optimization possible: Store the attribute names _fields_[x][0]
39464012
* in C accessible fields somewhere ?
39474013
*/
39484014

3949-
/* Check this code again for correctness! */
3950-
39514015
if (!PyTuple_Check(args)) {
39524016
PyErr_SetString(PyExc_TypeError,
39534017
"args not a tuple?");
39544018
return -1;
39554019
}
39564020
if (PyTuple_GET_SIZE(args)) {
3957-
fields = PyObject_GetAttrString(self, "_fields_");
3958-
if (!fields) {
3959-
PyErr_Clear();
3960-
fields = PyTuple_New(0);
3961-
if (!fields)
3962-
return -1;
3963-
}
3964-
3965-
if (PyTuple_GET_SIZE(args) > PySequence_Length(fields)) {
3966-
Py_DECREF(fields);
4021+
int res = _init_pos_args(self, Py_TYPE(self),
4022+
args, kwds, 0);
4023+
if (res == -1)
4024+
return -1;
4025+
if (res < PyTuple_GET_SIZE(args)) {
39674026
PyErr_SetString(PyExc_TypeError,
39684027
"too many initializers");
39694028
return -1;
39704029
}
3971-
3972-
for (i = 0; i < PyTuple_GET_SIZE(args); ++i) {
3973-
PyObject *pair = PySequence_GetItem(fields, i);
3974-
PyObject *name;
3975-
PyObject *val;
3976-
if (!pair) {
3977-
Py_DECREF(fields);
3978-
return IBUG("_fields_[i] failed");
3979-
}
3980-
3981-
name = PySequence_GetItem(pair, 0);
3982-
if (!name) {
3983-
Py_DECREF(pair);
3984-
Py_DECREF(fields);
3985-
return IBUG("_fields_[i][0] failed");
3986-
}
3987-
3988-
if (kwds && PyDict_GetItem(kwds, name)) {
3989-
char *field = PyBytes_AsString(name);
3990-
if (field == NULL) {
3991-
PyErr_Clear();
3992-
field = "???";
3993-
}
3994-
PyErr_Format(PyExc_TypeError,
3995-
"duplicate values for field %s",
3996-
field);
3997-
Py_DECREF(pair);
3998-
Py_DECREF(name);
3999-
Py_DECREF(fields);
4000-
return -1;
4001-
}
4002-
4003-
val = PyTuple_GET_ITEM(args, i);
4004-
if (-1 == PyObject_SetAttr(self, name, val)) {
4005-
Py_DECREF(pair);
4006-
Py_DECREF(name);
4007-
Py_DECREF(fields);
4008-
return -1;
4009-
}
4010-
4011-
Py_DECREF(name);
4012-
Py_DECREF(pair);
4013-
}
4014-
Py_DECREF(fields);
40154030
}
40164031

40174032
if (kwds) {

0 commit comments

Comments
 (0)