restiny 0.2.1__py3-none-any.whl → 0.5.0__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/__main__.py +26 -14
- restiny/assets/style.tcss +47 -1
- restiny/consts.py +236 -0
- restiny/data/db.py +60 -0
- restiny/data/models.py +90 -0
- restiny/data/repos.py +351 -0
- restiny/data/sql/__init__.py +3 -0
- restiny/entities.py +320 -0
- restiny/enums.py +14 -5
- restiny/httpx_auths.py +52 -0
- restiny/ui/__init__.py +15 -0
- restiny/ui/app.py +500 -0
- restiny/ui/collections_area.py +569 -0
- restiny/ui/request_area.py +575 -0
- restiny/ui/settings_screen.py +80 -0
- restiny/{core → ui}/url_area.py +50 -38
- restiny/utils.py +52 -15
- restiny/widgets/__init__.py +15 -1
- restiny/widgets/collections_tree.py +70 -0
- restiny/widgets/confirm_prompt.py +76 -0
- restiny/widgets/custom_input.py +20 -0
- restiny/widgets/dynamic_fields.py +65 -70
- restiny/widgets/password_input.py +161 -0
- restiny/widgets/path_chooser.py +12 -12
- {restiny-0.2.1.dist-info → restiny-0.5.0.dist-info}/METADATA +7 -5
- restiny-0.5.0.dist-info/RECORD +36 -0
- restiny/core/__init__.py +0 -15
- restiny/core/app.py +0 -348
- restiny/core/request_area.py +0 -337
- restiny-0.2.1.dist-info/RECORD +0 -24
- /restiny/{core → ui}/response_area.py +0 -0
- {restiny-0.2.1.dist-info → restiny-0.5.0.dist-info}/WHEEL +0 -0
- {restiny-0.2.1.dist-info → restiny-0.5.0.dist-info}/entry_points.txt +0 -0
- {restiny-0.2.1.dist-info → restiny-0.5.0.dist-info}/licenses/LICENSE +0 -0
- {restiny-0.2.1.dist-info → restiny-0.5.0.dist-info}/top_level.txt +0 -0
restiny/core/request_area.py
DELETED
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
|
|
4
|
-
from textual import on
|
|
5
|
-
from textual.app import ComposeResult
|
|
6
|
-
from textual.containers import Container, Horizontal
|
|
7
|
-
from textual.widgets import (
|
|
8
|
-
ContentSwitcher,
|
|
9
|
-
Input,
|
|
10
|
-
Label,
|
|
11
|
-
Select,
|
|
12
|
-
Static,
|
|
13
|
-
Switch,
|
|
14
|
-
TabbedContent,
|
|
15
|
-
TabPane,
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
from restiny.enums import BodyMode, BodyRawLanguage
|
|
19
|
-
from restiny.widgets import (
|
|
20
|
-
CustomTextArea,
|
|
21
|
-
DynamicFields,
|
|
22
|
-
PathChooser,
|
|
23
|
-
TextDynamicField,
|
|
24
|
-
)
|
|
25
|
-
from restiny.widgets.dynamic_fields import TextOrFileDynamicField
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
@dataclass
|
|
29
|
-
class HeaderField:
|
|
30
|
-
enabled: bool
|
|
31
|
-
key: str
|
|
32
|
-
value: str
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
@dataclass
|
|
36
|
-
class QueryParamField:
|
|
37
|
-
enabled: bool
|
|
38
|
-
key: str
|
|
39
|
-
value: str
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
@dataclass
|
|
43
|
-
class FormUrlEncodedField:
|
|
44
|
-
enabled: bool
|
|
45
|
-
key: str
|
|
46
|
-
value: str
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
@dataclass
|
|
50
|
-
class FormMultipartField:
|
|
51
|
-
enabled: bool
|
|
52
|
-
key: str
|
|
53
|
-
value: str | Path
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
@dataclass
|
|
57
|
-
class RequestAreaData:
|
|
58
|
-
@dataclass
|
|
59
|
-
class Options:
|
|
60
|
-
timeout: int | float | None
|
|
61
|
-
follow_redirects: bool
|
|
62
|
-
verify_ssl: bool
|
|
63
|
-
|
|
64
|
-
@dataclass
|
|
65
|
-
class Body:
|
|
66
|
-
enabled: bool
|
|
67
|
-
raw_language: BodyRawLanguage | None
|
|
68
|
-
type: BodyMode
|
|
69
|
-
payload: (
|
|
70
|
-
str
|
|
71
|
-
| Path
|
|
72
|
-
| list[FormUrlEncodedField]
|
|
73
|
-
| list[FormMultipartField]
|
|
74
|
-
| None
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
headers: list[HeaderField]
|
|
78
|
-
query_params: list[QueryParamField]
|
|
79
|
-
body: Body
|
|
80
|
-
options: Options
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
class RequestArea(Static):
|
|
84
|
-
ALLOW_MAXIMIZE = True
|
|
85
|
-
focusable = True
|
|
86
|
-
BORDER_TITLE = 'Request'
|
|
87
|
-
DEFAULT_CSS = """
|
|
88
|
-
RequestArea {
|
|
89
|
-
width: 1fr;
|
|
90
|
-
height: 1fr;
|
|
91
|
-
border: heavy black;
|
|
92
|
-
border-title-color: gray;
|
|
93
|
-
padding: 1;
|
|
94
|
-
}
|
|
95
|
-
"""
|
|
96
|
-
|
|
97
|
-
def compose(self) -> ComposeResult:
|
|
98
|
-
with TabbedContent():
|
|
99
|
-
with TabPane('Headers'):
|
|
100
|
-
yield DynamicFields(
|
|
101
|
-
fields=[TextDynamicField(enabled=False, key='', value='')],
|
|
102
|
-
id='headers',
|
|
103
|
-
)
|
|
104
|
-
with TabPane('Query params'):
|
|
105
|
-
yield DynamicFields(
|
|
106
|
-
fields=[TextDynamicField(enabled=False, key='', value='')],
|
|
107
|
-
id='params',
|
|
108
|
-
)
|
|
109
|
-
with TabPane('Body'):
|
|
110
|
-
with Horizontal(classes='h-auto'):
|
|
111
|
-
yield Switch(id='body-enabled', tooltip='Send body?')
|
|
112
|
-
yield Select(
|
|
113
|
-
(
|
|
114
|
-
('Raw', BodyMode.RAW),
|
|
115
|
-
('File', BodyMode.FILE),
|
|
116
|
-
('Form (urlencoded)', BodyMode.FORM_URLENCODED),
|
|
117
|
-
('Form (multipart)', BodyMode.FORM_MULTIPART),
|
|
118
|
-
),
|
|
119
|
-
allow_blank=False,
|
|
120
|
-
tooltip='Body type',
|
|
121
|
-
id='body-mode',
|
|
122
|
-
)
|
|
123
|
-
with ContentSwitcher(
|
|
124
|
-
id='body-mode-switcher',
|
|
125
|
-
initial='body-mode-raw',
|
|
126
|
-
classes='h-1fr',
|
|
127
|
-
):
|
|
128
|
-
with Container(id='body-mode-raw', classes='pt-1'):
|
|
129
|
-
yield Select(
|
|
130
|
-
(
|
|
131
|
-
('Plain', BodyRawLanguage.PLAIN),
|
|
132
|
-
('JSON', BodyRawLanguage.JSON),
|
|
133
|
-
('YAML', BodyRawLanguage.YAML),
|
|
134
|
-
('XML', BodyRawLanguage.XML),
|
|
135
|
-
('HTML', BodyRawLanguage.HTML),
|
|
136
|
-
),
|
|
137
|
-
allow_blank=False,
|
|
138
|
-
tooltip='Text type',
|
|
139
|
-
id='body-raw-language',
|
|
140
|
-
)
|
|
141
|
-
yield CustomTextArea.code_editor(
|
|
142
|
-
language='json', id='body-raw', classes='mt-1'
|
|
143
|
-
)
|
|
144
|
-
with Horizontal(
|
|
145
|
-
id='body-mode-file', classes='h-auto mt-1'
|
|
146
|
-
):
|
|
147
|
-
yield PathChooser.file(id='body-file')
|
|
148
|
-
with Horizontal(
|
|
149
|
-
id='body-mode-form-urlencoded', classes='h-auto mt-1'
|
|
150
|
-
):
|
|
151
|
-
yield DynamicFields(
|
|
152
|
-
[
|
|
153
|
-
TextDynamicField(
|
|
154
|
-
enabled=False, key='', value=''
|
|
155
|
-
)
|
|
156
|
-
],
|
|
157
|
-
id='body-form-urlencoded',
|
|
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
|
-
)
|
|
170
|
-
|
|
171
|
-
with TabPane('Options'):
|
|
172
|
-
with Horizontal(classes='h-auto'):
|
|
173
|
-
yield Label('Timeout', classes='pt-1 ml-1')
|
|
174
|
-
yield Input(
|
|
175
|
-
'5.5',
|
|
176
|
-
placeholder='5.5',
|
|
177
|
-
select_on_focus=False,
|
|
178
|
-
id='options-timeout',
|
|
179
|
-
classes='w-1fr',
|
|
180
|
-
)
|
|
181
|
-
with Horizontal(classes='mt-1 h-auto'):
|
|
182
|
-
yield Switch(id='options-follow-redirects')
|
|
183
|
-
yield Label('Follow redirects', classes='pt-1')
|
|
184
|
-
with Horizontal(classes='h-auto'):
|
|
185
|
-
yield Switch(id='options-verify-ssl')
|
|
186
|
-
yield Label('Verify SSL', classes='pt-1')
|
|
187
|
-
|
|
188
|
-
def on_mount(self) -> None:
|
|
189
|
-
self.header_fields = self.query_one('#headers', DynamicFields)
|
|
190
|
-
|
|
191
|
-
self.param_fields = self.query_one('#params', DynamicFields)
|
|
192
|
-
|
|
193
|
-
self.body_enabled_switch = self.query_one('#body-enabled', Switch)
|
|
194
|
-
self.body_mode_select = self.query_one('#body-mode', Select)
|
|
195
|
-
self.body_mode_switcher = self.query_one(
|
|
196
|
-
'#body-mode-switcher', ContentSwitcher
|
|
197
|
-
)
|
|
198
|
-
self.body_raw_editor = self.query_one('#body-raw', CustomTextArea)
|
|
199
|
-
self.body_raw_language_select = self.query_one(
|
|
200
|
-
'#body-raw-language', Select
|
|
201
|
-
)
|
|
202
|
-
self.body_file_path_chooser = self.query_one('#body-file', PathChooser)
|
|
203
|
-
self.body_form_urlencoded_fields = self.query_one(
|
|
204
|
-
'#body-form-urlencoded', DynamicFields
|
|
205
|
-
)
|
|
206
|
-
self.body_form_multipart_fields = self.query_one(
|
|
207
|
-
'#body-form-multipart', DynamicFields
|
|
208
|
-
)
|
|
209
|
-
|
|
210
|
-
self.options_timeout_input = self.query_one('#options-timeout', Input)
|
|
211
|
-
self.options_follow_redirects_switch = self.query_one(
|
|
212
|
-
'#options-follow-redirects', Switch
|
|
213
|
-
)
|
|
214
|
-
self.options_verify_ssl_switch = self.query_one(
|
|
215
|
-
'#options-verify-ssl', Switch
|
|
216
|
-
)
|
|
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
|
-
|
|
226
|
-
@on(Select.Changed, '#body-mode')
|
|
227
|
-
def _on_change_body_type(self, message: Select.Changed) -> None:
|
|
228
|
-
if message.value == BodyMode.FILE:
|
|
229
|
-
self.body_mode_switcher.current = 'body-mode-file'
|
|
230
|
-
elif message.value == BodyMode.RAW:
|
|
231
|
-
self.body_mode_switcher.current = 'body-mode-raw'
|
|
232
|
-
elif message.value == BodyMode.FORM_URLENCODED:
|
|
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'
|
|
236
|
-
|
|
237
|
-
@on(Select.Changed, '#body-raw-language')
|
|
238
|
-
def _on_change_body_raw_language(self, message: Select.Changed) -> None:
|
|
239
|
-
self.body_raw_editor.language = message.value
|
|
240
|
-
|
|
241
|
-
@on(DynamicFields.FieldFilled, '#body-form-urlencoded')
|
|
242
|
-
def _on_form_filled(self, message: DynamicFields.FieldFilled) -> None:
|
|
243
|
-
self.body_enabled_switch.value = True
|
|
244
|
-
|
|
245
|
-
@on(DynamicFields.FieldEmpty, '#body-form-urlencoded')
|
|
246
|
-
def _on_form_empty(self, message: DynamicFields.FieldEmpty) -> None:
|
|
247
|
-
if not message.control.filled_fields:
|
|
248
|
-
self.body_enabled_switch.value = False
|
|
249
|
-
|
|
250
|
-
@on(CustomTextArea.Changed, '#body-raw')
|
|
251
|
-
def _on_change_body_raw(self, message: CustomTextArea.Changed) -> None:
|
|
252
|
-
if self.body_raw_editor.text == '':
|
|
253
|
-
self.body_enabled_switch.value = False
|
|
254
|
-
else:
|
|
255
|
-
self.body_enabled_switch.value = True
|
|
256
|
-
|
|
257
|
-
@on(Input.Changed, '#options-timeout')
|
|
258
|
-
def _on_change_timeout(self, message: Input.Changed) -> None:
|
|
259
|
-
new_value = message.value
|
|
260
|
-
|
|
261
|
-
if new_value == '':
|
|
262
|
-
return
|
|
263
|
-
|
|
264
|
-
try:
|
|
265
|
-
float(new_value)
|
|
266
|
-
except Exception:
|
|
267
|
-
self.options_timeout_input.value = (
|
|
268
|
-
self.options_timeout_input.value[:-1]
|
|
269
|
-
)
|
|
270
|
-
|
|
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
|
-
)
|
|
309
|
-
)
|
|
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'],
|
|
318
|
-
)
|
|
319
|
-
)
|
|
320
|
-
|
|
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
|
-
)
|
|
327
|
-
|
|
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)
|
|
332
|
-
|
|
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,
|
|
337
|
-
)
|
restiny-0.2.1.dist-info/RECORD
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|