Last active
September 17, 2021 13:18
-
-
Save komodovaran/0b65d360445fdef2753764c27a93056c to your computer and use it in GitHub Desktop.
Experimental ventures into type-safe global Streamlit state and out-of-order layouts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from abc import ABC | |
import streamlit as st | |
class _TypedState: | |
""" | |
Values should be set here to appear in auto-complete. Otherwise assume they don't exist in the global state | |
""" | |
def __init__(self) -> None: | |
self.some_value: int = 0 | |
class Component(ABC): | |
""" | |
Base component that takes care of state reference | |
""" | |
# Make a typed state object | |
st.session_state["state"] = _TypedState() | |
# Make it available to all child classes without needing super().__init__() | |
state: _TypedState = st.session_state["state"] | |
class TextBox(Component): | |
""" | |
Inherit from parent component and initialize a reference to Streamlit's state, but typed | |
""" | |
def __init__(self, name: str) -> None: | |
st.text(f"Shared state for {name} is: {self.state.some_value}") | |
class Slider(Component): | |
""" | |
Changes state for all components here | |
""" | |
def __init__(self) -> None: | |
self.state.some_value = st.slider( | |
min_value=0, max_value=100, value=self.state.some_value, label="change state value (set 0 to disable text)" | |
) | |
class Layout: | |
""" | |
Layout and no other concerns | |
""" | |
text1 = st.empty() | |
text2 = st.empty() | |
text3 = st.empty() | |
# Will appear last because of layout | |
slider = st.empty() | |
class App(Component): | |
""" | |
Tie everything together | |
""" | |
def __init__(self) -> None: | |
layout = Layout() | |
# Must be first to control state flow "downwards" | |
with layout.slider: | |
Slider() | |
if self.state.some_value == 0: | |
return | |
with layout.text1: | |
TextBox("text 1") | |
with layout.text2: | |
TextBox("text 2") | |
with layout.text3: | |
TextBox("text 3") | |
if __name__ == "__main__": | |
App() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment