google / mesop

Rapidly build AI apps in Python
https://google.github.io/mesop/
Apache License 2.0
5.27k stars 251 forks source link

Error when using stateclass with dictionary containing another stateclass object #814

Open MySweetEden opened 3 weeks ago

MySweetEden commented 3 weeks ago

Environment • OS: macOS • Python version: 3.12.1 • mesop version: 0.12.0

Situation I encountered an issue when executing a program using the mesop command, specifically when stateclass is used with a dictionary that contains another stateclass object. This results in an error after saving the program.

Command mesop app.py

Program

import json
from dataclasses import field

import mesop as me

@me.stateclass
class Class:
    class1: str = "class1"
    class2: str = "class2"

    def update(self, state1, state2):
        self.state1 = state1
        self.state2 = state2

@me.stateclass
class State:
    state1: dict[str, Class] = field(default_factory=dict)

@me.page(
    title="test",
    security_policy=me.SecurityPolicy(dangerously_disable_trusted_types=True),
)
def page():
    state = me.state(State)
    me.text("first: " + json.dumps(me.asdict(state)))

    object1 = Class()
    object1.update("test1", "test2")
    state.state1["object1"] = object1
    me.text("second: " + json.dumps(me.asdict(state)))

Error Message asdict() should be called on dataclass instances

Steps to Reproduce

  1. Run the above program with the command mesop app.py.
  2. Save the program again without making any changes.
  3. Observe the error message.

Expected Behavior The program should correctly serialize the stateclass instance, even when it contains a dictionary of other stateclass objects.

Actual Behavior The program raises an error stating that asdict() should be called on dataclass instances. The error appears when stateclass is used with a dictionary containing another stateclass object.

MySweetEden commented 3 weeks ago

This issue seems to be similar to the issue with the dataclass implementation. Nested lists of lists of Dataclasses does not de-serializing correctly in state

MySweetEden commented 3 weeks ago

Analysis The stateclass is defined in the Mesop library, as seen in the stateclass implementation. Upon inspection, it’s clear that stateclass is wrapped with the dataclass_with_defaults function.

The dataclass_with_defaults function is defined here, and it uses the standard dataclass from Python’s dataclasses module.

The error occurs due to a known issue with nested dataclasses, which causes bugs when one dataclass is nested inside another.

Solution A workaround is to use dataclass from Pydantic instead of the standard dataclasses module. Pydantic’s dataclass handles nested classes more robustly, preventing the issue from arising. More details can be found in the Pydantic documentation on dataclasses.

Concern However, switching from the standard dataclass to Pydantic’s dataclass could potentially affect other parts of the program that rely on the standard implementation. This change may introduce new bugs or compatibility issues, so it’s important to thoroughly test the program after making the switch to ensure everything functions as expected.