diff options
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | docs/reference/ChangeLog | 14 | ||||
-rw-r--r-- | docs/reference/pygtk-gdkcolor.xml | 24 | ||||
-rw-r--r-- | docs/reference/pygtk-gdkrectangle.xml | 12 | ||||
-rw-r--r-- | docs/reference/pygtk-gdkregion.xml | 11 | ||||
-rw-r--r-- | gtk/gdk.override | 31 | ||||
-rw-r--r-- | gtk/gdkcolor.override | 31 | ||||
-rw-r--r-- | gtk/gdkrectangle.override | 33 | ||||
-rw-r--r-- | tests/Makefile.am | 40 | ||||
-rw-r--r-- | tests/test_color.py | 60 | ||||
-rw-r--r-- | tests/test_conversion.py | 29 | ||||
-rw-r--r-- | tests/test_rectangle.py | 28 |
12 files changed, 286 insertions, 48 deletions
@@ -1,3 +1,24 @@ +2008-08-02 Paul Pogonyshev <pogonyshev@gmx.net> + + Bug 527212 – types with well-defined equality semantics are not + properly comparable + + * gtk/gdk.override (_wrap_pygdk_region_tp_richcompare): New + function. + + * gtk/gdkcolor.override (_wrap_gdk_color_tp_richcompare): New + function. + + * gtk/gdkrectangle.override (_wrap_gdk_rectangle_tp_richcompare): + New function. + + * tests/test_conversion.py (testColorCreation): Move to thematic + test file. + + * tests/Makefile.am: + * tests/test_color.py: + * tests/test_rectangle.py: Two new test files. + 2008-07-29 Gian Mario Tagliaretti <gianmt@gnome.org> * configure.ac: pygobject 2.15.3 is required to compile pygtk 2.14. diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index 0635f42e..00db8482 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,17 @@ +2008-08-02 Paul Pogonyshev <pogonyshev@gmx.net> + + Bug 527212 – types with well-defined equality semantics are not + properly comparable + + * pygtk-gdkcolor.xml: Document new constructor option. Document + proper comparison as of PyGTK 2.14. + + * pygtk-gdkregion.xml: Document proper comparison as of PyGTK + 2.14. + + * pygtk-gdkrectangle.xml: Document proper comparison as of PyGTK + 2.14. + 2008-07-26 Paul Pogonyshev <pogonyshev@gmx.net> * pygtk-gtkbuilder.xml (connect_signals): Fix signature and diff --git a/docs/reference/pygtk-gdkcolor.xml b/docs/reference/pygtk-gdkcolor.xml index ccd69e8b..efc21fd6 100644 --- a/docs/reference/pygtk-gdkcolor.xml +++ b/docs/reference/pygtk-gdkcolor.xml @@ -109,6 +109,14 @@ objects since these colors will be allocated when an attempt is made to use the <link linkend="class-gtkstyle"><classname>gtk.Style</classname></link> object.</para> + <para> + Starting with PyGTK 2.14 <classname>gtk.gdk.Color</classname> objects are properly + comparable. By Python rules, colors (being mutable) are now unhashable. If you + need to use them as dictionary keys, use string representation instead. You can + convert string representation to <classname>gtk.gdk.Color</classname> objects using + the constructor. + </para> + </refsect1> <refsect1 id="constructor-gdkcolor"> @@ -128,6 +136,11 @@ object.</para> <methodparam><parameter role="keyword">pixel</parameter> <initializer>0</initializer></methodparam> + </constructorsynopsis></programlisting> + <programlisting><constructorsynopsis language="python"> + <methodname>gtk.gdk.Color</methodname> + <methodparam><parameter + role="keyword">spec</parameter></methodparam> </constructorsynopsis></programlisting> <variablelist> <varlistentry> @@ -151,6 +164,10 @@ object.</para> colormap</simpara></listitem> </varlistentry> <varlistentry> + <term><parameter role="keyword">spec</parameter> :</term> + <listitem><simpara>String containing color specification</simpara></listitem> + </varlistentry> + <varlistentry> <term><emphasis>Returns</emphasis> :</term> <listitem><simpara>a new <link linkend="class-gdkcolor"><classname>gtk.gdk.Color</classname></link> @@ -158,6 +175,10 @@ object</simpara></listitem> </varlistentry> </variablelist> + <note> + <para>Second form of the constructor is available in PyGTK 2.14 and above.</para> + </note> + <para>Creates a new <link linkend="class-gdkcolor"><classname>gtk.gdk.Color</classname></link> object with the color component values specified by <parameter>red</parameter>, @@ -166,6 +187,9 @@ with the color component values specified by <parameter>red</parameter>, value of <parameter>pixel</parameter> will be overwritten when the color is allocated.</para> + <para>Second form of the constructor is analogous to + <link linkend="function-gdk--color-parse"><function>gtk.gdk.color_parse</function></link>.</para> + </refsect1> <refsect1> diff --git a/docs/reference/pygtk-gdkrectangle.xml b/docs/reference/pygtk-gdkrectangle.xml index 19de9bb3..222ab3f5 100644 --- a/docs/reference/pygtk-gdkrectangle.xml +++ b/docs/reference/pygtk-gdkrectangle.xml @@ -101,6 +101,18 @@ holds the position and size of a rectangle. The position is specified by the "x" and "y" attributes and the size, by the "width" and "height" attributes.</para> + <para> + Starting with PyGTK 2.14 <classname>gtk.gdk.Rectangle</classname> objects are + properly comparable. By Python rules, rectangles (being mutable) are now + unhashable. If you need to use them as dictionary keys, convert rectangle objects + to tuples first. You can convert such tuples back + to <classname>gtk.gdk.Rectangle</classname> using the following code: + </para> + + <programlisting> + rectangle = gtk.gdk.Rectangle(*tuple) + </programlisting> + </refsect1> <refsect1 id="constructor-gdkrectangle"> diff --git a/docs/reference/pygtk-gdkregion.xml b/docs/reference/pygtk-gdkregion.xml index d2631743..5cfa1830 100644 --- a/docs/reference/pygtk-gdkregion.xml +++ b/docs/reference/pygtk-gdkregion.xml @@ -125,6 +125,12 @@ linkend="function-gdk--region-rectangle">gtk.gdk.region_rectangle</link></method linkend="method-gdkgc--set-clip-region"><methodname>gtk.gdk.GC.set_clip_region</methodname>()</link> method).</para> + <para> + Starting with PyGTK 2.14 <classname>gtk.gdk.Region</classname> objects are + properly comparable. By Python rules, regions (being mutable) are now + unhashable. + </para> + </refsect1> <refsect1 id="constructor-gdkregion"> @@ -228,6 +234,11 @@ object</simpara></listitem> region specified by <parameter>other</parameter> is equal to this region.</para> + <note> + <para>Since PyGTK 2.14 Python comparison operator (<literal>==</literal>) can be + used for the same result.</para> + </note> + </refsect2> <refsect2 id="method-gdkregion--point-in"> diff --git a/gtk/gdk.override b/gtk/gdk.override index cba1ea5d..d56d4e2e 100644 --- a/gtk/gdk.override +++ b/gtk/gdk.override @@ -534,6 +534,37 @@ _wrap_gdk_region_get_rectangles(PyGObject *self) return py_rects; } %% +override-slot GdkRegion.tp_richcompare +static PyObject * +_wrap_pygdk_region_tp_richcompare(PyObject *self, PyObject *other, int op) +{ + PyObject *result; + + if (PyObject_TypeCheck(self, &PyGdkRegion_Type) + && PyObject_TypeCheck(other, &PyGdkRegion_Type)) { + GdkRegion *region1 = pyg_boxed_get(self, GdkRegion); + GdkRegion *region2 = pyg_boxed_get(other, GdkRegion); + + switch (op) { + case Py_EQ: + result = (gdk_region_equal(region1, region2) + ? Py_True : Py_False); + break; + case Py_NE: + result = (!gdk_region_equal(region1, region2) + ? Py_True : Py_False); + break; + default: + result = Py_NotImplemented; + } + } + else + result = Py_NotImplemented; + + Py_INCREF(result); + return result; +} +%% override-attr GdkDevice.axes static PyObject * _wrap_gdk_device__get_axes(PyGObject *self, void *closure) diff --git a/gtk/gdkcolor.override b/gtk/gdkcolor.override index 98f58ee7..fe995265 100644 --- a/gtk/gdkcolor.override +++ b/gtk/gdkcolor.override @@ -190,6 +190,37 @@ _wrap_gdk_color_alloc(PyGObject *self, PyObject *args, PyObject *kwargs) return _wrap_gdk_colormap_alloc_color(self, args, kwargs); } %% +override-slot GdkColor.tp_richcompare +static PyObject * +_wrap_gdk_color_tp_richcompare(PyObject *self, PyObject *other, int op) +{ + PyObject *result; + + if (PyObject_TypeCheck(self, &PyGdkColor_Type) + && PyObject_TypeCheck(other, &PyGdkColor_Type)) { + GdkColor *color1 = pyg_boxed_get(self, GdkColor); + GdkColor *color2 = pyg_boxed_get(other, GdkColor); + + switch (op) { + case Py_EQ: + result = (gdk_color_equal(color1, color2) + ? Py_True : Py_False); + break; + case Py_NE: + result = (!gdk_color_equal(color1, color2) + ? Py_True : Py_False); + break; + default: + result = Py_NotImplemented; + } + } + else + result = Py_NotImplemented; + + Py_INCREF(result); + return result; +} +%% override gdk_colormap_query_color kwargs static PyObject * _wrap_gdk_colormap_query_color(PyGObject *self, PyObject *args, diff --git a/gtk/gdkrectangle.override b/gtk/gdkrectangle.override index e1a0fcf0..06274c42 100644 --- a/gtk/gdkrectangle.override +++ b/gtk/gdkrectangle.override @@ -214,3 +214,36 @@ _wrap_gdk_rectangle_union(PyGObject *self, PyObject *args, return pyg_boxed_new(GDK_TYPE_RECTANGLE, &dest, TRUE, TRUE); } +%% +override-slot GdkRectangle.tp_richcompare +static PyObject * +_wrap_gdk_rectangle_tp_richcompare(PyObject *self, PyObject *other, int op) +{ + PyObject *result; + + if (PyObject_TypeCheck(self, &PyGdkRectangle_Type) + && PyObject_TypeCheck(other, &PyGdkRectangle_Type)) { + GdkRectangle *rect1 = pyg_boxed_get(self, GdkRectangle); + GdkRectangle *rect2 = pyg_boxed_get(other, GdkRectangle); + + switch (op) { + case Py_EQ: + result = (rect1->x == rect2->x && rect1->y == rect2->y + && rect1->width == rect2->width && rect1->height == rect2->height + ? Py_True : Py_False); + break; + case Py_NE: + result = (rect1->x != rect2->x || rect1->y != rect2->y + || rect1->width != rect2->width || rect1->height != rect2->height + ? Py_True : Py_False); + break; + default: + result = Py_NotImplemented; + } + } + else + result = Py_NotImplemented; + + Py_INCREF(result); + return result; +} diff --git a/tests/Makefile.am b/tests/Makefile.am index e5756f4c..3ca928b9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,24 +1,26 @@ EXTRA_DIST = $(tests) common.py runtests.py testmodule.py leak.glade -tests = \ - test_actiongroup.py \ - test_api.py \ - test_bin.py \ - test_button.py \ - test_container.py - test_conversion.py \ - test_dialog.py \ - test_enum.py \ - test_gdk.py \ - test_glade.py \ - test_liststore.py - test_pango.py \ - test_plug.py \ - test_radiobutton.py \ - test_style.py \ - test_textview.py \ - test_treeview.py \ - test_filechooserdialog.py +tests = \ + test_actiongroup.py \ + test_api.py \ + test_bin.py \ + test_button.py \ + test_color.py \ + test_container.py \ + test_conversion.py \ + test_dialog.py \ + test_enum.py \ + test_filechooserdialog.py \ + test_gdk.py \ + test_glade.py \ + test_liststore.py \ + test_pango.py \ + test_plug.py \ + test_radiobutton.py \ + test_rectangle.py \ + test_style.py \ + test_textview.py \ + test_treeview.py GTK_PY_FILES = __init__.py _lazyutils.py compat.py deprecation.py keysyms.py diff --git a/tests/test_color.py b/tests/test_color.py new file mode 100644 index 00000000..616c716e --- /dev/null +++ b/tests/test_color.py @@ -0,0 +1,60 @@ +# -*- Mode: Python -*- + +import unittest + +from common import gtk + + +class Tests(unittest.TestCase): + + def test_constructor(self): + """ Test GdkColor creation """ + + c = gtk.gdk.Color(1, 2, 3) + self.assertEqual(c.red, 1) + self.assertEqual(c.green, 2) + self.assertEqual(c.blue, 3) + + c = gtk.gdk.Color(pixel=0xffff) + self.assertEqual(c.pixel, 0xffff) + + c = gtk.gdk.Color(pixel=0xffffL) + self.assertEqual(c.pixel, 0xffff) + + c = gtk.gdk.Color(pixel=0xffffffffL) + self.assertEqual(c.pixel, 0xffffffffL) + + c = gtk.gdk.Color('red') + self.assertEqual(c.red, 65535) + self.assertEqual(c.green, 0) + self.assertEqual(c.blue, 0) + + c = gtk.gdk.Color('#ff0000') + self.assertEqual(c.red, 65535) + self.assertEqual(c.green, 0) + self.assertEqual(c.blue, 0) + + self.assertRaises(TypeError, lambda: gtk.gdk.Color([])) + + def test_equal(self): + self.assertEqual(gtk.gdk.Color(0, 0, 0), gtk.gdk.Color(0, 0, 0)) + self.assertEqual(gtk.gdk.Color(100, 200, 300), gtk.gdk.Color(100, 200, 300)) + self.assertEqual(gtk.gdk.Color('#abc'), gtk.gdk.Color('#aabbcc')) + self.assertEqual(gtk.gdk.Color('#100020003000'), gtk.gdk.Color(0x1000, 0x2000, 0x3000)) + + def test_not_equal(self): + self.assertNotEqual(gtk.gdk.Color('red'), gtk.gdk.Color('blue')) + self.assertNotEqual(gtk.gdk.Color(1, 0, 0), gtk.gdk.Color(0, 0, 0)) + self.assertNotEqual(gtk.gdk.Color(0, 1, 0), gtk.gdk.Color(0, 0, 0)) + self.assertNotEqual(gtk.gdk.Color(0, 0, 1), gtk.gdk.Color(0, 0, 0)) + + def test_non_hashable(self): + self.assertRaises(TypeError, lambda: hash(gtk.gdk.Color())) + + def dict_key(): + {} [gtk.gdk.Color()] = 'must raise' + self.assertRaises(TypeError, dict_key) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_conversion.py b/tests/test_conversion.py index a63d7914..2642d11e 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -52,35 +52,6 @@ class Tests(unittest.TestCase): self.assertEqual(entry.get_property('invisible_char'), valid_value, valid_value) - def testColorCreation(self): - """ Test GdkColor creation """ - - c = gtk.gdk.Color(1, 2, 3) - self.assertEqual(c.red, 1) - self.assertEqual(c.green, 2) - self.assertEqual(c.blue, 3) - - c = gtk.gdk.Color(pixel=0xffff) - self.assertEqual(c.pixel, 0xffff) - - c = gtk.gdk.Color(pixel=0xffffL) - self.assertEqual(c.pixel, 0xffff) - - c = gtk.gdk.Color(pixel=0xffffffffL) - self.assertEqual(c.pixel, 0xffffffffL) - - c = gtk.gdk.Color('red') - self.assertEqual(c.red, 65535) - self.assertEqual(c.green, 0) - self.assertEqual(c.blue, 0) - - c = gtk.gdk.Color('#ff0000') - self.assertEqual(c.red, 65535) - self.assertEqual(c.green, 0) - self.assertEqual(c.blue, 0) - - self.assertRaises(TypeError, lambda: gtk.gdk.Color([])) - def testUIntArg(self): child = gtk.DrawingArea() table = gtk.Table(2, 2, False) diff --git a/tests/test_rectangle.py b/tests/test_rectangle.py new file mode 100644 index 00000000..ab5b0646 --- /dev/null +++ b/tests/test_rectangle.py @@ -0,0 +1,28 @@ +# -*- Mode: Python -*- + +import unittest + +from common import gtk + + +class Tests(unittest.TestCase): + + def test_equal(self): + self.assertEqual(gtk.gdk.Rectangle(0, 0, 1, 1), gtk.gdk.Rectangle(0, 0, 1, 1)) + + def test_not_equal(self): + self.assertNotEqual(gtk.gdk.Rectangle(1, 0, 10, 10), gtk.gdk.Rectangle(0, 0, 10, 10)) + self.assertNotEqual(gtk.gdk.Rectangle(0, 1, 10, 10), gtk.gdk.Rectangle(0, 0, 10, 10)) + self.assertNotEqual(gtk.gdk.Rectangle(0, 0, 11, 10), gtk.gdk.Rectangle(0, 0, 10, 10)) + self.assertNotEqual(gtk.gdk.Rectangle(0, 0, 10, 11), gtk.gdk.Rectangle(0, 0, 10, 10)) + + def test_non_hashable(self): + self.assertRaises(TypeError, lambda: hash(gtk.gdk.Rectangle())) + + def dict_key(): + {} [gtk.gdk.Rectangle()] = 'must raise' + self.assertRaises(TypeError, dict_key) + + +if __name__ == '__main__': + unittest.main() |