Python GTK3 inheritance - python

How can I inherit a GTK+3 class in python ? I'm trying to create a inherited class of Gtk.Application and what I got is a segfault.
I've tried a lot of things, but with this I got a segfault:
class Program(Gtk.Application):
def __init__(self):
super().__init__(self)
...
prg = Program.new("app_id", flags)

if I try your code snippet I actually get:
Traceback (most recent call last):
File "pyclass.py", line 12, in <module>
prg = Program.new("app_id", 0)
TypeError: Application constructor cannot be used to create instances of a subclass Program
which is expected, since you're trying to call the Python wrapper for gtk_application_new() by using Program.new().
you should use the Python constructor form:
class Program(Gtk.Application):
def __init__(self):
Gtk.Application.__init__(self,
application_id="org.example.Foo",
flags=Gio.ApplicationFlags.FLAGS_NONE)
prg = Program()
sys.exit(prg.run(sys.argv));
this will actually warn you that you haven't implemented the GApplication::activate virtual function, which can be achieved by overriding the do_activate virtual method in your Program class:
class Program(Gtk.Application):
def __init__(self):
Gtk.Application.__init__(self,
application_id="org.example.Foo",
flags=Gio.ApplicationFlags.FLAGS_NONE)
def do_activate(self):
print("Activated!")
this will print Activated! on the console, before quitting.

Related

Python Inheritance initialize problems

I have threading class in serverThread.py file as shown:
import threading
class serverThread(threading.Thread):
def __init__(self, name):
try:
threading.Thread.__init__(self)
self.name = name
except:
exit()
def run(self):
print("Hello")
I created a new project.I want to inherit class from above class as shown:
import serverThread
class tcpThread(serverThread):
def __init__(self, name):
serverThread.__init__(self,name)
def run():
serverThread.run(self)
t1 = tcpThread("Tcp Server")
t1.start()
When I run this script gives me error:
Error:
Traceback (most recent call last): File "serverTcpThread.py", line 4, in <module> class tcpThread(serverThread): TypeError: module.&lowbar;&lowbar;init&lowbar;&lowbar;() takes at most 2 arguments (3 given)
The error you're reporting is probably because the base class is imported from a bad path, cannot reproduce here.
That said, there's another (similar) error: when redefining the run method, you have to pass the self parameter
class tcpThread(serverThread):
def __init__(self, name):
serverThread.__init__(self,name)
def run(self):
serverThread.run(self)
the code runs fine after that. note that there's no need to redefine the run method only to call the parent method.

Why do I get "AttributeError: 'super' object has no attribute '__del__'" when calling the destructor of super from my Thread subclass' destructor?

