Getting lazy with decorators
Peter Otten
__peter__ at web.de
Sun Jun 24 04:07:45 EDT 2012
Josh English wrote:
> I'm creating a cmd.Cmd class, and I have developed a helper method to
> easily handle help_xxx methods.
>
> I'm trying to figure out if there is an even lazier way I could do this
> with decorators.
>
> Here is the code:
> *********************
> import cmd
>
>
> def add_help(func):
> if not hasattr(func, 'im_class'):
> return func #probably should raise an error
> cls = func.im_class
> setattr(cls, func.im_func.__name__.replace("do","help"), None)
>
> return func
>
>
> class BaseCmd(cmd.Cmd):
> def __init__(self, *args, **kwargs):
> cmd.Cmd.__init__(self, *args, **kwargs)
>
> def show_help(self, func):
> print "\n".join((line.strip() for line in
> func.__doc__.splitlines()))
>
> @add_help
> def do_done(self, line):
> """done
> Quits this and goes to higher level or quits the application.
> I mean, what else do you expect?
> """
> return True
>
> if __name__=='__main__':
> c = BaseCmd()
>
> print c.help_done
>
>
> *********************
>
> This generates "AttributeError: BaseCmd instance has no attribute
> 'help_done'"
>
> The show_help method is the shortcut I want to use (I'm pretty sure it's
> from Doug Hellman's site). I'm wondering if it's possible to use a
> decorator such as add_help to automatically create the appropriate
> help_xxx function.
>
> In the decorator, I can get the function and the name of the class, but I
> can't find the instance of the class that the method is attached to.
> Maybe this is just one step of lazy too far.
>
>
> Am I right in thinking that I can't do this? There is no way to access the
> class instance from the method?
You cannot access a class instance because even the class itself doesn't
exist yet. You could get hold of the class namespace with sys._getframe(),
def add_help(f):
exec """\
def help_%s(self):
f = getattr(self, %r)
self.show_help(f)
""" % (f.__name__[3:], f.__name__) in sys._getframe(1).f_locals
return f
but here's a simpler approach:
import cmd
def add_help(f):
def help(self):
self.show_help(f)
f.help = help
return f
class BaseCmd(cmd.Cmd):
def __init__(self, *args, **kwargs):
cmd.Cmd.__init__(self, *args, **kwargs)
def show_help(self, func):
print "\n".join((line.strip() for line in
func.__doc__.splitlines()))
def __getattr__(self, name):
if name.startswith("help_"):
helpfunc = getattr(self, "do_" + name[5:]).help
setattr(self.__class__, name, helpfunc)
return getattr(self, name)
raise AttributeError
@add_help
def do_done(self, line):
"""done
Quits this and goes to higher level or quits the application.
I mean, what else do you expect?
"""
return True
if __name__=='__main__':
c = BaseCmd()
c.cmdloop()
More information about the Python-list
mailing list