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.

Reply via email to