Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

weave does not work with "generated" functions #7

Open
imposeren opened this issue May 12, 2016 · 3 comments
Open

weave does not work with "generated" functions #7

imposeren opened this issue May 12, 2016 · 3 comments

Comments

@imposeren
Copy link

imposeren commented May 12, 2016

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

@ionelmc
Copy link
Owner

ionelmc commented May 12, 2016

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.

@imposeren
Copy link
Author

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

@ionelmc
Copy link
Owner

ionelmc commented May 12, 2016

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants