Preliminary wxPropertyGrid Bindings in SVN trunk

1 view
Skip to first unread message

Jaakko Salli

unread,
May 29, 2009, 12:40:04 PM5/29/09
to wxPyth...@googlegroups.com

Hi All,

I've just added the first version of wxPropertyGrid bindings
for wxPython 2.9.0 in the SVN trunk. They seem to build just
fine, but I get strange errors when running the demo (based
on my old test_propgrid.py). It seems my global variables
class instance, derived from wxModule, is not really
initialized.

Note that this problem does not appear when running my
plain test_propgrid.py, available here:

http://personal.inet.fi/private/jmsalli/test_propgrid.py

Any ideas what could be causing the problem?

Also, the first wxPython 2.9 release is going to be
based on the code in WX_2_9_0_BRANCH, right? I've made
my C++ code tweaks there.

Thanks,
Jaakko

Robin Dunn

unread,
May 29, 2009, 1:10:04 PM5/29/09
to wxPyth...@googlegroups.com
Jaakko Salli wrote:
>
> Hi All,
>
> I've just added the first version of wxPropertyGrid bindings
> for wxPython 2.9.0 in the SVN trunk.

Thanks! I've been meaning to ask you about them but it kept slipping my
mind.

> They seem to build just
> fine, but I get strange errors when running the demo (based
> on my old test_propgrid.py). It seems my global variables
> class instance, derived from wxModule, is not really
> initialized.
>
> Note that this problem does not appear when running my
> plain test_propgrid.py, available here:
>
> http://personal.inet.fi/private/jmsalli/test_propgrid.py
>
> Any ideas what could be causing the problem?

wxModules are initialized and executed when wxWidgets is first loaded
and is initializing its own globals, but when your python module is
imported later after that has happened there isn't anything to trigger
the execution of the new wxModules in the newly loaded dynamic
libraries. So you need to provide a function that will do it for you,
and then call that function when the Python module is imported.

For example, look in XRC at the wxXmlInitResourceModule function. In
the .i file I've got code like this that gets merged into the module's
init function:

%init %{
wxXmlInitResourceModule();
%}


>
> Also, the first wxPython 2.9 release is going to be
> based on the code in WX_2_9_0_BRANCH, right? I've made
> my C++ code tweaks there.

Yes. I didn't make a 2.9.0 specific branch because I thought it was
only going to be active for a few days and because I figured that I
would not be working on more than one 2.9.x branch at a time. At least
one of my assumptions was correct. ;-)

--
Robin Dunn
Software Craftsman
http://wxPython.org

Jaakko Salli

unread,
May 29, 2009, 2:24:39 PM5/29/09
to wxPyth...@googlegroups.com
Robin Dunn wrote:

> Jaakko Salli wrote:
>> Any ideas what could be causing the problem?
>
> wxModules are initialized and executed when wxWidgets is first loaded
> and is initializing its own globals, but when your python module is
> imported later after that has happened there isn't anything to trigger
> the execution of the new wxModules in the newly loaded dynamic
> libraries. So you need to provide a function that will do it for you,
> and then call that function when the Python module is imported.
>
> For example, look in XRC at the wxXmlInitResourceModule function. In
> the .i file I've got code like this that gets merged into the module's
> init function:
>
> %init %{
> wxXmlInitResourceModule();
> %}
>
All right, that's pretty much what I had to do to get it working now.

Thanks,
Jaakko


Robin Dunn

unread,
May 30, 2009, 1:06:19 AM5/30/09
to wxPyth...@googlegroups.com

It would be nice to be able to get rid of these swig warnings:


../wxWidgets/include/wx/propgrid/propgridpagestate.h:275: Warning(362):
operator= ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:275: Warning(383):
operator++ ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:275: Warning(383):
operator++ ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:275: Warning(384):
operator-- ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:275: Warning(384):
operator-- ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:286: Warning(362):
operator= ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:286: Warning(383):
operator++ ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:286: Warning(383):
operator++ ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:286: Warning(384):
operator-- ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:286: Warning(384):
operator-- ignored
../wxWidgets/include/wx/propgrid/propgridpagestate.h:303: Warning(362):
operator= ignored
../wxWidgets/include/wx/propgrid/manager.h:66: Warning(402): Base class
'wxPropertyGridPageState' is incomplete.
../wxWidgets/include/wx/propgrid/propgriddefs.h:272: Warning(402): Only
forward declaration 'wxPropertyGridPageState' was found.
src/propgrid_cbacks.i:481: Warning(401): Nothing known about base class
'wxSystemColourProperty'. Ignored.
src/propgrid_cbacks.i:856: Warning(401): Nothing known about base class
'wxColourProperty'. Ignored.

