On Thursday, May 14, 2015 at 11:09:47 AM UTC-5, Edward K. Ream wrote: > Not sure why it works, but I see that it does... > this decorator should replace g.command and all other cmd decorators.
Upon further review, I don't believe this problem is solvable. This snippet: type0 = args and str(type(args[0])) isClass = '.' in type0 if g.isPython3 else type0 == "<type 'instance'>" className = args[0].__class__.__name__ if isClass else None is a simplified version of how Reinhard proposed to calculate the class name. Alas, this code executes too late. Indeed, wrappers must be entered into a global commands_dict *when the decorator first executes*. There are no args available at that time. At present, g.new_cmd_decorator does this as follows: def new_cmd_decorator(name,ivars): ''' Return a new decorator for a command with the given name. Compute the class instance using the ivar string or list. ''' def _decorator(func): def wrapper(event): c = event.c self = g.ivars2instance(c,g,ivars) func(self,event=event) # Don't use a keyword for self. # This allows the VimCommands class to use vc instead. wrapper.__name__ = 'wrapper: %s' % name wrapper.__doc__ = func.__doc__ global_commands_dict[name]=wrapper # Put the *wrapper* into the global dict. return func # The decorator must return the func itself. return _decorator This works because ivars is bound by the per-command (actually per-module) decorators. When Leo sees a command, it looks up the wrapper in the dict and simply calls the wrapper with an event arg. The *wrapper *must compute "self" if and only if the wrapper represents a wrapper of a method. Yes, this is complicated. The following is my best illustration of the problem that can't be solved. from functools import wraps commands_dict = {} def cmd(name): def _decorator(func): # Compute ivar name *here* if 0: # This won't work. No args are available. type0 = args and str(type(args[0])) isClass = '.' in type0 if g.isPython3 else type0 == "<type 'instance'>" className = args[0].__class__.__name__ if isClass else None className = '???' if className: @wraps(func) def wrapper(event): c = event.get('c') ivars = g.cmd_instance_dict.get(className) if ivars: obj = ivars2instance(c,g,ivars) self = getattr(c,ivarName) func(self,event) else: g.trace('not a known class:',className) else: @wraps(func) def wrapper(event): func(event) commands_dict[name]=wrapper return func return _decorator @cmd('command1') def pureFunction(event=None): g.trace('event',event) class MyClass: @cmd('command2') def aMethod(self, event=None): g.trace('self',self.__class__.__name__,'event',event) # Simulate Leo's command dispatching. d = commands_dict event = {'c':c} for command in d.keys(): wrapper = d.get(command) wrapper(event) if 0: # These tests are irrelevant. # The calls must be made from commands_dict. pureFunction() pureFunction("abc") pureFunction(pureFunction) pureFunction(MyClass) MyClass().aMethod() MyClass().aMethod("abc") MyClass().aMethod(pureFunction) MyClass().aMethod(MyClass) In other words, I can see no way to compute className when needed. Once again, we seem to be stuck. Happily, the present decorators work just fine. Your comments, please. Edward -- You received this message because you are subscribed to the Google Groups "leo-editor" group. To unsubscribe from this group and stop receiving emails from it, send an email to leo-editor+unsubscr...@googlegroups.com. To post to this group, send email to leo-editor@googlegroups.com. Visit this group at http://groups.google.com/group/leo-editor. For more options, visit https://groups.google.com/d/optout.