restiny 0.1.2__py3-none-any.whl → 0.2.1__py3-none-any.whl

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.
@@ -1,5 +1,5 @@
1
+ from enum import StrEnum
1
2
  from pathlib import Path
2
- from typing import Literal
3
3
 
4
4
  from textual import on
5
5
  from textual.app import ComposeResult
@@ -55,6 +55,7 @@ class PathChooserScreen(ModalScreen):
55
55
  with Horizontal(classes='w-auto h-auto mt-1'):
56
56
  yield Input(
57
57
  placeholder='--empty--',
58
+ select_on_focus=False,
58
59
  disabled=True,
59
60
  type='text',
60
61
  classes='w-1fr',
@@ -181,73 +182,117 @@ class DirectoryChooserScreen(PathChooserScreen):
181
182
  return True
182
183
 
183
184
 
185
+ class _PathType(StrEnum):
186
+ FILE = 'file'
187
+ DIR = 'directory'
188
+
189
+
184
190
  class PathChooser(Widget):
185
191
  DEFAULT_CSS = """
186
192
  PathChooser {
193
+ width: 1fr;
187
194
  height: auto;
188
- width: auto;
195
+ layout: grid;
196
+ grid-size: 2 1;
197
+ grid-columns: 1fr auto;
189
198
  }
190
199
 
191
- Input {
192
- width: 1fr;
200
+ PathChooser > Input {
201
+ margin-right: 0;
202
+ border-right: none;
193
203
  }
194
204
 
195
- Button {
196
- width: auto;
205
+ PathChooser > Button {
206
+ margin-left: 0;
207
+ border-left: none;
197
208
  }
198
209
  """
199
210
 
200
- path: Reactive[Path | None] = Reactive(None, init=True)
201
-
202
211
  class Changed(Message):
203
212
  """
204
213
  Sent when the user change the selected path.
205
214
  """
206
215
 
207
- def __init__(self, path: Path | None) -> None:
216
+ def __init__(
217
+ self, path_chooser: PathChooser, path: Path | None
218
+ ) -> None:
208
219
  super().__init__()
220
+ self.path_chooser = path_chooser
209
221
  self.path = path
210
222
 
223
+ @property
224
+ def control(self) -> 'PathChooser':
225
+ return self.path_chooser
226
+
211
227
  @classmethod
212
228
  def file(cls, *args, **kwargs) -> 'PathChooser':
213
- return cls(*args, **kwargs, path_type='file')
229
+ return cls(*args, **kwargs, path_type=_PathType.FILE)
214
230
 
215
231
  @classmethod
216
232
  def directory(cls, *args, **kwargs) -> 'PathChooser':
217
- return cls(*args, **kwargs, path_type='directory')
233
+ return cls(*args, **kwargs, path_type=_PathType.DIR)
218
234
 
219
235
  def __init__(
220
- self, path_type: Literal['file', 'directory'], *args, **kwargs
236
+ self,
237
+ path_type: _PathType,
238
+ path: Path | None = None,
239
+ *args,
240
+ **kwargs,
221
241
  ) -> None:
222
242
  super().__init__(*args, **kwargs)
223
243
  self.path_type = path_type
244
+ self._initial_path = path
224
245
 
225
246
  def compose(self) -> ComposeResult:
226
- with Horizontal():
227
- yield Input(placeholder='--empty--', disabled=True)
228
- yield Button(f' Choose {self.path_type} ')
247
+ icon = ''
248
+ if self.path_type == _PathType.FILE:
249
+ icon = ' 📄 '
250
+ elif self.path_type == _PathType.DIR:
251
+ icon = ' 🗂 '
252
+
253
+ yield Input(
254
+ self._initial_path,
255
+ placeholder='--empty--',
256
+ select_on_focus=False,
257
+ disabled=True,
258
+ id='path',
259
+ )
260
+ yield Button(icon, tooltip=f'Choose {self.path_type}', id='choose')
229
261
 
230
262
  def on_mount(self) -> None:
231
- self.input = self.query_one(Input)
232
- self.button = self.query_one(Button)
263
+ self.path_input = self.query_one('#path', Input)
264
+ self.choose_button = self.query_one('#choose', Button)
265
+
266
+ @property
267
+ def path(self) -> Path | None:
268
+ if self.path_input.value != '':
269
+ return Path(self.path_input.value)
270
+ return None
271
+
272
+ @path.setter
273
+ def path(self, value: Path | None) -> None:
274
+ value = str(value) if value else ''
275
+ self.path_input.value = value
276
+ self.path_input.tooltip = value
277
+
278
+ @on(Input.Changed, '#path')
279
+ def _on_path_changed(self, message: Input.Changed) -> None:
280
+ self.post_message(
281
+ message=self.Changed(path_chooser=self, path=self.path)
282
+ )
233
283
 
234
- @on(Button.Pressed)
235
- def open_path_chooser(self) -> None:
284
+ @on(Button.Pressed, '#choose')
285
+ def _on_path_choose(self) -> None:
236
286
  def set_path(path: Path | None = None) -> None:
237
287
  self.path = path
238
288
 
239
- if self.path_type == 'file':
289
+ if self.path_type == _PathType.FILE:
240
290
  self.app.push_screen(
241
291
  screen=FileChooserScreen(),
242
292
  callback=set_path,
243
293
  )
244
- elif self.path_type == 'directory':
294
+ elif self.path_type == _PathType.DIR:
245
295
  self.app.push_screen(
246
296
  screen=DirectoryChooserScreen(),
247
297
  callback=set_path,
248
298
  )
249
-
250
- def watch_path(self, value: Path | None) -> None:
251
- self.input.value = str(value) if value else ''
252
- self.input.tooltip = str(value) if value else ''
253
- self.post_message(message=self.Changed(path=value))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: restiny
3
- Version: 0.1.2
3
+ Version: 0.2.1
4
4
  Summary: A minimalist HTTP client, no bullshit
5
5
  Author-email: Kalebe Chimanski de Almeida <kalebe.chi.almeida@gmail.com>
6
6
  License: Apache License
@@ -220,6 +220,7 @@ Classifier: Programming Language :: Python :: 3.10
220
220
  Classifier: Programming Language :: Python :: 3.11
221
221
  Classifier: Programming Language :: Python :: 3.12
222
222
  Classifier: Programming Language :: Python :: 3.13
223
+ Classifier: Programming Language :: Python :: 3.14
223
224
  Classifier: Operating System :: POSIX :: Linux
224
225
  Classifier: Operating System :: MacOS
225
226
  Classifier: Operating System :: Microsoft :: Windows :: Windows 10
@@ -230,14 +231,14 @@ Classifier: Natural Language :: English
230
231
  Requires-Python: >=3.10
231
232
  Description-Content-Type: text/markdown
232
233
  License-File: LICENSE
233
- Requires-Dist: textual<6.3,>=6.2
234
+ Requires-Dist: textual<6.4,>=6.3
234
235
  Requires-Dist: textual[syntax]
235
236
  Requires-Dist: httpx<0.29,>=0.28
236
237
  Requires-Dist: pyperclip<1.10,>=1.9
237
238
  Dynamic: license-file
238
239
 
239
240
  ![OS support](https://img.shields.io/badge/OS-macOS%20Linux%20Windows-red)
240
- ![Python versions](https://img.shields.io/badge/Python-3.10%20|%203.11%20|%203.12%20|%203.13-blue)
241
+ ![Python versions](https://img.shields.io/badge/Python-3.10%20|%203.11%20|%203.12%20|%203.13%20|%203.14-blue)
241
242
 
242
243
 
243
244
  - [RESTiny](#restiny)
@@ -253,7 +254,7 @@ Dynamic: license-file
253
254
 
254
255
  _A minimal, elegant HTTP client for Python — with a TUI interface powered by [Textual](https://github.com/Textualize/textual)._
255
256
 
256
- <img width="1905" alt="image" src="https://github.com/user-attachments/assets/e6f0c03a-e98e-40cd-af1d-38489d650fb1" />
257
+ ![image](https://github.com/user-attachments/assets/e6f0c03a-e98e-40cd-af1d-38489d650fb1)
257
258
 
258
259
  ## How to install
259
260
 
@@ -0,0 +1,24 @@
1
+ restiny/__about__.py,sha256=PmcQ2PI2oP8irnLtJLJby2YfW6sBvLAmL-VpABzTqwc,22
2
+ restiny/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ restiny/__main__.py,sha256=omMWZ9xgxXbDE6nyVhE8AnVkohPaXhTAn6cYx6OeRMk,609
4
+ restiny/consts.py,sha256=brPBT5j_Yf7lVPo6mVRPPNUHxGnfDfkLWC4Xr_y3UWo,237
5
+ restiny/enums.py,sha256=24ApCF1KoGfu-0XpIT_dbZrnOQx7SjmUKFbt5aMa_dg,873
6
+ restiny/utils.py,sha256=AD8mtM-AuWhcXbTk3-j9gZWs8SoVnI5SbbUw0cnYEUw,3113
7
+ restiny/assets/__init__.py,sha256=JL1KARlToF6ZR7KeUjlDAHgwwVM2qXYaIl4wHeFW2zU,93
8
+ restiny/assets/style.tcss,sha256=qq8kLab6TuaDNk7V3El9FzAVb1tjVr3JzYSjBbKwPzM,563
9
+ restiny/core/__init__.py,sha256=qEyvxrQifEiazkiGoaaJwVhKgbXqVu-Y75M-2HWG73U,373
10
+ restiny/core/app.py,sha256=_chnNKCcuJ0U6XIlvTxotVZM0AYprHaSO-qBy4x1L_Q,12591
11
+ restiny/core/request_area.py,sha256=aeWFRZ49h33bxeWt7-XNmQGrxpTnO2cEQ4fewseLm6Q,11570
12
+ restiny/core/response_area.py,sha256=Rzq82muK9gXWHIHdLqetFG403n7JdE65Rka0Siw339I,4195
13
+ restiny/core/url_area.py,sha256=-DIiNrBSUsIPDMb7TZI_PiG-fM-Karhwv-vwui89g8I,3298
14
+ restiny/widgets/__init__.py,sha256=ncQ1uFdIoSuQ2DYmsMxGdu3D4Sf9mMiM1VweDHJuDNQ,464
15
+ restiny/widgets/custom_directory_tree.py,sha256=sNTaI0DBAO56MyOy6qMZPgWXiTUQbBrJdn1GtOdxrDc,1268
16
+ restiny/widgets/custom_text_area.py,sha256=ykmG-6MiMhz6BqNzP8f14jUTWWKjsCOIEhgciP-01Y8,14032
17
+ restiny/widgets/dynamic_fields.py,sha256=tqRE8PkfqTQnYA7RwjFIWpTINryp2NqXqWbmtRYlcvE,16283
18
+ restiny/widgets/path_chooser.py,sha256=hW7KdKOisxwsMSKDLRn7aEj2-7VXLyzDGdN6m6JR7cI,9212
19
+ restiny-0.2.1.dist-info/licenses/LICENSE,sha256=Z190MKguypkrjaCldiorEbMmBQp7ylvx09oyE4oDCTs,11361
20
+ restiny-0.2.1.dist-info/METADATA,sha256=n9GcZmgSaPmnl5Us-CUJVslSIddoGB3WrYdpz_VBnHI,16126
21
+ restiny-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
22
+ restiny-0.2.1.dist-info/entry_points.txt,sha256=F9zW8bAPAwIihltqjzYow4ahmH_B6VkAHzQFA-8QOn4,50
23
+ restiny-0.2.1.dist-info/top_level.txt,sha256=1MQ_Q-fV1Dwbu4zU3g1Eg-CfRgC412X-mvMIrEdrlbk,8
24
+ restiny-0.2.1.dist-info/RECORD,,
File without changes
restiny/screens/dialog.py DELETED
@@ -1,109 +0,0 @@
1
- from textual import on
2
- from textual.app import ComposeResult
3
- from textual.binding import Binding
4
- from textual.containers import Horizontal, Vertical
5
- from textual.screen import ModalScreen
6
- from textual.widgets import Button, Label
7
-
8
-
9
- class ConfirmDialogScreen(ModalScreen):
10
- DEFAULT_CSS = """
11
- ConfirmDialogScreen {
12
- align: center middle;
13
- }
14
-
15
- #modal-content {
16
- border: heavy black;
17
- border-title-color: gray;
18
- background: $surface;
19
- width: auto;
20
- height: auto;
21
- padding-top: 1;
22
- padding-left: 1;
23
- padding-right: 1;
24
- }
25
-
26
- #buttons-container {
27
- width: auto;
28
- height: auto;
29
- align-horizontal: right;
30
- }
31
- """
32
-
33
- BINDINGS = [Binding('escape', 'dismiss', show=False)]
34
-
35
- def __init__(
36
- self,
37
- title: str,
38
- text: str,
39
- confirm_label: str = 'Confirm',
40
- cancel_label: str = 'Cancel',
41
- ) -> None:
42
- super().__init__()
43
- self.title = title
44
- self.text = text
45
- self.confirm_label = confirm_label
46
- self.cancel_label = cancel_label
47
-
48
- def compose(self) -> ComposeResult:
49
- with Vertical(id='modal-content'):
50
- yield Label(self.text)
51
- with Horizontal(id='buttons-container'):
52
- yield Button(self.cancel_label, flat=True, id='cancel')
53
- yield Button(self.confirm_label, flat=True, id='confirm')
54
-
55
- def on_mount(self) -> None:
56
- self.query_one('#modal-content').border_title = self.title
57
-
58
- @on(Button.Pressed, '#cancel')
59
- def cancel(self) -> None:
60
- self.dismiss(result=False)
61
-
62
- @on(Button.Pressed, '#confirm')
63
- def confirm(self) -> None:
64
- self.dismiss(result=True)
65
-
66
-
67
- class InfoDialogScreen(ModalScreen):
68
- DEFAULT_CSS = """
69
- InfoDialogScreen {
70
- align: center middle;
71
- }
72
-
73
- #modal-content {
74
- border: heavy black;
75
- border-title-color: gray;
76
- background: $surface;
77
- width: auto;
78
- height: auto;
79
- padding-top: 1;
80
- padding-left: 1;
81
- padding-right: 1;
82
- }
83
-
84
- #button-container {
85
- width: 100%;
86
- height: auto;
87
- align-horizontal: right;
88
- }
89
- """
90
-
91
- BINDINGS = [Binding('escape', 'dismiss', show=False)]
92
-
93
- def __init__(self, title: str, text: str):
94
- super().__init__()
95
- self.title = title
96
- self.text = text
97
-
98
- def compose(self) -> ComposeResult:
99
- with Vertical(id='modal-content'):
100
- yield Label(self.text)
101
- with Vertical(id='button-container'):
102
- yield Button('Ok', flat=True)
103
-
104
- def on_mount(self) -> None:
105
- self.query_one('#modal-content').border_title = self.title
106
-
107
- @on(Button.Pressed)
108
- def ok(self, message: Button.Pressed) -> None:
109
- self.dismiss()
@@ -1,29 +0,0 @@
1
- restiny/__about__.py,sha256=mdp2CftfqYbdKtP-eWv1z7rAUycYv6X1ntXSMUf8Kss,22
2
- restiny/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- restiny/__main__.py,sha256=omMWZ9xgxXbDE6nyVhE8AnVkohPaXhTAn6cYx6OeRMk,609
4
- restiny/consts.py,sha256=brPBT5j_Yf7lVPo6mVRPPNUHxGnfDfkLWC4Xr_y3UWo,237
5
- restiny/enums.py,sha256=qj8Vsa26XmVMtqjmmjmBvDTOJUE289ZaY51DjFBGNkY,874
6
- restiny/utils.py,sha256=AD8mtM-AuWhcXbTk3-j9gZWs8SoVnI5SbbUw0cnYEUw,3113
7
- restiny/assets/__init__.py,sha256=JL1KARlToF6ZR7KeUjlDAHgwwVM2qXYaIl4wHeFW2zU,93
8
- restiny/assets/style.tcss,sha256=qq8kLab6TuaDNk7V3El9FzAVb1tjVr3JzYSjBbKwPzM,563
9
- restiny/assets/__pycache__/__init__.cpython-310.pyc,sha256=RBF41dtvLLn5P8hv7HliL7kAqLb3TlgE7yTCCUOgbe8,234
10
- restiny/assets/__pycache__/__init__.cpython-313.pyc,sha256=w9J2aawnq4UE6wO7H8rBKMQrLzutfMYvLMRy4kEdwA8,320
11
- restiny/assets/__pycache__/__init__.cpython-314.pyc,sha256=w73xdw4S_NGUMK0kQQPULiz09WzQvPP_uF7G0Bj5_TM,284
12
- restiny/core/__init__.py,sha256=qEyvxrQifEiazkiGoaaJwVhKgbXqVu-Y75M-2HWG73U,373
13
- restiny/core/app.py,sha256=ks10wIDF4DS537eLxU0vx9izCLym5zJJOSnRYu0l4LQ,13547
14
- restiny/core/request_area.py,sha256=ppUFKsGDtSmFL8s_p6sJrOhGnPl6bvuBQ-wlt9gQ2iQ,11356
15
- restiny/core/response_area.py,sha256=zCJz8dTDnb5APKODCF0JqQimdnpKYSDa5A81cRiKBbc,3111
16
- restiny/core/url_area.py,sha256=rDcoVoLR_v8WHJJfwJUUFil1FcWnpvkPNBwzb5KaH6Y,3052
17
- restiny/screens/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- restiny/screens/dialog.py,sha256=-AcJxMvkEUm947ch6BqcMNTRlfXr82frqamYgBqTics,2793
19
- restiny/widgets/__init__.py,sha256=hoJKf9MCkd_OG1A4GHZxStmGHgkr2_JHHSJA-WOPeBE,456
20
- restiny/widgets/custom_directory_tree.py,sha256=sNTaI0DBAO56MyOy6qMZPgWXiTUQbBrJdn1GtOdxrDc,1268
21
- restiny/widgets/custom_text_area.py,sha256=ykmG-6MiMhz6BqNzP8f14jUTWWKjsCOIEhgciP-01Y8,14032
22
- restiny/widgets/dynamic_fields.py,sha256=dSpaBvKM8afnauT7VpT5jNb3h1e8G1qkAQuwy_zRm7M,8551
23
- restiny/widgets/path_chooser.py,sha256=_CHBE6075R3qXoDXFiEl3FMT_jiXolAI0lcfeh2Cx4I,8068
24
- restiny-0.1.2.dist-info/licenses/LICENSE,sha256=Z190MKguypkrjaCldiorEbMmBQp7ylvx09oyE4oDCTs,11361
25
- restiny-0.1.2.dist-info/METADATA,sha256=ttQa3IMtJgJwVq3XpqWbXrlD0sK3akMnDhim3SpMEWE,16093
26
- restiny-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
- restiny-0.1.2.dist-info/entry_points.txt,sha256=F9zW8bAPAwIihltqjzYow4ahmH_B6VkAHzQFA-8QOn4,50
28
- restiny-0.1.2.dist-info/top_level.txt,sha256=1MQ_Q-fV1Dwbu4zU3g1Eg-CfRgC412X-mvMIrEdrlbk,8
29
- restiny-0.1.2.dist-info/RECORD,,