stui-terminal 0.1.0rc2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. stui_terminal-0.1.0rc2/.github/workflows/ci.yml +30 -0
  2. stui_terminal-0.1.0rc2/.github/workflows/publish.yml +107 -0
  3. stui_terminal-0.1.0rc2/AGENTS.md +11 -0
  4. stui_terminal-0.1.0rc2/CHANGELOG.md +29 -0
  5. stui_terminal-0.1.0rc2/CONTRIBUTING.md +44 -0
  6. stui_terminal-0.1.0rc2/LICENSE +21 -0
  7. stui_terminal-0.1.0rc2/MANIFEST.in +13 -0
  8. stui_terminal-0.1.0rc2/PKG-INFO +258 -0
  9. stui_terminal-0.1.0rc2/README.md +236 -0
  10. stui_terminal-0.1.0rc2/RELEASE_NOTES_v0.1.0rc1.md +83 -0
  11. stui_terminal-0.1.0rc2/RELEASE_NOTES_v0.1.0rc2.md +92 -0
  12. stui_terminal-0.1.0rc2/assets/model_demo.svg +178 -0
  13. stui_terminal-0.1.0rc2/docs/announcement-drafts.md +92 -0
  14. stui_terminal-0.1.0rc2/docs/publishing.md +139 -0
  15. stui_terminal-0.1.0rc2/examples/basic.py +14 -0
  16. stui_terminal-0.1.0rc2/examples/counter.py +20 -0
  17. stui_terminal-0.1.0rc2/examples/model_demo.py +43 -0
  18. stui_terminal-0.1.0rc2/pyproject.toml +50 -0
  19. stui_terminal-0.1.0rc2/setup.cfg +4 -0
  20. stui_terminal-0.1.0rc2/src/stui/__init__.py +40 -0
  21. stui_terminal-0.1.0rc2/src/stui/__main__.py +4 -0
  22. stui_terminal-0.1.0rc2/src/stui/api.py +187 -0
  23. stui_terminal-0.1.0rc2/src/stui/app.py +343 -0
  24. stui_terminal-0.1.0rc2/src/stui/cli.py +52 -0
  25. stui_terminal-0.1.0rc2/src/stui/elements.py +103 -0
  26. stui_terminal-0.1.0rc2/src/stui/runtime.py +293 -0
  27. stui_terminal-0.1.0rc2/src/stui/session_state.py +57 -0
  28. stui_terminal-0.1.0rc2/src/stui/widgets/__init__.py +3 -0
  29. stui_terminal-0.1.0rc2/src/stui/widgets/slider.py +132 -0
  30. stui_terminal-0.1.0rc2/src/stui_terminal.egg-info/PKG-INFO +258 -0
  31. stui_terminal-0.1.0rc2/src/stui_terminal.egg-info/SOURCES.txt +46 -0
  32. stui_terminal-0.1.0rc2/src/stui_terminal.egg-info/dependency_links.txt +1 -0
  33. stui_terminal-0.1.0rc2/src/stui_terminal.egg-info/entry_points.txt +2 -0
  34. stui_terminal-0.1.0rc2/src/stui_terminal.egg-info/requires.txt +9 -0
  35. stui_terminal-0.1.0rc2/src/stui_terminal.egg-info/top_level.txt +1 -0
  36. stui_terminal-0.1.0rc2/tests/test_app_smoke.py +74 -0
  37. stui_terminal-0.1.0rc2/tests/test_button.py +48 -0
  38. stui_terminal-0.1.0rc2/tests/test_callbacks.py +163 -0
  39. stui_terminal-0.1.0rc2/tests/test_cli.py +61 -0
  40. stui_terminal-0.1.0rc2/tests/test_keys.py +62 -0
  41. stui_terminal-0.1.0rc2/tests/test_phase2_elements.py +68 -0
  42. stui_terminal-0.1.0rc2/tests/test_phase2_widgets.py +122 -0
  43. stui_terminal-0.1.0rc2/tests/test_runtime.py +89 -0
  44. stui_terminal-0.1.0rc2/tests/test_runtime_hardening.py +218 -0
  45. stui_terminal-0.1.0rc2/tests/test_session_state.py +29 -0
  46. stui_terminal-0.1.0rc2/tests/test_slider.py +27 -0
  47. stui_terminal-0.1.0rc2/tests/test_static_policy.py +87 -0
  48. stui_terminal-0.1.0rc2/tests/test_widget_edge_cases.py +127 -0