Robin Dunn

unread,
May 30, 2009, 1:24:59 AM5/30/09
to wxPyth...@googlegroups.com

I'm getting some Assertion errors when starting up the demo, and also
some tracebacks:

22:07:18: Debug:
/projects/wx/2.9/wxWidgets/src/propgrid/property.cpp(458): assert "s ==
g_invalidStringContent" failed in InitAfterAdded(): Implement
ValueToString() instead of GetValueAsString()
22:07:45: Debug:
/projects/wx/2.9/wxWidgets/src/propgrid/property.cpp(458): assert "s ==
g_invalidStringContent" failed in InitAfterAdded(): Implement
ValueToString() instead of GetValueAsString()
22:07:48: Debug:
/projects/wx/2.9/wxWidgets/src/propgrid/propgridiface.cpp(571): assert
"p" failed in GetPropertyByNameA(): no property with name 'NotARealProperty'
Traceback (most recent call last):
File "/projects/wx/2.9/wxPython/demo/PropertyGrid.py", line 512, in
OnPropGridSelect
print('%s selected'%(event.GetPropertyName()))
AttributeError: 'PropertyGridEvent' object has no attribute
'GetPropertyName'
Traceback (most recent call last):
File "/projects/wx/2.9/wxPython/demo/PropertyGrid.py", line 512, in
OnPropGridSelect
print('%s selected'%(event.GetPropertyName()))
AttributeError: 'PropertyGridEvent' object has no attribute
'GetPropertyName'


Also, some of the property widgets are a little too cramped on the Mac.
I'll attach a couple samples.

There is also this message from the SWIG runtime: "swig/python detected
a memory leak of type 'wxColourPropertyValue *', no destructor found."
This means that there is a wxColourPropertyValue object that was created
in Python and the runtime thinks that the proxy object still owns the
C++ object, but there is no destructor for it to call. To take care of
this you can simply define a destructor for SWIG to see (it will just
generate the "delete obj" code and it won't matter if there is a real
dtor or just the implicit one created by the compiler.) If ownership of
that object is ever transfered to some other object then be sure to use
the disown directive so SWIG will clear the flag indicating that the
proxy owns the C++ object. For example, in the wxListCtrl class I have
this for disowning the imagelist when it is passed to AssignImageList:

%disownarg( wxImageList *imageList );
void AssignImageList(wxImageList *imageList, int which);
%cleardisown( wxImageList *imageList );

Snap001.png
Snap002.png
Snap003.png

Jaakko Salli

unread,
May 30, 2009, 3:13:29 AM5/30/09
to wxPyth...@googlegroups.com
Robin Dunn wrote:
>
> It would be nice to be able to get rid of these swig warnings:
>
>
> ../wxWidgets/include/wx/propgrid/propgridpagestate.h:275: Warning(362):
> operator= ignored
> ../wxWidgets/include/wx/propgrid/propgridpagestate.h:275: Warning(383):
> operator++ ignored
> ../wxWidgets/include/wx/propgrid/propgridpagestate.h:275: Warning(383):
> operator++ ignored
> ../wxWidgets/include/wx/propgrid/propgridpagestate.h:275: Warning(384):
> operator-- ignored
> ../wxWidgets/include/wx/propgrid/propgridpagestate.h:275: Warning(384):
> operator-- ignored
> ../wxWidgets/include/wx/propgrid/propgridpagestate.h:286: Warning(362):
> operator= ignored
> ../wxWidgets/include/wx/propgrid/propgridpagestate.h:286: Warning(383):
> operator++ ignored
> ../wxWidgets/include/wx/propgrid/propgridpagestate.h:286: Warning(383):
> operator++ ignored
> ../wxWidgets/include/wx/propgrid/propgridpagestate.h:286: Warning(384):
> operator-- ignored
> ../wxWidgets/include/wx/propgrid/propgridpagestate.h:286: Warning(384):
> operator-- ignored
> ../wxWidgets/include/wx/propgrid/propgridpagestate.h:303: Warning(362):
> operator= ignored
What is the best way to do this without adding '#ifndef SWIG' sections
in the header files? Just disable the warning?

