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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.