@@ -0,0 +1,30 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+ name: Python ${{ matrix.python-version }}
10
+ runs-on: ubuntu-latest
11
+
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ python-version: ["3.11", "3.12"]
16
+
17
+ steps:
18
+ - name: Check out repository
19
+ uses: actions/checkout@v4
20
+
21
+ - name: Set up Python
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+
26
+ - name: Install package
27
+ run: python -m pip install -e ".[dev]"
28
+
29
+ - name: Run tests
30
+ run: python -m pytest
@@ -0,0 +1,107 @@
1
+ name: Publish
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+ inputs:
9
+ publish_to_testpypi:
10
+ description: "Publish to TestPyPI after the testpypi environment is configured"
11
+ required: true
12
+ type: boolean
13
+ default: false
14
+ publish_to_pypi:
15
+ description: "Publish to real PyPI after the pypi environment is configured"
16
+ required: true
17
+ type: boolean
18
+ default: false
19
+
20
+ permissions:
21
+ contents: read
22
+
23
+ jobs:
24
+ build:
25
+ name: Build and check distributions
26
+ runs-on: ubuntu-latest
27
+
28
+ steps:
29
+ - name: Check out repository
30
+ uses: actions/checkout@v4
31
+
32
+ - name: Set up Python
33
+ uses: actions/setup-python@v5
34
+ with:
35
+ python-version: "3.11"
36
+
37
+ - name: Install build tools
38
+ run: python -m pip install --upgrade build twine
39
+
40
+ - name: Build sdist and wheel
41
+ run: python -m build
42
+
43
+ - name: Check distributions
44
+ run: python -m twine check dist/*
45
+
46
+ - name: Upload distributions
47
+ uses: actions/upload-artifact@v4
48
+ with:
49
+ name: python-distributions
50
+ path: dist/*
51
+ if-no-files-found: error
52
+
53
+ publish-testpypi:
54
+ name: Publish to TestPyPI
55
+ needs: build
56
+ if: >-
57
+ ${{
58
+ github.event_name == 'workflow_dispatch' &&
59
+ inputs.publish_to_testpypi &&
60
+ startsWith(github.ref, 'refs/tags/v')
61
+ }}
62
+ runs-on: ubuntu-latest
63
+ environment: testpypi
64
+ permissions:
65
+ contents: read
66
+ id-token: write
67
+
68
+ steps:
69
+ - name: Download distributions
70
+ uses: actions/download-artifact@v4
71
+ with:
72
+ name: python-distributions
73
+ path: dist/
74
+
75
+ - name: Publish distributions to TestPyPI
76
+ uses: pypa/gh-action-pypi-publish@release/v1
77
+ with:
78
+ repository-url: https://test.pypi.org/legacy/
79
+ packages-dir: dist/
80
+ skip-existing: true
81
+
82
+ publish-pypi:
83
+ name: Publish to PyPI
84
+ needs: build
85
+ if: >-
86
+ ${{
87
+ github.event_name == 'workflow_dispatch' &&
88
+ inputs.publish_to_pypi &&
89
+ startsWith(github.ref, 'refs/tags/v')
90
+ }}
91
+ runs-on: ubuntu-latest
92
+ environment: pypi
93
+ permissions:
94
+ contents: read
95
+ id-token: write
96
+
97
+ steps:
98
+ - name: Download distributions
99
+ uses: actions/download-artifact@v4
100
+ with:
101
+ name: python-distributions
102
+ path: dist/
103
+
104
+ - name: Publish distributions to PyPI
105
+ uses: pypa/gh-action-pypi-publish@release/v1
106
+ with:
107
+ packages-dir: dist/
@@ -0,0 +1,11 @@
1
+ # stui Agent Notes
2
+
3
+ - Always run `python3.11 -m pytest` after code changes.
4
+ - Keep the public API small and Streamlit-inspired, not Streamlit-compatible.
5
+ - Do not add browser, server, websocket, or port-forwarding code.
6
+ - Do not depend on Streamlit at runtime.
7
+ - Do not copy GPL slider code or depend on packages such as `textual-slider`.
8
+ - Prefer Textual first-party widgets where they exist.
9
+ - Keep the MVP implementation readable and direct before adding abstractions.
10
+ - Keep public docs honest: `stui` is not official Streamlit, not affiliated with Streamlit, and not a Streamlit compatibility layer.
11
+ - When working alongside other agents, do not revert edits you did not make.
@@ -0,0 +1,29 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ This project is currently pre-1.0, so APIs may change while the MVP is being
6
+ shaped.
7
+
8
+ ## 0.1.0rc2 - 2026-05-09
9
+
10
+ ### Changed
11
+
12
+ - Updated install documentation for the future PyPI distribution name,
13
+ `stui-terminal`.
14
+ - Clarified that the distribution name is `stui-terminal`, while the import
15
+ package and CLI remain `stui`.
16
+ - Preserved editable local development install instructions for contributors.
17
+
18
+ ## 0.1.0rc1 - 2026-05-08
19
+
20
+ ### Added
21
+
22
+ - Initial terminal-native `stui` MVP with top-to-bottom script reruns.
23
+ - Public APIs for text output, alerts, button, slider, text input, checkbox,
24
+ and session state.
25
+ - Textual terminal renderer with keyboard-first widget interactions.
26
+ - CLI entrypoints for `stui run ...` and `python -m stui run ...`.
27
+ - Example apps for the basic demo, counter, and model-parameter playground.
28
+ - Test suite, static policy checks, CI workflow, contributor guide, and release
29
+ candidate documentation.
@@ -0,0 +1,44 @@
1
+ # Contributing
2
+
3
+ Thanks for helping with `stui`. The project is still an MVP, so the best
4
+ contributions keep the surface area small, readable, and easy to test.
5
+
6
+ ## Local Setup
7
+
8
+ Use Python 3.11 or newer:
9
+
10
+ ```bash
11
+ python3.11 -m pip install -e ".[dev]"
12
+ python3.11 -m pytest
13
+ ```
14
+
15
+ ## Development Guidelines
16
+
17
+ - Keep the public API small and Streamlit-inspired, not Streamlit-compatible.
18
+ - Do not add browser, server, websocket, or port-forwarding code.
19
+ - Do not depend on Streamlit at runtime.
20
+ - Prefer Textual first-party widgets where they exist.
21
+ - Do not copy GPL slider code or depend on packages such as `textual-slider`.
22
+ - Keep MVP code direct before adding abstractions.
23
+ - Keep examples local and deterministic; avoid network calls unless the project
24
+ explicitly grows that capability later.
25
+
26
+ ## Tests
27
+
28
+ Run the full test suite after code changes:
29
+
30
+ ```bash
31
+ python3.11 -m pytest
32
+ ```
33
+
34
+ Documentation-only edits should still be checked for accuracy against the
35
+ current API and examples.
36
+
37
+ ## Public Claims
38
+
39
+ Please keep README and release notes honest:
40
+
41
+ - Say `stui` is inspired by Streamlit, not compatible with it.
42
+ - Say `stui` is not official Streamlit and is not affiliated with Streamlit.
43
+ - Avoid implying production hardening, broad widget coverage, browser support,
44
+ or long-term API stability before those things exist.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 MarMar Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,13 @@
1
+ include README.md
2
+ include LICENSE
3
+ include CHANGELOG.md
4
+ include RELEASE_NOTES_v0.1.0rc1.md
5
+ include RELEASE_NOTES_v0.1.0rc2.md
6
+ include CONTRIBUTING.md
7
+ include AGENTS.md
8
+ include pyproject.toml
9
+ recursive-include assets *.svg
10
+ recursive-include docs *.md
11
+ recursive-include examples *.py
12
+ recursive-include tests *.py
13
+ recursive-include .github/workflows *.yml
@@ -0,0 +1,258 @@
1
+ Metadata-Version: 2.4
2
+ Name: stui-terminal
3
+ Version: 0.1.0rc2
4
+ Summary: A tiny Streamlit-inspired terminal UI experiment.
5
+ Author: MarMar Labs
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/marmar9615-cloud/stui-terminal
8
+ Project-URL: Repository, https://github.com/marmar9615-cloud/stui-terminal
9
+ Project-URL: Issues, https://github.com/marmar9615-cloud/stui-terminal/issues
10
+ Requires-Python: >=3.11
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: rich>=13.7
14
+ Requires-Dist: textual>=0.89
15
+ Requires-Dist: typer>=0.12
16
+ Provides-Extra: dev
17
+ Requires-Dist: build>=1.2; extra == "dev"
18
+ Requires-Dist: pytest>=8.0; extra == "dev"
19
+ Requires-Dist: ruff>=0.8; extra == "dev"
20
+ Requires-Dist: twine>=5.1; extra == "dev"
21
+ Dynamic: license-file
22
+
23
+ # stui
24
+
25
+ [![CI](https://github.com/marmar9615-cloud/stui-terminal/actions/workflows/ci.yml/badge.svg)](https://github.com/marmar9615-cloud/stui-terminal/actions/workflows/ci.yml)
26
+
27
+ `stui` is a tiny Streamlit-inspired framework for building terminal-native
28
+ Python apps. Write a short script, run it in your terminal, and get a Textual UI
29
+ with stateful controls.
30
+
31
+ It is built for local tools, demos, data scripts, model debug panels, SSH
32
+ sessions, and headless environments where opening a browser, binding a port, or
33
+ running a dashboard server is unnecessary ceremony. The public API is
34
+ deliberately small and readable.
35
+
36
+ `stui` is not official Streamlit, is not affiliated with Streamlit, and is not a
37
+ Streamlit compatibility layer. The API intentionally feels familiar, but this
38
+ project keeps its own smaller surface area.
39
+
40
+ ## Preview
41
+
42
+ ![stui model demo terminal screenshot](assets/model_demo.svg)
43
+
44
+ ```text
45
+ ┌─ stui ───────────────────────────────────────────┐
46
+ │ stui demo │
47
+ │ │
48
+ │ x │
49
+ │ [██░░░░░░░░░░░░] 10 │
50
+ │ │
51
+ │ [ Increment ] │
52
+ │ │
53
+ │ x = 10 │
54
+ │ count = 0 │
55
+ │ │
56
+ │ q Quit r Rerun tab Focus next │
57
+ └──────────────────────────────────────────────────┘
58
+ ```
59
+
60
+ ## Install
61
+
62
+ Use Python 3.11 or newer.
63
+
64
+ Install the PyPI distribution named `stui-terminal`:
65
+
66
+ ```bash
67
+ python3.11 -m pip install stui-terminal
68
+ ```
69
+
70
+ The PyPI distribution name is `stui-terminal`, but the import package and CLI
71
+ are both `stui`:
72
+
73
+ ```python
74
+ import stui as st
75
+ ```
76
+
77
+ For local development from a checkout, use an editable install with the dev
78
+ extra:
79
+
80
+ ```bash
81
+ python3.11 -m venv .venv
82
+ . .venv/bin/activate
83
+ python3.11 -m pip install -e ".[dev]"
84
+ ```
85
+
86
+ For runtime-only local use, install without the dev extra:
87
+
88
+ ```bash
89
+ python3.11 -m pip install -e .
90
+ ```
91
+
92
+ ## Quickstart
93
+
94
+ Install from PyPI, then run your app:
95
+
96
+ ```bash
97
+ python3.11 -m pip install stui-terminal
98
+ stui run app.py
99
+ ```
100
+
101
+ Or set up the project from source and run the basic example:
102
+
103
+ ```bash
104
+ git clone https://github.com/marmar9615-cloud/stui-terminal.git
105
+ cd stui-terminal
106
+ python3.11 -m venv .venv
107
+ . .venv/bin/activate
108
+ python3.11 -m pip install -e ".[dev]"
109
+ stui run examples/basic.py
110
+ ```
111
+
112
+ You can also run through the module entry point:
113
+
114
+ ```bash
115
+ python3.11 -m stui run examples/counter.py
116
+ ```
117
+
118
+ Scripts use the public `stui` API:
119
+
120
+ ```python
121
+ import stui as st
122
+
123
+ st.title("stui demo")
124
+
125
+ if "count" not in st.session_state:
126
+ st.session_state.count = 0
127
+
128
+ value = st.slider("value", 0, 100, 25)
129
+
130
+ if st.button("Increment"):
131
+ st.session_state.count += 1
132
+
133
+ st.write("value =", value)
134
+ st.write("count =", st.session_state.count)
135
+ ```
136
+
137
+ More examples:
138
+
139
+ ```bash
140
+ stui run examples/counter.py
141
+ stui run examples/model_demo.py
142
+ ```
143
+
144
+ ## Why terminal-native?
145
+
146
+ Some useful Python apps do not need a browser runtime. `stui` keeps the
147
+ interface inside the terminal so it can fit naturally into:
148
+
149
+ - SSH sessions, remote machines, and headless boxes.
150
+ - Internal tools where opening ports or managing local server URLs is friction.
151
+ - Offline or locked-down environments where browser access is limited.
152
+ - Model, data, and DevOps workflows that already start from a shell.
153
+
154
+ That also keeps the boundary simple: `stui` does not start a web server, use
155
+ websockets, require port-forwarding, or depend on Streamlit at runtime.
156
+
157
+ ## Commands
158
+
159
+ ```bash
160
+ # Install the project for local development.
161
+ python3.11 -m venv .venv
162
+ . .venv/bin/activate
163
+ python3.11 -m pip install -e ".[dev]"
164
+
165
+ # Run the smoke-size example app.
166
+ stui run examples/basic.py
167
+
168
+ # Run the stateful counter example.
169
+ stui run examples/counter.py
170
+
171
+ # Run the deterministic model-parameter demo.
172
+ stui run examples/model_demo.py
173
+
174
+ # Run the test suite.
175
+ python3.11 -m pytest
176
+ ```
177
+
178
+ ## Keyboard Shortcuts
179
+
180
+ - `q`: quit the app
181
+ - `r`: rerun the script
182
+ - `tab`: focus the next widget
183
+ - `enter`: press the focused button
184
+ - `left` or `h`: decrease the focused slider
185
+ - `right` or `l`: increase the focused slider
186
+ - `home`: set the focused slider to its minimum value
187
+ - `end`: set the focused slider to its maximum value
188
+
189
+ ## Current API
190
+
191
+ The current public API is intentionally small:
192
+
193
+ - `st.title(body, *, key=None)`: render a title.
194
+ - `st.header(body, *, key=None)`: render a section header.
195
+ - `st.text(body)`: render plain text.
196
+ - `st.markdown(body)`: render Markdown-flavored text.
197
+ - `st.divider()`: render a horizontal divider.
198
+ - `st.info(body)`, `st.success(body)`, `st.warning(body)`, `st.error(body)`: render status messages.
199
+ - `st.write(*args)`: render simple text output.
200
+ - `st.button(label, key=None, help=None, disabled=False, on_click=None, args=None, kwargs=None)`: render a button and return `True` for the run where it was pressed.
201
+ - `st.slider(label, min_value=0, max_value=100, value=None, step=1, *, key=None, help=None, disabled=False, on_change=None, args=None, kwargs=None)`: render a numeric slider and return its current value.
202
+ - `st.text_input(label, value="", *, key=None, placeholder=None, disabled=False, on_change=None, args=None, kwargs=None)`: render a single-line text input and return its current value.
203
+ - `st.checkbox(label, value=False, *, key=None, disabled=False, on_change=None, args=None, kwargs=None)`: render a checkbox and return its current value.
204
+ - `st.session_state`: persist values across reruns with dict-style or attribute-style access.
205
+ - `st.rerun()`: request a script rerun.
206
+
207
+ Import the API as:
208
+
209
+ ```python
210
+ import stui as st
211
+ ```
212
+
213
+ ## Examples
214
+
215
+ ### Counter
216
+
217
+ `examples/counter.py` shows a minimal stateful app with increment, decrement, and
218
+ reset controls.
219
+
220
+ ```bash
221
+ stui run examples/counter.py
222
+ ```
223
+
224
+ ### Model Demo
225
+
226
+ `examples/model_demo.py` shows a small model-parameter playground using text
227
+ input, checkbox, sliders, status messages, session state, and deterministic
228
+ scoring. It is intentionally local and fake: there are no network calls or model
229
+ dependencies.
230
+
231
+ ```bash
232
+ stui run examples/model_demo.py
233
+ ```
234
+
235
+ ## Limitations
236
+
237
+ - No browser, web server, websocket, or port-forwarding runtime.
238
+ - No Streamlit dependency and no promise of Streamlit compatibility.
239
+ - No charts, tables, dataframes, forms, columns, sidebars, or file upload yet.
240
+ - Slider input supports numeric values only.
241
+ - Layout is currently linear and script-driven.
242
+ - The app reruns the script as interactions change state, so examples should keep top-level work lightweight.
243
+ - Error handling is still early and meant for development feedback.
244
+ - The package is an MVP and has not stabilized a long-term compatibility policy.
245
+
246
+ ## Roadmap
247
+
248
+ - Add small text output helpers such as `caption`.
249
+ - Add common controls such as `selectbox`, `radio`, and number inputs.
250
+ - Add simple display primitives for tables and progress.
251
+ - Improve focus behavior, accessibility hints, and keyboard discoverability.
252
+ - Expand example coverage for data scripts, model controls, DevOps panels, and internal tools.
253
+ - Keep the implementation clean-room, readable, and based on Textual first-party widgets where possible.
254
+
255
+ ## Contributing
256
+
257
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the local development workflow and
258
+ project boundaries.