FabienArcellier / writer-framework

No-code in the front, Python in the back. An open-source framework for creating data apps.
https://streamsync.cloud
Apache License 2.0
0 stars 1 forks source link

declare optional schema on streamsync state #24

Closed FabienArcellier closed 7 months ago

FabienArcellier commented 8 months ago

This proposal aims to provide a way to associate a streamsync state with an explicit schema. The developer can specify how the state he builds in streamsync is structured.

This parameter is optional. If it is not provided, the current behavior which consists of interpreting dictionaries as substates is preserved.

This mechanism may solve 3 problems:

The developer would have access to autocompletion in the handler from his IDE.

Here is a first draft of what this mechanism could produce.

from typing import Optional

import streamsync as ss
from streamsync.core import State, StreamsyncState

class AppState(State):
    title: str
    stats: State

class RootState(StreamsyncState):
    myapp: AppState
    _my_private_element: int
    message: Optional[str]
    counter: int
    graph: dict
    stats: streamsync.State

    @streamsync.property(depends_on=['graph'])
    def graph_size(self):
        return len(self.graph["data"])

# Its name starts with _, so this function won't be exposed
def _update_message(state: RootState):
    state.myapp.title = "My App"
    state['myapp']['title'] = "My App"

    state.set_page('hello')

initial_state = ss.init_state({
    "my_app": {
        "title": "My App"
    },
    "graph": {
        "data": [
            {
                "x": [
                    "giraffes",
                    "orangutans",
                    "monkeys"
                ],
                "y": [
                    20,
                    14,
                    23
                ],
                "type": "bar"
            }
        ]
    },
    "_my_private_element": 1337,
    "message": None,
    "counter": 26,
    "stats": {
        "increment": 0,
        "decrement": 0
    }
}, schema=RootState)

_update_message(initial_state)

initial_state.import_stylesheet('main', '/static/main.css')
raaymax commented 8 months ago

I really like the idea, looks good to me. Simple and straightforward, and easy to understand by reading the code.