Re: [matplotlib-devel] Possible bug in matplotlib.cbook.CallbackRegistry

2011-10-25 Thread tobin
Here is a bit more detail and a simple example.

The example below places red squares in an axes.  When the user clicks on an 
existing red square - another square is created and added. When the user hits 
any key a square is deleted from the axes.  The error is triggered by clicking 
on the red square and then hitting any key, and then clicking a red square 
again.

Diagnosis:
By monitoring cbook.py line 235 and cbook.py line 263 it can be seen that after 
the second mouse click (following one of the squares being deleted), that the 
process() function builds a loop and begins handling the button press 
callbacks.  Note that there is a dead reference coming later in this list.  The 
first callback involves another square being created and the connect() method 
being called.  In the connect() call - the dead reference is deleted from the 
callback list.  Now upon returning to the process() callback this dead 
reference is no longer in the callback list and a Key Exception is triggered 
once it gets to it in the loop.

Problem:
There are two locations where dead references are cleared from the callback 
list.  When these loops get intermingled - as the case with a callback leading 
to another connect mid-loop - the exception occurs when both loops attempt to 
delete the dead reference.

Possible Solutions:
1. Trap the KeyException at the point of attempting to delete it from the list 
in both places.

2. Place the dead reference check and deletion within a single method ... and 
perform this check at beginning of the process() and connect() methods before 
processing callbacks.


Sample Code


import matplotlib
matplotlib.use('WXAGG')

from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
from matplotlib.pyplot import Figure, Axes, Rectangle

import wx
import random

class SquareManager(object):
def __init__(self, axes):
self.axes = axes
self.canvas = axes.figure.canvas 
self.squares = []
self.last_x = 0

self.canvas.mpl_connect('key_press_event', self.on_key_press)

def add_square(self):
self.last_x += .1
s = Square(self, self.axes, [self.last_x, .4],
   .05, .05, facecolor='red', edgecolor='black')
self.squares.append(s)
self._refresh()

def on_key_press(self, evt):
if len(self.squares) == 0: return

# delete the first square - results in no error
# self.squares[0].remove()
# del self.squares[0]

# delete the last square - results in the error
self.squares[-1].remove()
del self.squares[-1]

self._refresh()

def _refresh(self):
self.canvas.draw()


class Square(Rectangle):
def __init__(self, manager, axes, *args, **kwds):
Rectangle.__init__(self, *args, **kwds)
axes.add_patch(self)

self.manager = manager
axes.figure.canvas.mpl_connect('button_press_event', self.selected)

def selected(self, evt):
within, _ = self.contains(evt)
if within:
self.manager.add_square()


app = wx.PySimpleApp()
frame = wx.Frame(None)
fig = Figure()
canvas = FigureCanvasWxAgg(frame, -1, fig)
a = Axes(fig, [.1, .1, .8, .8])
fig.add_axes(a)

sm = SquareManager(a)
sm.add_square()

frame.Show()
app.MainLoop()


# To demonstrate the error:
#
# 1. click on red sqaure
# 2. press any key
# 3. click on red sqaure again



 





--
The demand for IT networking professionals continues to grow, and the
demand for specialized networking skills is growing even more rapidly.
Take a complimentary Learning@Cisco Self-Assessment and learn 
about Cisco certifications, training, and career opportunities. 
http://p.sf.net/sfu/cisco-dev2dev
___
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel


Re: [matplotlib-devel] Possible bug in matplotlib.cbook.CallbackRegistry

2011-10-25 Thread Daniel Hyams
I've run into this same issue in the past, and have it "fixed" in my
own local copy of matplotlib.  I just placed a check to make sure that
cid actually was in the callbacks for s before deleting it.

That is quite possibly a band-aid; I never looked far enough in to
see.  But it is possibly another way of fixing the problem.


def process(self, s, *args, **kwargs):
"""
process signal *s*.  All of the functions registered to receive
callbacks on *s* will be called with *\*args* and *\*\*kwargs*
"""
if s in self.callbacks:
for cid, proxy in self.callbacks[s].items():
# Clean out dead references
if proxy.inst is not None and proxy.inst() is None:
   if cid in self.callbacks[s]: #<--- here
del self.callbacks[s][cid]
else:
proxy(*args, **kwargs)



