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 703338 - Regression: changed override on Gtk.Entry stopped working
Regression: changed override on Gtk.Entry stopped working
Status: RESOLVED DUPLICATE of bug 566571
Product: pygobject
Classification: Bindings
Component: general
3.8.x
Other Linux
: Normal normal
: ---
Assigned To: Nobody's working on this now (help wanted and appreciated)
Python bindings maintainers
Depends on:
Blocks:
 
 
Reported: 2013-06-30 11:48 UTC by Benny Malengier
Modified: 2014-08-23 05:22 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
test case showing the issue (47.57 KB, application/x-python)
2013-06-30 17:02 UTC, Benny Malengier
Details

Description Benny Malengier 2013-06-30 11:48:05 UTC
We start to obtain user bug submission for our application (Gramps) with changed override no longer working: attributes not accessible from the overrided method. 

It's unclear at the moment to us what change in gtk is causing this. 

The code is an inheritance of Gtk.Entry, with code:


    __gtype_name__ = 'ValidatableMaskedEntry'

    __gsignals__ = {
        'content-changed': (GObject.SignalFlags.RUN_FIRST, 
                            None, 
                            ()), 
        'validation-changed': (GObject.SignalFlags.RUN_FIRST, 
                               None, 
                               (GObject.TYPE_BOOLEAN, )), 
        'validate': (GObject.SignalFlags.RUN_LAST, 
                     GObject.TYPE_PYOBJECT, 
                     (GObject.TYPE_PYOBJECT, )), 
        'changed': 'override', 
    }

    __gproperties__ = {
        'data-type': (GObject.TYPE_PYOBJECT, 
                       'Data Type of the widget', 
                       'Type object', 
                       GObject.PARAM_READWRITE), 
        'mandatory': (GObject.TYPE_BOOLEAN, 
                      'Mandatory', 
                      'Mandatory', 
                      False, 
                      GObject.PARAM_READWRITE), 
    }

Note the 'changed' which is 'override'. 
This connects to following method:

    def do_changed(self):
        if self._block_changed:
            self.emit_stop_by_name('changed')
            return
        self.emit('content-changed')
        self.validate()

Since latest Debian Jessie and in Mageia with both gtk+-3.8 & 3.9 this code stopped working and gives error:

Unhandled exception
Traceback (most recent call last):
  • File "/usr/lib/python2.7/dist-packages/gramps/gui/widgets/validatedmaskedentry.py", line 1174 in do_changed
    if self._block_changed:
AttributeError: 'Entry' object has no attribute '_block_changed'

It seems that all attributes set in the __init__ method of the ValidatableMaskedEntry defined are no longer accessible from the the do_changed method.

I'll update this ticket if I obtain more info of users encountering this.
Comment 1 Benny Malengier 2013-06-30 15:49:29 UTC
Working workaround for above do_changed method:

     def do_changed(self):
-        if self._block_changed:
+        block_changed = getattr(self, '_block_changed', True)
+        if block_changed:
             self.emit_stop_by_name('changed')
             return
         self.emit('content-changed')

So it seems do_changed is now called before correct __init__ of the object, but by using getattr to see if the attribute is already present, one can work around the error.
Comment 2 Simon Feltman 2013-06-30 16:14:31 UTC
Hi Benny,

A simplified example exhibiting the problem would be helpful. There could be any number of things which changed in the stack that cause this to happen. I know there were some class initialization changes (bug 686149) which may affect this. But there is also the potential that GtkEntry now emits the signal upon instance initialisation. You could check this by putting print statements before and after the super class call in the sub-class __init__ (and also a print within do_changed).

class CustomEntry(Gtk.Entry):
    def __init__(self):
        print('before super')
        super().__init__()
        print('after super')

If this shows to be true (do_changed is called in between the super prints) then a potentially cleaner workaround would be to put the instance variable assignments before the super call and this bug can move to GTK+ (if it is still be considered a bug at that point).
Comment 3 Benny Malengier 2013-06-30 17:02:55 UTC
Created attachment 248096 [details]
test case showing the issue

Test with

python testgtkentry.py 

