nextpytk 0.4.7__tar.gz → 0.4.9__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.
- {nextpytk-0.4.7 → nextpytk-0.4.9}/PKG-INFO +27 -33
- {nextpytk-0.4.7 → nextpytk-0.4.9}/README.md +26 -32
- nextpytk-0.4.9/ROADMAP.md +61 -0
- {nextpytk-0.4.7 → nextpytk-0.4.9}/pyproject.toml +1 -1
- {nextpytk-0.4.7 → nextpytk-0.4.9}/src/nextpytk/app.py +245 -27
- {nextpytk-0.4.7 → nextpytk-0.4.9}/src/nextpytk/theme.py +56 -26
- {nextpytk-0.4.7 → nextpytk-0.4.9}/src/nextpytk/tokens.py +1 -1
- nextpytk-0.4.7/ROADMAP.md +0 -426
- {nextpytk-0.4.7 → nextpytk-0.4.9}/.gitignore +0 -0
- {nextpytk-0.4.7 → nextpytk-0.4.9}/LICENSE +0 -0
- {nextpytk-0.4.7 → nextpytk-0.4.9}/src/nextpytk/__init__.py +0 -0
- {nextpytk-0.4.7 → nextpytk-0.4.9}/src/nextpytk/layout.py +0 -0
- {nextpytk-0.4.7 → nextpytk-0.4.9}/src/nextpytk/types.py +0 -0
- {nextpytk-0.4.7 → nextpytk-0.4.9}/src/nextpytk/widgets.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nextpytk
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.9
|
|
4
4
|
Summary: Accessible, declarative Tkinter applications from ordinary Python functions.
|
|
5
5
|
Project-URL: Homepage, https://github.com/nishimotz/nextpytk
|
|
6
6
|
Project-URL: Repository, https://github.com/nishimotz/nextpytk
|
|
@@ -35,7 +35,7 @@ Uses ttk widgets where available.
|
|
|
35
35
|
|
|
36
36
|
## Quick Start
|
|
37
37
|
|
|
38
|
-
Start with an app where a button updates
|
|
38
|
+
Start with an app where a button updates its own label.
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
41
|
pip install nextpytk
|
|
@@ -46,59 +46,48 @@ from nextpytk import TkApp
|
|
|
46
46
|
|
|
47
47
|
app = TkApp(title="Hello")
|
|
48
48
|
|
|
49
|
-
@app.
|
|
50
|
-
def
|
|
51
|
-
return "
|
|
49
|
+
@app.button("hello")
|
|
50
|
+
def on_hello():
|
|
51
|
+
return "world"
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
def on_greet():
|
|
55
|
-
return {"msg": "Button clicked!"}
|
|
56
|
-
|
|
57
|
-
app.run(layout=["msg", "greet"])
|
|
53
|
+
app.run()
|
|
58
54
|
```
|
|
59
55
|
|
|
56
|
+
That's it: a window appears with a button labeled `hello`. Press it and the
|
|
57
|
+
label becomes `world`.
|
|
58
|
+
|
|
60
59
|
---
|
|
61
60
|
|
|
62
61
|
## How it works
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
This example registers two widgets: `msg` and `greet`.
|
|
67
|
-
|
|
68
|
-
```python
|
|
69
|
-
@app.status("msg")
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
`msg` is a status area that shows a message.
|
|
63
|
+
The minimal example packs a lot in. Let's unpack it.
|
|
73
64
|
|
|
74
65
|
```python
|
|
75
|
-
@app.button("
|
|
66
|
+
@app.button("hello")
|
|
76
67
|
```
|
|
77
68
|
|
|
78
|
-
`
|
|
79
|
-
|
|
80
|
-
Finally, name the display order:
|
|
69
|
+
Registers a button named `hello`. When `label=` is omitted, the widget name is
|
|
70
|
+
used as the button text.
|
|
81
71
|
|
|
82
72
|
```python
|
|
83
|
-
|
|
73
|
+
def on_hello():
|
|
74
|
+
return "world"
|
|
84
75
|
```
|
|
85
76
|
|
|
86
|
-
|
|
77
|
+
The callback runs when the button is pressed. Returning a plain string updates
|
|
78
|
+
that button's own label — it's sugar for `{"hello": "world"}`.
|
|
87
79
|
|
|
88
80
|
```python
|
|
89
|
-
|
|
81
|
+
app.run()
|
|
90
82
|
```
|
|
91
83
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
Because `msg` is the name of the registered status area, its text becomes
|
|
95
|
-
"Button clicked!".
|
|
84
|
+
With no `layout=`, registered widgets are arranged automatically into a single
|
|
85
|
+
column, so you don't have to declare one for a simple app.
|
|
96
86
|
|
|
97
|
-
|
|
87
|
+
The basic flow is:
|
|
98
88
|
|
|
99
89
|
* Register widgets by name
|
|
100
|
-
*
|
|
101
|
-
* Return a `dict` from a callback
|
|
90
|
+
* Return a `dict` (or a plain string) from a callback
|
|
102
91
|
* `state` updates and matching widgets refresh
|
|
103
92
|
|
|
104
93
|
---
|
|
@@ -858,6 +847,7 @@ uv run python examples/disk_usage_flat_async.py # ncdu-style viewer (async
|
|
|
858
847
|
uv run python examples/paired_demo.py # side-by-side paired layout with y-scroll sync
|
|
859
848
|
uv run python examples/swap_demo.py # dynamic region switching (Layout.target + @app.swap)
|
|
860
849
|
uv run python examples/bottom_bar_demo.py # pinned bottom bar (section side="bottom")
|
|
850
|
+
uv run python examples/live_validation.py # live validation via Tcl-var trace ingest (ingest_trace=True)
|
|
861
851
|
```
|
|
862
852
|
|
|
863
853
|
---
|
|
@@ -880,6 +870,10 @@ uv run python examples/bottom_bar_demo.py # pinned bottom bar (section sid
|
|
|
880
870
|
- **`CustomTkinter`**: Modern look via Canvas rendering. nextpytk takes the opposite approach: use native widgets and embed A11y from the start.
|
|
881
871
|
- **`TkRouter`** (israel-dryer, author of ttkbootstrap): Declarative view routing with URL-style paths, animated transitions, and history stack. Complements nextpytk's `multiview` — routing vs widget composition.
|
|
882
872
|
|
|
873
|
+
## Changelog
|
|
874
|
+
|
|
875
|
+
See [CHANGES.md](./CHANGES.md) for the full release history.
|
|
876
|
+
|
|
883
877
|
## License
|
|
884
878
|
|
|
885
879
|
MIT
|
|
@@ -11,7 +11,7 @@ Uses ttk widgets where available.
|
|
|
11
11
|
|
|
12
12
|
## Quick Start
|
|
13
13
|
|
|
14
|
-
Start with an app where a button updates
|
|
14
|
+
Start with an app where a button updates its own label.
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
17
|
pip install nextpytk
|
|
@@ -22,59 +22,48 @@ from nextpytk import TkApp
|
|
|
22
22
|
|
|
23
23
|
app = TkApp(title="Hello")
|
|
24
24
|
|
|
25
|
-
@app.
|
|
26
|
-
def
|
|
27
|
-
return "
|
|
25
|
+
@app.button("hello")
|
|
26
|
+
def on_hello():
|
|
27
|
+
return "world"
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
def on_greet():
|
|
31
|
-
return {"msg": "Button clicked!"}
|
|
32
|
-
|
|
33
|
-
app.run(layout=["msg", "greet"])
|
|
29
|
+
app.run()
|
|
34
30
|
```
|
|
35
31
|
|
|
32
|
+
That's it: a window appears with a button labeled `hello`. Press it and the
|
|
33
|
+
label becomes `world`.
|
|
34
|
+
|
|
36
35
|
---
|
|
37
36
|
|
|
38
37
|
## How it works
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
This example registers two widgets: `msg` and `greet`.
|
|
43
|
-
|
|
44
|
-
```python
|
|
45
|
-
@app.status("msg")
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
`msg` is a status area that shows a message.
|
|
39
|
+
The minimal example packs a lot in. Let's unpack it.
|
|
49
40
|
|
|
50
41
|
```python
|
|
51
|
-
@app.button("
|
|
42
|
+
@app.button("hello")
|
|
52
43
|
```
|
|
53
44
|
|
|
54
|
-
`
|
|
55
|
-
|
|
56
|
-
Finally, name the display order:
|
|
45
|
+
Registers a button named `hello`. When `label=` is omitted, the widget name is
|
|
46
|
+
used as the button text.
|
|
57
47
|
|
|
58
48
|
```python
|
|
59
|
-
|
|
49
|
+
def on_hello():
|
|
50
|
+
return "world"
|
|
60
51
|
```
|
|
61
52
|
|
|
62
|
-
|
|
53
|
+
The callback runs when the button is pressed. Returning a plain string updates
|
|
54
|
+
that button's own label — it's sugar for `{"hello": "world"}`.
|
|
63
55
|
|
|
64
56
|
```python
|
|
65
|
-
|
|
57
|
+
app.run()
|
|
66
58
|
```
|
|
67
59
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
Because `msg` is the name of the registered status area, its text becomes
|
|
71
|
-
"Button clicked!".
|
|
60
|
+
With no `layout=`, registered widgets are arranged automatically into a single
|
|
61
|
+
column, so you don't have to declare one for a simple app.
|
|
72
62
|
|
|
73
|
-
|
|
63
|
+
The basic flow is:
|
|
74
64
|
|
|
75
65
|
* Register widgets by name
|
|
76
|
-
*
|
|
77
|
-
* Return a `dict` from a callback
|
|
66
|
+
* Return a `dict` (or a plain string) from a callback
|
|
78
67
|
* `state` updates and matching widgets refresh
|
|
79
68
|
|
|
80
69
|
---
|
|
@@ -834,6 +823,7 @@ uv run python examples/disk_usage_flat_async.py # ncdu-style viewer (async
|
|
|
834
823
|
uv run python examples/paired_demo.py # side-by-side paired layout with y-scroll sync
|
|
835
824
|
uv run python examples/swap_demo.py # dynamic region switching (Layout.target + @app.swap)
|
|
836
825
|
uv run python examples/bottom_bar_demo.py # pinned bottom bar (section side="bottom")
|
|
826
|
+
uv run python examples/live_validation.py # live validation via Tcl-var trace ingest (ingest_trace=True)
|
|
837
827
|
```
|
|
838
828
|
|
|
839
829
|
---
|
|
@@ -856,6 +846,10 @@ uv run python examples/bottom_bar_demo.py # pinned bottom bar (section sid
|
|
|
856
846
|
- **`CustomTkinter`**: Modern look via Canvas rendering. nextpytk takes the opposite approach: use native widgets and embed A11y from the start.
|
|
857
847
|
- **`TkRouter`** (israel-dryer, author of ttkbootstrap): Declarative view routing with URL-style paths, animated transitions, and history stack. Complements nextpytk's `multiview` — routing vs widget composition.
|
|
858
848
|
|
|
849
|
+
## Changelog
|
|
850
|
+
|
|
851
|
+
See [CHANGES.md](./CHANGES.md) for the full release history.
|
|
852
|
+
|
|
859
853
|
## License
|
|
860
854
|
|
|
861
855
|
MIT
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# ROADMAP — nextpytk
|
|
2
|
+
|
|
3
|
+
> **Note:** Past release history lives in [CHANGES.md](./CHANGES.md).
|
|
4
|
+
> This file is the forward-looking plan (near-term, then v0.5.0, then longer term).
|
|
5
|
+
|
|
6
|
+
## Near term (post-0.4.8)
|
|
7
|
+
|
|
8
|
+
### A11y
|
|
9
|
+
|
|
10
|
+
- [ ] `@app.status` live-region behavior (ARIA `aria-live` equivalent / WCAG 4.1.3)
|
|
11
|
+
- [ ] Tk 9.1 `tk accessible set_acc_*` real-device verification (9.1b0 + NVDA)
|
|
12
|
+
- [ ] Role vocabulary mapping to Tk side
|
|
13
|
+
- [ ] Automatic `emit_selection_change` (leverage `apply_state` knowing which widgets changed)
|
|
14
|
+
|
|
15
|
+
### Type hints
|
|
16
|
+
|
|
17
|
+
- [ ] Further TypedDict / Protocol coverage for decorator arguments
|
|
18
|
+
- [ ] Fluent API equivalent to `_GridBuilder.columnconfigure`
|
|
19
|
+
|
|
20
|
+
### Widget expansion
|
|
21
|
+
|
|
22
|
+
- [ ] Per-widget `bind` for other widgets (`text`, `combobox`, `treeview`, `button`, etc.)
|
|
23
|
+
- [ ] `@app.filepicker` — `filedialog` wrapper (schema/tool naming still open)
|
|
24
|
+
|
|
25
|
+
### Layout DSL
|
|
26
|
+
|
|
27
|
+
- [ ] CSS-grid-inspired layout API for 0.5.0: explicit `grid-template-columns` / `grid-template-rows` strings (e.g. `"1fr 2fr"`, `"auto 1fr"`), area-based placement, and gap tokens. Reduce misuse by making rows/columns and widget placement visually aligned in one declaration.
|
|
28
|
+
- [ ] Wire visual Tab order for `side="bottom"` sections via `_wire_tab_order` (see v0.4.6 note in CHANGES.md).
|
|
29
|
+
|
|
30
|
+
### Agent / LLM integration
|
|
31
|
+
|
|
32
|
+
- [ ] Expose `schema()` as Function Calling definition (bind `sequence`, treeview column defs, etc.)
|
|
33
|
+
- [ ] `@agent_tool` integration (GUI operations as agent vocabulary)
|
|
34
|
+
- [ ] Surface `@app.filepicker` in `schema()` / tool vocabulary
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## v0.5.0 — themes / chrome decoupling
|
|
39
|
+
|
|
40
|
+
- Remove deprecated `theme=True/False` support; `theme` becomes `str` only.
|
|
41
|
+
- Remove deprecated `EventSeq.DOUBLE_CLICK`; use `EventSeq.PRIMARY_DOUBLE_CLICK` or `DOUBLE_BUTTON_1`.
|
|
42
|
+
- Remove deprecated index-order plural methods `col_weights`/`row_weights`/`col_minsizes`/`row_minsizes` and `Layout.cluster()` alias.
|
|
43
|
+
- Decouple `Layout().header()` / `.status()` chrome from Kizashi-specific tokens so they render safely with any ttk theme (`"none"`, `"clam"`, etc.).
|
|
44
|
+
- Extract Kizashi as a standalone ttk theme package so it can be proposed upstream or reused independently of nextpytk.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Longer term
|
|
49
|
+
|
|
50
|
+
### ttk Style layer
|
|
51
|
+
|
|
52
|
+
- [ ] `Layout.style("my_button", background=..., font=...)` style definitions
|
|
53
|
+
|
|
54
|
+
### Declarative components
|
|
55
|
+
|
|
56
|
+
- [ ] `@app.component` decorator (React-like reuse, replacing `Layout`)
|
|
57
|
+
- [ ] State type definitions and validation (no Pydantic)
|
|
58
|
+
|
|
59
|
+
### Testing
|
|
60
|
+
|
|
61
|
+
- [ ] WidgetSpec unit tests
|