Re: [Phoenix Issue] wx.FlexGridSizer.AddGrowableCol results in C++ assert

Adrian Hill <[email protected]>
Newsgroups gmane.comp.python.wxpython.devel
Message-ID <[email protected]>
I'm a little late to the party, but here's another possible data point for 
resolving the issue.

I found a similar problem using the example in Listing 9.14 in "wxPython in 
Action", but there is a difference
between 32-bit and 64-bit versions of Python 3.4  + wxPython_Phoenix, under 
Windows 7.

I modified the original example (all changed lines annotated on the 
attached validator2.py file) to use
wx.Validator instead of wx.PyValidator, and to use wx.App instead of 
wx.PySimpleApp. This removed
two expected warnings. Also, I added lines to print out the Python and 
Phoenix versions.

Using 32-bit Python, the dialog is displayed correctly, and these lines are 
written:
3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit 
(Intel)]
wxPython/Phoenix version: 3.0.3.dev1830+0b5f910 msw (phoenix)

Using 64-bit Python, the dialog is not displayed, and these lines are 
printed:
3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:44:40) [MSC v.1600 64 bit 
(AMD64)]
wxPython/Phoenix version: 3.0.3.dev1830+0b5f910 msw (phoenix)
Traceback (most recent call last):
  File "validator2.py", line 87, in <module>
    dlg = MyDialog(data)
  File "validator2.py", line 69, in __init__
    fgs.AddGrowableCol(1)
wx._core.wxAssertionError: C++ assertion "!m_cols || idx < (size_t)m_cols" 
failed at ..\..\src\common\sizer.cpp(1980) in 
wxFlexGridSizer::AddGrowableCol(): invalid column index

The last line is similar to that in the original post.

In summary, 32-bit worked, but 64-bit did not. The Phoenix versions were 
from the last .whl files on the daily build page.

If there are any other things I should try, please let me know.

Thanks

On Thursday, May 14, 2015 at 10:29:17 AM UTC-6, Const wrote:
>
> *Summary*
>  
> Environment: wxPython Phoenix, head of master branch, Windows 7 64-bit, 
> Python 3.4.3.
>  
>
> The error can be reproduced in the GenericDirCtrl demo of the wxPython 
> demo application. The following is a snippet of code from the demo around 
> the source of the error.
>
>     sz = wx.FlexGridSizer(cols=3, hgap=5, vgap=5)
>     sz.Add((35, 35))  # some space above
>     sz.Add((35, 35))
>     sz.Add((35, 35))
>
>     sz.Add(txt1)
>     sz.Add(txt2)
>     sz.Add(txt3)
>
>     sz.Add(dir1, 0, wx.EXPAND)
>     sz.Add(dir2, 0, wx.EXPAND)
>     sz.Add(dir3, 0, wx.EXPAND)
>
>     sz.Add((35,35))  # some space below
>
>     sz.AddGrowableRow(2)
>     sz.AddGrowableCol(0)  # <-- error here
>     sz.AddGrowableCol(1)
>     sz.AddGrowableCol(2)
>
> The error is :
>
>     "!m_cols || idx < (size_t)m_cols" failed at 
> ..\..\src\common\sizer.cpp(1980)
>     in wxFlexGridSizer::AddGrowableCol(): invalid column index
>
> *Details*
>  
> I've done some poking around to try and diagnose the problem. Here are 
> some observation.
>  
> (1)
>  
> In Python, if you specify the named argument, it works. For example:
>
>     sz.AddGrowableCol(0, proportion=0)
>
> Although, this does not:
>
>     sz.AddGrowableCol(0, 0)
>
> (2)
>  
> The C++, wxWidgets, version of the demo works as expected.
>  
> (3)
>  
> At the C++ level in wxWidgets, when AddGrowableCol(size_t idx, int 
> proportion) is called, the value of idx equals some super large number 
> (as reported by the C++ debugger), hence the reason the C++ assert fails 
> (perhaps idx is uninitialized?).
>  
> (4)
>  
> If I insert a printf("idx=%d\n", idx) to see the value of the idx inside 
> the SIP generated wrapper function meth_wxFlexGridSizer_AddGrowableRow() 
> (source file sip\cpp\sip_corewxFlexGridSizer.cpp), sz.AddGrowableCol() in 
> Python works (hence the demo) works. Remove the printf() and it does not.
>  
>
>     static PyObject *meth_wxFlexGridSizer_AddGrowableRow(PyObject 
> *sipSelf, PyObject *sipArgs, PyObject *sipKwds)
>     {
>         PyObject *sipParseErr = NULL;
>
>         {
>             size_t idx;
>             int proportion = 0;
>             wxFlexGridSizer *sipCpp;
>
>             static const char *sipKwdList[] = {
>                 sipName_idx,
>                 sipName_proportion,
>             };
>
>             if (sipParseKwdArgs(&sipParseErr, sipArgs, sipKwds, 
> sipKwdList, NULL, "Bm|i", &sipSelf, sipType_wxFlexGridSizer, &sipCpp, &idx, 
> &proportion))
>             {
>                 PyErr_Clear();
>
>                 *printf("idx=%d\n", idx)*
>                 sipCpp->AddGrowableRow(idx,proportion);
>
>                 if (PyErr_Occurred())
>                     return 0;
>
>                 Py_INCREF(Py_None);
>                 return Py_None;
>             }
>         }
>
>         /* Raise an exception if the arguments couldn't be parsed. */
>         sipNoMethod(sipParseErr, sipName_FlexGridSizer, 
> sipName_AddGrowableRow, NULL);
>
>         return NULL;
>     }
>
> (5)
>  
> wx.Sizer.InsertStretchSpace() also asserts for the similar reason of the 
> index argument being a large number.  Coincidently, it has the same 
> calling signature. 
>
> Before I attempt to probe this any further, does anyone have any idea what 
> might be going on?
>
>  
>
>

