Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python dynamic properties and mypy

I'm trying to mask some functions as properties (through a wrapper which is not important here) and add them to the object dynamically, however, I need code completion and mypy to work.

I figured out how to add a property dynamically (either through a metaclass or simply in constructor), but the problem I have is mypy doesn't pick it up (and neither does the IDE).

One workaround is to define an attribute with the same name/type, but I really don't like this approach (too much code, static set of attributes, repetition).

Is there a better way?

class Meta(type):
    def __new__(cls, clsname, bases, dct):

        def prop(self) -> int:
            return 1

        inst = super(Meta, cls).__new__(cls, clsname, bases, dct)
        inst.dynprop=property(prop)
        return inst

class Foo(metaclass=Meta):
    dynprop=int #this works, but I don't want it

class Bar(metaclass=Meta):pass

def somefunc(s:str):
    print(s)

foo=Foo()
bar=Bar()
somefunc(foo.dynprop)   #this is ok
somefunc(bar.dynprop)   #meta.py:24: error: "Bar" has no attribute "dynprop"
like image 636
dkone Avatar asked Nov 08 '22 00:11

dkone


1 Answers

Fix your IDE? :-). In Python there will always be corner cases where static analysis can't go . In this case you got the tools that ere supposed to be helping you getting in your way.

There is no way for either the IDE or Mypy to find about these dynamic attributes without running the code. I know there are IDEs, that at least in the past, resorted to actually importing a module to have auto-complete - but that also can trigger a host of collateral effects.

I'd say you will have to live without these tools in order to have your dynamic code - to the point of adding comments with the "don't check this" markup style. Autocomplete can't be possible at all.

like image 181
jsbueno Avatar answered Nov 14 '22 21:11

jsbueno