python-aspectlib icon indicating copy to clipboard operation
python-aspectlib copied to clipboard

weave does not work with "generated" functions

Open imposeren opened this issue 9 years ago • 3 comments

In [1]: def foo_factory(foo_name):                                                                                                                                                                                          
    def foo():
        pass
    foo.__name__ = foo_name
    return foo
   ...: 

In [2]: foo_func = foo_factory('foo_func')                                                                                                                                                                                    

In [3]: import aspectlib.contrib

In [4]: import aspectlib

In [5]: aspectlib.weave(foo_func, aspectlib.contrib.retry())                                                                                                                                   
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-5-03b12c5d089d> in <module>()
----> 1 aspectlib.weave(foo_func, aspectlib.contrib.retry())

/home/yaroslavklyuyev/.virtualenvs/aiwona/lib/python3.4/site-packages/aspectlib/__init__.py in weave(target, aspects, **options)
    474         path = deque(target.__qualname__.split('.')[:-1])
    475         while path:
--> 476             owner = getattr(owner, path.popleft())
    477         name = target.__name__
    478         logdebug("@ patching %r (%s) as a property.", target, name)

AttributeError: 'function' object has no attribute '<locals>'

In [6]: 

This issue can be solved by using dill.source.getname:

from demo import foo_func as custom_named_func
from dill.source import getname
from inspect import getmodule

module, object_name = getmodule(custom_named_func), getname(custom_named_func)
# results in <module 'demo' from '/some/path/demo.py'>, 'foo_func'

This can also be solved by setting __qualname__ in function factory. Maybe document it somewhere? Or better: raise exception that tells to set qualname when qualname contains '<locals>'

But still custom_named_func.__name__/custom_named_func.__qualname__ should match variable name or everything will fail

imposeren avatar May 12 '16 10:05 imposeren

Yes indeed, this looks like a bug but there's no way to do this correctly. I could just skip the <locals> part but that don't guarantee correct behavior.

However, aspectlib supports weaving with no direct reference: weave('__main__.foo_func', contrib.retry) would work very well in your case and moves the responsibility of correctly figuring out what to patch in your app.

ionelmc avatar May 12 '16 10:05 ionelmc

maybe raise exception that tells to use weave with string argument when qualname contains '<locals>'?

imposeren avatar May 12 '16 10:05 imposeren

That's a great idea. I think a better error should be raised for all "weaving issues".

ionelmc avatar May 12 '16 10:05 ionelmc