Jedi: Rename symbol not working with attributes in class operator implementation

Created on 11 Apr 2021  路  4Comments  路  Source: davidhalter/jedi

T9n1mhg028

See https://github.com/microsoft/vscode-python/issues/15922

Copied content (if the other issue is changed):

Environment data

  • VS Code version: 1.55.1
  • Extension version (available under the Extensions sidebar): v2020.10.332292344
  • OS and version: Windows 10
  • Python version (& distribution if applicable, e.g. Anaconda): 3.9.4
  • Type of virtual environment used (N/A | venv | virtualenv | conda | ...): -
  • Relevant/affected Python packages and their versions: -
  • Relevant/affected Python-related VS Code extensions and their versions: -
  • Value of the python.languageServer setting: Jedi

Expected behaviour

class MyClass:
    def __init__(self, my_attribute):
        self.my_attribute = my_attribute

    def __eq__(self, other):
        return self.my_attribute == other.my_attribute

Now rename the instance attribute: Symbol Rename (shortcut F2) on my_attribute (in self.my_attribute in line 3) and rename it e.g. to my_attribute2. You'll see that other.my_attribute won't be changed accordingly.

This also happens when adding type hints. The above code renaming should just work (because there is enough information for the refactoring tool to act correctly). But I even tried type hints (see PEP 484). Because of class name usage in definition of the class itself you have to use Forward References.

class MyClass:
    def __init__(self, my_attribute):
        self.my_attribute = my_attribute

    def __eq__(self, other: "MyClass"):
        return self.my_attribute == other.my_attribute

or instead of Forward References using something of the future PEP 563:

from __future__ import annotations 

class MyClass:
    def __init__(self, my_attribute):
        self.my_attribute = my_attribute

    def __eq__(self, other: MyClass):
        return self.my_attribute == other.my_attribute

But even with those type hints Symbol Rename does not work correctly.

It should work correctly.

Actual behaviour

It does not work correctly.

Steps to reproduce:

See above

T9n1mhg028

Edit: This seems to be a Jedi specific problem. (Microsoft language server doesn't has this problem)

Edit 2: Can someone maybe check, if the problem also exists with JediLSP? Couldn't install it yet. Maybe the problem is on the python extensions side for jedi?


Edit 3: Installed now vscode and tested jedilsp and pylance (was using vscodium before but that had problems with both). On jedilsp the version with the type hints works correctly (which jedi didn't, so it was more of an extension problem).

But: Still: In the version without type hints the renaming does not happen. I installed pylance and it recognized it and renamed it. When using pycharm, it asks about that renaming case and per default renames then as well.

All 4 comments

Installed now vscode and tested jedilsp and pylance (was using vscodium before but that had problems with both). On jedilsp the version with the type hints works correctly (which jedi didn't, so it was more of an extension problem).

IMO everything works as designed then. It should work with type hints and shouldn't without.

But: Still: In the version without type hints the renaming does not happen. I installed pylance and it recognized it and renamed it. When using pycharm, it asks about that renaming case and per default renames then as well.

This is something that's simply not fixable. How would Jedi know that other is a MyClass? This is simply a heuristic. I know that we could theoretically assume this, but I'm not sure that's a great idea. I will definitely keep it in mind for the Rust version that I'm writing, but this will not happen in Jedi. Sorry. There are a lot of cases where Python's dynamic nature is kind of a problem. And I chose to not use heuristics for all of these (because it makes Jedi also slower).

Thanks for writing the detailed report though!

@davidhalter

Thanks for writing the detailed report though!

You're welcome. Thank you for devloping such a great tool.

This is something that's simply not fixable. How would Jedi know that other is a MyClass? This is simply a heuristic. I know that we could theoretically assume this, but I'm not sure that's a great idea. I will definitely keep it in mind for the Rust version that I'm writing, but this will not happen in Jedi. Sorry. There are a lot of cases where Python's dynamic nature is kind of a problem. And I chose to not use heuristics for all of these (because it makes Jedi also slower).

I understand. Would it be possible to handle this like pycharm does? Inquiring the user on such a case, to let him/her choose what to do or do things like LSP not support such inquiring?

Greets DoS

I understand. Would it be possible to handle this like pycharm does? Inquiring the user on such a case, to let him/her choose what to do or do things like LSP not support such inquiring?

AFAIK the LSP protocol does not support this (I have read it quite thoroughly). IMO that's the correct approach with such names. However it's still unlikely that Jedi will support this, because the Jedi's API is probably not made for this. However I will keep it in mind for the next autocompletion project that I'm doing :).

@davidhalter Thank you.

Just to add: I appreciate your work. People like you make the world a better place.

Greets DoS007

Was this page helpful?
0 / 5 - 0 ratings