GNOME Bugzilla – Bug 526189
add __str__ and/or __repr__ to several types
Last modified: 2018-08-17 13:43:35 UTC
PyGTK would be easier to debug if its types provided __str__/__repr__ where meaningful. Currently, they all seem to inherit these methods from 'object', which is less useful than it could be. When implementing, we should also follow Python guidelines about __repr__: if it is possible to construct an equal object, then it should hold that eval (repr (x)) == x given some correct environment. For instance: repr (gtk.gdk.Color (1, 2, 3)) == 'gtk.gdk.Color(1, 2, 3)' If this is going to be accepted in principle, I can start creating patches.
+1 I really like this idea, I don't think there are any real backwards compatibility issues since the __repr__ output is private.
Created attachment 108628 [details] [review] patch for gtk.gdk.Color >>> gtk.gdk.color_parse('goldenrod') gtk.gdk.Color(56026, 42405, 8224) >>> str(gtk.gdk.color_parse('goldenrod')) 'Color(56026, 42405, 8224 [#daa520])' I think it is very useful to be able to easily find HTML-like value of a color, so __str__ is written to provide that.
Created attachment 108629 [details] [review] gtk.GtkStyleHelper __repr__ Only different from default for color arrays, because otherwise it would be quite useless anyway. >>> gtk.Button().style.bg <gtk.GtkStyleHelper object at 0x401a53e0 [colors: #dcdad5, #c4c2bd, #eeebe7, #4b6983, #dcdad5]> >>> str(gtk.Button().style.bg[1]) 'Color(50372, 49858, 48573 [#c4c2bd])' >>> gtk.Button().style.bg_pixmap <gtk.GtkStyleHelper object at 0x401a5668>
(In reply to comment #2) > Created an attachment (id=108628) [edit] > patch for gtk.gdk.Color > > >>> gtk.gdk.color_parse('goldenrod') > gtk.gdk.Color(56026, 42405, 8224) > >>> str(gtk.gdk.color_parse('goldenrod')) > 'Color(56026, 42405, 8224 [#daa520])' > > I think it is very useful to be able to easily find HTML-like value of a color, > so __str__ is written to provide that. > Can we perhaps change the color constructor to actually take a #xxxxxx value, and use that in the serialization?
> Can we perhaps change the color constructor to actually take a #xxxxxx value, > and use that in the serialization? >>> gtk.gdk.color_parse ('#ff00cc') gtk.gdk.Color(65535, 0, 52428) >>> gtk.gdk.Color ('#ff00cc') Traceback (most recent call last):
+ Trace 194643
We can, sort of (add special case: if constructor's argument is string call color_parse instead), but I don't quite like precision loss. It can lead to off-by-one errors in colors if you use a little different rounding than color_parse() does. On the other hand, color_parse() also accepts 12 digits (i.e. when each of RGB is 16 bits, instead of more common 8), so we can use the short form if it gives exact representation, or long form otherwise. This is akin to representation of strings: Python prefers single quotes, but will use double quotes if there is an apostrophe in the string. A more general question: does this look fine in general? I think it'd be better to combine into larger patches, e.g. one per submodule (GDK, Pango...). Also, I thought afterwards that instead of hardcoding type name in the string it is better to use "<%s ...", self->ob_type->tp_name. Runtime performance hit is negligible, but it feels "the right way" to me.
Created attachment 109073 [details] [review] add __repr__ to various GDK types (those deriving from GBoxed) This patch that adds __repr__ to the following types: gtk.gdk.Color, gtk.gdk.Cursor, gtk.gdk.Event and gtk.gdk.Rectangle. There are more types in GDK for which we can add meaningful __repr__ (e.g. for gtk.gdk.Device with device name), but other types derive from gobject.GObject. I'm not sure how to generate repr strings for those in the best way. I.e. currently it is like '<gtk.gdk.Device object at 0x401fbdec (GdkDevice at 0x8291c20)>' --- should customized __repr__ also have information about underlying C object, how it should be combined with additional data? This patch doesn't implement what you proposed about gtk.gdk.Color --- I feel it is better to open a separate issue for that, since proper solution involves additional gtk.gdk.Color.__init__ variant. Examples of this patch in action: >>> gtk.gdk.color_parse('red') gtk.gdk.Color(65535, 0, 0) >>> gtk.gdk.Cursor(gtk.gdk.ARROW) <gtk.gdk.Cursor at 0x401a5680: GDK_ARROW> >>> gtk.gdk.Event(gtk.gdk.ENTER_NOTIFY) <gtk.gdk.Event at 0x401a5698: GDK_ENTER_NOTIFY x=0.00, y=0.00, mode=GDK_CROSSING_NORMAL> >>> gtk.gdk.Rectangle(0, 0, 100, 100) gtk.gdk.Rectangle(0, 0, 100, 100)
Comment on attachment 109073 [details] [review] add __repr__ to various GDK types (those deriving from GBoxed) >Index: gtk/gdkcolor.override >+override-slot GdkCursor.tp_repr >+ return PyString_FromFormat("<%s at %p: %s>", >+ self->ob_type->tp_name, self, >+ type ? type->value_name : "UNKNOWN TYPE"); why not gtk.gdk.Cursor(...) ?
> why not gtk.gdk.Cursor(...) ? Because at least pixmap and pixbuf cursors cannot be recreated this way. Maybe simple type cursors can be, but not any random cursor.
Created attachment 113177 [details] [review] add __repr__ to various GDK types (those deriving from GBoxed): new Color representation Since patch in bug 527718 was committed, I can change representation of gtk.gdk.Color as you proposed: >>> gtk.gdk.Color('red') gtk.gdk.Color('#f00') >>> gtk.gdk.Color('#44fadd') gtk.gdk.Color('#44fadd') >>> c = gtk.gdk.Color(); c.red = 12345; c gtk.gdk.Color('#303900000000') I really should add some unit tests for gtk.gdk.Color and gtk.gdk.Rectangle, but that is impossible before bug 527212 is solved.
Created attachment 115739 [details] [review] _repr__, unit tests and docs for GDK types (those deriving from GBoxed) Patch in action: >>> gtk.gdk.Color('red') gtk.gdk.Color('#f00') >>> str(gtk.gdk.Color('red')) '#f00' >>> gtk.gdk.Color('red').to_string() '#ffff00000000' >>> gtk.gdk.Rectangle(10, 10) gtk.gdk.Rectangle(10, 10, 0, 0) >>> gtk.gdk.Event (gtk.gdk.BUTTON_PRESS) <gtk.gdk.Event at 0x401a9938: GDK_BUTTON_PRESS x=0.00, y=0.00, button=0>
Not closing the bug as there are plenty of other types for which __repr__ will be handy. Sending ChangeLog Sending docs/reference/ChangeLog Sending docs/reference/pygtk-gdkcolor.xml Sending docs/reference/pygtk-gdkevent.xml Sending docs/reference/pygtk-gdkrectangle.xml Sending gtk/gdk.override Sending gtk/gdkcolor.override Sending gtk/gdkevent.override Sending gtk/gdkrectangle.override Sending tests/test_color.py Sending tests/test_rectangle.py Transmitting file data ........... Committed revision 3029. 2008-08-28 Paul Pogonyshev <pogonyshev@gmx.net> Bug 526189 – add __str__ and/or __repr__ to several types * gtk/gdk.override (_wrap_gdk_cursor_tp_repr): New function. * gtk/gdkcolor.override (pygdk_color_to_string_smart) (_wrap_gdk_color_tp_repr, _wrap_gdk_color_tp_str): New functions. * gtk/gdkevent.override (_wrap_gdk_event_tp_repr): New function. * gtk/gdkrectangle.override (_wrap_gdk_rectangle_tp_repr): New function. * tests/test_color.py (Tests.test_repr, Tests.test_str): New tests. (Tests._test_color_list): New helper method. * tests/test_rectangle.py (Tests.test_repr): New test. (Tests._test_rectangle_list): New helper method. 2008-08-28 Paul Pogonyshev <pogonyshev@gmx.net> * pygtk-gdkrectangle.xml: Document __repr__. * pygtk-gdkcolor.xml: Document __repr__ and __str__. * pygtk-gdkevent.xml: Document __repr__.
pygtk is not under active development anymore and had its last code changes in 2013. Its codebase has been archived: https://gitlab.gnome.org/Archive/pygtk/commits/master PyGObject at https://gitlab.gnome.org/GNOME/pygobject is its successor. See https://pygobject.readthedocs.io/en/latest/guide/porting.html for porting info. Closing this report as WONTFIX as part of Bugzilla Housekeeping to reflect reality. Feel free to open a task in GNOME Gitlab if the issue described in this task still applies to a recent version of PyGObject. Thanks!