blipk / streamlitextras Goto Github PK
View Code? Open in Web Editor NEWStreamlitExtras
License: Other
StreamlitExtras
License: Other
Hi there, first of all, thanks for this awesome component, I think it will be really helpful and solve a lot of issues we have on our WebUI once we start using it in there, unfortunately we are for now stuck using python 3.8.5 on our environment and this component requires python 3.9 or higher. I would really appreciate if you could add support for python 3.8.5, I'm really interested in things like the threader, logger and router from this component, the other parts of this component also might fit in some way in our UI but for now those I mentioned are the ones I'm most interesting in as they will solve a lot of issues we have and allow us to do a lot more stuff with streamlit. Thanks for your time.
Example to reproduce:
import extra_streamlit_components as stx
import streamlit as st
@st.cache_resource
def get_manager():
return stx.CookieManager()
cookie_manager = get_manager()
Output:
CachedWidgetWarning: Your script uses a widget command in a cached function (function decorated with @st.cache_data or @st.cache_resource). This code will only be called when we detect a cache "miss", which can lead to unexpected results.
How to fix this:
Move all widget commands outside the cached function.
Or, if you know what you're doing, use experimental_allow_widgets=True in the cache decorator to enable widget replay and suppress this warning.
Traceback:
File "/Users/italo/.pyenv/versions/3.10.11/lib/python3.10/threading.py", line 973, in _bootstrap
self._bootstrap_inner()
File "/Users/italo/.pyenv/versions/3.10.11/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
self.run()
File "/Users/italo/.pyenv/versions/3.10.11/lib/python3.10/threading.py", line 953, in run
self._target(*self._args, **self._kwargs)
File "/Users/italo/dev/test.py", line 10, in <module>
cookie_manager = get_manager()
File "/Users/italo/dev/test.py", line 7, in get_manager
return stx.CookieManager()
File "/Users/italo/dev/.venv/lib/python3.10/site-packages/extra_streamlit_components/CookieManager/__init__.py", line 22, in __init__
self.cookies = self.cookie_manager(method="getAll", key=key, default={})
Despite the warning, it seems to work correctly. However, adding the experimental_allow_widgets=True
option in an attempt to suppress the warning breaks the cookies so that it resets on page refreshes.
Versions:
macOS: 14.4.1 (M1)
streamlit: 1.34.0
extra_streamlit_components: 0.1.71
Python: 3.10.11
Hello,
thank you for creating this project.
Description:
I tried this component in my project and I have noticed a bug when trying to set cookies. Specifically, when you try to set a cookie for the second time, the app will not stop running and I see continue reload in console logs.
I have also attached a minimal reproducible code snippet which demonstrate the issue.
To reproduce the bug, create a new Streamlit app that uses this component and run the following code:
import streamlit as st
from streamlitextras.cookiemanager import get_cookie_manager
from streamlitextras.logger import log
cookie_manager = None
def set_cookie(name, value):
log.debug("Setting cookie")
cookie_manager = get_cookie_manager()
cookie_manager.delayed_init() # Makes sure CookieManager stays in st.session_state
cookie_manager.set(name, value)
def main():
global cookie_manager
cookie_manager = get_cookie_manager()
cookie_manager.delayed_init() # Makes sure CookieManager stays in st.session_state
cookie_manager.set("my_cookie_name", "I'm a cookie!")
my_cookie_value = cookie_manager.get("my_cookie_name")
st.write(my_cookie_value) # "I'm a cookie"
my_cookies = cookie_manager.get_all("my_cookie_name")
st.write(my_cookies) # {"my_cookie_name": "I'm a cookie!"}
cookie_manager.delete("my_cookie_name")
my_cookie_value = cookie_manager.get("my_cookie_name")
st.write(my_cookie_value) # None
if __name__ == "__main__":
main()
set_cookie("another cookie", "I'm a cookie!")
Expected behavior:
Actual behavior:
Environment:
Please let me know if any more details are required. I would be happy to provide them.
Hi, @blipk
Thanks for your work, this repo does help a lot.
Encounters an error after upgrading to 0.2.41, using Python3.9.2.
File "/.venv/lib/python3.9/site-packages/streamlitextras/cookiemanager/init.py", line 5, in
from streamlitextras.logger import log
File "/.venv/lib/python3.9/site-packages/streamlitextras/logger/init.py", line 137, in
def bind_log(extras: dict | None = None) -> Logger:
TypeError: unsupported operand type(s) for |: 'type' and 'NoneType'
Union types is a new feature in Python3.10+, so Python3.10+ is required in future versions?
Dear @blipk,
I'm considering to use this component, as your code really seems robust (I'm still playing with Mohammed's CookieManager to learn a bit more about Streamlit execution model gripes).
Are you considering to directly support Google OAuth2 without the need of using Firebase service?
Thank you!
Hey, fantastic work on the package!
Thanks to you I could set up an authentication, and it works perfect in local development.
However, once I deployed to the Streamlit Cloud, it loses the user authentication at every manual refresh of the page.
I isolated the problem as the following: the _get_websocket_headers()
that is used by the authentication system to retrieve the Cookies, does not return any cookies once deployed on the Streamlit Cloud. I'm not sure why, because I can see the Cookies in the Websocket headers by inspecting the page.
Here is what _get_websocket_headers
returns in both situations:
Localhost:
{
"Host": "localhost:8501",
"Connection": "Upgrade",
"Pragma": "no-cache",
"Cache-Control": "no-cache",
"User-Agent": "[redacted]",
"Upgrade": "websocket",
"Origin": "[redacted]",
"Sec-Websocket-Version": "13",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "[redacted]",
"Cookie": "[redacted]",
"Sec-Websocket-Key": "[redacted]",
"Sec-Websocket-Extensions": "permessage-deflate; client_max_window_bits",
"Sec-Websocket-Protocol": "streamlit"
}
Streamlit Cloud
{
"Host": "[redacted]",
"User-Agent": "[redacted]",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "[redacted]",
"Cache-Control": "no-cache",
"Connection": "Upgrade",
"Origin": "[redacted]",
"Pragma": "no-cache",
"Sec-Websocket-Extensions": "permessage-deflate; client_max_window_bits",
"Sec-Websocket-Key": "[redacted]",
"Sec-Websocket-Protocol": "streamlit",
"Sec-Websocket-Version": "13",
"Upgrade": "websocket",
"X-Forwarded-For": "[redacted]",
"X-Streamlit-User": "[redacted]"
}
In the meantime, I seem to be able to fix it by fetching the cookie from the cookie_manager instead of the websocket headers. So I do it the following way:
class CustomAuthenticator(Authenticator):
@property
def auth_cookie(self):
"""
Gets the auth cookie from javascript cookies instead of
Websocket headers. As the websocket method does not
work on Streamlit Cloud
:returns: Returns the auth cookie or None if it doesnt exist
"""
logger.info("Running custom auth cookie fetching")
if "authentication_token" in st.session_state and st.session_state["authentication_token"]:
auth_cookie = st.session_state["authentication_token"]
return auth_cookie
cookie = None
cookie_manager = get_cookie_manager()
cookie = cookie_manager.get(AUTH_COOKIE_NAME)
logger.info(f"Done running. Found: {cookie}")
return cookie
def check_auth(title):
global auth
auth = get_auth(AUTH_COOKIE_NAME)
auth = CustomAuthenticator(
cookie_name=auth.cookie_name,
cookie_key=auth.cookie_key,
session_expiry_seconds=auth.session_expiry_seconds,
session_name=auth.session_name,
authenticator_name=auth.authenticator_name,
user_class=auth.user_class,
admin_ids=auth.admin_ids,
developer_ids=auth.developer_ids,
require_email_verification=auth.require_email_verification,
debug=auth.debug,
)
logger.info(f"auth: {auth}")
auth.delayed_init() # This is required to make sure current Authenticator stays in session state
auth_status = auth.auth_status
logger.info(f"auth_status: {auth_status}")
user = auth.current_user
logger.info(f"user: {user}")
if not auth_status or not user:
auth_page(title)
st.stop()
It works pretty OK, except that it usually refreshes the page once at least on every authentication check.
Not sure how to handle this in the best way. Maybe you have an idea?
Thanks a lot!
Good Morning,
I have been trying to use these components to build something like a multi page app. I appreciate the work that you have done to facilitate these sorts of things. The Authentication component is great. (With considerations given to the issue that I reported earlier.) I am just struggling to get the router to work correctly.
I was building off of the example that you give using a routes folder. Which works for loading the landing page. But, when I try to route from that landing page anywhere else it doesn't seem to actually do anything. With the landing page loading immediately over the page that I am trying to route to.
Any help that you can offer would be appreciated.
Thank you,
Evan
Hi, I don't have the luxury of upgrading python from 3.9.2 any sooner in the production. Could you please say which version of the threading module is supported ? I keep getting this error
TypeError: unsupported operand type(s) for |: 'type' and 'NoneType'
2024-01-13 19:31:59.623 Uncaught app exception
Traceback (most recent call last):
File "/home/.local/lib/python3.9/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 535, in _run_script
exec(code, module.dict)
File "/home/pic/my_streamlit.py", line 17, in
from streamlitextras.threader import streamlit_thread
File "/home/.local/lib/python3.9/site-packages/streamlitextras/threader/init.py", line 70, in
script_run_context: ScriptRunContext | None = None,
TypeError: unsupported operand type(s) for |: 'type' and 'NoneType'
User Authentication Fails when Display Name is None.
I wrote a PR fixing this. It is ready for review. (wrote it from my personal github account raven-black-dream)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.