diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | gobject/pygenum.c | 37 | ||||
-rw-r--r-- | tests/test_enum.py | 9 |
3 files changed, 46 insertions, 8 deletions
@@ -1,3 +1,11 @@ +2008-04-02 Paul Pogonyshev <pogonyshev@gmx.net> + + * gobject/pygenum.c: bug #428732 + (pyg_enum_new): Fix two wrong assertions about '__enum_values__' + size and contents. + (pyg_enum_reduce): New function (based on patch by Phil Dumont). + (pyg_enum_methods): Hook it up. + 2008-03-24 Paul Pogonyshev <pogonyshev@gmx.net> * gobject/pygenum.c (pyg_enum_richcompare): Don't return NULL diff --git a/gobject/pygenum.c b/gobject/pygenum.c index 876e464..2d6c544 100644 --- a/gobject/pygenum.c +++ b/gobject/pygenum.c @@ -99,19 +99,25 @@ pyg_enum_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) eclass = G_ENUM_CLASS(g_type_class_ref(gtype)); - if (value < 0 || value > eclass->n_values) { - PyErr_SetString(PyExc_ValueError, "value out of range"); - g_type_class_unref(eclass); - return NULL; - } + /* A check that 0 < value < eclass->n_values was here but got + * removed: enumeration values do not need to be consequitive, + * e.g. GtkPathPriorityType values are not. + */ values = PyObject_GetAttrString((PyObject *)type, "__enum_values__"); if (!values) { g_type_class_unref(eclass); return NULL; } - - if (!PyDict_Check(values) || PyDict_Size(values) != eclass->n_values) { + + /* Note that size of __enum_values__ dictionary can easily be less + * than 'n_values'. This happens if some values of the enum are + * numerically equal, e.g. gtk.ANCHOR_N == gtk.ANCHOR_NORTH. + * Johan said that "In retrospect, using a dictionary to store the + * values might not have been that good", but we need to keep + * backward compatibility. + */ + if (!PyDict_Check(values) || PyDict_Size(values) > eclass->n_values) { PyErr_SetString(PyExc_TypeError, "__enum_values__ badly formed"); Py_DECREF(values); g_type_class_unref(eclass); @@ -253,6 +259,16 @@ pyg_enum_add (PyObject * module, } static PyObject * +pyg_enum_reduce(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, ":GEnum.__reduce__")) + return NULL; + + return Py_BuildValue("(O(i)O)", self->ob_type, PyInt_AsLong(self), + PyObject_GetAttrString(self, "__dict__")); +} + +static PyObject * pyg_enum_get_value_name(PyGEnum *self, void *closure) { GEnumClass *enum_class; @@ -289,6 +305,11 @@ pyg_enum_get_value_nick(PyGEnum *self, void *closure) } +static PyMethodDef pyg_enum_methods[] = { + { "__reduce__", (PyCFunction)pyg_enum_reduce, METH_VARARGS }, + { NULL, NULL, 0 } +}; + static PyGetSetDef pyg_enum_getsets[] = { { "value_name", (getter)pyg_enum_get_value_name, (setter)0 }, { "value_nick", (getter)pyg_enum_get_value_nick, (setter)0 }, @@ -324,7 +345,7 @@ PyTypeObject PyGEnum_Type = { 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - 0, /* tp_methods */ + pyg_enum_methods, /* tp_methods */ 0, /* tp_members */ pyg_enum_getsets, /* tp_getset */ 0, /* tp_base */ diff --git a/tests/test_enum.py b/tests/test_enum.py index 6543cec..41d72a2 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -1,3 +1,4 @@ +import pickle import unittest import warnings @@ -96,6 +97,14 @@ class EnumTest(unittest.TestCase): self.failUnless(isinstance(default, gtk.WindowType)) self.assertEqual(default, gtk.WINDOW_TOPLEVEL) + def testPickling(self): + values = [getattr(gtk, name) for name in dir(gtk) + if isinstance(getattr(gtk, name), gobject.GEnum)] + for protocol in range(0, pickle.HIGHEST_PROTOCOL + 1): + for value in values: + self.assertEqual(value, pickle.loads(pickle.dumps(value, protocol))) + + class FlagsTest(unittest.TestCase): def testFlags(self): self.failUnless(issubclass(GFlags, int)) |