Make hooks.wrap preserve signatures, fixes hooking some pyqt5 callbacks

It looks like pyqt5 is playing dirty and checking the number of args of
functions before calling them. When using hooks.wrap, pyqt5 thinks it
can pass any amount of arguments (because *args) and you get exceptions
like this inside the wrap function, when calling the 'old' function:

>TypeError: onFindDupes() takes 1 positional argument but 2 were given

This commit fixes it by preserving the signature of the wrapped method,
by adding an optional dependency on the "decorator" module.

Making it an optional dependency is probably not the wisest idea but
since this is a small edge case it might be smoother to start like this.

I also added functools.wraps() as a fallback, which won't help much but
is slightly more correct.

See this article for details: https://hynek.me/articles/decorators/
This commit is contained in:
dequis 2017-07-16 23:25:34 -03:00
parent e8777e8630
commit 37ba8832f8
2 changed files with 17 additions and 1 deletions

View File

@ -13,6 +13,14 @@ If you call wrap() with pos='around', the original function will not be called
automatically but can be called with _old().
"""
import functools
try:
# optional: like functools.wraps, but signature-preserving
import decorator
except ImportError:
decorator = None
# Hooks
##############################################################################
@ -59,4 +67,11 @@ def wrap(old, new, pos="after"):
return old(*args, **kwargs)
else:
return new(_old=old, *args, **kwargs)
return repl
if decorator is None:
return functools.wraps(repl)
def decorator_wrapper(f, *args, **kwargs):
return repl(*args, **kwargs)
return decorator.decorator(decorator_wrapper)(old)

View File

@ -3,3 +3,4 @@ send2trash
httplib2
pyaudio
requests
decorator