ipython icon indicating copy to clipboard operation
ipython copied to clipboard

Feature Request : Autocomplete and docstring working when instantiating using class directly

Open aditya3434 opened this issue 1 year ago • 3 comments

Refer to the reproducer and gif below.

class Foo:

    def __init__(self):
        self.name = "My name"

    def get_name(self):
        '''
        This is a sample doctring
        '''
        print(self.name)

Animation

As shown, both autocomplete and docstring features are working when we instantiate an object first. However, they stop working correctly when we instantiate using class directly.

Some further points :-

  • In tab-completion, the intention is not to execute code so it makes sense that Foo().<TAB> doesn't work. But in doing Foo().get_name??, we are executing that cell, and hence, expecting the resulting docstring.
  • Alternatively, is it possible to statically determine what Foo() returns? In that case, we can use that result to fix both issues.
  • The autocomplete issue does fix itself when %config IPCompleter.use_jedi is set to True

aditya3434 avatar Feb 14 '24 09:02 aditya3434

In tab-completion, the intention is not to execute code so it makes sense that Foo().<TAB> doesn't work.

Correct. Users may decide to set Completer.evaluation to 'unsafe' in which case this works, but it has side-effects.

side-effects

Alternatively, is it possible to statically determine what Foo() returns? In that case, we can use that result to fix both issues.

Yes, this was partially implemented in https://github.com/ipython/ipython/pull/14185. It works if you re-run the cell like this:

kind-of-works

However, it does not work for stringified nor deferred annotations from PEP 649 yet:

does-not-work-yet

We could make it work for the case of class initialisation even without the need to specify the type annotation as __init__ can be assumed to return the instance of class it is defined in (unless a meta class modifies it).

krassowski avatar Feb 14 '24 10:02 krassowski

But in doing Foo().get_name??, we are executing that cell, and hence, expecting the resulting docstring.

In this case it is clear that you want to execute, but in general that might no be the case, in particular ?/?? will run multiple time if you do have a loop or anything else.

In general users get surprised either in completion or help when objects get executed, or if expressions are evaluated. In many case that is is ok, but in a few case where this is not, this can be devastating. From experience many user will tend to use ?/?? in the middle of a long black of code they are currently writing, forgetting that the rest of the code is also ran.

We can likely try to relax the regex that tries to capture what object we are getting help on, and add a flag, though it will likely not be perfect. You can use hist -t to see the history and that the () is seen as a delimiter leading to actually IPython asking info only on get_name.

get_ipython().run_line_magic('pinfo2', 'get_name')

Also as this is based on string transform and not proper parsing, it might not be as easy to properly detect which identifier or expression is targeted by ?/??, and recent changes is CPython make it harder and harder to do some of those transforms. So it might be a game of cat and mouse.

Carreau avatar Feb 20 '24 18:02 Carreau

Conceptually I wonder if we could use guarded_eval for ?/?? inspections, the same way we use it for completions - the guards would prevent side effects. However, it might require some adjustments to ensure it is as reliable for docstring discovery as it is for attribute discovery.

krassowski avatar Feb 26 '24 13:02 krassowski