pyscript icon indicating copy to clipboard operation
pyscript copied to clipboard

How to use class inheritance correctly

Open cjlapao opened this issue 1 year ago • 5 comments

I am trying to create some modules that contains code that is reusable and I am trying to use class inheritance to do so.

for example

class Device:
    def __init__(self, device_id, **args):
      self._device_id = device_id
      self._name = args.get("name", device_id)
      self._domain = device_id.split(".")[0]
      self._friendly_name = args.get("friendly_name", self._name)
      self._brightness = args.get("brightness", 0)
      self._color_temp = args.get("color_temp", 0)
      self._group = args.get("group", None)


    def info(self):
        return f"Name: {self.name()}\nID: {self.device_id()}\nArgs: {self._args}"

class TestLight(Device):
    def __init__(self, device_id, **args):
        # super().__init__(device_id, **args)
        log.info(f"Creating TestLight with {args}")
        self._automation_device_id = None

    def turn_on(self, **kwargs):
        if self._domain == "light" or self._domain == "switch":
            self.call_service("turn_on", **kwargs)
            return True
        return False

    def turn_off(self, **kwargs):
        if self._domain == "light" or self._domain == "switch":
            self.call_service("turn_off", **kwargs)
            return True
        return False

    def call_service(self, action, **kwargs):
        # Placeholder for service call logic
        print(f"Calling service {action} with {kwargs}")

this then creates an error as the super seems to not work properly

Is there any way I can bypass this?

cjlapao avatar Aug 24 '24 07:08 cjlapao

My workaround: https://github.com/ALERTua/ha_pyscript_modules/blob/main/entities/switch.py#L5 its super: https://github.com/ALERTua/ha_pyscript_modules/blob/main/entities/entity.py#L74

ALERTua avatar Aug 24 '24 07:08 ALERTua

@ALERTua Yes I did something similar yesterday,

class TestLight(Device):
    def __init__(self, device_id: str, **args):
        Device.init(self, device_id, **args)
        if self.is_debug_enabled():
            log.debug(f"Creating light {device_id} with {args}")
        clean_args = self.clean_args(**args)
        self.set_args(**clean_args)
        self._attributes = LightAttributes(device_id)
        self._tiggers = []
        self.init(**args)

This is my approach, very similar

thanks

cjlapao avatar Aug 26 '24 04:08 cjlapao

As you discovered, certain class features don't work properly in pyscript. One specific challenge is that all functions in pyscript are async, including class methods you create. That means that things like creating magic methods (eg, operator overloading) won't work, since python will expect those methods to be regular functions. One workaround is to create the class using regular python with @pyscript_compile.

craigbarratt avatar Aug 26 '24 05:08 craigbarratt

I would pin this issue for future generations and close it. Glad I helped.

ALERTua avatar Aug 26 '24 06:08 ALERTua

I agree, I am satisfied with the solution I found and all works really well for me

cjlapao avatar Aug 27 '24 12:08 cjlapao