> ../wxWidgets/include/wx/propgrid/manager.h:66: Warning(402): Base class
> 'wxPropertyGridPageState' is incomplete.
> ../wxWidgets/include/wx/propgrid/propgriddefs.h:272: Warning(402): Only
> forward declaration 'wxPropertyGridPageState' was found.
> src/propgrid_cbacks.i:481: Warning(401): Nothing known about base class
> 'wxSystemColourProperty'. Ignored.
> src/propgrid_cbacks.i:856: Warning(401): Nothing known about base class
> 'wxColourProperty'. Ignored.

Thing is, I'm not sure if it is a good idea to expose all the property
classes in wxPython, as that's *a lot* of SWIG code, and wxPG .pyd
file is already almost double the size of wxAUI one. That is why many
property classes and wxPropertyGridPageState have "#ifndef SWIG"
condition around them. Naturally, you can still create these properties
using factory functions provided in propgrid.i, but you can't derive
from them (I've tried to exclude property classes that are particularly
un-useful as a basis for derived user properties). I guess I could
disable the SWIG warning if I cannot think of any better overall
solution.

Thanks,
Jaakko

Jaakko Salli

unread,
May 30, 2009, 3:29:35 AM5/30/09
to wxPyth...@googlegroups.com
Robin Dunn wrote:
> I'm getting some Assertion errors when starting up the demo, and also
> some tracebacks:
>
> 22:07:18: Debug:
> /projects/wx/2.9/wxWidgets/src/propgrid/property.cpp(458): assert "s ==
> g_invalidStringContent" failed in InitAfterAdded(): Implement
> ValueToString() instead of GetValueAsString()
> 22:07:45: Debug:
> /projects/wx/2.9/wxWidgets/src/propgrid/property.cpp(458): assert "s ==
> g_invalidStringContent" failed in InitAfterAdded(): Implement
> ValueToString() instead of GetValueAsString()
> 22:07:48: Debug:
> /projects/wx/2.9/wxWidgets/src/propgrid/propgridiface.cpp(571): assert
> "p" failed in GetPropertyByNameA(): no property with name 'NotARealProperty'
The above ones I don't get, at least not by just starting up the demo.
I'm testing on WinXP SP3, with Python 2.6.2 and wxPython debug builds
compiled using VC9 (debugging in VC2008 Express IDE).

> Traceback (most recent call last):
> File "/projects/wx/2.9/wxPython/demo/PropertyGrid.py", line 512, in
> OnPropGridSelect
> print('%s selected'%(event.GetPropertyName()))
> AttributeError: 'PropertyGridEvent' object has no attribute
> 'GetPropertyName'
> Traceback (most recent call last):
> File "/projects/wx/2.9/wxPython/demo/PropertyGrid.py", line 512, in
> OnPropGridSelect
> print('%s selected'%(event.GetPropertyName()))
> AttributeError: 'PropertyGridEvent' object has no attribute
> 'GetPropertyName'

These I got and they should be fixed now in SVN trunk.

>
>
> Also, some of the property widgets are a little too cramped on the Mac.
> I'll attach a couple samples.

Right, but as of this time I don't have a Mac OS X box to develop with,
I don't think I can do much about it.

>
> There is also this message from the SWIG runtime: "swig/python detected
> a memory leak of type 'wxColourPropertyValue *', no destructor found."
> This means that there is a wxColourPropertyValue object that was created
> in Python and the runtime thinks that the proxy object still owns the
> C++ object, but there is no destructor for it to call. To take care of
> this you can simply define a destructor for SWIG to see (it will just
> generate the "delete obj" code and it won't matter if there is a real
> dtor or just the implicit one created by the compiler.) If ownership of
> that object is ever transfered to some other object then be sure to use
> the disown directive so SWIG will clear the flag indicating that the
> proxy owns the C++ object. For example, in the wxListCtrl class I have
> this for disowning the imagelist when it is passed to AssignImageList:
>
> %disownarg( wxImageList *imageList );
> void AssignImageList(wxImageList *imageList, int which);
> %cleardisown( wxImageList *imageList );
>

