[PyQt] Re: Virtual methods and an extra reference

Sundance sundance at ierne.eu.org
Mon Jun 23 14:13:05 BST 2008

Phil wrote:

> I will look at this properly when I have the time.

Thank you, Phil -- it's appreciated.

In the meanwhile, for those who may come across this thread in the 
future, here's a working workaround (as opposed to the almost-working-
but-not-quite one from earlier *g*):

1) Rename the problematic methods, for instance by putting an underscore 
in front: paintEvent() becomes _paintEvent().

2) In your object's constructor, add such a line as:
   s.paintEvent = WeakCallable( s._paintEvent )

3) Add somewhere the following code:

---[ Code ]------------------------------------------------------------
import new
from weakref import ref, ReferenceError

class WeakCallableRef:

  def __init__( s, fn, callback=None ):

    assert callable( fn )

    s._methname = None
    s._objref   = None
    s._fnref    = None
    s._dead     = False
    s._callback = callback

    obj = getattr( fn, "im_self", None )

    if obj:  ## fn is a bound method
      s._objref = ref( obj,        s.markDead )
      s._fnref  = ref( fn.im_func, s.markDead )
      s._class  = fn.im_class

    else:  ## fn is a static method or a plain function
      s._fnref = ref( fn, s.markDead )

  def markDead( s, ref ):

    if not s._dead:
      s._dead = True
      if s._callback: s._callback( s )

  def __call__( s ):

    if s._dead: return None

    if s._objref:  ## bound method

      fn  = s._fnref()
      obj = s._objref()

      if None not in ( fn, obj ):
        return new.instancemethod( fn, obj, s._class )

      return s._fnref()

class WeakCallable:

  def __init__( s, fn ):

    s._ref = WeakCallableRef( fn )

  def __call__( s, *args, **kwargs ):

    fn = s._ref()
    if fn: return fn( *args, **kwargs )

    raise ReferenceError( "Attempted to call dead WeakCallable %s!" \
                                                                  % s )

... And you should be good.

The above aggregates the feedback from this thread -- thank you, 
Kevin! -- into one neat, reasonably simple if generally loathesome 

Goodness, how I hate workarounds.

-- S.

More information about the PyQt mailing list