wxPython 4.0.2

Robin Dunn:

If the change really rubs you the wrong way

It really does. The author of the deprecation notice seems to live in a world where people hardwire constant ID numbers in their application. Who does that? If library authors do that, then the numbers are bound to collide sooner or later.

The deprecation notice says:

Deprecated: Ids generated by it can conflict with the Ids defined by the user code

But wx.NewId is the *solution* to that problem, not the cause of it. The solution to the problem of hardwired constant ID numbers is to stop hardwiring constant ID numbers.

Monkeypatching wx is no good, because to avoid collisions everyone must use the same mechanism to allocate numbers, and if I make my own allocation function for my own private use, then that is not the case.

Before I go on a mass editing spree to replace wx.NewId, can you confirm that wx.Window.NewControlId is the proper replacement?

regards, Anders

Robin Dunn:

If the change really rubs you the wrong way

It really does. The author of the deprecation notice seems to live in a world where people hardwire constant ID numbers in their application. Who does that? If library authors do that, then the numbers are bound to collide sooner or later.

Until recently the usual way to bind events in C++ wxWidgets is to use the static event table, which means static IDs are needed. (Dynamically binding handers is becoming more popular now, thanks in part to wxPython’s example with our Bind()). Duplicate IDs only really becomes a problem when the widgets with that ID are in the same containment hierarchy, and the events for those widgets are being caught in a common ancestor instead of within the widget itself or its immediate parent. That means that even with static IDs it is not a problem in something like 95% or better of the cases.

The deprecation notice says:

Deprecated: Ids generated by it can conflict with the Ids defined by the user code

But wx.NewId is the solution to that problem, not the cause of it. The solution to the problem of hardwired constant ID numbers is to stop hardwiring constant ID numbers.

Monkeypatching wx is no good, because to avoid collisions everyone must use the same mechanism to allocate numbers, and if I make my own allocation function for my own private use, then that is not the case.

But there are also potential conflicts with wxNewId because anything that uses wx.ID_ANY to allow wx to allocate the ID will be using NewControlId instead of wxNewId

Before I go on a mass editing spree to replace wx.NewId, can you confirm that wx.Window.NewControlId is the proper replacement?

It is. It uses an internal management class to reserve IDs when used and release them when the widget is destroyed, so even if the internal counter wraps around those IDs that are still active will not be reused.

···

On Tuesday, June 19, 2018 at 3:14:59 AM UTC-7, Anders Munch wrote:

Robin

hello, in the process of managing NewId deprecation warnings, replacing them with other code, I would like to silent these warnings in production code. In another thread a couple of days ago, before wxpython 4.0.2, I ended up with this solution:

if main_is_frozen():
with warnings.catch_warnings():
warnings.simplefilter(‘ignore’)
#warnings.filterwarnings(‘ignore’)
run()
else:
run()

Unfortunately NewId deprecation warning by pass this filters. What could be used instead?

thank in advance

Marco

···

On Tuesday, June 19, 2018 at 6:47:10 PM UTC+2, Robin Dunn wrote:

On Tuesday, June 19, 2018 at 3:14:59 AM UTC-7, Anders Munch wrote:

Robin Dunn:

If the change really rubs you the wrong way

It really does. The author of the deprecation notice seems to live in a world where people hardwire constant ID numbers in their application. Who does that? If library authors do that, then the numbers are bound to collide sooner or later.

Until recently the usual way to bind events in C++ wxWidgets is to use the static event table, which means static IDs are needed. (Dynamically binding handers is becoming more popular now, thanks in part to wxPython’s example with our Bind()). Duplicate IDs only really becomes a problem when the widgets with that ID are in the same containment hierarchy, and the events for those widgets are being caught in a common ancestor instead of within the widget itself or its immediate parent. That means that even with static IDs it is not a problem in something like 95% or better of the cases.

The deprecation notice says:

Deprecated: Ids generated by it can conflict with the Ids defined by the user code

But wx.NewId is the solution to that problem, not the cause of it. The solution to the problem of hardwired constant ID numbers is to stop hardwiring constant ID numbers.

Monkeypatching wx is no good, because to avoid collisions everyone must use the same mechanism to allocate numbers, and if I make my own allocation function for my own private use, then that is not the case.

