mininterface 0.5.0__tar.gz → 0.6.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 (35) hide show
  1. mininterface-0.6.0rc2/PKG-INFO +303 -0
  2. mininterface-0.6.0rc2/README.md +279 -0
  3. mininterface-0.6.0rc2/mininterface/__init__.py +187 -0
  4. {mininterface-0.5.0 → mininterface-0.6.0rc2}/mininterface/__main__.py +8 -4
  5. {mininterface-0.5.0 → mininterface-0.6.0rc2}/mininterface/auxiliary.py +7 -15
  6. mininterface-0.6.0rc2/mininterface/cli_parser.py +200 -0
  7. mininterface-0.6.0rc2/mininterface/common.py +8 -0
  8. mininterface-0.6.0rc2/mininterface/experimental.py +54 -0
  9. mininterface-0.6.0rc2/mininterface/facet.py +56 -0
  10. mininterface-0.6.0rc2/mininterface/form_dict.py +144 -0
  11. mininterface-0.6.0rc2/mininterface/gui_interface/__init__.py +58 -0
  12. mininterface-0.6.0rc2/mininterface/gui_interface/tk_facet.py +20 -0
  13. mininterface-0.6.0rc2/mininterface/gui_interface/tk_window.py +139 -0
  14. mininterface-0.6.0rc2/mininterface/gui_interface/utils.py +161 -0
  15. mininterface-0.6.0rc2/mininterface/mininterface.py +253 -0
  16. mininterface-0.5.0/mininterface/Redirectable.py → mininterface-0.6.0rc2/mininterface/redirectable.py +6 -2
  17. mininterface-0.6.0rc2/mininterface/tag.py +601 -0
  18. mininterface-0.5.0/mininterface/TextInterface.py → mininterface-0.6.0rc2/mininterface/text_interface.py +9 -7
  19. mininterface-0.6.0rc2/mininterface/textual_interface/__init__.py +59 -0
  20. mininterface-0.6.0rc2/mininterface/textual_interface/textual_app.py +144 -0
  21. mininterface-0.6.0rc2/mininterface/textual_interface/textual_button_app.py +96 -0
  22. mininterface-0.6.0rc2/mininterface/textual_interface/textual_facet.py +18 -0
  23. mininterface-0.6.0rc2/mininterface/textual_interface/widgets.py +71 -0
  24. mininterface-0.6.0rc2/mininterface/types.py +71 -0
  25. mininterface-0.6.0rc2/mininterface/validators.py +143 -0
  26. {mininterface-0.5.0 → mininterface-0.6.0rc2}/pyproject.toml +6 -2
  27. mininterface-0.5.0/PKG-INFO +0 -254
  28. mininterface-0.5.0/README.md +0 -230
  29. mininterface-0.5.0/mininterface/FormDict.py +0 -128
  30. mininterface-0.5.0/mininterface/FormField.py +0 -163
  31. mininterface-0.5.0/mininterface/GuiInterface.py +0 -172
  32. mininterface-0.5.0/mininterface/Mininterface.py +0 -144
  33. mininterface-0.5.0/mininterface/TextualInterface.py +0 -234
  34. mininterface-0.5.0/mininterface/__init__.py +0 -95
  35. mininterface-0.5.0/mininterface/common.py +0 -2
@@ -0,0 +1,303 @@
1
+ Metadata-Version: 2.1
2
+ Name: mininterface
3
+ Version: 0.6.0rc2
4
+ Summary: A minimal access to GUI, TUI, CLI and config
5
+ Home-page: https://github.com/CZ-NIC/mininterface
6
+ License: GPL-3.0-or-later
7
+ Author: Edvard Rejthar
8
+ Author-email: edvard.rejthar@nic.cz
9
+ Requires-Python: >=3.10,<4.0
10
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Dist: envelope
16
+ Requires-Dist: pyyaml
17
+ Requires-Dist: requests
18
+ Requires-Dist: textual
19
+ Requires-Dist: tkinter-tooltip
20
+ Requires-Dist: tkinter_form (==0.1.5.2)
21
+ Requires-Dist: tyro
22
+ Description-Content-Type: text/markdown
23
+
24
+ # Mininterface – access to GUI, TUI, CLI and config files
25
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
26
+ [![Build Status](https://github.com/CZ-NIC/mininterface/actions/workflows/run-unittest.yml/badge.svg)](https://github.com/CZ-NIC/mininterface/actions)
27
+
28
+ Write the program core, do not bother with the input/output.
29
+
30
+ ![Hello world example: GUI window](asset/hello-world.png "A minimal use case – GUI")
31
+ ![Hello world example: TUI fallback](asset/hello-tui.webp "A minimal use case – TUI fallback")
32
+
33
+ Check out the code, which is surprisingly short, that displays such a window or its textual fallback.
34
+
35
+ ```python
36
+ from dataclasses import dataclass
37
+ from mininterface import run
38
+
39
+ @dataclass
40
+ class Env:
41
+ """Set of options."""
42
+
43
+ test: bool = False
44
+ """ My testing flag """
45
+
46
+ important_number: int = 4
47
+ """ This number is very important """
48
+
49
+ if __name__ == "__main__":
50
+ env = run(Env, prog="My application").env
51
+ # Attributes are suggested by the IDE
52
+ # along with the hint text 'This number is very important'.
53
+ print(env.important_number)
54
+ ```
55
+
56
+ # Contents
57
+ - [You got CLI](#you-got-cli)
58
+ - [You got config file management](#you-got-config-file-management)
59
+ - [You got dialogues](#you-got-dialogues)
60
+ - [Background](#background)
61
+ - [Installation](#installation)
62
+ - [Docs](#docs)
63
+ - [Examples](#examples)
64
+
65
+ ## You got CLI
66
+ It was all the code you need. No lengthy blocks of code imposed by an external dependency. Besides the GUI/TUI, you receive powerful YAML-configurable CLI parsing.
67
+
68
+ ```bash
69
+ $ ./hello.py
70
+ usage: My application [-h] [--test | --no-test] [--important-number INT]
71
+
72
+ Set of options.
73
+
74
+ ╭─ options ──────────────────────────────────────────────────────────╮
75
+ │ -h, --help show this help message and exit │
76
+ │ --test, --no-test My testing flag (default: False) │
77
+ │ --important-number INT This number is very important (default: 4) │
78
+ ╰────────────────────────────────────────────────────────────────────╯
79
+ ```
80
+
81
+ ## You got config file management
82
+ Loading config file is a piece of cake. Alongside `program.py`, put `program.yaml` and put there some of the arguments. They are seamlessly taken as defaults.
83
+
84
+ ```yaml
85
+ important_number: 555
86
+ ```
87
+
88
+ ## You got dialogues
89
+ Check out several useful methods to handle user dialogues. Here we bound the interface to a `with` statement that redirects stdout directly to the window.
90
+
91
+ ```python
92
+ with run(Env) as m:
93
+ print(f"Your important number is {m.env.important_number}")
94
+ boolean = m.is_yes("Is that alright?")
95
+ ```
96
+
97
+ ![Small window with the text 'Your important number'](asset/hello-with-statement.webp "With statement to redirect the output")
98
+ ![The same in terminal'](asset/hello-with-statement-tui.avif "With statement in TUI fallback")
99
+
100
+ # Background
101
+
102
+ Wrapper between the [tyro](https://github.com/brentyi/tyro) `argparse` replacement and [tkinter_form](https://github.com/JohanEstebanCuervo/tkinter_form/) that converts dicts into a GUI.
103
+
104
+ Writing a small and useful program might be a task that takes fifteen minutes. Adding a CLI to specify the parameters is not so much overhead. But building a simple GUI around it? HOURS! Hours spent on researching GUI libraries, wondering why the Python desktop app ecosystem lags so far behind the web world. All you need is a few input fields validated through a clickable window... You do not deserve to add hundred of lines of the code just to define some editable fields. `Mininterface` is here to help.
105
+
106
+ The config variables needed by your program are kept in cozy dataclasses. Write less! The syntax of [tyro](https://github.com/brentyi/tyro) does not require any overhead (as its `argparse` alternatives do). You just annotate a class attribute, append a simple docstring and get a fully functional application:
107
+ * Call it as `program.py --help` to display full help.
108
+ * Use any flag in CLI: `program.py --test` causes `env.test` be set to `True`.
109
+ * The main benefit: Launch it without parameters as `program.py` to get a full working window with all the flags ready to be edited.
110
+ * Running on a remote machine? Automatic regression to the text interface.
111
+
112
+ # Installation
113
+
114
+ Install with a single command from [PyPi](https://pypi.org/project/mininterface/).
115
+
116
+ ```bash
117
+ pip install mininterface
118
+ ```
119
+
120
+ # Docs
121
+ See the docs overview at [https://cz-nic.github.io/mininterface/](https://cz-nic.github.io/mininterface/Overview/).
122
+
123
+ # Examples
124
+
125
+ ## A complex dataclass.
126
+
127
+ ```python3
128
+ from typing import Annotated
129
+ from dataclasses import dataclass
130
+ from mininterface.validators import not_empty
131
+ from mininterface import run, Tag, Validation
132
+
133
+ @dataclass
134
+ class NestedEnv:
135
+ another_number: int = 7
136
+ """ This field is nested """
137
+
138
+ @dataclass
139
+ class Env:
140
+ nested_config: NestedEnv
141
+
142
+ mandatory_str: str
143
+ """ As there is not default value, you will be prompted automatically to fill up the field """
144
+
145
+ my_number: int | None = None
146
+ """ This is not just a dummy number, if left empty, it is None. """
147
+
148
+ my_string: str = "Hello"
149
+ """ A dummy string """
150
+
151
+ my_flag: bool = False
152
+ """ Checkbox test """
153
+
154
+ my_validated: Annotated[str, Validation(not_empty)] = "hello"
155
+ """ A validated field """
156
+
157
+ m = run(Env, title="My program")
158
+ # See some values
159
+ print(m.env.nested_config.another_number) # 7
160
+ print(m.env)
161
+ # Env(nested_config=NestedEnv(another_number=7), my_number=5, my_string='Hello', my_flag=False, my_validated='hello')
162
+
163
+ # Edit values in a dialog
164
+ m.form()
165
+ ```
166
+
167
+ ## Form with paths
168
+
169
+ We have a dict with some paths. Here is how it looks.
170
+
171
+ ```python
172
+ from pathlib import Path
173
+ from mininterface import run, Tag
174
+
175
+ m = run(title="My program")
176
+ my_dictionary = {
177
+ "paths": Tag("", annotation=list[Path]),
178
+ "default_paths": Tag([Path("/tmp"), Path("/usr")], annotation=list[Path])
179
+ }
180
+
181
+ # Edit values in a dialog
182
+ m.form(my_dictionary)
183
+ ```
184
+
185
+ ![List of paths](asset/list_of_paths.avif)
186
+
187
+
188
+
189
+
190
+
191
+
192
+
193
+
194
+
195
+
196
+
197
+
198
+
199
+
200
+
201
+
202
+
203
+
204
+
205
+
206
+
207
+
208
+
209
+
210
+
211
+
212
+
213
+
214
+
215
+
216
+
217
+
218
+
219
+
220
+
221
+
222
+
223
+
224
+
225
+
226
+
227
+
228
+
229
+
230
+
231
+
232
+
233
+
234
+
235
+
236
+
237
+
238
+
239
+
240
+
241
+
242
+
243
+
244
+
245
+
246
+
247
+
248
+
249
+
250
+
251
+
252
+
253
+
254
+
255
+
256
+
257
+
258
+
259
+
260
+
261
+
262
+
263
+
264
+
265
+
266
+
267
+
268
+
269
+
270
+
271
+
272
+
273
+
274
+
275
+
276
+
277
+
278
+
279
+
280
+
281
+
282
+
283
+
284
+
285
+
286
+
287
+
288
+
289
+
290
+
291
+
292
+
293
+
294
+
295
+
296
+
297
+
298
+
299
+
300
+
301
+
302
+
303
+
@@ -0,0 +1,279 @@
1
+ # Mininterface – access to GUI, TUI, CLI and config files
2
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
3
+ [![Build Status](https://github.com/CZ-NIC/mininterface/actions/workflows/run-unittest.yml/badge.svg)](https://github.com/CZ-NIC/mininterface/actions)
4
+
5
+ Write the program core, do not bother with the input/output.
6
+
7
+ ![Hello world example: GUI window](asset/hello-world.png "A minimal use case – GUI")
8
+ ![Hello world example: TUI fallback](asset/hello-tui.webp "A minimal use case – TUI fallback")
9
+
10
+ Check out the code, which is surprisingly short, that displays such a window or its textual fallback.
11
+
12
+ ```python
13
+ from dataclasses import dataclass
14
+ from mininterface import run
15
+
16
+ @dataclass
17
+ class Env:
18
+ """Set of options."""
19
+
20
+ test: bool = False
21
+ """ My testing flag """
22
+
23
+ important_number: int = 4
24
+ """ This number is very important """
25
+
26
+ if __name__ == "__main__":
27
+ env = run(Env, prog="My application").env
28
+ # Attributes are suggested by the IDE
29
+ # along with the hint text 'This number is very important'.
30
+ print(env.important_number)
31
+ ```
32
+
33
+ # Contents
34
+ - [You got CLI](#you-got-cli)
35
+ - [You got config file management](#you-got-config-file-management)
36
+ - [You got dialogues](#you-got-dialogues)
37
+ - [Background](#background)
38
+ - [Installation](#installation)
39
+ - [Docs](#docs)
40
+ - [Examples](#examples)
41
+
42
+ ## You got CLI
43
+ It was all the code you need. No lengthy blocks of code imposed by an external dependency. Besides the GUI/TUI, you receive powerful YAML-configurable CLI parsing.
44
+
45
+ ```bash
46
+ $ ./hello.py
47
+ usage: My application [-h] [--test | --no-test] [--important-number INT]
48
+
49
+ Set of options.
50
+
51
+ ╭─ options ──────────────────────────────────────────────────────────╮
52
+ │ -h, --help show this help message and exit │
53
+ │ --test, --no-test My testing flag (default: False) │
54
+ │ --important-number INT This number is very important (default: 4) │
55
+ ╰────────────────────────────────────────────────────────────────────╯
56
+ ```
57
+
58
+ ## You got config file management
59
+ Loading config file is a piece of cake. Alongside `program.py`, put `program.yaml` and put there some of the arguments. They are seamlessly taken as defaults.
60
+
61
+ ```yaml
62
+ important_number: 555
63
+ ```
64
+
65
+ ## You got dialogues
66
+ Check out several useful methods to handle user dialogues. Here we bound the interface to a `with` statement that redirects stdout directly to the window.
67
+
68
+ ```python
69
+ with run(Env) as m:
70
+ print(f"Your important number is {m.env.important_number}")
71
+ boolean = m.is_yes("Is that alright?")
72
+ ```
73
+
74
+ ![Small window with the text 'Your important number'](asset/hello-with-statement.webp "With statement to redirect the output")
75
+ ![The same in terminal'](asset/hello-with-statement-tui.avif "With statement in TUI fallback")
76
+
77
+ # Background
78
+
79
+ Wrapper between the [tyro](https://github.com/brentyi/tyro) `argparse` replacement and [tkinter_form](https://github.com/JohanEstebanCuervo/tkinter_form/) that converts dicts into a GUI.
80
+
81
+ Writing a small and useful program might be a task that takes fifteen minutes. Adding a CLI to specify the parameters is not so much overhead. But building a simple GUI around it? HOURS! Hours spent on researching GUI libraries, wondering why the Python desktop app ecosystem lags so far behind the web world. All you need is a few input fields validated through a clickable window... You do not deserve to add hundred of lines of the code just to define some editable fields. `Mininterface` is here to help.
82
+
83
+ The config variables needed by your program are kept in cozy dataclasses. Write less! The syntax of [tyro](https://github.com/brentyi/tyro) does not require any overhead (as its `argparse` alternatives do). You just annotate a class attribute, append a simple docstring and get a fully functional application:
84
+ * Call it as `program.py --help` to display full help.
85
+ * Use any flag in CLI: `program.py --test` causes `env.test` be set to `True`.
86
+ * The main benefit: Launch it without parameters as `program.py` to get a full working window with all the flags ready to be edited.
87
+ * Running on a remote machine? Automatic regression to the text interface.
88
+
89
+ # Installation
90
+
91
+ Install with a single command from [PyPi](https://pypi.org/project/mininterface/).
92
+
93
+ ```bash
94
+ pip install mininterface
95
+ ```
96
+
97
+ # Docs
98
+ See the docs overview at [https://cz-nic.github.io/mininterface/](https://cz-nic.github.io/mininterface/Overview/).
99
+
100
+ # Examples
101
+
102
+ ## A complex dataclass.
103
+
104
+ ```python3
105
+ from typing import Annotated
106
+ from dataclasses import dataclass
107
+ from mininterface.validators import not_empty
108
+ from mininterface import run, Tag, Validation
109
+
110
+ @dataclass
111
+ class NestedEnv:
112
+ another_number: int = 7
113
+ """ This field is nested """
114
+
115
+ @dataclass
116
+ class Env:
117
+ nested_config: NestedEnv
118
+
119
+ mandatory_str: str
120
+ """ As there is not default value, you will be prompted automatically to fill up the field """
121
+
122
+ my_number: int | None = None
123
+ """ This is not just a dummy number, if left empty, it is None. """
124
+
125
+ my_string: str = "Hello"
126
+ """ A dummy string """
127
+
128
+ my_flag: bool = False
129
+ """ Checkbox test """
130
+
131
+ my_validated: Annotated[str, Validation(not_empty)] = "hello"
132
+ """ A validated field """
133
+
134
+ m = run(Env, title="My program")
135
+ # See some values
136
+ print(m.env.nested_config.another_number) # 7
137
+ print(m.env)
138
+ # Env(nested_config=NestedEnv(another_number=7), my_number=5, my_string='Hello', my_flag=False, my_validated='hello')
139
+
140
+ # Edit values in a dialog
141
+ m.form()
142
+ ```
143
+
144
+ ## Form with paths
145
+
146
+ We have a dict with some paths. Here is how it looks.
147
+
148
+ ```python
149
+ from pathlib import Path
150
+ from mininterface import run, Tag
151
+
152
+ m = run(title="My program")
153
+ my_dictionary = {
154
+ "paths": Tag("", annotation=list[Path]),
155
+ "default_paths": Tag([Path("/tmp"), Path("/usr")], annotation=list[Path])
156
+ }
157
+
158
+ # Edit values in a dialog
159
+ m.form(my_dictionary)
160
+ ```
161
+
162
+ ![List of paths](asset/list_of_paths.avif)
163
+
164
+
165
+
166
+
167
+
168
+
169
+
170
+
171
+
172
+
173
+
174
+
175
+
176
+
177
+
178
+
179
+
180
+
181
+
182
+
183
+
184
+
185
+
186
+
187
+
188
+
189
+
190
+
191
+
192
+
193
+
194
+
195
+
196
+
197
+
198
+
199
+
200
+
201
+
202
+
203
+
204
+
205
+
206
+
207
+
208
+
209
+
210
+
211
+
212
+
213
+
214
+
215
+
216
+
217
+
218
+
219
+
220
+
221
+
222
+
223
+
224
+
225
+
226
+
227
+
228
+
229
+
230
+
231
+
232
+
233
+
234
+
235
+
236
+
237
+
238
+
239
+
240
+
241
+
242
+
243
+
244
+
245
+
246
+
247
+
248
+
249
+
250
+
251
+
252
+
253
+
254
+
255
+
256
+
257
+
258
+
259
+
260
+
261
+
262
+
263
+
264
+
265
+
266
+
267
+
268
+
269
+
270
+
271
+
272
+
273
+
274
+
275
+
276
+
277
+
278
+
279
+