Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to have Python IDEs offer autocompletion for dynamically generated class attributes?

Are there any tricks I can employ to get IDEs to offer code completion for dynamically generated class attributes? For instance


class A:
    
    def __init__(self):
        setattr(self, "a", 5)

This code will set the class attribute of A called a to the value of 5. But IDEs do not know about a and therefore you do not get code completion for it. I've read that the __dir__ method can be hooked, but the suggestion made in that answer has not worked for me. Does anybody have any ideas?

like image 320
CiaranWelsh Avatar asked Aug 16 '20 11:08

CiaranWelsh


2 Answers

I believe you will find the answer here. In short, Pycharm currently does not (and probably in the observable future will not) support dynamic attributes. That's because it analyzes code statically, and can't "see" what attributes a class might have. On the other hand, when you run your code in (say) iPython, once an instance of such class is created, the editor can get the attributes of the specific instance that resides in the memory, and thus show them in autocomplete. In such cases __dir__ helps. I assume that would be the case also with other IDEs.

So if you really need the autocompletion feature, you may want to try using Jupyter notebook. Still, you will have to instantiate your variable prior to getting autocomplete.

Another possible solution is to exploit that IDE supports .pyi files (Python interface file stub). You can add to your code a little snippet that instantiate the class with dynamic attributes, and writes down a class interface file (.pyi). Then IDE will use it for autocompletion. Obviously, this solution will have a "one run delay", but as in PyCharm you can switch to such file just by clicking on the asterisk near the class name, you can manually update it when having massive changes.

like image 144
igrinis Avatar answered Oct 10 '22 13:10

igrinis


For this, I had to use Union type to get all the possible autocomplete options. It takes some extra time to write it, but when my program is huge, it is worth it.

from typing import Union


class dynamic1(object):
    def __init__(self):
        self.b = 5
        self.c = 0


class dynamic2(dynamic1):
    def __init__(self):
        self.e = 10
        self.d = 11


class dynamic3:
    def __init__(self):
        self.f = 12


def func(li):
    return li[1]


def func() -> Union[dynamic1, dynamic2, dynamic3]:
    a = [dynamic1(), dynamic2(), dynamic3()]
    b = func(a)
    return b

Code in action

like image 43
Yansh Avatar answered Oct 10 '22 11:10

Yansh