But there are also potential conflicts with wxNewId because anything that uses wx.ID_ANY to allow wx to allocate the ID will be using NewControlId instead of wxNewId

Before I go on a mass editing spree to replace wx.NewId, can you confirm that wx.Window.NewControlId is the proper replacement?

It is. It uses an internal management class to reserve IDs when used and release them when the widget is destroyed, so even if the internal counter wraps around those IDs that are still active will not be reused.

Robin

Is that code before or after the import of wx? There is warnings.simplefilter('default', wxPyDeprecationWarning) happening in the wx module which could be overriding your ‘ignore’.

···

On Tuesday, June 19, 2018 at 11:59:10 AM UTC-7, Marco Prosperi wrote:

hello, in the process of managing NewId deprecation warnings, replacing them with other code, I would like to silent these warnings in production code. In another thread a couple of days ago, before wxpython 4.0.2, I ended up with this solution:

if main_is_frozen():
with warnings.catch_warnings():
warnings.simplefilter(‘ignore’)
#warnings.filterwarnings(‘ignore’)
run()
else:
run()

Unfortunately NewId deprecation warning by pass this filters. What could be used instead?

Robin

Is that code before or after the import of wx? There is warnings.simplefilter('default', wxPyDeprecationWarning) happening in the wx module which could be overriding your ‘ignore’.

In run() I create the main Frame and create main loop. NewId warnings show up if import wx at the top of the script, outside of everything, but also if I import it in run function. I’ve tried to reduce everything to a simple app (attached) to understand better. In this case NewId warnings are never shown, even if I don’t filter them! Can’t understand

python 3.5,win10,wxpython 4.0.2

wxsample.py (414 Bytes)

···

Robin

NewControlId values being deallocated automatically when the widget is destroyed gives rise to a new problem. In my context menus, I have some fixed entries (“Expand all” on a tree, for instance). I keep a data structure, including the id, around and use that when creating the popup menu. Works great the first time the context menu is built, but the second time I get the error below. Seems I need some static ids outside the range controlled by the IdManager. How do I generate those without collisions?

lm/gui/contextMenu.py 865 in addToMenu:

0865 item = wx.MenuItem(menu, self.id, self.text, kind=kind)

