wrapt
wrapt copied to clipboard
PyCharm warnings about unfilled parameters
This library amazing, thank you for making it.
However, one minor issue when I use it in PyCharm (and probably other linters)...
I've written this simple decorator:
@wrapt.decorator
def serialize_response(wrapped, _instance, args, kwargs):
return serialize_object(wrapped(*args, **kwargs))
Then I use it like this:
@serialize_response # <-- warnings appear here
def get_address(self, id_number: str, customer_ip: str) -> dict:
The warning looks like this:
Is there any way to get around this warning without prefixing the method with # noinspection PyArgumentList
?
That is odd. Any idea what mechanism PyCharm uses to introspect the method details? The wrapt
package uses various tricks so normal Python introspection functions work fine. It looks like PyCharm is not using normal methods for introspecting functions. Can you add trying using inspect.getfullargspec()
on the function to see what it produces.
@GrahamDumpleton This is the output (formatted by me):
FullArgSpec(
args=['wrapped', '_instance', 'args', 'kwargs'],
varargs=None,
varkw=None,
defaults=None,
kwonlyargs=[],
kwonlydefaults=None,
annotations={},
)
I honestly don't know how PyCharm performs introspection :/
What exact version of Python is this, and what distribution if not the original CPython from the PSF?
When inspect.getfullargspec()
is applied to the decorated function, you should get the original arguments. Eg.
>>> import wrapt
>>> @wrapt.decorator
... def wrapper(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs)
...
>>> import inspect
>>> @wrapper
... def func(a, b, **c): pass
...
>>> inspect.getfullargspec(func)
FullArgSpec(args=['a', 'b'], varargs=None, varkw='c', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})
@GrahamDumpleton My apologies, I thought you meant getfullargspec
of the decorator itself (wrapper
in your example), doh. Obviously you meant the wrapped function, here is the correct output:
FullArgSpec(
args=['self', 'id_number', 'customer_ip'],
varargs=None,
varkw=None,
defaults=None,
kwonlyargs=[],
kwonlydefaults=None,
annotations={
'return': <class 'dict'>,
'customer_ip': <class 'str'>,
'id_number': <class 'str'>
}
)
This is the full Python version information:
Python 3.5.7 (default, Apr 10 2019, 14:22:52)
[GCC 4.2.1 Compatible Apple LLVM 10.0.1 (clang-1001.0.46.3)] on darwin
(If it matters, I built and installed this Python version using pyenv.)
This is the detailed PyCharm information:
PyCharm 2019.1.2 (Professional Edition) Build #PY-191.7141.48, built on May 7, 2019 JRE: 11.0.2+9-b159.56 x86_64 JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o macOS 10.14.4
Yes, but PyCharm is possibly looking at what you did. The highlighting is actually on the decorator and not the wrapped function, and getsignature()
doesn't actually return a signature that would make sense in that situation. I'll need to do some testing and have a think about it.
Would you possibly be able to install the develop
branch on this repo and try it.
pip install https://github.com/GrahamDumpleton/wrapt/archive/develop.zip
I have made a change which means the decorator created should return as signature that of the original decorator function, and not the wrapper.
FullArgSpec(args=['wrapper', 'enabled', 'adapter'], varargs=None, varkw=None, defaults=(None, None, None), kwonlyargs=[], kwonlydefaults=None, annotations={})
This should hopefully satisfy what the linters are looking for.
Note that the develop
branch does include another change for an odd issue related to garbage collection. If you see any really strange issues that affect your program, including crashes, let me know.
Unfortunately, using the develop.zip archive, PyCharm still complains with the same warning:
With this code:
import wrapt
@wrapt.decorator
def wrapper(wrapped, _instance, args, kwargs):
return wrapped(*args, **kwargs)
@wrapper
def foo():
pass
...getfullargspec(wrapper)
returns, as you promised:
FullArgSpec(args=['wrapper', 'enabled', 'adapter'], varargs=None, varkw=None, defaults=(None, None, None), kwonlyargs=[], kwonlydefaults=None, annotations={})
...and getfullargspec(foo)
returns:
FullArgSpec(args=[], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})
So I'm not sure what is really going on here? It's the same behavior in Python 3.5.6 and 3.7.3. I've tried searching for an explanation of how PyCharm introspects these things, to no avail :(
I believe I'm seeing a similar issue with https://github.com/microsoft/pyright/.
import wrapt
@wrapt.decorator
def foo(wrapper, instance, args, kwargs):
return wrapper(*args, **kwargs)
@foo <---- error Arguments missing for parameters "instance", "args", "kwargs"
def bar(x: int) -> int:
return x
Here are a couple of related discussions: https://github.com/microsoft/pyright/issues/413, https://github.com/microsoft/pyright/issues/774, which seem to suggest that wrapt.decorator
could be typed in a way that improves the situation. I'm no expert, what do you think, @GrahamDumpleton ?
Experiencing the same as well with Pylance with the general example
Arguments missing for parameters "instance", "args", "kwargs"Pylance[reportGeneralTypeIssues](https://github.com/microsoft/pyright/blob/main/docs/configuration.md#reportGeneralTypeIssues)
(function) def debug_stats(
wrapped: (...) -> Any,
instance: Any,
args: Any,
kwargs: Any
) -> ((...) -> Any)