change in top of file 
workaround = True
for the workaround.
Comment 4 Benny Malengier 2013-06-30 17:03:32 UTC
I made a test case which is uploaded. Asked user to test, I don't have 3.8 installed myself yet.
Comment 5 Benny Malengier 2013-06-30 17:09:10 UTC
About
"a potentially cleaner workaround would be to put the instance variable
assignments before the super call"

They already are before the super (well here actually MaskedEntry.__init__(self) ), so it must be something more exotic.

See in test case:

        self._block_changed = False

        print ('before super')
        MaskedEntry.__init__(self)
        print ('after super')
Comment 6 Benny Malengier 2013-07-01 06:52:22 UTC
Ok, the tester reports that with the uploaded testcase, the bug does not happen, so what happens in our app is more complicated (in the app there is an extra undoable buffer on the entry, and glade is used to construct the entries, those are the most immediate differences that pop up). 

I'll try to test it myself further when I upgrade my stack myself, and then update the testcase if I find a way to trigger it.
Comment 7 Simon Feltman 2013-07-01 19:02:08 UTC
I was also unable to get the example to reproduce the problem on versions 3.8.2 and 3.9.3.
Comment 8 Tobias Mueller 2013-11-23 20:35:13 UTC
reopening as I can't see any open non developer question.
Comment 9 Simon Feltman 2013-11-23 20:59:16 UTC
(In reply to comment #8)
> reopening as I can't see any open non developer question.

I guess it wasn't explicitly asked.


(In reply to comment #6)
> I'll try to test it myself further when I upgrade my stack myself, and then
> update the testcase if I find a way to trigger it.

Benny can you still reproduce this with newer versions of the stack?
The attached test case has a dependency on "gramps". If I remove that import and delete the contents of the "on_validate" handler, I don't see any problems with the script. But I'm not entirely sure that justifies that this has been fixed...
Comment 10 Simon Feltman 2014-04-14 20:55:40 UTC
I've been unable to reproduce this, is it still an issue?
Comment 11 Benny Malengier 2014-04-14 21:21:23 UTC
If I undo the patch in 
https://bugzilla.gnome.org/show_bug.cgi?id=703338#c1
in the shipped version 4.0.x of Gramps, we still have the crash.

In case you have Gramps 4.0.0+ installed, changing 

--- a/gramps/gui/widgets/validatedmaskedentry.py
+++ b/gramps/gui/widgets/validatedmaskedentry.py
@@ -1176,8 +1176,9 @@ class ValidatableMaskedEntry(MaskedEntry):
 
     # Virtual methods
     def do_changed(self):
-        block_changed = getattr(self, '_block_changed', True)
-        if block_changed:
+        #block_changed = getattr(self, '_block_changed', True)
+        #if block_changed:
+        if self._block_changed:
             self.stop_emission_by_name('changed')
             return
         self.emit('content-changed')

and running the app: create empty family tree-> load, go to event view->add event
hits the bug.

However, the testcase does not hit this bug, as the user indicated.
For us, the fact the workaround works is great, however, it seems the workaround is still needed. It must be something inherent in the stacking of classes as used in Gramps though, so no idea on how to create a reduced test case.
Comment 12 Simon Feltman 2014-04-14 21:34:06 UTC
Ok, thanks for the update.
Comment 13 Benny Malengier 2014-04-14 21:36:07 UTC
My stack is not that recent though:
 gtk++     : 3.8.6
 pygobject : 3.10.0

John Ralls is a Gramps developers, you could ping him perhaps to try with more recent version. It's a one line change in the Gramps code to see if it still happens.
Comment 14 Simon Feltman 2014-08-23 04:44:58 UTC
Confirming. This is probably the same or very similar to bug 566571. The problem is vfuncs are overriding the *parent* class vfunc in GtkEntry which is very broken. This can be seen as follows:

class E(Gtk.Entry):
    def do_changed(self):
        print('on_changed')

e = Gtk.Entry()
e.emit('changed')  # prints changed
Comment 15 Simon Feltman 2014-08-23 05:22:43 UTC
This is indeed the same bug since "changed" is actually a vfunc of the GtkEditable interface. A workaround is explicitly re-inherit from GtkEditable:

class MyEntry(Gtk.Entry, Gtk.Editable):
    def do_changed(self):
        ...

I recommend doing this since without it, all entries will contain overridden vfunc AFAICT...

*** This bug has been marked as a duplicate of bug 566571 ***