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 625033 - recurse up through base classes when setting up vfuncs
recurse up through base classes when setting up vfuncs
Status: RESOLVED FIXED
Product: pygobject
Classification: Bindings
Component: introspection
Git master
Other Linux
: Normal normal
: ---
Assigned To: Nobody's working on this now (help wanted and appreciated)
Python bindings maintainers
Depends on:
Blocks: 625942
 
 
Reported: 2010-07-22 13:19 UTC by Jonathan Matthew
Modified: 2010-11-30 22:12 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
this seems to work (2.32 KB, patch)
2010-07-22 13:21 UTC, Jonathan Matthew
none Details | Review
fixed, with test (3.66 KB, patch)
2010-07-29 00:38 UTC, Jonathan Matthew
needs-work Details | Review
implement richcompare for GIBaseInfo (1.79 KB, patch)
2010-09-28 03:58 UTC, Jonathan Matthew
committed Details | Review
updated, use vfunc info flags (14.58 KB, patch)
2010-10-29 14:01 UTC, Jonathan Matthew
none Details | Review
exclude gi.overrides module from vfunc requirements (14.67 KB, patch)
2010-11-06 10:56 UTC, Jonathan Matthew
committed Details | Review

Description Jonathan Matthew 2010-07-22 13:19:37 UTC
GObjectMeta.__init__ only sets up vfuncs in the immediate base class, so vfuncs further up the class hierarchy cannot be overridden.

In rhythmbox, we have RBSource (base class for all music sources) and RBBrowserSource (a subclass of RBSource that creates the genre/artist/album browsers) defined in C, and most plugins that create sources do so by subclassing RBBrowserSource.  As things stand, they can't override methods in RBSource.
Comment 1 Jonathan Matthew 2010-07-22 13:21:59 UTC
Created attachment 166388 [details] [review]
this seems to work
Comment 2 johnp 2010-07-28 09:05:56 UTC
This needs a test of some sort.   As far as the code goes it looks correct but is there a case where more than one vfuncs have the same name but you only want to override one of them?
Comment 3 Jonathan Matthew 2010-07-29 00:38:12 UTC
Created attachment 166749 [details] [review]
fixed, with test

No longer breaks existing tests - the is_function_in_classes check in _setup_vfuncs needs to check against the class we're defining vfuncs for, not the one we're currently recursing through.

Added a test in TestPythonGObject, creating a subclass of GIMarshallingTests.SubObject and overriding a GIMarshallingTests.Object vfunc on it.
Comment 4 Jonathan Matthew 2010-07-29 00:55:01 UTC
I'm not sure what should happen if there are multiple instances of the same vfunc name in the class hierarchy.  Maybe we should support implementing vfuncs with explicit class names, like do_Source_whatever, do_BrowserSource_whatever, and treat ambiguities as errors?  Are there any known cases of this that we can look at to see what makes sense?
Comment 5 johnp 2010-09-07 02:04:08 UTC
Comment on attachment 166749 [details] [review]
fixed, with test

Looks good except I would assert if we encounter two or more virtual methods of the same name when trying to override that method.  If the results are unknown we should not allow it as it could be dangerous.
Comment 6 Jonathan Matthew 2010-09-28 03:58:52 UTC
Created attachment 171244 [details] [review]
implement richcompare for GIBaseInfo

This allows us to compare GIBaseInfos for equality (and inequality) in python, which we need since it's OK to have multiple instances of the same vfunc, just not multiple different vfuncs with the same name.
Comment 7 Jonathan Matthew 2010-09-28 04:45:40 UTC
I think I've got this mostly working now, with one major exception: The Gtk.Button override fails because we now try to set up vfuncs for Gtk.Activatable, which fails with:

TypeError: Class implementing Gtk.Activatable should implement the method do_update()

It doesn't have a problem with sync_action_properties on the same class, though.  I think it's finding the wrapper for gtk_activatable_sync_action_properties, which is just the vfunc accessor, so it shouldn't satisfy the requirement to implement the sync_action_properties method.

