main ea4a9065828e cached
13 files
15.7 KB
4.1k tokens
7 symbols
1 requests
Download .txt
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
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Streamlit Component</title>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta name="description" content="Streamlit Component" />
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
  </body>
</html>


================================================
FILE: streamlit_autorefresh/frontend/src/index.ts
================================================
import { Streamlit, RenderData } from "streamlit-component-lib"

function counter(): () => number {
  let count = 0

  return function (): number {
    count += 1
    return count
  }
}

class ArgsCheck {
  limit: number | null = null
  interval: number | null = null
  key: string | null = null

  setLimit(limit: number | null) {
    const hasChanged = limit !== this.limit
    this.limit = limit

    return hasChanged
  }

  setInterval(intervalTime: number) {
    const hasChanged = intervalTime !== this.interval
    this.interval = intervalTime

    return hasChanged
  }

  setKey(key: string | null) {
    const hasChanged = key !== this.key
    this.key = key

    return hasChanged
  }
}

const refreshCounter = counter()
const argsChecker = new ArgsCheck()
let interval: number

/**
 * The component's render function. This will be called immediately after
 * the component is initially loaded, and then again every time the
 * component gets new data from Python.
 */
function onRender(event: Event): void {
  document.body.innerHTML = ""
  // Get the RenderData from the event
  const data = (event as CustomEvent<RenderData>).detail
  const refreshLimit = data.args.limit ? parseInt(data.args.limit, 10) : null
  const refreshInterval = parseInt(data.args.interval, 10)
  const shouldReset = argsChecker.setInterval(refreshInterval) || 
    argsChecker.setKey(data.args.key) || argsChecker.setLimit(refreshLimit)
  if (interval) {
    if (data.args.debounce || shouldReset) {
      clearInterval(interval)
    } else {
      // We already have an interval so clear the screen.
      return
    }
  }

  interval = window.setInterval(() => {
    const newCount = Math.min(refreshCounter(), Number.MAX_SAFE_INTEGER)
    // There is no refresh counter or we are within the limit
    if (!refreshLimit || newCount < refreshLimit) {
      Streamlit.setComponentValue(newCount)
    } else {
      // No need to keep pinging, so clear the interval
      clearInterval(interval)
    }
  }, refreshInterval)
}

// Attach our `onRender` handler to Streamlit's render event.
Streamlit.events.addEventListener(Streamlit.RENDER_EVENT, onRender)

// Tell Streamlit we're ready to start receiving data. We won't get our
// first RENDER_EVENT until we call this function.
Streamlit.setComponentReady()

// Finally, tell Streamlit to update our initial height. We omit the
// `height` parameter here to have it default to our scrollHeight.
Streamlit.setFrameHeight(0)


================================================
FILE: streamlit_autorefresh/frontend/src/react-app-env.d.ts
================================================
/// <reference types="react-scripts" />


================================================
FILE: streamlit_autorefresh/frontend/tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react"
  },
  "include": ["src"]
}
Download .txt
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
Download .txt
SYMBOL INDEX (7 symbols across 2 files)

FILE: streamlit_autorefresh/__init__.py
  function st_autorefresh (line 46) | def st_autorefresh(interval=1000, *, limit=None, debounce=True, key=None):

FILE: streamlit_autorefresh/frontend/src/index.ts
  function counter (line 3) | function counter(): () => number {
  class ArgsCheck (line 12) | class ArgsCheck {
    method setLimit (line 17) | setLimit(limit: number | null) {
    method setInterval (line 24) | setInterval(intervalTime: number) {
    method setKey (line 31) | setKey(key: string | null) {
  function onRender (line 48) | function onRender(event: Event): void {
Condensed preview — 13 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (18K chars).
[
  {
    "path": ".gitignore",
    "chars": 1630,
    "preview": "########################################################################\n# Python - https://github.com/github/gitignore/"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 345,
    "preview": "# Changelog\n\n## 1.0.1\n\n- Fix: Changes to interval, refresh limit, or key indicate a reset of the\n  interval.\n\n## 1.0.0\n\n"
  },
  {
    "path": "LICENSE",
    "chars": 1074,
    "preview": "Copyright (c) 2018 The Python Packaging Authority\n\nPermission is hereby granted, free of charge, to any person obtaining"
  },
  {
    "path": "MANIFEST.in",
    "chars": 57,
    "preview": "recursive-include streamlit_autorefresh/frontend/build *\n"
  },
  {
    "path": "README.md",
    "chars": 3144,
    "preview": "# Streamlit Autorefresh\n\nStreamlit component to force a refresh without tying up a script.\n## Overview\n\nStreamlit apps a"
  },
  {
    "path": "setup.py",
    "chars": 737,
    "preview": "import setuptools\n\nsetuptools.setup(\n    name=\"streamlit-autorefresh\",\n    version=\"1.0.1\",\n    author=\"Ken McGrady\",\n  "
  },
  {
    "path": "streamlit_autorefresh/__init__.py",
    "chars": 4802,
    "preview": "import os\nimport streamlit.components.v1 as components\n\n# Create a _RELEASE constant. We'll set this to False while we'r"
  },
  {
    "path": "streamlit_autorefresh/frontend/.prettierrc",
    "chars": 67,
    "preview": "{\n  \"endOfLine\": \"lf\",\n  \"semi\": false,\n  \"trailingComma\": \"es5\"\n}\n"
  },
  {
    "path": "streamlit_autorefresh/frontend/package.json",
    "chars": 858,
    "preview": "{\n  \"name\": \"streamlit_component_template\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"@testing-l"
  },
  {
    "path": "streamlit_autorefresh/frontend/public/index.html",
    "chars": 406,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <title>Streamlit Component</title>\n    <meta charset=\"UTF-8\" />\n    <meta "
  },
  {
    "path": "streamlit_autorefresh/frontend/src/index.ts",
    "chars": 2466,
    "preview": "import { Streamlit, RenderData } from \"streamlit-component-lib\"\n\nfunction counter(): () => number {\n  let count = 0\n\n  r"
  },
  {
    "path": "streamlit_autorefresh/frontend/src/react-app-env.d.ts",
    "chars": 40,
    "preview": "/// <reference types=\"react-scripts\" />\n"
  },
  {
    "path": "streamlit_autorefresh/frontend/tsconfig.json",
    "chars": 459,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"es5\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"sk"
  }
]

About this extraction

This page contains the full source code of the kmcgrady/streamlit-autorefresh GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 13 files (15.7 KB), approximately 4.1k tokens, and a symbol index with 7 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!