Metadata-Version: 2.4
Name: streamtree
Version: 0.11.0
Summary: StreamTree: declarative, typed composition for Streamlit.
Author: StreamTree contributors
License-Expression: MIT
Project-URL: Homepage, https://github.com/streamtree-dev/streamtree
Project-URL: Documentation, https://streamtree.readthedocs.io/en/latest/
Project-URL: Repository, https://github.com/streamtree-dev/streamtree
Project-URL: Issues, https://github.com/streamtree-dev/streamtree/issues
Project-URL: Changelog, https://github.com/streamtree-dev/streamtree/blob/main/CHANGELOG.md
Keywords: streamlit,ui,components,declarative
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic>=2.4.0
Requires-Dist: streamlit>=1.33.0
Requires-Dist: typing-extensions>=4.8.0
Provides-Extra: tables
Requires-Dist: streamlit-aggrid>=0.3.0; extra == "tables"
Requires-Dist: pandas>=2.0.0; extra == "tables"
Provides-Extra: charts
Requires-Dist: plotly>=5.18.0; extra == "charts"
Requires-Dist: altair>=5.0.0; extra == "charts"
Requires-Dist: streamlit-echarts>=0.4.0; extra == "charts"
Provides-Extra: ui
Requires-Dist: streamlit-extras>=0.4.3; extra == "ui"
Provides-Extra: auth
Requires-Dist: streamlit-authenticator>=0.3.3; extra == "auth"
Provides-Extra: asyncio
Provides-Extra: async
Provides-Extra: cli
Requires-Dist: typer>=0.12.3; extra == "cli"
Provides-Extra: pages
Provides-Extra: runner
Provides-Extra: all
Requires-Dist: streamlit-aggrid>=0.3.0; extra == "all"
Requires-Dist: pandas>=2.0.0; extra == "all"
Requires-Dist: plotly>=5.18.0; extra == "all"
Requires-Dist: altair>=5.0.0; extra == "all"
Requires-Dist: streamlit-echarts>=0.4.0; extra == "all"
Requires-Dist: streamlit-extras>=0.4.3; extra == "all"
Requires-Dist: streamlit-authenticator>=0.3.3; extra == "all"
Requires-Dist: typer>=0.12.3; extra == "all"
Provides-Extra: dev
Requires-Dist: mkdocs>=1.6.0; extra == "dev"
Requires-Dist: mkdocs-material>=9.5.0; extra == "dev"
Requires-Dist: mkdocstrings[python]>=0.26.0; extra == "dev"
Requires-Dist: mkdocs-autorefs>=1.0.0; extra == "dev"
Requires-Dist: pytest>=7.4.0; extra == "dev"
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
Requires-Dist: pytest-xdist>=3.5.0; extra == "dev"
Requires-Dist: mypy>=1.8.0; extra == "dev"
Requires-Dist: ruff>=0.2.0; extra == "dev"
Requires-Dist: ty>=0.0.30; extra == "dev"
Requires-Dist: typer>=0.12.3; extra == "dev"
Requires-Dist: streamlit-authenticator>=0.3.3; extra == "dev"
Requires-Dist: streamlit-extras>=0.4.3; extra == "dev"
Requires-Dist: streamlit-aggrid>=0.3.0; extra == "dev"
Requires-Dist: pandas>=2.0.0; extra == "dev"
Requires-Dist: plotly>=5.18.0; extra == "dev"
Requires-Dist: altair>=5.0.0; extra == "dev"
Requires-Dist: streamlit-echarts>=0.4.0; extra == "dev"
Dynamic: license-file

# StreamTree

