2Functions & classes that extend the streamlit library
3If ss is not found in this module, it means you don't have streamlit installed.
7from .misc
import isiterable
8from .imports
import lazy_import
9st = lazy_import(
'streamlit')
17 """ A better streamlit.session_state interface.
18 This class is accessable via it
's only instance, `ss`. Do not instantiate this class directly.
19 You can use `ss` as a drop-
in replacement
for st.session_state,
and it will work.
21 - Variables are specified once
with defaults,
and can be reset
and maintained across pages
23 the . operator to access
and set variables,
and it won
't throw an error if it doesn't already
24 exist, instead it will
return None.
25 - *_changed (named {varname}_changed) gets updated automatically
26 when the value gets set. The *_changed variable will
not get reset upon the script rerunning
27 though, unless you call
reset_changed() at the end of the script. It will also
not detect
28 if the value was changed by widgets. To check
if any variables were changed at *all*,
30 Note that *_changed doesn
't ever get reset to False, unless a variable is manually set
31 to the same value it already has. To reset all the variables, call ss.reset_changed().
32 This is usually done at the end of a file
and/
or before any st.rerun() calls.
33 - `current_page`
and `page_changed` variables store the filepath of the
34 page we
're currently in, and if the page was just changed, respectively.
36 note_page() at the top of each page
in your project that you want variables to be maintained
in.
37 -
maintain_state() will keep all the variables the same across pages. If arguements are
38 passed, it only maintains those. kwargs passed sets the given variables to those values.
39 - The `just_loaded` variable gets set to `
True` only
if it
's the first time the page is loaded.
40 All other times it's set to `False`. Resetting the page counts as loading the page for
42 - Variables you want to keep track of via query parameters (so they get preserved between
43 page reloads,
or for sharing URLs
with people), you can do that by either specifying
44 names of the variables positionally to
setup(),
or by calling the
add_query() method.
45 The
setup()
and add_query() methods will automatically load them on page startup,
or
46 you can load them yourself on first run using `just_loaded`.
48 - Query params will
not stay maintained across pages,
if the varibles change between
50 - Using containers
with query params behaves oddly sometimes. You may have to parse them
51 yourself using eval().
52 - TODO: auto-setting the page config on all pages
60 """ The constructor. Not to be called by you. Stop it."""
61 st.session_state[
'ss'] = self
62 st.session_state[
'just_loaded'] =
True
66 """ Handles setting the value, the {var}_changes, and the _prev_{var} variables """
67 if name
not in st.session_state:
68 st.session_state[name] = value
69 st.session_state[name +
'_changed'] = st.session_state[name] != value
70 st.session_state[
'_prev_' + name] = st.session_state[name]
71 st.session_state[name] = value
77 """ Shadows __setitem__() """
81 """ Handles getting variables from either session_state or query parameters """
85 if name
in self.
_query and name
in st.query_params:
88 if name
in st.session_state:
89 session = st.session_state[name]
99 if session
is not None and name
in self.
_query:
103 elif session
is None and queried
is not None:
104 st.session_state[name] = queried
108 return queried
or session
111 """ shadows __getitem__() """
114 def __delitem__(self, name:str):
115 if name
in self.
_dict:
117 del st.session_state[name]
119 def __delattr__(self, name:str):
122 def __contains__(self, name:str):
123 return name
in st.session_state
127 """ Handles how we serialize the _query params """
128 if isinstance(to, dict):
129 to = {repr(key): repr(val)
for key, val
in to.items()}
130 elif isinstance(to, (list, tuple, set)):
131 to = type(to)([repr(i)
for i
in to])
132 st.query_params[name] = repr(to)
135 """ Handles how we deserialize the query params
136 TODO: this only evaluates the first level of containers
138 return eval(st.query_params[name])
141 """ Pass default values of all the variables you're using.
143 If a variable is provided via positional args,
and not keyword args, this sets it to be watched
144 by query parameters
as well.
146 assert not len(set(queries) - set(vars.keys())),
'A query variable set isnt in the variables given with default values'
152 """ Ensures that all the variables we're keeping track of exist in st.session_state, at least
153 with default values. This can be, but shouldn
't need to be called by the user
155 for var, val
in self.
_dict.items():
156 if var
not in st.session_state:
157 st.session_state[var] = val
158 if var
in self.
_query and var
not in st.query_params:
160 if var +
'_changed' not in st.session_state:
161 st.session_state[var +
'_changed'] =
True
162 if '_prev_' + var
not in st.session_state:
163 st.session_state[
'_prev_' + var] =
None
166 """ Maintain variable states across files, and notes the page we're in """
172 """ Checks if any variables have been changed by widgets, and if so, updates their associated
175 for var
in self.
_dict.keys():
176 if var
not in st.session_state:
177 st.session_state[var] = self.
_dict[var]
178 if '_prev_' + var
not in st.session_state:
179 st.session_state[
'_prev_' + var] =
None
181 st.session_state[var +
'_changed'] = st.session_state[var] != st.session_state[
'_prev_' + var]
182 st.session_state[
'_prev_' + var] = st.session_state[var]
185 """ Maintain the current variables with the values they currently have across pages """
189 if var
not in self.
_dict:
190 raise ValueError(
"Variable specified not already being watched. To add it, please use keyword arguments to specify a default.")
192 st.session_state[var] = st.session_state[var]
194 for var, val
in self.
_dict.items():
197 elif var
not in st.session_state:
198 st.session_state[var] = val
200 st.session_state[var] = st.session_state[var]
201 for var, val
in kwargs.items():
203 if var
not in self.
_dict:
204 self.
_dict[var] = val
205 st.session_state[var] = val
208 """ Manually take note of what page we're running from """
218 if 'current_page' not in st.session_state:
219 st.session_state[
'current_page'] = file
222 st.session_state[
'current_page_changed'] = st.session_state[
'page_changed'] = \
223 st.session_state[
'current_page'] != file
224 st.session_state[
'current_page'] = file
227 """ Reset all variables to their defaults """
228 for var, val
in self.
_dict.items():
230 if var
in st.session_state:
231 st.session_state[var +
'_changed'] = st.session_state[var] != val
233 st.session_state[var +
'_changed'] =
True
239 """ Sets all the *_changed variables to False """
240 for var
in self.
_dict.keys():
241 st.session_state[var +
'_changed'] =
False
242 st.session_state[
'just_loaded'] =
False
245 """ Available just for compatibility """
249 """ Sets a single variable to be maintained and guarenteed to exist in st.session_state """
251 if name
not in st.session_state:
252 st.session_state[name] = default
253 self.
_dict[name] = default
257 """ Adds variables to be monitored with query parameters as well. Names must already be set
258 to be watched. This should only realistically be called once, in the main file.
261 if name
not in self.
_dict:
262 raise ValueError(f
"{name} not previously set to be watched, please provide a default.")
270 if 'just_loaded' not in st.session_state:
271 st.session_state[
'just_loaded'] =
True
273 if st.session_state[
'just_loaded']:
274 for name
in st.query_params.to_dict().keys():
def __setitem__(self, str name, value)
Handles setting the value, the {var}_changes, and the prev{var} variables.
def __getitem__(self, str name)
Handles getting variables from either session_state or query parameters.
def maintain_state(self, *args, exclude=[], calls=1, **kwargs)
Maintain the current variables with the values they currently have across pages.
def reset(self)
Reset all variables to their defaults.
def note_page(self, file, calls=1)
Manually take note of what page we're running from.
def update(self, file)
Maintain variable states across files, and notes the page we're in.
def __setattr__(self, str name, value)
Shadows setitem()
def check_changed(self)
Checks if any variables have been changed by widgets, and if so, updates their associated *_changed v...
def add_query(self, *names)
Adds variables to be monitored with query parameters as well.
def _set_query_param(self, name, to)
Handles how we serialize the _query params.
def reset_changed(self)
Sets all the *_changed variables to False.
def __init__(self)
The constructor.
def watch(self, str name, default)
Sets a single variable to be maintained and guarenteed to exist in st.session_state.
def setup(self, *queries, **vars)
Pass default values of all the variables you're using.
def __getattr__(self, str name)
shadows getitem()
def __delitem__(self, str name)
def get(self, name)
Available just for compatibility.
def ensure_exist(self)
Ensures that all the variables we're keeping track of exist in st.session_state, at least with defaul...
def _get_query_param(self, name)
Handles how we deserialize the query params TODO: this only evaluates the first level of containers.
A better streamlit.session_state interface.