wxAssertionError: C++ assertion “gs_autoIdsRefCount[winid] != ID_FREE” failed at …..\src\common\windowid.cpp(146) in `anonymous-namespace’::DecIdRefCount(): id count already 0

···

On Tuesday, June 19, 2018 at 9:47:10 AM UTC-7, Robin Dunn wrote:

Before I go on a mass editing spree to replace wx.NewId, can you confirm that wx.Window.NewControlId is the proper replacement?

It is. It uses an internal management class to reserve IDs when used and release them when the widget is destroyed, so even if the internal counter wraps around those IDs that are still active will not be reused.

I guess I need to wrap wxIdManager.

···

On Wednesday, June 20, 2018 at 5:23:47 PM UTC-7, efahl wrote:

On Tuesday, June 19, 2018 at 9:47:10 AM UTC-7, Robin Dunn wrote:

Before I go on a mass editing spree to replace wx.NewId, can you confirm that wx.Window.NewControlId is the proper replacement?

It is. It uses an internal management class to reserve IDs when used and release them when the widget is destroyed, so even if the internal counter wraps around those IDs that are still active will not be reused.

NewControlId values being deallocated automatically when the widget is destroyed gives rise to a new problem. In my context menus, I have some fixed entries (“Expand all” on a tree, for instance). I keep a data structure, including the id, around and use that when creating the popup menu. Works great the first time the context menu is built, but the second time I get the error below. Seems I need some static ids outside the range controlled by the IdManager. How do I generate those without collisions?

Robin

But looking at the wxIdManager’s interface, it doesn’t appear to offer that functionality? It would need something like a StaticControlId() method to produced values that are not put into the ref counted pool. Or will your envisioned wrapper add a “don’t deallocate” option and re-increment the ref count or something like that?

My current solution is to replace only those problematic NewControlId calls with this… (I only have a couple dozen, so I don’t think I’ll run out of space.)

@staticvariable(next=wx.ID_HIGHEST)

def StaticId():

StaticId.next += 1

return StaticId.next

···

On Wednesday, June 20, 2018 at 6:46:58 PM UTC-7, Robin Dunn wrote:

On Wednesday, June 20, 2018 at 5:23:47 PM UTC-7, efahl wrote:

NewControlId values being deallocated automatically when the widget is destroyed gives rise to a new problem. In my context menus, I have some fixed entries (“Expand all” on a tree, for instance). I keep a data structure, including the id, around and use that when creating the popup menu. Works great the first time the context menu is built, but the second time I get the error below. Seems I need some static ids outside the range controlled by the IdManager. How do I generate those without collisions?

I guess I need to wrap wxIdManager.

There is another class that is not documented which is used by the widgets to auto unreserve the IDs. I may have to do something with that. We’ll see how it goes.

···

On Wednesday, June 20, 2018 at 7:30:42 PM UTC-7, efahl wrote:

On Wednesday, June 20, 2018 at 6:46:58 PM UTC-7, Robin Dunn wrote:

On Wednesday, June 20, 2018 at 5:23:47 PM UTC-7, efahl wrote:

NewControlId values being deallocated automatically when the widget is destroyed gives rise to a new problem. In my context menus, I have some fixed entries (“Expand all” on a tree, for instance). I keep a data structure, including the id, around and use that when creating the popup menu. Works great the first time the context menu is built, but the second time I get the error below. Seems I need some static ids outside the range controlled by the IdManager. How do I generate those without collisions?

I guess I need to wrap wxIdManager.

But looking at the wxIdManager’s interface, it doesn’t appear to offer that functionality? It would need something like a StaticControlId() method to produced values that are not put into the ref counted pool. Or will your envisioned wrapper add a “don’t deallocate” option and re-increment the ref count or something like that?

Robin

Hi All,

Last night’s snapshot build includes a change for this issue. Please give it a quick test if you are able. I’d like to do a new release ASAP, but I’d like to make sure that it doesn’t somehow make things worse before building and finalizing 4.0.3. There are still a couple more minor things on the way related to the new class and function, but what’s in the snapshot should work fine for replacing the typical usage of wx.NewId. I still recommend using wx.ID_ANY and obj.GetId() when you can, but wx.NewIdRef will work well when you want to reuse IDs. Here is the changelog item for the change:

  • Added wrappers for the wx.WindowIDRef class and added the wx.NewIdRef

    function. These will make it possible to create reserved Window IDs using the

    same mechanism which is used when passing wx.ID_ANY to a widget constructor.

    The object returned by wx.NewIdRef will automatically convert to an int when

    passing it to a window constructor, and can also be used as the source in a

    Bind(). (#896)

Basically, wx.NewIdRef returns a wx.WindowIDRef that has been initialized with wx.IdManager.ReserveId() (same as what wx.Window.NewControlId() uses.) The returned WindowIDRef can be used and reused the same as the integers returned by wx.NewId, but they are safe from ID conflicts with anything else that uses the wx.IdManager or uses wx.ID_ANY.

For the curious, all the details of the change are here: Add wx.WindowIDRef and wx.NewIdRef by RobinD42 · Pull Request #897 · wxWidgets/Phoenix · GitHub

Please post any followups about this to wxPython-dev.

···

On Thursday, June 21, 2018 at 11:23:24 AM UTC-7, Robin Dunn wrote:

On Wednesday, June 20, 2018 at 7:30:42 PM UTC-7, efahl wrote:

On Wednesday, June 20, 2018 at 6:46:58 PM UTC-7, Robin Dunn wrote:

On Wednesday, June 20, 2018 at 5:23:47 PM UTC-7, efahl wrote:

NewControlId values being deallocated automatically when the widget is destroyed gives rise to a new problem. In my context menus, I have some fixed entries (“Expand all” on a tree, for instance). I keep a data structure, including the id, around and use that when creating the popup menu. Works great the first time the context menu is built, but the second time I get the error below. Seems I need some static ids outside the range controlled by the IdManager. How do I generate those without collisions?

I guess I need to wrap wxIdManager.

But looking at the wxIdManager’s interface, it doesn’t appear to offer that functionality? It would need something like a StaticControlId() method to produced values that are not put into the ref counted pool. Or will your envisioned wrapper add a “don’t deallocate” option and re-increment the ref count or something like that?

There is another class that is not documented which is used by the widgets to auto unreserve the IDs. I may have to do something with that. We’ll see how it goes.

Robin