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

Tab completion not working for class when it has property with typing.Literal annotated return value #14412

Open
wenjuno opened this issue Apr 20, 2024 · 6 comments

Comments

@wenjuno
Copy link

wenjuno commented Apr 20, 2024

Here is an example class:

import typing
class A:
    @property
    def value(self) -> typing.Literal['a']:
        return 'a'
    def get(self) -> typing.Literal['a']:
        return 'a'
a = A()

Now if I type a.<Tab> in IPython console, nothing will show up. If I put the same code in Python console, the second Tab will display the two methods.

@krassowski
Copy link
Member

I can confirm that this does not work by default in 8.23.0 which looks like a jedi problem.
After executing %config c.IPCompleter.use_jedi = False it works well.

@wenjuno can you confirm that your setup used the default completer and that disabling jedi with the config command as per above fixes it for you?

@wenjuno
Copy link
Author

wenjuno commented Apr 20, 2024

Hi @krassowski Thanks for the reply. Sorry I'm not familiar with the IPython configuration, I'm not sure how to confirm my configuration. I tried the command but it raised exception:

In [1]: %config c.IPCompleter.use_jedi = False
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[1], line 1
----> 1 get_ipython().run_line_magic('config', 'c.IPCompleter.use_jedi = False')

File IPython/core/interactiveshell.py:2480, in InteractiveShell.run_line_magic(self, magic_name, line, _stack_depth)
   2478     kwargs['local_ns'] = self.get_local_scope(stack_depth)
   2479 with self.builtin_trap:
-> 2480     result = fn(*args, **kwargs)
   2482 # The code below prevents the output from being displayed
   2483 # when using magics with decorator @output_can_be_silenced
   2484 # when the last Python token in the expression is a ';'.
   2485 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False):

File IPython/core/magics/config.py:134, in ConfigMagics.config(self, s)
    130 # otherwise, assume we are setting configurables.
    131 # leave quotes on args when splitting, because we want
    132 # unquoted args to eval in user_ns
    133 cfg = Config()
--> 134 exec("cfg."+line, self.shell.user_ns, locals())
    136 for configurable in configurables:
    137     try:

File <string>:1

AttributeError: 'LazyConfigValue' object has no attribute 'IPCompleter'

I might have a different configuration?
I look at ~/.ipython/profile_default/ipython_config.py, the only things not commented out are:

c.InteractiveShell.colors = 'Linux'
c.TerminalInteractiveShell.colors = 'Linux'

I follow the instruction here (https://ipython.readthedocs.io/en/stable/config/intro.html) to create a new profile. In the ipython_config.py file, I add c.IPCompleter.use_jedi = False. After relaunch IPython with the profile, the tab completion works. (But FYI with the new profile the %config magic command still gives me the same exception).

So, should we report this to jedi instead? Thanks.

@krassowski
Copy link
Member

@wenjuno whoops, sorry typo! I meant: %config IPCompleter.use_jedi = False

@krassowski
Copy link
Member

After relaunch IPython with the profile, the tab completion works.

Great to hear!

@krassowski
Copy link
Member

So, should we report this to jedi instead? Thanks.

Let's see:

import jedi
code = """import typing
class A:
    @property
    def value(self) -> typing.Literal['a']:
        return 'a'
    def get(self) -> typing.Literal['a']:
        return 'a'
a = A()
a."""
script = jedi.Script(code)
script.complete(line=len(code.splitlines()), column=2)

[<Completion: get>,
<Completion: value>,
...]

Well, this works with script what about Interpreter:

import jedi
code = """import typing
class A:
    @property
    def value(self) -> typing.Literal['a']:
        return 'a'
    def get(self) -> typing.Literal['a']:
        return 'a'
a = A()
a."""
script = jedi.Interpreter(code, [])
script.complete(line=len(code.splitlines()), column=2)

Also works. Maybe this is an integration problem?

@Carreau
Copy link
Member

Carreau commented Apr 22, 2024

script = jedi.Interpreter(code, [])
script.complete(line=len(code.splitlines()), column=2)

that's an improper use of Interpreter.

import jedi
import typing


class A:
    @property
    def value(self) -> typing.Literal["a"]:
        return "a"

    def get(self) -> typing.Literal["a"]:
        return "a"


a = A()

interp = jedi.Interpreter("a.", [{"a": a}])
interp.complete(line=1, column=2)

Raises with AttributeError: 'TreeInstance' object has no attribute 'with_generics'. So it is likely an upstream jedi. Unclear it will be fixed.

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

No branches or pull requests

3 participants