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.
- restiny/__about__.py +1 -1
- restiny/core/app.py +184 -177
- restiny/core/request_area.py +102 -100
- restiny/core/response_area.py +53 -20
- restiny/core/url_area.py +28 -20
- restiny/enums.py +0 -1
- restiny/widgets/__init__.py +2 -2
- restiny/widgets/dynamic_fields.py +375 -96
- restiny/widgets/path_chooser.py +71 -26
- {restiny-0.1.2.dist-info → restiny-0.2.1.dist-info}/METADATA +5 -4
- restiny-0.2.1.dist-info/RECORD +24 -0
- restiny/assets/__pycache__/__init__.cpython-310.pyc +0 -0
- restiny/assets/__pycache__/__init__.cpython-313.pyc +0 -0
- restiny/assets/__pycache__/__init__.cpython-314.pyc +0 -0
- restiny/screens/__init__.py +0 -0
- restiny/screens/dialog.py +0 -109
- restiny-0.1.2.dist-info/RECORD +0 -29
- {restiny-0.1.2.dist-info → restiny-0.2.1.dist-info}/WHEEL +0 -0
- {restiny-0.1.2.dist-info → restiny-0.2.1.dist-info}/entry_points.txt +0 -0
- {restiny-0.1.2.dist-info → restiny-0.2.1.dist-info}/licenses/LICENSE +0 -0
- {restiny-0.1.2.dist-info → restiny-0.2.1.dist-info}/top_level.txt +0 -0
restiny/core/request_area.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import mimetypes
|
|
2
1
|
from dataclasses import dataclass
|
|
3
2
|
from pathlib import Path
|
|
4
3
|
|
|
@@ -19,10 +18,11 @@ from textual.widgets import (
|
|
|
19
18
|
from restiny.enums import BodyMode, BodyRawLanguage
|
|
20
19
|
from restiny.widgets import (
|
|
21
20
|
CustomTextArea,
|
|
22
|
-
DynamicField,
|
|
23
21
|
DynamicFields,
|
|
24
22
|
PathChooser,
|
|
23
|
+
TextDynamicField,
|
|
25
24
|
)
|
|
25
|
+
from restiny.widgets.dynamic_fields import TextOrFileDynamicField
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
@dataclass
|
|
@@ -98,12 +98,12 @@ class RequestArea(Static):
|
|
|
98
98
|
with TabbedContent():
|
|
99
99
|
with TabPane('Headers'):
|
|
100
100
|
yield DynamicFields(
|
|
101
|
-
fields=[
|
|
101
|
+
fields=[TextDynamicField(enabled=False, key='', value='')],
|
|
102
102
|
id='headers',
|
|
103
103
|
)
|
|
104
104
|
with TabPane('Query params'):
|
|
105
105
|
yield DynamicFields(
|
|
106
|
-
fields=[
|
|
106
|
+
fields=[TextDynamicField(enabled=False, key='', value='')],
|
|
107
107
|
id='params',
|
|
108
108
|
)
|
|
109
109
|
with TabPane('Body'):
|
|
@@ -114,7 +114,7 @@ class RequestArea(Static):
|
|
|
114
114
|
('Raw', BodyMode.RAW),
|
|
115
115
|
('File', BodyMode.FILE),
|
|
116
116
|
('Form (urlencoded)', BodyMode.FORM_URLENCODED),
|
|
117
|
-
|
|
117
|
+
('Form (multipart)', BodyMode.FORM_MULTIPART),
|
|
118
118
|
),
|
|
119
119
|
allow_blank=False,
|
|
120
120
|
tooltip='Body type',
|
|
@@ -149,9 +149,24 @@ class RequestArea(Static):
|
|
|
149
149
|
id='body-mode-form-urlencoded', classes='h-auto mt-1'
|
|
150
150
|
):
|
|
151
151
|
yield DynamicFields(
|
|
152
|
-
[
|
|
152
|
+
[
|
|
153
|
+
TextDynamicField(
|
|
154
|
+
enabled=False, key='', value=''
|
|
155
|
+
)
|
|
156
|
+
],
|
|
153
157
|
id='body-form-urlencoded',
|
|
154
158
|
)
|
|
159
|
+
with Horizontal(
|
|
160
|
+
id='body-mode-form-multipart', classes='h-auto mt-1'
|
|
161
|
+
):
|
|
162
|
+
yield DynamicFields(
|
|
163
|
+
[
|
|
164
|
+
TextOrFileDynamicField(
|
|
165
|
+
enabled=False, key='', value=''
|
|
166
|
+
)
|
|
167
|
+
],
|
|
168
|
+
id='body-form-multipart',
|
|
169
|
+
)
|
|
155
170
|
|
|
156
171
|
with TabPane('Options'):
|
|
157
172
|
with Horizontal(classes='h-auto'):
|
|
@@ -159,6 +174,7 @@ class RequestArea(Static):
|
|
|
159
174
|
yield Input(
|
|
160
175
|
'5.5',
|
|
161
176
|
placeholder='5.5',
|
|
177
|
+
select_on_focus=False,
|
|
162
178
|
id='options-timeout',
|
|
163
179
|
classes='w-1fr',
|
|
164
180
|
)
|
|
@@ -187,6 +203,9 @@ class RequestArea(Static):
|
|
|
187
203
|
self.body_form_urlencoded_fields = self.query_one(
|
|
188
204
|
'#body-form-urlencoded', DynamicFields
|
|
189
205
|
)
|
|
206
|
+
self.body_form_multipart_fields = self.query_one(
|
|
207
|
+
'#body-form-multipart', DynamicFields
|
|
208
|
+
)
|
|
190
209
|
|
|
191
210
|
self.options_timeout_input = self.query_one('#options-timeout', Input)
|
|
192
211
|
self.options_follow_redirects_switch = self.query_one(
|
|
@@ -196,61 +215,47 @@ class RequestArea(Static):
|
|
|
196
215
|
'#options-verify-ssl', Switch
|
|
197
216
|
)
|
|
198
217
|
|
|
218
|
+
def get_data(self) -> RequestAreaData:
|
|
219
|
+
return RequestAreaData(
|
|
220
|
+
headers=self._get_headers(),
|
|
221
|
+
query_params=self._get_query_params(),
|
|
222
|
+
body=self._get_body(),
|
|
223
|
+
options=self._get_options(),
|
|
224
|
+
)
|
|
225
|
+
|
|
199
226
|
@on(Select.Changed, '#body-mode')
|
|
200
|
-
def
|
|
227
|
+
def _on_change_body_type(self, message: Select.Changed) -> None:
|
|
201
228
|
if message.value == BodyMode.FILE:
|
|
202
229
|
self.body_mode_switcher.current = 'body-mode-file'
|
|
203
230
|
elif message.value == BodyMode.RAW:
|
|
204
231
|
self.body_mode_switcher.current = 'body-mode-raw'
|
|
205
232
|
elif message.value == BodyMode.FORM_URLENCODED:
|
|
206
233
|
self.body_mode_switcher.current = 'body-mode-form-urlencoded'
|
|
234
|
+
elif message.value == BodyMode.FORM_MULTIPART:
|
|
235
|
+
self.body_mode_switcher.current = 'body-mode-form-multipart'
|
|
207
236
|
|
|
208
237
|
@on(Select.Changed, '#body-raw-language')
|
|
209
|
-
def
|
|
238
|
+
def _on_change_body_raw_language(self, message: Select.Changed) -> None:
|
|
210
239
|
self.body_raw_editor.language = message.value
|
|
211
240
|
|
|
212
241
|
@on(DynamicFields.FieldFilled, '#body-form-urlencoded')
|
|
213
|
-
def
|
|
242
|
+
def _on_form_filled(self, message: DynamicFields.FieldFilled) -> None:
|
|
214
243
|
self.body_enabled_switch.value = True
|
|
215
244
|
|
|
216
245
|
@on(DynamicFields.FieldEmpty, '#body-form-urlencoded')
|
|
217
|
-
def
|
|
246
|
+
def _on_form_empty(self, message: DynamicFields.FieldEmpty) -> None:
|
|
218
247
|
if not message.control.filled_fields:
|
|
219
248
|
self.body_enabled_switch.value = False
|
|
220
249
|
|
|
221
250
|
@on(CustomTextArea.Changed, '#body-raw')
|
|
222
|
-
def
|
|
251
|
+
def _on_change_body_raw(self, message: CustomTextArea.Changed) -> None:
|
|
223
252
|
if self.body_raw_editor.text == '':
|
|
224
253
|
self.body_enabled_switch.value = False
|
|
225
254
|
else:
|
|
226
255
|
self.body_enabled_switch.value = True
|
|
227
256
|
|
|
228
|
-
@on(PathChooser.Changed)
|
|
229
|
-
async def on_change_file(self, message: PathChooser.Changed) -> None:
|
|
230
|
-
content_type_header_field: DynamicField | None = None
|
|
231
|
-
for header_field in self.header_fields.fields:
|
|
232
|
-
if header_field.key.lower() == 'content-type':
|
|
233
|
-
content_type_header_field = header_field
|
|
234
|
-
break
|
|
235
|
-
|
|
236
|
-
content_type: str | None = mimetypes.guess_type(str(message.path))[0]
|
|
237
|
-
if not content_type:
|
|
238
|
-
return
|
|
239
|
-
|
|
240
|
-
if content_type_header_field:
|
|
241
|
-
content_type_header_field.value = content_type
|
|
242
|
-
return
|
|
243
|
-
|
|
244
|
-
empty_field = self.header_fields.empty_fields[0]
|
|
245
|
-
empty_field.enabled = True
|
|
246
|
-
empty_field.key = 'Content-Type'
|
|
247
|
-
empty_field.value = content_type
|
|
248
|
-
await self.header_fields.add_field(
|
|
249
|
-
field=DynamicField(enabled=False, key='', value='')
|
|
250
|
-
)
|
|
251
|
-
|
|
252
257
|
@on(Input.Changed, '#options-timeout')
|
|
253
|
-
def
|
|
258
|
+
def _on_change_timeout(self, message: Input.Changed) -> None:
|
|
254
259
|
new_value = message.value
|
|
255
260
|
|
|
256
261
|
if new_value == '':
|
|
@@ -263,73 +268,70 @@ class RequestArea(Static):
|
|
|
263
268
|
self.options_timeout_input.value[:-1]
|
|
264
269
|
)
|
|
265
270
|
|
|
266
|
-
def
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
271
|
+
def _get_headers(self) -> list[HeaderField]:
|
|
272
|
+
return [
|
|
273
|
+
HeaderField(
|
|
274
|
+
enabled=header_field['enabled'],
|
|
275
|
+
key=header_field['key'],
|
|
276
|
+
value=header_field['value'],
|
|
277
|
+
)
|
|
278
|
+
for header_field in self.header_fields.values
|
|
279
|
+
]
|
|
280
|
+
|
|
281
|
+
def _get_query_params(self) -> list[QueryParamField]:
|
|
282
|
+
return [
|
|
283
|
+
QueryParamField(
|
|
284
|
+
enabled=query_param_field['enabled'],
|
|
285
|
+
key=query_param_field['key'],
|
|
286
|
+
value=query_param_field['value'],
|
|
287
|
+
)
|
|
288
|
+
for query_param_field in self.param_fields.values
|
|
289
|
+
]
|
|
290
|
+
|
|
291
|
+
def _get_body(self) -> RequestAreaData.Body:
|
|
292
|
+
body_send: bool = self.body_enabled_switch.value
|
|
293
|
+
body_type: str = BodyMode(self.body_mode_select.value)
|
|
294
|
+
|
|
295
|
+
payload = None
|
|
296
|
+
if body_type == BodyMode.RAW:
|
|
297
|
+
payload = self.body_raw_editor.text
|
|
298
|
+
elif body_type == BodyMode.FILE:
|
|
299
|
+
payload = self.body_file_path_chooser.path
|
|
300
|
+
elif body_type == BodyMode.FORM_URLENCODED:
|
|
301
|
+
payload = []
|
|
302
|
+
for form_item in self.body_form_urlencoded_fields.values:
|
|
303
|
+
payload.append(
|
|
304
|
+
FormUrlEncodedField(
|
|
305
|
+
enabled=form_item['enabled'],
|
|
306
|
+
key=form_item['key'],
|
|
307
|
+
value=form_item['value'],
|
|
308
|
+
)
|
|
283
309
|
)
|
|
284
|
-
|
|
285
|
-
]
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
if body_type == BodyMode.RAW:
|
|
293
|
-
payload = self.body_raw_editor.text
|
|
294
|
-
elif body_type == BodyMode.FILE:
|
|
295
|
-
payload = self.body_file_path_chooser.path
|
|
296
|
-
elif body_type == BodyMode.FORM_URLENCODED:
|
|
297
|
-
payload = []
|
|
298
|
-
for form_item in self.body_form_urlencoded_fields.values:
|
|
299
|
-
payload.append(
|
|
300
|
-
FormUrlEncodedField(
|
|
301
|
-
enabled=form_item['enabled'],
|
|
302
|
-
key=form_item['key'],
|
|
303
|
-
value=form_item['value'],
|
|
304
|
-
)
|
|
310
|
+
elif body_type == BodyMode.FORM_MULTIPART:
|
|
311
|
+
payload = []
|
|
312
|
+
for form_item in self.body_form_multipart_fields.values:
|
|
313
|
+
payload.append(
|
|
314
|
+
FormMultipartField(
|
|
315
|
+
enabled=form_item['enabled'],
|
|
316
|
+
key=form_item['key'],
|
|
317
|
+
value=form_item['value'],
|
|
305
318
|
)
|
|
319
|
+
)
|
|
306
320
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
payload=payload,
|
|
314
|
-
)
|
|
321
|
+
return RequestAreaData.Body(
|
|
322
|
+
enabled=body_send,
|
|
323
|
+
raw_language=BodyRawLanguage(self.body_raw_language_select.value),
|
|
324
|
+
type=body_type,
|
|
325
|
+
payload=payload,
|
|
326
|
+
)
|
|
315
327
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
328
|
+
def _get_options(self) -> RequestAreaData.Options:
|
|
329
|
+
timeout = None
|
|
330
|
+
if self.options_timeout_input.value:
|
|
331
|
+
timeout = float(self.options_timeout_input.value)
|
|
320
332
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
)
|
|
326
|
-
|
|
327
|
-
return RequestAreaData(
|
|
328
|
-
headers=get_headers(),
|
|
329
|
-
query_params=get_query_params(),
|
|
330
|
-
body=get_body(),
|
|
331
|
-
options=get_options(),
|
|
333
|
+
return RequestAreaData.Options(
|
|
334
|
+
timeout=timeout,
|
|
335
|
+
follow_redirects=self.options_follow_redirects_switch.value,
|
|
336
|
+
verify_ssl=self.options_verify_ssl_switch.value,
|
|
332
337
|
)
|
|
333
|
-
|
|
334
|
-
def set_content_type() -> None:
|
|
335
|
-
raise NotImplementedError()
|
restiny/core/response_area.py
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from http import HTTPStatus
|
|
3
|
+
|
|
1
4
|
from textual import on
|
|
2
5
|
from textual.app import ComposeResult
|
|
3
|
-
from textual.
|
|
6
|
+
from textual.containers import VerticalScroll
|
|
4
7
|
from textual.widgets import (
|
|
5
8
|
ContentSwitcher,
|
|
6
9
|
DataTable,
|
|
@@ -15,6 +18,16 @@ from restiny.enums import BodyRawLanguage
|
|
|
15
18
|
from restiny.widgets import CustomTextArea
|
|
16
19
|
|
|
17
20
|
|
|
21
|
+
@dataclass
|
|
22
|
+
class ResponseAreaData:
|
|
23
|
+
status: HTTPStatus
|
|
24
|
+
size: int
|
|
25
|
+
elapsed_time: float | int
|
|
26
|
+
headers: dict
|
|
27
|
+
body_raw_language: BodyRawLanguage
|
|
28
|
+
body_raw: str
|
|
29
|
+
|
|
30
|
+
|
|
18
31
|
# TODO: Implement 'Trace' tab pane
|
|
19
32
|
class ResponseArea(Static):
|
|
20
33
|
ALLOW_MAXIMIZE = True
|
|
@@ -38,8 +51,6 @@ class ResponseArea(Static):
|
|
|
38
51
|
|
|
39
52
|
"""
|
|
40
53
|
|
|
41
|
-
has_response: bool = Reactive(False, layout=True, init=True)
|
|
42
|
-
|
|
43
54
|
def compose(self) -> ComposeResult:
|
|
44
55
|
with ContentSwitcher(id='response-switcher', initial='no-content'):
|
|
45
56
|
yield Label(
|
|
@@ -49,7 +60,8 @@ class ResponseArea(Static):
|
|
|
49
60
|
|
|
50
61
|
with TabbedContent(id='content'):
|
|
51
62
|
with TabPane('Headers'):
|
|
52
|
-
|
|
63
|
+
with VerticalScroll():
|
|
64
|
+
yield DataTable(show_cursor=False, id='headers')
|
|
53
65
|
with TabPane('Body'):
|
|
54
66
|
yield Select(
|
|
55
67
|
(
|
|
@@ -60,11 +72,11 @@ class ResponseArea(Static):
|
|
|
60
72
|
('XML', BodyRawLanguage.XML),
|
|
61
73
|
),
|
|
62
74
|
allow_blank=False,
|
|
63
|
-
tooltip='
|
|
64
|
-
id='body-
|
|
75
|
+
tooltip='Syntax highlighting for the response body',
|
|
76
|
+
id='body-raw-language',
|
|
65
77
|
)
|
|
66
78
|
yield CustomTextArea.code_editor(
|
|
67
|
-
id='body', read_only=True, classes='mt-1'
|
|
79
|
+
id='body-raw', read_only=True, classes='mt-1'
|
|
68
80
|
)
|
|
69
81
|
|
|
70
82
|
def on_mount(self) -> None:
|
|
@@ -73,25 +85,46 @@ class ResponseArea(Static):
|
|
|
73
85
|
)
|
|
74
86
|
|
|
75
87
|
self.headers_data_table = self.query_one('#headers', DataTable)
|
|
76
|
-
self.
|
|
77
|
-
|
|
88
|
+
self.body_raw_language_select = self.query_one(
|
|
89
|
+
'#body-raw-language', Select
|
|
90
|
+
)
|
|
91
|
+
self.body_raw_editor = self.query_one('#body-raw', CustomTextArea)
|
|
78
92
|
|
|
79
93
|
self.headers_data_table.add_columns('Key', 'Value')
|
|
80
94
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
self.
|
|
95
|
+
def set_data(self, data: ResponseAreaData | None) -> None:
|
|
96
|
+
self.border_title = self.BORDER_TITLE
|
|
97
|
+
self.border_subtitle = ''
|
|
98
|
+
self.headers_data_table.clear()
|
|
99
|
+
self.body_raw_language_select.value = BodyRawLanguage.PLAIN
|
|
100
|
+
self.body_raw_editor.clear()
|
|
84
101
|
|
|
85
|
-
|
|
102
|
+
if data is None:
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
self.border_title = f'Response - {data.status} {data.status.phrase}'
|
|
106
|
+
self.border_subtitle = (
|
|
107
|
+
f'{data.size} bytes in {data.elapsed_time} seconds'
|
|
108
|
+
)
|
|
109
|
+
for header_key, header_value in data.headers.items():
|
|
110
|
+
self.headers_data_table.add_row(header_key, header_value)
|
|
111
|
+
self.body_raw_language_select.value = data.body_raw_language
|
|
112
|
+
self.body_raw_editor.text = data.body_raw
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def is_showing_response(self) -> bool:
|
|
116
|
+
if self._response_switcher.current == 'content':
|
|
117
|
+
return True
|
|
118
|
+
elif self._response_switcher.current == 'no-content':
|
|
119
|
+
return False
|
|
120
|
+
|
|
121
|
+
@is_showing_response.setter
|
|
122
|
+
def is_showing_response(self, value: bool) -> None:
|
|
86
123
|
if value is True:
|
|
87
124
|
self._response_switcher.current = 'content'
|
|
88
125
|
elif value is False:
|
|
89
126
|
self._response_switcher.current = 'no-content'
|
|
90
|
-
self.reset_response()
|
|
91
127
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
self.
|
|
95
|
-
self.headers_data_table.clear()
|
|
96
|
-
self.body_type_select.value = BodyRawLanguage.PLAIN
|
|
97
|
-
self.body_text_area.clear()
|
|
128
|
+
@on(Select.Changed, '#body-raw-language')
|
|
129
|
+
def _on_body_raw_language_changed(self, message: Select.Changed) -> None:
|
|
130
|
+
self.body_raw_editor.language = self.body_raw_language_select.value
|
restiny/core/url_area.py
CHANGED
|
@@ -3,7 +3,6 @@ from dataclasses import dataclass
|
|
|
3
3
|
from textual import on
|
|
4
4
|
from textual.app import ComposeResult
|
|
5
5
|
from textual.message import Message
|
|
6
|
-
from textual.reactive import Reactive
|
|
7
6
|
from textual.widgets import Button, ContentSwitcher, Input, Select, Static
|
|
8
7
|
|
|
9
8
|
from restiny.enums import HTTPMethod
|
|
@@ -29,8 +28,6 @@ class URLArea(Static):
|
|
|
29
28
|
}
|
|
30
29
|
"""
|
|
31
30
|
|
|
32
|
-
request_pending = Reactive(False)
|
|
33
|
-
|
|
34
31
|
class SendRequest(Message):
|
|
35
32
|
"""
|
|
36
33
|
Sent when the user send a request.
|
|
@@ -47,11 +44,15 @@ class URLArea(Static):
|
|
|
47
44
|
def __init__(self) -> None:
|
|
48
45
|
super().__init__()
|
|
49
46
|
|
|
47
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
48
|
+
super().__init__(*args, **kwargs)
|
|
49
|
+
self._request_pending = False
|
|
50
|
+
|
|
50
51
|
def compose(self) -> ComposeResult:
|
|
51
52
|
yield Select.from_values(
|
|
52
53
|
values=HTTPMethod.values(), allow_blank=False, id='method'
|
|
53
54
|
)
|
|
54
|
-
yield Input(placeholder='Enter URL', id='url')
|
|
55
|
+
yield Input(placeholder='Enter URL', select_on_focus=False, id='url')
|
|
55
56
|
with ContentSwitcher(
|
|
56
57
|
id='request-button-switcher', initial='send-request'
|
|
57
58
|
):
|
|
@@ -78,9 +79,28 @@ class URLArea(Static):
|
|
|
78
79
|
self.send_request_button = self.query_one('#send-request', Button)
|
|
79
80
|
self.cancel_request_button = self.query_one('#cancel-request', Button)
|
|
80
81
|
|
|
82
|
+
def get_data(self) -> URLAreaData:
|
|
83
|
+
return URLAreaData(
|
|
84
|
+
method=self.method_select.value,
|
|
85
|
+
url=self.url_input.value,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def request_pending(self) -> bool:
|
|
90
|
+
return self._request_pending
|
|
91
|
+
|
|
92
|
+
@request_pending.setter
|
|
93
|
+
def request_pending(self, value: bool) -> None:
|
|
94
|
+
if value is True:
|
|
95
|
+
self._request_button_switcher.current = 'cancel-request'
|
|
96
|
+
elif value is False:
|
|
97
|
+
self._request_button_switcher.current = 'send-request'
|
|
98
|
+
|
|
99
|
+
self._request_pending = value
|
|
100
|
+
|
|
81
101
|
@on(Button.Pressed, '#send-request')
|
|
82
|
-
@on(Input.Submitted)
|
|
83
|
-
def
|
|
102
|
+
@on(Input.Submitted, '#url')
|
|
103
|
+
def _on_send_request(
|
|
84
104
|
self, message: Button.Pressed | Input.Submitted
|
|
85
105
|
) -> None:
|
|
86
106
|
if self.request_pending:
|
|
@@ -88,22 +108,10 @@ class URLArea(Static):
|
|
|
88
108
|
|
|
89
109
|
self.post_message(message=self.SendRequest())
|
|
90
110
|
|
|
91
|
-
@on(Input.Submitted)
|
|
92
111
|
@on(Button.Pressed, '#cancel-request')
|
|
93
|
-
|
|
112
|
+
@on(Input.Submitted, '#url')
|
|
113
|
+
def _on_cancel_request(self, message: Button.Pressed) -> None:
|
|
94
114
|
if not self.request_pending:
|
|
95
115
|
return
|
|
96
116
|
|
|
97
117
|
self.post_message(message=self.CancelRequest())
|
|
98
|
-
|
|
99
|
-
def watch_request_pending(self, value: bool) -> None:
|
|
100
|
-
if value is True:
|
|
101
|
-
self._request_button_switcher.current = 'cancel-request'
|
|
102
|
-
elif value is False:
|
|
103
|
-
self._request_button_switcher.current = 'send-request'
|
|
104
|
-
|
|
105
|
-
def get_data(self) -> URLAreaData:
|
|
106
|
-
return URLAreaData(
|
|
107
|
-
method=self.method_select.value,
|
|
108
|
-
url=self.url_input.value,
|
|
109
|
-
)
|
restiny/enums.py
CHANGED
restiny/widgets/__init__.py
CHANGED
|
@@ -4,11 +4,11 @@ This module contains reusable widgets used in the DataFox interface.
|
|
|
4
4
|
|
|
5
5
|
from restiny.widgets.custom_directory_tree import CustomDirectoryTree
|
|
6
6
|
from restiny.widgets.custom_text_area import CustomTextArea
|
|
7
|
-
from restiny.widgets.dynamic_fields import
|
|
7
|
+
from restiny.widgets.dynamic_fields import DynamicFields, TextDynamicField
|
|
8
8
|
from restiny.widgets.path_chooser import PathChooser
|
|
9
9
|
|
|
10
10
|
__all__ = [
|
|
11
|
-
'
|
|
11
|
+
'TextDynamicField',
|
|
12
12
|
'DynamicFields',
|
|
13
13
|
'CustomDirectoryTree',
|
|
14
14
|
'CustomTextArea',
|