Construct class from superclass instance
Asked Answered
G

1

1

So you have some function, say Gtk.Builder.get_object(), which returns some widget. In our case a Gtk.Window().

I have a subclass of Gtk.Window() which adds some signal handlers.

class Window(Gtk.Window):

Is it possible to use the widget returned by Gtk.Builder.get_object() to construct Window()? I think it should be using __new__() or something, but I can't figure it out.

Girardi answered 11/3, 2013 at 3:32 Comment(3)
Can you write to the __class__ attribute of the Gtk.Window instance you're getting?Livraison
@Livraison Is that safe? I made a quick test where I set window.__class__ = cls in __new__(). I seem to be able to call methods from the subclass doing this, but __init__ still isn't run. According to my interpretation of the docs it should, so IDK.Girardi
It should be safe as long as the class you're setting is a subclass of the instance's previous class. I'm not sure why it wouldn't call __init__ if you're returning the modified instance from __new__. I'm going to write the suggestion up as an answer, but feel free not to accept it until we can figure out what's going wrong.Livraison
L
1

I think using __new__ is exactly what you want to be doing. If you can set the __class__ attribute of the superclass instance you're getting to the subclass, you should be all set.

Here's what I think you need:

class Window(Gtk.Window):
    def __new__(cls, *args, **kwargs):
        self = Gtk.Builder.get_object()
        self.__class__ = cls
        return self

Python should detect that the value that was created by __new__ is an instance of the class (thanks to the __class__ value), then it will call __init__ and other methods as appropriate.

Livraison answered 11/3, 2013 at 4:54 Comment(3)
@Girardi - This should work. In CPython, you can safely reassign __class__ for instances of heap types that have a compatible memory layout, which is checked at runtime. If __init__ doesn't run, the metaclass __call__ method must be overridden.Avifauna
Ok, this does seems to work, actually. I defined new like def __new__(cls, data_dir) and created the object like Window.__new__(Window, '..'), but this must be incorrect.Girardi
I just checked, and gobject.GObjectMeta doesn't override type.__call__.Avifauna

© 2022 - 2024 — McMap. All rights reserved.