[PyQt] Bug in QTableView.setModel()

Aaron Digulla digulla at hepe.com
Tue Jan 8 12:12:10 GMT 2008


Quoting Phil Thompson <phil at riverbankcomputing.co.uk>:

> I'm happy to consider ways to make this more obvious (even if it's just a
> better FAQ), but I'm not happy about departing from the Qt API and
> introducing inconsistencies in fundamental behaviour.

Then let me put it this way: If I wanted to care about who calls the  
dtor, I'd be using C++ and not Python. ;-)

As a Python developer, I expect PyQt to behave like python code: As  
long as anyone (my code, PyQr or Qt) still has references to some  
object, the dtor must not be called, no matter what and PyQt as a  
*python* wrapper for Qt should follow the Python rules, not the Qt  
rules, especially not in a case where there is no conflict.

As I see it, managing the reference counter in setModel() is an easy  
fix, it doesn't break the Qt API and it makes PyQt behave like any  
Python expects. So what is the specific point not to do it?

As for "ownership": Qt had to introduce this concept to avoid memory  
leaks. This is not necessary in Python (because Python handles this  
behind the scenes), so I suggest to ignore all "ownership"-style calls  
and/or wrap them in the Pyhton equivalent (to makes sure that objects  
aren't GC'd as long as someone still needs them). I'd guess that would  
fix most of the issues with little effort on your side plus reduce the  
amount of discussion and "I don't understand"-like mails considerably.

The ultimate goal should be to have

     edit.setDocument(QTextDocument(edit))

and

     edit.setDocument(QTextDocument())

behave the same way: Make sure that QTextDocument() lives as long as  
edit needs it. Pseudocode:

   setModel(model):
     if model():
        if isPython(model()):  model().refount--
        elif model().owner == NULL: ShouldNotHappenException
     if model:
        if isPython(model):  model.refount++
        else:
          # Someone tried the Qt style -> avoid
          model.owner = NULL # Owner is Python[1]
          model = PyWrapper(model)
          model.refount++
     super.setModel(model)

In this code, you could also print a warning if someone used  
QTextDocument(edit) or install a python GC object as the owner of the  
model which manages the relationships (face it: A model is not going  
to be used by more than 10..100 parents, so we could simply store  
everything in a map or list or something).

Alternatively, you could add a thin wrapper for PyQt which works the  
Python way and print a warning if setModel() is called with a  
QTextDocument() which has no owner. Then users who don't want to care  
about dtor calling could use PyQTextDocument(), etc. instead.

PS: Without your mail, I still wouldn't have a clue as to what is  
going on. There are some traces of information about this in the FAQ  
and elsewhere but they are far from easy to understand even after  
knowing your explanation. So if you refuse to fix the non-python  
behavior of PyQt, then please at least fix the documentation:  
http://www.riverbankcomputing.co.uk/pyqt/faq.php  
http://www.riverbankcomputing.com/Docs/PyQt4/pyqt4ref.html#garbage-collection  
and  
http://www.riverbankcomputing.com/Docs/PyQt4/html/qtextedit.html#setDocument

These may seem clear to you but as a Python developer, I don't know  
why I should care that "[t]he parent QObject of the provided document  
remains the owner of the object." Only after reading all three  
documents, it becomes clear that "owner" means "who GCs the  
object/makes sure that it isn't GCd" (or calls the dtor).

Regards,

-- 
Aaron "Optimizer" Digulla a.k.a. Philmann Dark
"It's not the universe that's limited, it's our imagination.
Follow me and I'll show you something beyond the limits."
http://www.pdark.de/



More information about the PyQt mailing list