<div dir="ltr">Hi Phil, Hi Baz, Hi List,<div><br></div><div>sorry, I didn't have time to respond earlier.</div><div><br></div><div>The changes I did are to SIP, and I guess, Phil, you do</div><div>intend to have more releases of SIP? So, all I write</div>

<div>applies to PyQt5, too, it's just that I was to lazy to install</div><div>Qt5 on my machine...</div><div><br></div><div><span style="font-family:arial,sans-serif;font-size:12.666666984558105px">> At the moment (having just started to think about it again) I'm against </span></div>
<div><span style="font-family:arial,sans-serif;font-size:12.666666984558105px">> your original patch as it is too different to the C++ behaviour.</span></div><div><br></div><div>well, thats the difference between Python and C++. In C++, the</div>
<div>order of base classes defines the memory layout of the combined</div><div style>class, the members of the base classes are simply put one after</div><div style>the other in memory. Qt needs its classes to go first, probably they</div>
<div style>cannot deal with the situation where their data members end up</div><div style>somewhere they don't expect. In Python, thats all different. The</div><div style>memory layout is defined by the biggest base class, no matter where</div>
<div style>it appears in the list of bases. The inheritance from two classes</div><div style>with incompatible memory layout is prohibited, and Python will raise</div><div style>an error (yes, C++ is more flexible here). This should have happened</div>
<div style>with PyQt classes, it's just that PyQt uses pointers to the C++ objects,</div><div style>and so the size of the Python object does not change, so Python </div><div style>incorrectly does not detect the fact that the memory layout for two</div>
<div style>different Qt base classes is, in fact, incompatible. Detecting this is</div><div style>the goal of my second patch.</div><div style><br></div><div style>The order of base classes in Python is, on the other hand, by no</div>
<div style>means irrelevant: it defines the order in which methods are called. </div><div style>So the first base class will overwrite methods of the second, etc.</div><div style>This is why mixin classes have to go before the classes they</div>
<div style>are supposed to mix in: they are supposed to overwrite their</div><div style>methods, and not the other way around. Now, often an overwriting</div><div style>method intends to call the overwritten method, in Python that's</div>
<div style>nowadays often done by calling super(). Unfortunately, PyQt does</div><div style>not do that (except, sometimes, for __init__). This is why PyQt</div><div style>classes naturally go last in the list of base classes.</div>
<div><div class="gmail_extra"><div class="gmail_quote"><div> </div><div>> On the face of it, this seems like an entirely good thing to do.</div>
<div>></div><div>> However, I suppose it's only fair to point out that this will probably </div><div>> break code for at least some people, if this blog post is anything to go by:</div><div>></div><div>>    <a href="http://trevorius.com/scrapbook/python/pyqt-multiple-inheritance/" target="_blank">http://trevorius.com/<u></u>scrapbook/python/pyqt-<u></u>multiple-inheritance/</a></div>

<div>></div><div>> Of course, you could say that they got what they deserved for trying </div><div>> to do something in PyQt that just wouldn't be allowed in Qt itself. But </div><div>> whatever the rights and wrongs, there are going to be a few people</div>

<div>> who might hope that this patch is only applied if the issue with custom</div><div>> signals can be resolved first.</div><div><br></div><div>Thanks for pointing me to this website. Well, those are exactly the </div>

<div>usecases I intended to solve. So, my patch will keep all the code</div><div>presented on that website working, while resolving all but one of</div><div>the issues mentioned there. This website is a very good analysis</div>

<div>of the problem, so let's go through it:</div><div><br></div><div>1. The first inherited widget must have the deepest base-class.<br></div><div><br></div><div>This is the issue I solve with my first patch. Instead of asking the </div>

<div>programmer to put the deepest base-class first, I am looking in the </div><div>bases list for the deepest base class. So as long as the programmer</div><div>has followed the advice, nothing will change. If not, the code would </div>

<div>not have worked before and now will work properly.</div><div><br></div><div>1a. You cannot use super(). (mentioned further down on the website)</div><div><br></div><div>This is a non astonishing corollary of No 1. The rule to put the deepest</div>

<div>base class first breaks python's method resolution order, because</div><div>it tells python that the deepest base-classes methods should be called</div><div>first - a very strange concept of a base class. This is why I am </div>

<div>lifting that rule for enabling putting the deepest base class last - that's</div><div>where it belongs. So, with my patch super() works as intended.</div><div><br></div><div>2. Only additional signals defined in the first inherited widget are used.<br>

</div><div><br></div><div>This is slightly modified with my patch: only additional signals in the</div><div>first base class and the deepest base class are used. I actually don't</div><div>know how that happened. Only important thing: old code will still work.</div>

<div><br></div><div>3. Name clashes are resolved by calling the first class’s methods<br></div><div><br></div><div>This is the same problem as No 1a.</div><div><br></div><div style><br></div><div style>Now let's talk about my second patch. It enforces PyQt classes</div>
<div style>to go last, and not inherit from incompatible classes. That's the </div><div style>right thing to do according to all I wrote above. Unfortunately it</div><div style>will break code from the mentioned website. So for backwards</div>
<div style>compatiblity, it should only give a warning. It also breaks the</div><div style>new __init__-calls-super() from PyQt5. But as I wrote above,</div><div style>this is also weird, as it expects mixin classes to go behind </div>
<div style>PyQt classes, which is just the wrong way around. So it</div><div style>should be deprecated and removed from the documentation </div><div style>before too many people start using this feature. For those who</div>
<div style>did: just inverse the order of base classes, and all will work</div><div style>as expected, with both the current version of PyQt and my</div><div style>modified version.</div><div style><br></div><div style>So, to conclude: my patches are still relevant as they applies to SIP,</div>
<div style>the first one does not break old code but will lift unecessary limitations,</div><div style>while the second one breaks flawed old code and thus should only </div><div style>raise a warning.</div><div style><br>
</div><div style>Greetings</div><div style><br></div><div style>Martin</div><div style><br></div></div>
</div></div></div>