Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Hack to implement a confirm_button in Streamlit v0.35
import streamlit as st
import collections
import functools
import inspect
import textwrap
def cache_on_button_press(label, **cache_kwargs):
"""Function decorator to memoize function executions.
Parameters
----------
label : str
The label for the button to display prior to running the cached funnction.
cache_kwargs : Dict[Any, Any]
Additional parameters (such as show_spinner) to pass into the underlying @st.cache decorator.
Example
-------
This show how you could write a username/password tester:
>>> @cache_on_button_press('Authenticate')
... def authenticate(username, password):
... return username == "buddha" and password == "s4msara"
...
... username = st.text_input('username')
... password = st.text_input('password')
...
... if authenticate(username, password):
... st.success('Logged in.')
... else:
... st.error('Incorrect username or password')
"""
internal_cache_kwargs = dict(cache_kwargs)
internal_cache_kwargs['allow_output_mutation'] = True
internal_cache_kwargs['show_spinner'] = False
def function_decorator(func):
@functools.wraps(func)
def wrapped_func(*args, **kwargs):
@st.cache(**internal_cache_kwargs)
def get_cache_entry(func, args, kwargs):
class ButtonCacheEntry:
def __init__(self):
self.evaluated = False
self.return_value = None
def evaluate(self):
self.evaluated = True
self.return_value = func(*args, **kwargs)
return ButtonCacheEntry()
cache_entry = get_cache_entry(func, args, kwargs)
if not cache_entry.evaluated:
if st.button(label):
cache_entry.evaluate()
else:
raise st.ScriptRunner.StopException
return cache_entry.return_value
return wrapped_func
return function_decorator
def confirm_button_example():
@cache_on_button_press('Authenticate')
def authenticate(username, password):
return username == "buddha" and password == "s4msara"
username = st.text_input('username')
password = st.text_input('password')
if authenticate(username, password):
st.success('You are authenticated!')
st.write(st.slider('Test widget'))
else:
st.error('The username or password you have entered is invalid.')
def display_func_source(func):
code = inspect.getsource(confirm_button_example)
code = '\n'.join(code.splitlines()[1:]) # remove first line
st.code(textwrap.dedent(code))
if __name__ == '__main__':
st.write("""
This example shows a hack to create a "confirm button" in Streamlit, e.g.
to authenticate a username / password pair.
The correct answer is `buddha` / `s4msara`.
""")
display_func_source(confirm_button_example)
confirm_button_example()
@treuille

This comment has been minimized.

Copy link
Owner Author

@treuille treuille commented Oct 25, 2019

To see this gist in action, please run:

https://gist.githubusercontent.com/treuille/bc4eacbb00bfc846b73eec2984869645/raw/059fd9e0fe6687daaf55683427ddc5c600fa3b22/confirm_button_hack.py
@treuille

This comment has been minimized.

Copy link
Owner Author

@treuille treuille commented Nov 11, 2019

As mentioned here, the general usage pattern is:

arg_1 = st.some_widget(...)
arg_2 = st.some_widget(...)
...

@cache_on_button_press('Submit')
def some_long_computation(arg_1, arg_2, ...)
   ... # <- some long computation

return_value = some_long_computation(arg_1, arg_2, ...)
# do something with the return value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.