Jedi: wrong docstring for wrapped function

Created on 6 Apr 2017  路  14Comments  路  Source: davidhalter/jedi

Expected Behaviour

I would expect that jedi shows the correct docstring and function reference for wrapped functions.
In the same scenario jupyter notebook works correctly:

jupyter notebook

Actual Behaviour

jedi

Shows wrong wrapping function reference. Based on Sublime text and anaconda DamnWidget/anaconda#644

Steps to Reproduce

from functools import wraps


def decorator(name=None):
    """wrapper doc string"""
    def _decorate(func):
        @wraps(func)
        def wrapper():
            print(name)
            return func()
        return wrapper
    return _decorate


@decorator('testing')
def wrap_user():
    """Nice doc string"""
    print('doing stuff...')

print(wrap_user.__name__)
print(wrap_user.__doc__)
wrap_user()

Execution results in:

Nice doc string
testing
doing stuff...

which is good name and docstring.

feature

Most helpful comment

If you want to push an issue, just add a :+1: on top, I occasionally sort by those.

Comments are just annoying and don't really help you guys.

All 14 comments

I think the jupyter notebook has it way easier to show the correct signatures, because it can actually look at evaluated code. But in any case I think we should implement this, too.

I see the point about jupyter, didn't realize that it actually needs to run the code before showing tooltips.
At the beginning I thought the bug only relates to decorators with arguments but it looks like all decorators cause problems for jedi. Following is even simpler example.

Still it is worth looking into functools.wraps, as it is Python way to help with decorated function names.

from functools import wraps
def simple_decorator(func):
    'simple decorator docstring'
    @wraps(func)
    def _wrapper():
        '_wrapper docstring'
        print('here')
        return func()
    return _wrapper

@simple_decorator
def nice_func():
    'nice func docstring'
    print('bar')

print(nice_func.__name__)
print(nice_func.__doc__)

Finally, evaluating code might potentially be very harmful.

Jedi does not evaluate code. And you're right trying to statically analyze code and check for wraps calls would probably make sense.

First, thank you for the great work on Jedi!
I wanted to ask if there any plans to investigate implementing this. It would be great if eg VSCode and other IDEs using Jedi could show docstrings and function signatures for decorated methods using @wraps. Some libraries decorate the bulk of their APIs, really leading to a suboptimal IDE experience when using them, given this current limitation.

@malmaud There is currently no plan to that, but I'm planning on improving *args/**kwargs support for decorators, so people can see what they are actually pushing into a function. That should happen pretty soon.

Since you reminded me about this issue, I might also take a look at this in the same process (even if people are not using wraps, people that are using IDE's are usually happy enough with good heuristics).

Ah, great. Any solution that allows IDEs to show docstrings and/or original arguments of decorated functions, however heuristically, would be awesome.

Is there any update? This causes the IDE shows incorrect arguments options if func is using decorator ..
Or is there any temporary workaround to make it work now?

For example:

  1. Without decorator, the auto completion works properly.
    image
  2. With decorator, the auto completion will be overwritten by decorator's passing arguments.
    image

Any news on a possible fix?

If you want to push an issue, just add a :+1: on top, I occasionally sort by those.

Comments are just annoying and don't really help you guys.

If I have a file /tmp/docstr.py:

class B:
    """This is what I get"""
    def __init__(self):
        pass

class A:
    def __init__(self):
        pass

    @property
    def func(self):
        """This is what I want"""
        return B()

a = A()
a.f

and run following code:

import jedi
with open('/tmp/docstr.py') as f:
    s = jedi.Script(f.read(), 16, 3)
    comps = s.completions()
    print(comps[0].docstring())

I will get the docstring of B rather than func.

I think this example has the same cause with this issue?

I didn't realize how easy this could have been. Sorry for that.

Anyways, it's fixed now. This issue doesn't fix the signature issue, which is a separate one that I'm going to fix now.

I seem to have incurred in this bug again.

I'm using ST3 with Anaconda plugin. Normally showing docstrings works perfectly, except, it seems for functions that are wrapped in a decorator, such as this (see screen):

image

Any idea how to fix this?

@wtfzambo Please give me a complete example that I can reproduce. You should probably also open a new issue, because this issue was definitely fixed (it's actively tested).

@davidhalter ok I'll open a new issue

Was this page helpful?
0 / 5 - 0 ratings