-- 
You received this message because you are subscribed to the Google Groups "wxPython-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
For more options, visit https://groups.google.com/d/optout.
validator2.py (text/x-python, 2.9 KB)
import wx
import pprint
import sys      #AJH: Added so we can see Python version.

about_txt = """\
The validator used in this example shows how the validator
can be used to transfer data to and from each text control
automatically when the dialog is shown and dismissed."""


class DataXferValidator(wx.Validator):   #AJH:  was wx.PyValidator
     def __init__(self, data, key):
         wx.Validator.__init__(self)     #AJH:  was wx.PyValidator
         self.data = data
         self.key = key

     def Clone(self):
         """
         Note that every validator must implement the Clone() method.
         """
         return DataXferValidator(self.data, self.key)

     def Validate(self, win):
         return True

     def TransferToWindow(self):
         textCtrl = self.GetWindow()
         textCtrl.SetValue(self.data.get(self.key, ""))
         return True 

     def TransferFromWindow(self):
         textCtrl = self.GetWindow()
         self.data[self.key] = textCtrl.GetValue()
         return True



class MyDialog(wx.Dialog):
    def __init__(self, data):
        wx.Dialog.__init__(self, None, -1, "Validators: data transfer")

        # Create the text controls
        about   = wx.StaticText(self, -1, about_txt)
        name_l  = wx.StaticText(self, -1, "Name:")
        email_l = wx.StaticText(self, -1, "Email:")
        phone_l = wx.StaticText(self, -1, "Phone:")
        
        name_t  = wx.TextCtrl(self, validator=DataXferValidator(data, "name"))
        email_t = wx.TextCtrl(self, validator=DataXferValidator(data, "email"))
        phone_t = wx.TextCtrl(self, validator=DataXferValidator(data, "phone"))

        # Use standard button IDs
        okay   = wx.Button(self, wx.ID_OK)
        okay.SetDefault()
        cancel = wx.Button(self, wx.ID_CANCEL)

        # Layout with sizers
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(about, 0, wx.ALL, 5)
        sizer.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.ALL, 5)
        
        fgs = wx.FlexGridSizer(3, 2, 5, 5)
        fgs.Add(name_l, 0, wx.ALIGN_RIGHT)
        fgs.Add(name_t, 0, wx.EXPAND)
        fgs.Add(email_l, 0, wx.ALIGN_RIGHT)
        fgs.Add(email_t, 0, wx.EXPAND)
        fgs.Add(phone_l, 0, wx.ALIGN_RIGHT)
        fgs.Add(phone_t, 0, wx.EXPAND)
        fgs.AddGrowableCol(1)
        sizer.Add(fgs, 0, wx.EXPAND|wx.ALL, 5)

        btns = wx.StdDialogButtonSizer()
        btns.AddButton(okay)
        btns.AddButton(cancel)
        btns.Realize()
        sizer.Add(btns, 0, wx.EXPAND|wx.ALL, 5)

        self.SetSizer(sizer)
        sizer.Fit(self)
        

print(sys.version)                               #AJH:  added line
print('wxPython/Phoenix version:', wx.version()) #AJH:  added line
app = wx.App()                                   #AJH:  was wx.PySimpleApp()

data = { "name" : "Jordyn Dunn" }
dlg = MyDialog(data)
dlg.ShowModal()
dlg.Destroy()

wx.MessageBox("You entered these values:\n\n" +
              pprint.pformat(data))

app.MainLoop()
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.