After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 526189 - add __str__ and/or __repr__ to several types
add __str__ and/or __repr__ to several types
Status: RESOLVED WONTFIX
Product: pygtk
Classification: Bindings
Component: general
Git Master
Other All
: Normal enhancement
: ---
Assigned To: Nobody's working on this now (help wanted and appreciated)
Python bindings maintainers
gnome[unmaintained]
Depends on:
Blocks:
 
 
Reported: 2008-04-04 16:37 UTC by Paul Pogonyshev
Modified: 2018-08-17 13:43 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
patch for gtk.gdk.Color (1.05 KB, patch)
2008-04-04 20:06 UTC, Paul Pogonyshev
none Details | Review
gtk.GtkStyleHelper __repr__ (1.51 KB, patch)
2008-04-04 20:35 UTC, Paul Pogonyshev
none Details | Review
add __repr__ to various GDK types (those deriving from GBoxed) (8.78 KB, patch)
2008-04-11 19:49 UTC, Paul Pogonyshev
none Details | Review
add __repr__ to various GDK types (those deriving from GBoxed): new Color representation (9.63 KB, patch)
2008-06-21 18:34 UTC, Paul Pogonyshev
none Details | Review
_repr__, unit tests and docs for GDK types (those deriving from GBoxed) (15.32 KB, patch)
2008-08-02 17:19 UTC, Paul Pogonyshev
committed Details | Review

Description Paul Pogonyshev 2008-04-04 16:37:59 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.
Comment 1 Johan (not receiving bugmail) Dahlin 2008-04-04 19:10:48 UTC
+1

I really like this idea, I don't think there are any real backwards compatibility issues since the __repr__ output is private.
Comment 2 Paul Pogonyshev 2008-04-04 20:06:22 UTC
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.
Comment 3 Paul Pogonyshev 2008-04-04 20:35:29 UTC
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>
Comment 4 Johan (not receiving bugmail) Dahlin 2008-04-08 16:15:28 UTC
(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?
Comment 5 Paul Pogonyshev 2008-04-08 19:37:32 UTC
> 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):
  • File "<stdin>", line 1 in <module>
TypeError: an integer is required

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.
Comment 6 Paul Pogonyshev 2008-04-11 19:49:15 UTC
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 7 Johan (not receiving bugmail) Dahlin 2008-04-11 19:55:59 UTC
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(...) ?
Comment 8 Paul Pogonyshev 2008-04-11 20:03:51 UTC
> 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.
Comment 9 Paul Pogonyshev 2008-06-21 18:34:15 UTC
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.
Comment 10 Paul Pogonyshev 2008-08-02 17:19:59 UTC
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>
Comment 11 Paul Pogonyshev 2008-08-28 19:40:50 UTC
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__.
Comment 12 André Klapper 2018-08-17 13:43:35 UTC
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!