restiny 0.2.0__py3-none-any.whl → 0.3.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.

Potentially problematic release.


This version of restiny might be problematic. Click here for more details.

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 on_send_request(
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
- def on_cancel_request(self, message: Button.Pressed) -> None:
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
@@ -41,3 +41,10 @@ class ContentType(StrEnum):
41
41
  XML = 'application/xml'
42
42
  FORM_URLENCODED = 'application/x-www-form-urlencoded'
43
43
  FORM_MULTIPART = 'multipart/form-data'
44
+
45
+
46
+ class AuthMode(StrEnum):
47
+ BASIC = 'basic'
48
+ BEARER = 'bearer'
49
+ API_KEY = 'api_key'
50
+ DIGEST = 'digest'
restiny/httpx_auths.py ADDED
@@ -0,0 +1,52 @@
1
+ from collections.abc import Generator
2
+
3
+ import httpx
4
+
5
+
6
+ class BearerAuth(httpx.Auth):
7
+ """
8
+ Adds a Bearer token to the Authorization header of each request.
9
+ """
10
+
11
+ def __init__(self, token: str) -> None:
12
+ self._token = token
13
+
14
+ def auth_flow(
15
+ self, request: httpx.Request
16
+ ) -> Generator[httpx.Request, httpx.Response]:
17
+ request.headers['authorization'] = f'Bearer {self._token}'
18
+ yield request
19
+
20
+
21
+ class APIKeyHeaderAuth(httpx.Auth):
22
+ """
23
+ Adds an API key to the request headers.
24
+ """
25
+
26
+ def __init__(self, key: str, value: str) -> None:
27
+ self._key = key
28
+ self._value = value
29
+
30
+ def auth_flow(
31
+ self, request: httpx.Request
32
+ ) -> Generator[httpx.Request, httpx.Response]:
33
+ request.headers[self._key] = self._value
34
+ yield request
35
+
36
+
37
+ class APIKeyParamAuth(httpx.Auth):
38
+ """
39
+ Adds an API key as a query parameter to the request URL.
40
+ """
41
+
42
+ def __init__(self, key: str, value: str) -> None:
43
+ self._key = key
44
+ self._value = value
45
+
46
+ def auth_flow(
47
+ self, request: httpx.Request
48
+ ) -> Generator[httpx.Request, httpx.Response]:
49
+ request.url = request.url.copy_with(
50
+ params=request.url.params.set(self._key, self._value)
51
+ )
52
+ yield request
restiny/test.py ADDED
@@ -0,0 +1,13 @@
1
+ import random
2
+
3
+
4
+ def test(aaa={}):
5
+ aaa[random.randint(1, 10)] = random.randint(1, 10)
6
+ print(aaa)
7
+
8
+
9
+ test()
10
+ test()
11
+ test()
12
+ test()
13
+ test()
restiny/utils.py CHANGED
@@ -8,32 +8,43 @@ import httpx
8
8
  def build_curl_cmd(
9
9
  method: str,
10
10
  url: str,
11
- headers: dict[str, str] = {},
12
- params: dict[str, str] = {},
13
- raw_body: str | None = None,
14
- form_urlencoded: dict[str, str] = {},
15
- form_multipart: dict[str, str | Path] = {},
16
- files: list[Path] = [],
11
+ headers: dict[str, str] | None = None,
12
+ params: dict[str, str] | None = None,
13
+ body_raw: str | None = None,
14
+ body_form_urlencoded: dict[str, str] | None = None,
15
+ body_form_multipart: dict[str, str | Path] | None = None,
16
+ body_files: list[Path] | None = None,
17
+ auth_basic: tuple[str, str] | None = None,
18
+ auth_bearer: str | None = None,
19
+ auth_api_key_header: tuple[str, str] | None = None,
20
+ auth_api_key_param: tuple[str, str] | None = None,
21
+ auth_digest: tuple[str, str] | None = None,
17
22
  ) -> str:
18
23
  cmd_parts = ['curl']
24
+
25
+ # Method
19
26
  cmd_parts.extend(['--request', method])
20
27
 
21
- url = str(httpx.URL(url).copy_merge_params(params))
28
+ # URL + Params
29
+ if params:
30
+ url = str(httpx.URL(url).copy_merge_params(params))
22
31
  cmd_parts.extend(['--url', shlex.quote(url)])
23
32
 
33
+ # Headers
24
34
  for header_key, header_value in headers.items():
25
35
  header = f'{header_key}: {header_value}'
26
36
  cmd_parts.extend(['--header', shlex.quote(header)])
27
37
 
28
- if raw_body:
29
- cmd_parts.extend(['--data', shlex.quote(raw_body)])
30
- elif form_urlencoded:
31
- for form_key, form_value in form_urlencoded.items():
38
+ # Body
39
+ if body_raw:
40
+ cmd_parts.extend(['--data', shlex.quote(body_raw)])
41
+ elif body_form_urlencoded:
42
+ for form_key, form_value in body_form_urlencoded.items():
32
43
  cmd_parts.extend(
33
44
  ['--data', shlex.quote(f'{form_key}={form_value}')]
34
45
  )
35
- elif form_multipart:
36
- for form_key, form_value in form_multipart.items():
46
+ elif body_form_multipart:
47
+ for form_key, form_value in body_form_multipart.items():
37
48
  if isinstance(form_value, str):
38
49
  cmd_parts.extend(
39
50
  ['--form', shlex.quote(f'{form_key}={form_value}')]
@@ -42,10 +53,29 @@ def build_curl_cmd(
42
53
  cmd_parts.extend(
43
54
  ['--form', shlex.quote(f'{form_key}=@{form_value}')]
44
55
  )
45
- elif files:
46
- for file in files:
56
+ elif body_files:
57
+ for file in body_files:
47
58
  cmd_parts.extend(['--data', shlex.quote(f'@{file}')])
48
59
 
60
+ # Auth
61
+ if auth_basic:
62
+ user, pwd = auth_basic
63
+ cmd_parts.extend(['--user', shlex.quote(f'{user}:{pwd}')])
64
+ elif auth_bearer:
65
+ token = auth_bearer
66
+ cmd_parts.extend(['--header', shlex.quote(f'Authorization: {token}')])
67
+ elif auth_api_key_header:
68
+ key, value = auth_api_key_header
69
+ cmd_parts.extend(['--header', shlex.quote(f'{key}: {value}')])
70
+ elif auth_api_key_param:
71
+ key, value = auth_api_key_param
72
+ url_arg_index = cmd_parts.index('--url')
73
+ new_url = str(httpx.URL(url).copy_merge_params({key: value}))
74
+ cmd_parts[url_arg_index + 1] = shlex.quote(new_url)
75
+ elif auth_digest:
76
+ user, pwd = auth_digest
77
+ cmd_parts.extend(['--digest', '--user', shlex.quote(f'{user}:{pwd}')])
78
+
49
79
  return ' '.join(cmd_parts)
50
80
 
51
81
 
@@ -5,6 +5,7 @@ This module contains reusable widgets used in the DataFox interface.
5
5
  from restiny.widgets.custom_directory_tree import CustomDirectoryTree
6
6
  from restiny.widgets.custom_text_area import CustomTextArea
7
7
  from restiny.widgets.dynamic_fields import DynamicFields, TextDynamicField
8
+ from restiny.widgets.password_input import PasswordInput
8
9
  from restiny.widgets.path_chooser import PathChooser
9
10
 
10
11
  __all__ = [
@@ -13,4 +14,5 @@ __all__ = [
13
14
  'CustomDirectoryTree',
14
15
  'CustomTextArea',
15
16
  'PathChooser',
17
+ 'PasswordInput',
16
18
  ]