[![PyPI version](https://img.shields.io/pypi/v/streamtree)](https://pypi.org/project/streamtree/)
[![Python versions](https://img.shields.io/pypi/pyversions/streamtree)](https://pypi.org/project/streamtree/)
[![Docs](https://img.shields.io/readthedocs/streamtree/latest?style=flat&logo=readthedocs&label=docs)](https://streamtree.readthedocs.io/en/latest/)
[![License](https://img.shields.io/pypi/l/streamtree)](https://github.com/streamtree-dev/streamtree/blob/main/LICENSE)
[![CI](https://github.com/eddiethedean/streamtree/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/eddiethedean/streamtree/actions/workflows/ci.yml?query=branch%3Amain)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://docs.astral.sh/ruff/)

**Declarative, typed composition for [Streamlit](https://streamlit.io/).** Build UI as Python data (`@component` functions return element trees); the renderer maps them to `st.*` on each rerun. No separate frontend build.

**Documentation (primary):** **[streamtree.readthedocs.io](https://streamtree.readthedocs.io/en/latest/)** — getting started, recipes, full example source, guides, API reference, and changelog.

## At a glance

| Without StreamTree | With StreamTree |
|--------------------|-----------------|
| Long imperative scripts | `@component` + layouts/widgets as a **tree** |
| Ad hoc `session_state` keys | `state()` scoped to the **render path** |
| Hard to test structure | `streamtree.testing.render_to_tree()` and **`summarize_tree_kinds()`** |

**Includes:** layouts (`Page`, `VStack`, `Form`, `Routes`, …), optional **`[tables]`** / **`[charts]`** / **`[ui]`** / **`[auth]`**, **`streamtree.asyncio`** task helpers, multipage discovery in **`streamtree.helpers.pages`**, optional **`[cli]`** (`streamtree run`, `doctor`, `init`, `tree`, …). Details, version notes, and extras matrix live in the docs.

## Requirements

Python **3.10+**, **Streamlit ≥ 1.33**, **Pydantic v2** (see `pyproject.toml`).

## Install

```bash
pip install streamtree
pip install "streamtree[cli]"    # Typer + streamtree run / doctor / init / tree
# Optional: [tables] [charts] [ui] [auth] — see Dependency strategy on RTD
```

From a clone (contributors):

```bash
git clone https://github.com/streamtree-dev/streamtree.git
cd streamtree
uv sync --extra dev
```

## Quick start

```python
from streamtree import component, render
from streamtree.elements import Button, Card, Page, Text
from streamtree.state import state


@component
def Counter():
    count = state(0)
    return Card(
        Text(f"Count: {count()}"),
        Button("Increment", on_click=lambda: count.increment(1)),
        Button("Reset", on_click=lambda: count.set(0)),
    )


if __name__ == "__main__":
    render(Page(Counter()))
```

```bash
streamlit run examples/counter.py
# with [cli]:  streamtree run examples/counter.py
```

More patterns (interop with raw `st.*`, `App` / theme, async, routing, multipage, CRUD) are in the **[recipes](https://streamtree.readthedocs.io/en/latest/recipes/)** and **[examples](https://streamtree.readthedocs.io/en/latest/EXAMPLES/)** sections on Read the Docs.

## Documentation map

| Start here | Read the Docs |
|------------|----------------|
| Install & mental model | [Getting started](https://streamtree.readthedocs.io/en/latest/getting-started/) |
| How-to cookbook | [Recipes](https://streamtree.readthedocs.io/en/latest/recipes/) |
| Every `examples/*.py` inlined | [Examples (full source)](https://streamtree.readthedocs.io/en/latest/EXAMPLES/) |
| Testing & `AppTest` | [Testing & debugging](https://streamtree.readthedocs.io/en/latest/TESTING_AND_DEBUG/) |
| Plan, roadmap, deps, performance, phases | [Guides](https://streamtree.readthedocs.io/en/latest/PLAN/) (use the site nav: *Design & roadmap* / *Operations*) |
| Release history | [Changelog](https://streamtree.readthedocs.io/en/latest/CHANGELOG/) |

Design files remain in `docs/` in the repo; the site above is the supported reading path for **stable** releases.

## Contributing

```bash
uv sync --extra dev
uv run ruff format --check .
uv run ruff check src tests
uv run ty check src
uv run pytest
uv run python -m mkdocs build --strict
uv build
```

Same checks with **pip**: `pip install -e ".[dev]"`, then the same `ruff`, `ty`, `pytest`, `mkdocs build --strict`, and `uv build` (or `python -m build`). **Coverage** is enforced at 100% on `src/streamtree` (see `pyproject.toml`). GitHub Actions live under [`.github/workflows/`](https://github.com/eddiethedean/streamtree/tree/main/.github/workflows) (**`ci.yml`**, **`release.yml`**, and **`reusable-*.yml`**); you can re-run **`CI`** manually via **Actions → CI → Run workflow**.

## Releases

Before tagging **`v*.*.*`**: align **`pyproject.toml`** version, **`CHANGELOG.md`**, and package metadata (see **`tests/test_package_meta.py`**). CI and the [release workflow](https://github.com/eddiethedean/streamtree/blob/main/.github/workflows/release.yml) run lint, typecheck, tests, MkDocs, and **`uv build`**; publishing needs a valid **PyPI** token or trusted publishing setup (details in workflow comments and PyPI docs).

## Limits (Streamlit)

No stable cross-rerun APIs for arbitrary widget focus or DOM control. Prefer **`session_state`**, **query params** (`streamtree.routing`, …), **`st.rerun`**, and **`key=`** discipline. **`Portal` / `PortalMount`** move subtrees within a script; they do not replace Streamlit’s execution model. See **[Portals & prefetch](https://streamtree.readthedocs.io/en/latest/PHASE2_PORTALS_AND_PREFETCH/)** on RTD.

## License

MIT — [LICENSE](https://github.com/streamtree-dev/streamtree/blob/main/LICENSE).
