[PyQt] sip_api_can_convert_to_type chokes on converting a Python list to a QLIst of enums.

Phil Thompson phil at riverbankcomputing.com
Thu Jul 15 17:42:23 BST 2010


On Wed, 14 Jul 2010 10:42:42 +0200, Gerard Vermeulen <gav451 at gmail.com>
wrote:
> Hi,
> 
> I have the following sip declaration (left some irrelevant
> ConvertToSubclass stuff out):
> 
> class QwtPickerMachine
> {
> %TypeHeaderCode
> #include <qwt_picker_machine.h>
> %End // %TypeHeaderCode
> 
> public:
>     enum Command {
>         Begin,
>         Append,
>         Move,
>         End
>     }; // enum Command
> 
>     virtual ~QwtPickerMachine();
>     virtual QList<QwtPickerMachine::Command> transition(const
> QwtEventPattern&, const QEvent*) = 0;
>     void reset();
>     int state() const;
>     void setState(int);
> protected:
>     QwtPickerMachine();
> ..
> }
> 
> And a Python demo program where QwtPicker::transition() is overridden:
> 
> class PickerMachine(QwtPickerMachine):
>   
>     def __init__(self, *args):
>         QwtPickerMachine.__init__(self, *args)
> 
>     # __init__()
>   
>     def transition(self, eventPattern,  e):
>         commands = []
>         print commands
>         # handle the mouse events
>         if e.type() == QEvent.MouseButtonPress:
>             if eventPattern.mouseMatch(QwtEventPattern.MouseSelect1, e):
>                 if self.state() == 0:
>                     commands.append(QwtPickerMachine.Begin)
>                     commands.append(QwtPickerMachine.Append)
>                     self.setState(1)
>         elif e.type() == QEvent.MouseMove:
>             if self.state != 0:
>                 commands.append(Qwt.QwtPickerMachine.Append)
>         elif e.type() == QEvent.MouseButtonRelease:
>             commands.append(QwtPickerMachine.End)
>             self.setState(0)
>         # handling of the keyboard events is left as an excercise
>         print commands
>         return commands # "return []" works.
>         return []
> 
>     # transition()
>       
> # class PickerMachine()        
> 
> And a modified siplib.c where
> 
>     printf("td_flags: %d; td_sipTypeName: %s\n", td->td_flags,
> sipTypeName(td));
> 
> is added before the assert statement in sip_api_can_convert_to_type().
> 
> My demo program fails in when siplib has to handle the list that is
> returned by PickerMachine.transition():
> 
>  1. QList<QwtPickerMachine::Command>
> sipQwtPickerMachine::transition(const QwtEventPattern&,const QEvent *)
> (this=0x00f0bcd0)
>  2. []
>  3. meth_QwtEventPattern_mouseMatch()
>  4. td_flags: 16; td_sipTypeName: QMouseEvent
>  5. meth_QwtPickerMachine_state()
>  6. meth_QwtPickerMachine_setState()
>  7. [0, 1]
>  8. dealloc_QwtEventPattern()
>  9. td_flags: 2; td_sipTypeName: QList<QwtPickerMachine::Command>
> 10. td_flags: 3; td_sipTypeName: QwtPickerMachine::Command
> 11. python: siplib.c:7505: sip_api_can_convert_to_type: Assertion
> `(((td)->td_flags & 0x0007) == 0x0000) || (((td)->td_flags & 0x0007) ==
> 0x0002)' failed.
> 12. Aborted
> 
> where line 2 and 7 are written by the print statements in the Python
> code above, line 4, 9, and 10 by the printf added to
> sip_api_can_convert_to_type() and the other lines by the sip tracing
> mechanism.

It's a fundamental and long-standing SIP design bug. The template argument
support doesn't distinguish between named enums and classes so it is using
%ConvertToTypeCode written for classes and applying it to an enum.

The workaround is to explicitly provide a %MappedType - see
QList<QLocale::Country> in qlocale.sip for an example.

Phil


More information about the PyQt mailing list