In my Python (3.6) program, I have a thread object, like so:
class MyThread(threading.Thread):
def __init__(self):
super(MyThread, self).__init__()
...
def __del__(self):
...
super(type(self), self).__del__()
def run(self):
...
used in the main program like this:
def main():
my_thread = MyThread()
my_thread.start()
...
my_thread.join()
But as soon as I try to run this program, I get the following Python crash:
Exception ignored in: <bound method MyThread.__del__ of <MyThread(Thread-6, stopped 1234)>>
Traceback (most recent call last):
File "c:/my_proj/my_program.py", line 123, in __del__
super(type(self), self).__del__()
AttributeError: 'super' object has no attribute '__del__'
Why is this, and how can it be fixed?
Is it not allowed to call the __del__() method of super explicitly like this, or what? (Google seems to tell me otherwise, but still won't give me any answer to why this happens)
super(type(self), self) is always wrong. In Python 2, you must explicitly name the current class, e.g. super(MyThread, self). In Python 3, you can simply use super():
class MyThread(threading.Thread):
def __init__(self):
super().__init__()
# ...
def run(self):
# ...
That said, if if the superclass has no __del__ then you'll get this AttributeError. If your base classes have no __del__ you can simply omit it. There is rarely a good reason to implement __del__ in your class.
If you need controlled cleanup, consider using implementing a context manager.

python inheritance and/or descriptors differences in 2.7 and 3

I'm trying to understand a little more about how python classes and descriptors work. I have the following code.
class Base():
def __init__(self):
self.a = 'base_a'
def get_a(self):
return self._x
def set_a(self,val):
self._x = val
def delete_a(self):
pass
a = property(get_a,set_a,delete_a)
class Derived(Base):
def __init__(self):
Base.__init__(self)
#property
def a(self):
return 'derived_a'
t = Derived()
print(t.a)
Running in Python 2.7, I get
[carl#home tmp-carl]$ python2.7 test.py
base_a
Running in Python 3.3, I get
[carl#home tmp-carl]$ python3 test.py
Traceback (most recent call last):
File "test.py", line 25, in <module>
t = Derived()
File "test.py", line 18, in __init__
Base.__init__(self)
File "test.py", line 5, in __init__
self.a = 'base_a'
AttributeError: can't set attribute
I think I understand the Python3.3 behavior. t is an instance of Derived so Base::__init__ searches for t.__dict__['a'], doesn't find it. It goes to Derived.__dict__['a'], finds the read-only property and errors. It never makes it to Base.__dict__['a'], which is read-write.
But if this is true, I don't understand why Python2.7 works at all. It seems as if it completely ignores the overwritten property in Derived.
Can anyone explain this to me?
Python 2.x has two types of classes: old-style, and new-style. Descriptors (of which property is one) only work in new-style classes. In order to create a new-style class in 2.x you must derive from object.
class Base(object):
All classes in 3.x are new-style classes.

Can I use wxPython wx.ItemContainer in a derived class?

I'm trying to make a new wx.Choice-like control (actually a replacement for wx.Choice) which uses the wx.ItemContainer to manage the list of items. Here is a minimal example showing the error:
import wx
class c(wx.ItemContainer):
def __init__(my): pass
x = c()
x.Clear()
This fails with:
Traceback (most recent call last):
File "", line 1, in
File "c:\python25\lib\site-packages\wx-2.8-msw-unicode\wx\_core.py", line 1178
7, in Clear
return _core_.ItemContainer_Clear(*args, **kwargs)
TypeError: in method 'ItemContainer_Clear', expected argument 1 of type 'wxItemContainer *'
The other controls using ItemContainer seem to be internal to wxWindows, so it may not be possible for me to use it this way. However, it would certainly be convenient.
Any ideas on what I'm doing wrong?
wx.ItemContainer can't be instantiated directly e.g. try
x = wx.ItemContainer()
it throws error
Traceback (most recent call last):
File "C:\<string>", line 1, in <module>
File "D:\Python25\Lib\site-packages\wx-2.8-msw-unicode\wx\_core.py", line 11812, in __init__
def __init__(self): raise AttributeError, "No constructor defined"
AttributeError: No constructor defined
Reason being it is a type of interface(if we can call that in python) and you can not call __init__ on it, instead use it as second base and override the methods you use e.g.
class C(wx.PyControl, wx.ItemContainer):
def __init__(self, *args, **kwargs):
wx.PyControl.__init__(self, *args, **kwargs)
def Clear(self):
pass
app = wx.PySimpleApp()
frame = wx.Frame(None,title="ItemContainer Test")
x = C(frame)
x.Clear()
frame.Show()
app.SetTopWindow(frame)
app.MainLoop()
Your suspicions are on the right track. You can't subclass any of the wxWidgets types, because they're in the C++ domain and only nominally wrapped in Python. Instead, you need a Py* class, which you can subclass. The explanation is given in this Wiki entry on writing custom controls.
For ItemContainer, there doesn't appear to be such a wrapper - and the fact that ItemContainer is used as a parent in a multiple inheritance pattern may even complicate matters.
I suspect that from within wxPython, it may not be possible to replace ItemContainer--and if you do need it, it will have to be integrated at the C++ level.

Python Cmd module, subclassing issue

I'm trying to work out what's not working in this code:
#!/usr/bin/python
import cmd
class My_class (cmd.Cmd):
"""docstring for Twitter_handler"""
def __init__(self):
super(My_class, self).__init__()
if __name__ == '__main__':
my_handler = My_class()
Here's the error I get
Traceback (most recent call last):
File "main.py", line 12, in <module>
my_handler = My_class()
File "main.py", line 9, in __init__
super(My_class, self).__init__()
TypeError: super() argument 1 must be type, not classobj
If I change the superclass of "My_class" to an object it works fine. Where am I going wrong?
super() only works for new-style classes
cmd.Cmd is not a new style class in Python 2.5, 2.6, 2.7.
Note that your code does not raise an exception in Python 3.0.
So if super() doesn't work use :
import cmd
class My_class(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self)
You can still use super() if your MyClass extends object. This works even though the cmd.Cmd module is not a new-style class. Like this:
#!/usr/bin/python
import cmd
class My_class (cmd.Cmd, object):
"""docstring for Twitter_handler"""
def __init__(self):
super(My_class, self).__init__()
if __name__ == '__main__':
my_handler = My_class()

Categories

Resources