GtkButton implements both those methods, but I can't figure out how to check for that here.
Comment 8 johnp 2010-10-05 15:20:41 UTC
This can't go in until the test passes
Comment 9 Jonathan Matthew 2010-10-06 14:40:20 UTC
Looks like I'll need to fix bug 619606 before this is useful.  I've got some mostly-working code that checks method pointers to determine whether a vfunc has an implementation for a class, and with that instead of the current check, lots of things fail due to missing implementations GtkBuildable methods on gtk widget classes and so on.
Comment 10 johnp 2010-10-28 21:45:13 UTC
Patch added to bug 619606 - think you can whip this bug into shape so we can add it to the release?
Comment 11 Jonathan Matthew 2010-10-28 22:30:14 UTC
Sure, that shouldn't be a problem.

We're also missing annotations in g-i to make it possible to set those flags, but I've got most of a patch for that somewhere.
Comment 12 Jonathan Matthew 2010-10-29 11:24:56 UTC
Annotation patch is on bug 633447.
Comment 13 Jonathan Matthew 2010-10-29 14:01:25 UTC
Created attachment 173481 [details] [review]
updated, use vfunc info flags

This looks at the class/interface vtable to figure out if there's already an implementation, uses the vfunc flags to figure out if there needs to be an implementation, and checks other classes/interfaces to figure out if the method name is ambiguous.

The test for the last bit is commented out for now because it requires an addition to GIMarshallingTests - we need two interfaces with the same method name in there to check that ambiguous method overrides are detected.
Comment 14 johnp 2010-10-29 17:39:50 UTC
I've been thinking about this a bit and I think for the overrides we should just not error out.  We are overriding an interface to create a new interface so the methods shouldn't have to be implemented.  When a user uses a class that inherits from the interface, then we should error out if they have not implemented all of the vfuncs.  We still need to know absolutely which need to be implemented.
Comment 15 Jonathan Matthew 2010-10-31 05:25:35 UTC
I'm not sure I follow you - we should check that all required methods have been implemented at object construction time rather than class creation time?

With the current patch, if I have interface Namespace.Interface with virtual method 'invoke', this code, which seems like it should be OK:

class BaseObject(Namespace.Interface):
    def __init__(self):
        pass

class ActualObject(BaseObject):
    def do_invoke(self):
        whatever

won't work because the vfunc implementation check for BaseObject will fail.  If we deferred the check to the first time we created an instance of a class, it would only error out if I tried to create an instance of BaseObject.  Is that more or less what you're getting at?
Comment 16 johnp 2010-11-02 15:57:52 UTC
What I was thinking is we don't error out if the object implementing the interface is within the "gi.overrides" module.  If the user is implementing an interface, we do error out on class creation time.
Comment 17 Jonathan Matthew 2010-11-06 10:55:47 UTC
Sounds reasonable.

I guess to open that up a bit more, we could provide a way to mark a GType implemented in python as abstract, then check impl.__gtype__.is_abstract() before erroring out.
Comment 18 Jonathan Matthew 2010-11-06 10:56:41 UTC
Created attachment 173939 [details] [review]
exclude gi.overrides module from vfunc requirements
Comment 19 johnp 2010-11-10 04:22:09 UTC
Comment on attachment 171244 [details] [review]
implement richcompare for GIBaseInfo

committed this in preparation of committing the main patch after a bit more review.
Comment 20 johnp 2010-11-30 22:03:49 UTC
Comment on attachment 173939 [details] [review]
exclude gi.overrides module from vfunc requirements

I committed this as two commits with fixups.  First I committed the supporting methods as they applied cleanly. I then refactored the types.py patch and fix a couple of things.  See next comment for details
Comment 21 johnp 2010-11-30 22:10:14 UTC
* refactored def find_vfunc_in_other_classes(vfunc, base, classes) to be def find_vfunc_conflict_in_bases(vfunc, bases):
* base parameter not used in find_vfunc_conflict_in_bases so I removed it
* when calling find_vfunc_conflict_in_bases I send in the cls.__bases__ not impl.__bases__ because when recursing up the inheritance stack there is no need to check the children, the conflict would have already be caught
* removed the vfunc_info.must_override() check because that isn't hooked up in GI and will always return False
Comment 22 johnp 2010-11-30 22:12:27 UTC
BTW the code is pretty confusing as it is.  I don't think we can make it much clearer so I accepted as is.  We should probably look to see if we can clean it up so that it is easier to understand what the code is doing.