I am trying to set up some decorators so that I can do something like:
class Ball(object): def __init__(self, owner): self.owner = owner class Example(CommandSource): @command @when(lambda self, ball: ball.owner == self) def throwBall(self, ball):
This does not currently work, since the argument itself is not passed when calling lambda validation.
Now something like this works great:
class Example(CommandSource): @command @when(lambda ball: ball.is_round) def throwBall(self, ball): pass
But this also does not work:
class Example(CommandSource): def verify_owner(self, ball): return ball.owner == self @command @when(verify_owner) def throwBall(self, ball): pass
The goal is to be able to mark methods in the class as a "command" and get a list of commands that are valid to run. Actually, the method launch has not changed. I would like to use decorators here, as this is apparently the least klunky way to do this. Essentially, I'm trying to set up a bit of DSL using Python.
But I'm having difficulties, especially with the self argument. Here is my current implementation of command , when and CommandSource :
def command(cmd): if getattr(cmd, 'command', False): return cmd def wrapper(*args, **kwargs): return cmd(*args, **kwargs) wrapper.validators = [] wrapper.command = True return wrapper def when(predicate): def createCommand(cmd): newcmd = command(cmd) newcmd.validators.append(predicate) return newcmd return createCommand class CommandSource(object): def listCommands(self, *args, **kwargs): commands = [] for command in dir(self.__class__): func = getattr(self, command, None) if func == None or getattr(func, 'command', False) == False: continue valid = True for validator in func.validators: if not validator(*args, **kwargs): valid = False break if valid: commands.append(command) return commands