Confusing behavior when state reloads an enum

I’m running Streamlit locally:
Python 3.12.3
streamlit 1.34.0

I am trying to store an enum in the Streamlit session state. When the page reloads (like after a button click) the enum appears to be set correctly, but it fails when I try to actually compare it against the enum.

I expected to be able to match the enum after the state reloaded after a button press. It fails.

I’m wondering if maybe the enum is getting redefined and it somehow just fails to see them as equal even when they are? Is this just a bad pattern for using in a SL app?

from enum import Enum, auto 
import streamlit as st

class State(Enum):
    RED = auto()
    GREEN = auto()
    BLUE = auto() 

st.title("State App")


default_values = {'current_index': 0, 'current_question': 0, 'score': 0, 
                  'selected_option': None, 'answer_submitted': False, 'state': State.RED}

for key, value in default_values.items():
    st.session_state.setdefault(key, value)


def toggle():
    print(f"In toggle, state variable is {st.session_state.state} {type(st.session_state.state)}")
    match st.session_state.state:
        case State.GREEN:
            print(f"In toggle function, matched to green")
            st.session_state.state = State.BLUE
        case State.RED:
            print(f"In toggle function, matched to red")    
            st.session_state.state = State.GREEN
        case State.BLUE:
            print(f"In toggle function, matched to blue")    
            st.session_state.state = State.RED        
        case _:
            print(f"In toggle function, no match. It's {st.session_state.state} {type(st.session_state.state)}")
            print(f"Equality: {State.GREEN==st.session_state.state}")
              
st.write(f"Current Color is {st.session_state.state} {type(st.session_state.state)}")
st.button('Next', on_click=toggle)   


match st.session_state.state:
    case State.GREEN:
        print(f"In body, state matched to green")
    case State.RED:
        print(f"In body, state matched to red")    
    case State.BLUE:
        print(f"In body, state matched to blue")            
    case _:
        print(f"In body, no match. It's {st.session_state.state}")

Output:

            
In body, state matched to red
In toggle, state variable is State.RED <enum 'State'>
In toggle function, matched to red
In if statement, it's green
In body, no match. It's State.GREEN
In toggle, state variable is State.GREEN <enum 'State'>
In toggle function, no match. It's State.GREEN <enum 'State'>
Equality: False
In body, no match. It's State.GREEN

This is expected behavior for Streamlit. When the page reruns, you define a new class. The object saved in Session State is an instance from the class defined during a previous rerun.

If you define your classes in external files and import them, you can get around this.

Thank you.

Another workaround I guess: I switched my Enum to an IntEnum and was able to use the match appropriately in this way.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.