Yes, I received this error message as well and wondered about it.
I'll try to fix it soon.

Thanks,
Jaakko

Robin Dunn

unread,
May 30, 2009, 1:13:27 PM5/30/09
to wxPyth...@googlegroups.com

You can use the %ignore directive with the function signature before the
%include's to exclude just those items.


>
>> ../wxWidgets/include/wx/propgrid/manager.h:66: Warning(402): Base class
>> 'wxPropertyGridPageState' is incomplete.
>> ../wxWidgets/include/wx/propgrid/propgriddefs.h:272: Warning(402): Only
>> forward declaration 'wxPropertyGridPageState' was found.
>> src/propgrid_cbacks.i:481: Warning(401): Nothing known about base class
>> 'wxSystemColourProperty'. Ignored.
>> src/propgrid_cbacks.i:856: Warning(401): Nothing known about base class
>> 'wxColourProperty'. Ignored.
> Thing is, I'm not sure if it is a good idea to expose all the property
> classes in wxPython, as that's *a lot* of SWIG code, and wxPG .pyd
> file is already almost double the size of wxAUI one. That is why many
> property classes and wxPropertyGridPageState have "#ifndef SWIG"
> condition around them.

Ignoring a base class without a warning might be a bit more tricky.
Maybe just a forward declaration will take care of it. Don't stress too
much about it though, it's not a huge deal if you can't get rid of the
warnings.

Jaakko Salli

unread,
May 31, 2009, 8:25:52 AM5/31/09
to wxPyth...@googlegroups.com
Jaakko Salli wrote:
> Robin Dunn wrote:
>> There is also this message from the SWIG runtime: "swig/python detected
>> a memory leak of type 'wxColourPropertyValue *', no destructor found."
>> This means that there is a wxColourPropertyValue object that was created
>> in Python and the runtime thinks that the proxy object still owns the
>> C++ object, but there is no destructor for it to call. To take care of
>> this you can simply define a destructor for SWIG to see (it will just
>> generate the "delete obj" code and it won't matter if there is a real
>> dtor or just the implicit one created by the compiler.) If ownership of
>> that object is ever transfered to some other object then be sure to use
>> the disown directive so SWIG will clear the flag indicating that the
>> proxy owns the C++ object. For example, in the wxListCtrl class I have
>> this for disowning the imagelist when it is passed to AssignImageList:
>>
>> %disownarg( wxImageList *imageList );
>> void AssignImageList(wxImageList *imageList, int which);
>> %cleardisown( wxImageList *imageList );w

>>
> Yes, I received this error message as well and wondered about it.
> I'll try to fix it soon.
>
I have to admit I'm a bit stuck here. wxColourPropertyValue
(in advprops.h) inherits from wxObject and has a virtual
destructor that is visible to SWIG. I've added, for testings purposes,

%disownarg(wxColourPropertyValue& v);
%disownarg(const wxColourPropertyValue& value);

which should cover all the cases visible to SWIG, but unfortunately
that doesn't make any difference. Only place where ownership might
be transferred is in PyObject<->wxVariant conversion code, but at least
my breakpoints in VC2008 IDE did not show that it was ever called. Also,
I handle wxCPV in the conversion code in the same way as wxFont and
wxColour, so I think that should not matter.

Any additional debug tips are appreciated!

Thanks,
Jaakko

Robin Dunn

unread,
Jun 1, 2009, 9:51:55 PM6/1/09
to wxPyth...@googlegroups.com
Jaakko Salli wrote:
> Robin Dunn wrote:
>> I'm getting some Assertion errors when starting up the demo, and also
>> some tracebacks:
>>
>> 22:07:18: Debug:
>> /projects/wx/2.9/wxWidgets/src/propgrid/property.cpp(458): assert "s ==
>> g_invalidStringContent" failed in InitAfterAdded(): Implement
>> ValueToString() instead of GetValueAsString()
>> 22:07:45: Debug:
>> /projects/wx/2.9/wxWidgets/src/propgrid/property.cpp(458): assert "s ==
>> g_invalidStringContent" failed in InitAfterAdded(): Implement
>> ValueToString() instead of GetValueAsString()
>> 22:07:48: Debug:
>> /projects/wx/2.9/wxWidgets/src/propgrid/propgridiface.cpp(571): assert
>> "p" failed in GetPropertyByNameA(): no property with name 'NotARealProperty'
> The above ones I don't get, at least not by just starting up the demo.
> I'm testing on WinXP SP3, with Python 2.6.2 and wxPython debug builds
> compiled using VC9 (debugging in VC2008 Express IDE).

Try running the PropertyGrid.py standalone (IOW, not from within the
demo app.) The default assertion mode for wxPython apps is the
assertions are turned into exceptions but those can be suppressed as
you've done for the NotARealProperty and etc. items with an empty
try/except, or sometimes other code nesting situations can cause the
error to be cleared before it is displayed as is happening with the
ValueToString assertions. The default wx mode on the other hand is to
show an assertion dialog and the run.py script (used when running a
sample standalone) sets the assertion mode to behave that way so you can
be sure to see those messages

I've made some changes to the demo to avoid the assertions, but
somethings is still not right with the property classes defined in the
demo. Could you please take a look at those?


>> Also, some of the property widgets are a little too cramped on the Mac.
>> I'll attach a couple samples.
> Right, but as of this time I don't have a Mac OS X box to develop with,
> I don't think I can do much about it.

Time to recruit a helper who has a mac. ;-)

Robin Dunn

unread,
Jun 1, 2009, 9:53:42 PM6/1/09
to wxPyth...@googlegroups.com

Best tips I can offer is to actually debug it! ;-) Since I didn't do
that before and just made an assumption about the problem I sent you on
a wild snake chase.

I just used a Python debugger and tracked down the source of the problem
to the wxpg.SystemColourProperty in the demo. When the
GetPropertyValues is called from the demo there is a problem in
converting the value of that variant type and so what is being returned
is the bare PySwigObject without any proxy class wrapped around it. I
then jumped into the C++ debugger and found that when your
wxVariant_to_PyObject tries to convert a variant of type
"wxColourPropertyValue" the SWIG_Python_NewPointerObject function is not
creating a new proxy instance because there is no Python class defined
for wxColourPropertyValue. SWIG knows about the existance of the type,
but since advprops.h was not being %included then it didn't see the full
definition and it was not generating any wrapper code for it. Adding
that %include and giving that header an additional #ifndef SWIG seems to
have taken care of it. (Although the Get/SetPropertyValues in the demo
for that type could use some help.)

Jaakko Salli

unread,
Jun 2, 2009, 10:34:19 AM6/2/09
to wxPyth...@googlegroups.com
Robin Dunn wrote:
> Jaakko Salli wrote:
>> Any additional debug tips are appreciated!
>
> Best tips I can offer is to actually debug it! ;-) Since I didn't do
> that before and just made an assumption about the problem I sent you on
> a wild snake chase.
>
> I just used a Python debugger and tracked down the source of the problem
> to the wxpg.SystemColourProperty in the demo. When the
> GetPropertyValues is called from the demo there is a problem in
> converting the value of that variant type and so what is being returned
> is the bare PySwigObject without any proxy class wrapped around it. I
> then jumped into the C++ debugger and found that when your
> wxVariant_to_PyObject tries to convert a variant of type
> "wxColourPropertyValue" the SWIG_Python_NewPointerObject function is not
> creating a new proxy instance because there is no Python class defined
> for wxColourPropertyValue. SWIG knows about the existance of the type,
> but since advprops.h was not being %included then it didn't see the full
> definition and it was not generating any wrapper code for it. Adding
> that %include and giving that header an additional #ifndef SWIG seems to
> have taken care of it. (Although the Get/SetPropertyValues in the demo
> for that type could use some help.)
>
Many thanks for debugging and resolving this. One more useful thing to
back port into wxPG 1.4 ;)

Jaakko

Reply all
Reply to author
Forward
0 new messages