@decoretors to make coding faster!

I woke up today and thought - oh maybe using decorators for simple function designation would make panda look nicer. And it does for me! What do you guys think?

def task(fun):
    taskMgr.add(fun, str(fun))
    return fun

def event(eventname,*args):
    def eventMaker(fun):
        print fun
        DirectObject().accept( eventname , fun , list(args))
        return fun
    return eventMaker

# i think looking at this code i can see what it does fast
# instead of one define section and one assign section

@event('k')
def pressK():
    print "you pressed K"

@event('l',"hi how are you?")
@event('l-up',"bye")
def pressL(msg):
    print msg

showoff = False
@event('t',True)
@event('t-up',False)
def showOffToggle(state):
    global showoff
    showoff = state

@task
def showUp(task):
    if showoff:
        render.ls()
    return task.cont

Nice use of decorators. Digging deeper into Python is fun.

One weakness though: The event maker creates a new instance of DirectObject for each event. This is useful for global functions (like toggle some wireframe render mode). But not useful if you want several events modify one instance of DirectObject, for example w/a/s/d movement keys for a player object. In this case you would have to create an instance of DirectObject before and pass it as an argument to the decorator.

enn0x

no its better to use
messenger.accept(event, self, method, extraArgs, 1)
i was just to lazy to look at how Direct Object does it before.

def event(eventname,*args):
    def eventMaker(fun):
        print fun
        messenger.accept( eventname, fun, fun , list(args),1)
        return fun
    return eventMaker 

I’ve been mucking about with PStatCollector to find the slowdown in my game and I found decorators to be a good way to simplify collecting the runtimes of functions.

def pstat(func):
    from pandac.PandaModules import PStatCollector
    collectorName = "Debug:%s" % func.__name__
    if hasattr(base, 'custom_collectors'):
        if collectorName in base.custom_collectors.keys():
            pstat = base.custom_collectors[collectorName]
        else:
            base.custom_collectors[collectorName] = PStatCollector(collectorName)
            pstat = base.custom_collectors[collectorName]
    else:
        base.custom_collectors = {}
        base.custom_collectors[collectorName] = PStatCollector(collectorName)
        pstat = base.custom_collectors[collectorName]
    def doPstat(*args, **kargs):
        pstat.start()
        returned = func(*args, **kargs)
        pstat.stop()
        return returned
    doPstat.__name__ = func.__name__
    doPstat.__dict__ = func.__dict__
    doPstat.__doc__ = func.__doc__
    return doPstat

OH wow thanks i was going to dig deeper into pstating the server right now it is not because it does not use the run() method - but this could very well work.

Hey Decorators Gurus :slight_smile:

How would you make a DecisionChain Decorator?

I’ve got a function CanPost(User) that must answer “True” if user is allowed to Post and “False” elsewhere.

I would like to have some decorators to implement rules on when you “CanPost”:

  • ex BlackListRestriction (forbid the post if user is in a black list)
  • ex AgeLimitRestriction (forbid the post if user is below an age limit).
    But each Decorators should be terminal (ie if 1 decorator says false, other are not used , results is false).

@Blacklist (“TOTO”)
@AgeLimit(“13”)
def CanPost(User)

If User Name is “TOTO” then it’s directly false
If User Name is not “TOTO” and User Age is 10 then it’s directly false
If User Name is not “TOTO” and User age is >13 then CanPost is checked

Here i’m lost how to design my decorators to be usable in such a chain.

Ah, learned something from solving this. Decorators with arguments is a bit brain breaking since its a function that returns a decorator. Just, wrapped my head around it though.

def Blacklist(banned_user):
    def BlackWrap(func):
        def BlackFunc(*args, **kargs):
            # username = getUserNameFunc(*args, **kargs)
            username = args[0]['user']
            if username  == banned_user:
                return False
            else:
                return func(*args, **kargs)
        BlackFunc.__name__ == func.__name__
        BlackFunc.__dict__ == func.__dict__
        BlackFunc.__doc__ == func.__doc__
        return BlackFunc
    return BlackWrap

def AgeLimit(age_limit):
    def AgeWrap(func):
        def AgeCheck(*args, **kargs):
            # userage = getUserAgeFunc(*args, **kargs)
            userage = args[0]['age']
            if userage < age_limit:
                return False
            else:
                return func(*args, **kargs)
        AgeCheck.__name__ = func.__name__
        AgeCheck.__dict__ = func.__dict__
        AgeCheck.__doc__ = func.__doc__
        return AgeCheck
    return AgeWrap

My test:

>>> CanPost( {'user':'ZeroByte', 'age':13} )
True
>>> CanPost( {'user':'ZeroByte', 'age':12} )
False
>>> CanPost( {'user':'TOTO', 'age':12} )
False
>>> CanPost( {'user':'TOTO', 'age':13} )
False

Huh, i need to wrap my mind around this one but it seems promising :slight_smile:

Thanks a lot