On Tue, Oct 25, 2011 at 1:09 PM,   wrote:
> Here is a bit more detail and a simple example.
>
> The example below places red squares in an axes.  When the user clicks on an 
> existing red square - another square is created and added. When the user hits 
> any key a square is deleted from the axes.  The error is triggered by 
> clicking on the red square and then hitting any key, and then clicking a red 
> square again.
>
> Diagnosis:
> By monitoring cbook.py line 235 and cbook.py line 263 it can be seen that 
> after the second mouse click (following one of the squares being deleted), 
> that the process() function builds a loop and begins handling the button 
> press callbacks.  Note that there is a dead reference coming later in this 
> list.  The first callback involves another square being created and the 
> connect() method being called.  In the connect() call - the dead reference is 
> deleted from the callback list.  Now upon returning to the process() callback 
> this dead reference is no longer in the callback list and a Key Exception is 
> triggered once it gets to it in the loop.
>
> Problem:
> There are two locations where dead references are cleared from the callback 
> list.  When these loops get intermingled - as the case with a callback 
> leading to another connect mid-loop - the exception occurs when both loops 
> attempt to delete the dead reference.
>
> Possible Solutions:
> 1. Trap the KeyException at the point of attempting to delete it from the 
> list in both places.
>
> 2. Place the dead reference check and deletion within a single method ... and 
> perform this check at beginning of the process() and connect() methods before 
> processing callbacks.
>
>
> Sample Code
> 
>
> import matplotlib
> matplotlib.use('WXAGG')
>
> from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
> from matplotlib.pyplot import Figure, Axes, Rectangle
>
> import wx
> import random
>
> class SquareManager(object):
>    def __init__(self, axes):
>        self.axes = axes
>        self.canvas = axes.figure.canvas
>        self.squares = []
>        self.last_x = 0
>
>        self.canvas.mpl_connect('key_press_event', self.on_key_press)
>
>    def add_square(self):
>        self.last_x += .1
>        s = Square(self, self.axes, [self.last_x, .4],
>                   .05, .05, facecolor='red', edgecolor='black')
>        self.squares.append(s)
>        self._refresh()
>
>    def on_key_press(self, evt):
>        if len(self.squares) == 0: return
>
>        # delete the first square - results in no error
>        # self.squares[0].remove()
>        # del self.squares[0]
>
>        # delete the last square - results in the error
>        self.squares[-1].remove()
>        del self.squares[-1]
>
>        self._refresh()
>
>    def _refresh(self):
>        self.canvas.draw()
>
>
> class Square(Rectangle):
>    def __init__(self, manager, axes, *args, **kwds):
>        Rectangle.__init__(self, *args, **kwds)
>        axes.add_patch(self)
>
>        self.manager = manager
>        axes.figure.canvas.mpl_connect('button_press_event', self.selected)
>
>    def selected(self, evt):
>        within, _ = self.contains(evt)
>        if within:
>            self.manager.add_square()
>
>
> app = wx.PySimpleApp()
> frame = wx.Frame(None)
> fig = Figure()
> canvas = FigureCanvasWxAgg(frame, -1, fig)
> a = Axes(fig, [.1, .1, .8, .8])
> fig.add_axes(a)
>
> sm = SquareManager(a)
> sm.add_square()
>
> frame.Show()
> app.MainLoop()
>
>
> # To demonstrate the error:
> #
> # 1. click on red sqaure
> # 2. press any key
> # 3. click on red sqaure again
>
>
>
>
>
>
>
>
>
> --
> The demand for IT networking professionals continues to grow, and the
> demand for specialized networking skills is growing even more rapidly.
> Take a complimentary Learning@Cisco Self-Assessment and learn
> about Cisco certifications, training, and career opportunities.
> http://p.sf.net/sfu/cisco-dev2dev
> _

Re: [matplotlib-devel] Possible bug in matplotlib.cbook.CallbackRegistry

2011-10-25 Thread Tobin H. Van Pelt

Daniel -

Yes that works.  In my case - I hate to edit any existing third party  
code bases - or it bites me later when I upgrade.


For now - I simply do my own dead reference clean up externally when  
doing the deletes. Really, that would be the same as just doing a  
disconnect - but for other reasons (not worth going into detail here)  
- I prefer deleting and not having to know all of the connection  
points.  My solution ensures that the dead references aren't around  
later.


I mainly wanted to get it out into the devel community - get smart  
eyeballs on it - and hope that it gets addresses in a future release.


It will likely be a fairly straightforward fix - as you show.


--
The demand for IT networking professionals continues to grow, and the
demand for specialized networking skills is growing even more rapidly.
Take a complimentary Learning@Cisco Self-Assessment and learn 
about Cisco certifications, training, and career opportunities. 
http://p.sf.net/sfu/cisco-dev2dev___
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel


[matplotlib-devel] which to fork from?

2011-10-25 Thread Daniel Hyams
For small bugfixes, am I supposed to fork from v1.1.x, or master?

-- 
Daniel Hyams
dhy...@gmail.com

--
The demand for IT networking professionals continues to grow, and the
demand for specialized networking skills is growing even more rapidly.
Take a complimentary Learning@Cisco Self-Assessment and learn 
about Cisco certifications, training, and career opportunities. 
http://p.sf.net/sfu/cisco-dev2dev
___
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel


Re: [matplotlib-devel] which to fork from?

2011-10-25 Thread Benjamin Root
On Tuesday, October 25, 2011, Daniel Hyams  wrote:
> For small bugfixes, am I supposed to fork from v1.1.x, or master?
>

V1.1.x is the maintenance branch.  Master is for new features.  When
bugfixes are made and merged to v1.1.x, we then merge it to master.

Ben Root
--
The demand for IT networking professionals continues to grow, and the
demand for specialized networking skills is growing even more rapidly.
Take a complimentary Learning@Cisco Self-Assessment and learn 
about Cisco certifications, training, and career opportunities. 
http://p.sf.net/sfu/cisco-dev2dev___
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel


Re: [matplotlib-devel] which to fork from?

2011-10-25 Thread Paul Ivanov
On Tue, Oct 25, 2011 at 3:52 PM, Daniel Hyams  wrote:
> For small bugfixes, am I supposed to fork from v1.1.x, or master?

I say 'master'  (Mike's been pushing some things to v1.1.x, but as he
said in a comment to #551, "Pushed to v1.1.x since this is pretty
serious yet simple-to-fix bug -- it should be on the maintenance
branch.")



best,
-- 
Paul Ivanov
314 address only used for lists,  off-list direct email at:
http://pirsquared.org | GPG/PGP key id: 0x0F3E28F7

--
The demand for IT networking professionals continues to grow, and the
demand for specialized networking skills is growing even more rapidly.
Take a complimentary Learning@Cisco Self-Assessment and learn 
about Cisco certifications, training, and career opportunities. 
http://p.sf.net/sfu/cisco-dev2dev
___
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel