ihatehippies 11 Junior Poster

I've been using the Aspects module to trace and patch routines on the fly in my wxPython app. The problem I've run in to occurs when wx binds an event to a function. ie:

an event is binded to function <function func at 0x03969A30>

after aspects.with_wrap() func now becomes <function func at 0x03973030>

the namespace is updated but is seems that wx maintains a copy of the old function in memory rather than just a reference. When the event is triggered the old routine is called rather than the new 'patched' one. So far the only dependable way to fix this is to rebind all of the events to the new routines.... Sometimes events seem to rebind themselves, but I haven't been able to figure out what triggers it.

Below is my 'ActivePatching' module(still a work in progress)a. Also I modified aspects.with_wrap to return (wrapid, newmethod) instead of just the standard wrapid.

from traceback import format_exc as E
from aspects import aspects
import inspect


PRECEDING_TYPE, \
SUCCEEDING_TYPE,\
MUTATING_TYPE,  \
OVERRIDING_TYPE = range(4)

def Patch(Type, Target, Patch, *args, **kwargs):
    """Specify patch type: 0:Preceding, 1:Succeeding, 2:Mutating, 3:Overriding"""
    try:
        return Interceder(Type, Target, Patch, *args, **kwargs)
    except:
        print E()


class Interceder:
    def __init__(self, TYPE, target, patch, *args, **kwargs):
        self.aspects = aspects
        self.type = TYPE
        
        self.original = target
        assert inspect.isroutine(target)
        assert hasattr(target, 'im_class') or inspect.isfunction(target)
        self.patch = patch
        self.p_args = args
        self.p_kwargs = kwargs

        self.args = ()
        self.kwargs= ()
        # I modified with_wrap to return the new method as well as the id
        self.wrapid, self.newmethod = self.aspects.with_wrap(self.intermediary, target)
        self.unwrapper = CreateUnwrapper(self.newmethod)

        try:
            self.newmethod.__InvokeUnwrapper__ = self.unwrapper
        except:
            print E()
            print "could not attach unwrap method"

    def intermediary(self, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs

        if self.type == PRECEDING_TYPE:
            # patch code is run immediately
            # before orginial code
            rv = self.patch(*args, **kwargs)
            rv = yield self.aspects.proceed
            yield self.aspects.return_stop
            
        elif self.type == OVERRIDING_TYPE:
            # patch code is run in place
            # of original code
            rv = self.patch(*args, **kwargs)
            yield self.aspects.return_stop(rv)
            
        elif self.type == SUCCEEDING_TYPE:
            # patch code is run immediately
            # following original code
            yield self.aspects.proceed
            rv = self.patch(*args, **kwargs)
            yield self.aspects.return_stop
        elif self.type == MUTATING_TYPE:
            # mutating type; receives return from
            # original method, processes it, and returns
            # its own value
            rv = yield self.aspects.proceed
            rv = self.patch(rv, *args, **kwargs)
            yield self.aspects.return_stop(rv)
            

def CreateUnwrapper(Routine):
    def remove_wrap(routine=Routine):
        from aspects import aspects
        try:
            while hasattr(routine, '__aspects_wrapid'):
                routine = aspects.peel_around(routine)

        except Exception, e:
            print 'unwrapping error', e

    return remove_wrap
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.