Repository: kmcgrady/streamlit-autorefresh Branch: main Commit: ea4a9065828e Files: 13 Total size: 15.7 KB Directory structure: gitextract_ca7g3vvt/ ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── MANIFEST.in ├── README.md ├── setup.py └── streamlit_autorefresh/ ├── __init__.py └── frontend/ ├── .prettierrc ├── package.json ├── public/ │ └── index.html ├── src/ │ ├── index.ts │ └── react-app-env.d.ts └── tsconfig.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ ######################################################################## # Python - https://github.com/github/gitignore/blob/master/Python.gitignore ######################################################################## # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # Distribution / packaging build/ dist/ eggs/ .eggs/ *.egg-info/ *.egg # Unit test / coverage reports .coverage .coverage\.* .pytest_cache/ .mypy_cache/ test-reports # Test fixtures cffi_bin # Pyenv Stuff .python-version ######################################################################## # OSX - https://github.com/github/gitignore/blob/master/Global/macOS.gitignore ######################################################################## .DS_Store .DocumentRevisions-V100 .fseventsd .Spotlight-V100 .TemporaryItems .Trashes .VolumeIcon.icns .com.apple.timemachine.donotpresent ######################################################################## # node - https://github.com/github/gitignore/blob/master/Node.gitignore ######################################################################## # Logs npm-debug.log* yarn-debug.log* yarn-error.log* # Dependency directories node_modules/ # Coverage directory used by tools like istanbul coverage/ # Lockfiles yarn.lock package-lock.json ######################################################################## # JetBrains ######################################################################## .idea ######################################################################## # VSCode ######################################################################## .vscode/ ================================================ FILE: CHANGELOG.md ================================================ # Changelog ## 1.0.1 - Fix: Changes to interval, refresh limit, or key indicate a reset of the interval. ## 1.0.0 - **BREAKING CHANGE** - Parameters outside of `interval` have moved to keyword-only parameters. - Added `debounce` parameter that delays refresh when user interaction occurs. Defaults to `True` to mimic original behavior ================================================ FILE: LICENSE ================================================ Copyright (c) 2018 The Python Packaging Authority Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: MANIFEST.in ================================================ recursive-include streamlit_autorefresh/frontend/build * ================================================ FILE: README.md ================================================ # Streamlit Autorefresh Streamlit component to force a refresh without tying up a script. ## Overview Streamlit apps are scripts that a server runs based on interactions. When a user interacts with the web app, the script reruns. One Streamlit use case is a dashboard or realtime stats application. The purpose is to regularly display stats on some interval. Currently, the best way to support this is an infinite loop in the script, but that is not a great practice and has led to a less desirable developer experience in shutting down scripts and servers. ### How does this component help? This component provides a timer on the frontend to regularly ping the Streamlit server to rerun. This effectively allows the script to successfully execute and finish properly and avoid tying up server resources. It effectively puts a little more work on the user's browser than on the server. # Installation ``` pip install streamlit-autorefresh ``` # Parameters ``` interval: int Amount of time in milliseconds to limit: int or None Amount of refreshes to allow. If none, it will refresh infinitely. While infinite refreshes sounds nice, it will continue to utilize computing resources. debounce: boolean Whether to delay the autorefresh when user interaction occurs. Defaults to True in order to avoid refreshes interfering with interaction effects on scripts. key: str or None An optional key that uniquely identifies this component. If this is None, and the component's arguments are changed, the component will be re-mounted in the Streamlit frontend and lose its current state. ``` ## Returns ``` int Number of times the refresh has been triggered or max value of int ``` # Example Usage ```python import streamlit as st from streamlit_autorefresh import st_autorefresh # Run the autorefresh about every 2000 milliseconds (2 seconds) and stop # after it's been refreshed 100 times. count = st_autorefresh(interval=2000, limit=100, key="fizzbuzzcounter") # The function returns a counter for number of refreshes. This allows the # ability to make special requests at different intervals based on the count if count == 0: st.write("Count is zero") elif count % 3 == 0 and count % 5 == 0: st.write("FizzBuzz") elif count % 3 == 0: st.write("Fizz") elif count % 5 == 0: st.write("Buzz") else: st.write(f"Count: {count}") ``` ## Caveats This is a rather simplistic implementation and feature requests are welcome! - The Frontend timer is not a perfect system, so the refresh interval is a rough estimate. Feel free to adjust the interval to a limit that's practical - Just like an infinite loop, a small interval, will constantly ping and make server do more work and should be treated with caution. - We recommend a `key` be added. It can be a string literal, but it will help in maintaining the refresh rate and count. - We recommend _NOT_ calling `st_autorefresh` multiple times in a script. It will effectively create multiple timers and refresh at weird rates. It's best to use one function call and utilize the counter to better adjust different refresh rates ================================================ FILE: setup.py ================================================ import setuptools setuptools.setup( name="streamlit-autorefresh", version="1.0.1", author="Ken McGrady", author_email="ken.mcgrady@gmail.com", description="Simple way to autorefresh your Streamlit apps", long_description="Simple way to autorefresh your Streamlit apps", long_description_content_type="text/plain", url="https://github.com/kmcgrady/streamlit-autorefresh", packages=setuptools.find_packages(), include_package_data=True, classifiers=[], python_requires=">=3.6", install_requires=[ # By definition, a Custom Component depends on Streamlit. # If your component has other Python dependencies, list # them here. "streamlit >= 0.75", ], ) ================================================ FILE: streamlit_autorefresh/__init__.py ================================================ import os import streamlit.components.v1 as components # Create a _RELEASE constant. We'll set this to False while we're developing # the component, and True when we're ready to package and distribute it. # (This is, of course, optional - there are innumerable ways to manage your # release process.) _RELEASE = False # Declare a Streamlit component. `declare_component` returns a function # that is used to create instances of the component. We're naming this # function "_component_func", with an underscore prefix, because we don't want # to expose it directly to users. Instead, we will create a custom wrapper # function, below, that will serve as our component's public API. # It's worth noting that this call to `declare_component` is the # *only thing* you need to do to create the binding between Streamlit and # your component frontend. Everything else we do in this file is simply a # best practice. if not _RELEASE: _component_func = components.declare_component( # We give the component a simple, descriptive name ("my_component" # does not fit this bill, so please choose something better for your # own component :) "st_autorefresh", # Pass `url` here to tell Streamlit that the component will be served # by the local dev server that you run via `npm run start`. # (This is useful while your component is in development.) url="http://localhost:3001", ) else: # When we're distributing a production version of the component, we'll # replace the `url` param with `path`, and point it to to the component's # build directory: parent_dir = os.path.dirname(os.path.abspath(__file__)) build_dir = os.path.join(parent_dir, "frontend/build") _component_func = components.declare_component("st_autorefresh", path=build_dir) # Create a wrapper function for the component. This is an optional # best practice - we could simply expose the component function returned by # `declare_component` and call it done. The wrapper allows us to customize # our component's API: we can pre-process its input args, post-process its # output value, and add a docstring for users. def st_autorefresh(interval=1000, *, limit=None, debounce=True, key=None): """Create an autorefresh instance to trigger a refresh of the application Parameters ---------- interval: int Amount of time in milliseconds to limit: int or None Amount of refreshes to allow. If none, it will refresh infinitely. While infinite refreshes sounds nice, it will continue to utilize computing resources. debounce: boolean Whether to delay the autorefresh when user interaction occurs. Defaults to True in order to avoid refreshes interfering with interaction effects on scripts. key: str or None An optional key that uniquely identifies this component. If this is None, and the component's arguments are changed, the component will be re-mounted in the Streamlit frontend and lose its current state. Returns ------- int Number of times the refresh has been triggered or max value of int """ count = _component_func(interval=interval, limit=limit, debounce=debounce, key=key) if count is None: return 0 return int(count) # Add some test code to play with the component while it's in development. # During development, we can run this just as we would any other Streamlit # app: `$ streamlit run my_component/__init__.py` if not _RELEASE: import streamlit as st secs = st.selectbox("Select a time reset", [1, 2, 3, 5], 1, lambda x: str(x) + " seconds") should_debounce = st.checkbox("Debounce?", True) st.button("Click me for a distraction") # We use the special "key" argument to assign a fixed identity to this # component instance. By default, when a component's arguments change, # it is considered a new instance and will be re-mounted on the frontend # and lose its current state. In this case, we want to vary the component's # "name" argument without having it get recreated. # Run the autorefresh about every 2000 milliseconds (2 seconds) and stop # after it's been refreshed 100 times. count = st_autorefresh(interval=secs * 1000, limit=100, debounce=should_debounce, key="fizzbuzzcounter") # The function returns a counter for number of refreshes. This allows the # ability to make special requests at different intervals based on the count if count == 0: st.write("Count is zero") elif count % 3 == 0 and count % 5 == 0: st.write("FizzBuzz") elif count % 3 == 0: st.write("Fizz") elif count % 5 == 0: st.write("Buzz") else: st.write(f"Count: {count}") ================================================ FILE: streamlit_autorefresh/frontend/.prettierrc ================================================ { "endOfLine": "lf", "semi": false, "trailingComma": "es5" } ================================================ FILE: streamlit_autorefresh/frontend/package.json ================================================ { "name": "streamlit_component_template", "version": "0.1.0", "private": true, "dependencies": { "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", "@types/jest": "^24.0.0", "@types/node": "^12.0.0", "react-scripts": "3.4.1", "streamlit-component-lib": "^1.1.3", "typescript": "^4.9.5" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }, "eslintConfig": { "extends": "react-app" }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] }, "homepage": "." } ================================================ FILE: streamlit_autorefresh/frontend/public/index.html ================================================