Wednesday, 8 November 2023

Pylance not working autocomplete for dynamically instantiated classes

from typing import Literal, overload, TypeVar, Generic, Type
import enum
import abc
import typing

class Version(enum.Enum):
    Version1 = 1
    Version2 = 2
    Version3 = 3


import abc
from typing import Type


class Machine1BaseConfig:
    @abc.abstractmethod
    def __init__(self, *args, **kwargs) -> None:
        pass

class Machine1Config_1(Machine1BaseConfig):
    def __init__(self, fueltype, speed) -> None:
        self.fueltype = fueltype
        self.speed = speed

class Machine1Config_2(Machine1BaseConfig):
    def __init__(self, speed, weight) -> None:
        self.speed = speed
        self.weight = weight

class Machine1FacadeConfig:
    @classmethod
    def get_version(cls, version: Version) -> Type[typing.Union[Machine1Config_1, Machine1Config_2]]:
        config_map = {
            Version.Version1: Machine1Config_1,
            Version.Version2: Machine1Config_2,
            Version.Version3: Machine1Config_2,
        }
        return config_map[version]
        

class Machine2BaseConfig:
    @abc.abstractmethod
    def __init__(self, *args, **kwargs) -> None:
        pass

class Machine2Config_1(Machine2BaseConfig):
    def __init__(self, gridsize) -> None:
        self.gridsize = gridsize

class Machine2Config_2(Machine2BaseConfig):
    def __init__(self, loadtype, duration) -> None:
        self.loadtype = loadtype
        self.duration = duration

class Machine2FacadeConfig:
    @classmethod
    def get_version(cls, version: Version) -> Type[typing.Union[Machine2Config_1, Machine2Config_2]]:
        config_map = {
            Version.Version1: Machine2Config_1,
            Version.Version2: Machine2Config_1,
            Version.Version3: Machine2Config_2,
        }
        return config_map[version]


class Factory:
    def __init__(self, version: Version) -> None:
        self.version = version

    @property
    def Machine1Config(self):
        return Machine1FacadeConfig.get_version(self.version)

    @property
    def Machine2Config(self):
        return Machine2FacadeConfig.get_version(self.version)


factory_instance = Factory(Version.Version1)
machine1_config_instance = factory_instance.Machine1Config()
machine2_config_instance = factory_instance.Machine2Config()

In the provided Python code, the Factory class is used to instantiate configuration objects for two different types of machines (Machine1 and Machine2) based on a specified version. The problem is when using Pylance/Pyright with Visual Studio Code, I'm experiencing issues with autocomplete not correctly suggesting parameters for dynamically instantiated classes (Machine1Config and Machine2Config) in a factory design pattern. How can I improve my code to enable more accurate and helpful autocompletion suggestions by Pylance for these dynamically determined types?

I have thought that this should somehow work with @overload decorater but I can't wrap my head around it how to quite implement it.

Furthermore currently with the type hint Type[typing.Union[Machine1Config_1, Machine1Config_2]] Pylance suggests all key word arguments of Machine1Config_1 and Machine1Config_2, so fueltype, speed, weight. If I leave this type hint away there is no autocompletion at all.



from Pylance not working autocomplete for dynamically instantiated classes

No comments:

Post a Comment