Use experimental_singleton with Enum's

Hi all :wave:!

I recently read the new blog post about singletons and memo chaches. Of course I wanted to try it out ASAP so I upgraded to 0.89 and gave it a try.

Instead of passing around strings, I often use Enum classes to structure my code a bit better. Here is an example:

class Agg(Enum):
    '''Defines value aggregation.'''
    MIN = 'min'
    AVG = 'avg'
    MAX = 'max'

I would like to pass an value of Agg to a function get_data, which also takes a db connection con as argument. Here is a schema of it:

@st.experimental_singleton
def get_data(_con: psycopg2.connect,
             agg: Agg):
     if agg == Agg.MIN:
        # create cursor, create sql string with "min" aggregation
     elif agg == Agg.AVG:
        # create cursor, create sql string with "avg" aggregation
    ...

I don’t care if psycopg2 changes over time, so I exclude it from the hashing step by prefixing _con with an underscore. agg on the other hand can change and I do care, so I cannot exclude it. However, I receive the following error in my code:

UnhashableParamError: Cannot hash argument 'agg' (of type Agg) in 'get_data'.

To address this, you can tell Streamlit not to hash this argument by adding a leading underscore to the argument's name in the function signature:


@st.experimental_singleton
def get_data(_agg, ...):
    ...

In fact, hashing Agg is quite easy (hash(Agg.MIN) --> -5742032495632092010) but I am unsure on how to pass this information to st.experimental_singleton. I also tried the following by nothing worked for me:

@st.experimental_singleton(func=hash)
@st.experimental_singleton(func=lambda _: hash)
@st.experimental_singleton(func={Agg: lambda _: hash})

Any help is appreciated!

1 Like