nadeshiko-sdk 0.1.0__py3-none-any.whl → 0.2.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.
- nadeshiko/__init__.py +1 -2
- nadeshiko/_version.py +1 -1
- nadeshiko/client.py +189 -55
- {nadeshiko_sdk-0.1.0.dist-info → nadeshiko_sdk-0.2.0.dist-info}/METADATA +4 -1
- {nadeshiko_sdk-0.1.0.dist-info → nadeshiko_sdk-0.2.0.dist-info}/RECORD +6 -6
- {nadeshiko_sdk-0.1.0.dist-info → nadeshiko_sdk-0.2.0.dist-info}/WHEEL +0 -0
nadeshiko/__init__.py
CHANGED
nadeshiko/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.
|
|
1
|
+
__version__ = "0.2.0"
|
nadeshiko/client.py
CHANGED
|
@@ -1,103 +1,226 @@
|
|
|
1
1
|
import ssl
|
|
2
|
-
from enum import Enum
|
|
3
2
|
from typing import Any
|
|
4
3
|
|
|
5
4
|
import httpx
|
|
6
5
|
from attrs import define, evolve, field
|
|
7
6
|
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
@define
|
|
9
|
+
class Client:
|
|
10
|
+
"""A class for keeping track of data related to the API
|
|
11
|
+
|
|
12
|
+
The following are accepted as keyword arguments and will be used to construct httpx Clients internally:
|
|
13
|
+
|
|
14
|
+
``base_url``: The base URL for the API, all requests are made to a relative path to this URL
|
|
15
|
+
|
|
16
|
+
``cookies``: A dictionary of cookies to be sent with every request
|
|
17
|
+
|
|
18
|
+
``headers``: A dictionary of headers to be sent with every request
|
|
19
|
+
|
|
20
|
+
``timeout``: The maximum amount of a time a request can take. API functions will raise
|
|
21
|
+
httpx.TimeoutException if this is exceeded.
|
|
22
|
+
|
|
23
|
+
``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production,
|
|
24
|
+
but can be set to False for testing purposes.
|
|
25
|
+
|
|
26
|
+
``follow_redirects``: Whether or not to follow redirects. Default value is False.
|
|
27
|
+
|
|
28
|
+
``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
Attributes:
|
|
32
|
+
raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a
|
|
33
|
+
status code that was not documented in the source OpenAPI document. Can also be provided as a keyword
|
|
34
|
+
argument to the constructor.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
raise_on_unexpected_status: bool = field(default=False, kw_only=True)
|
|
38
|
+
_base_url: str = field(alias="base_url")
|
|
39
|
+
_cookies: dict[str, str] = field(factory=dict, kw_only=True, alias="cookies")
|
|
40
|
+
_headers: dict[str, str] = field(factory=dict, kw_only=True, alias="headers")
|
|
41
|
+
_timeout: httpx.Timeout | None = field(default=None, kw_only=True, alias="timeout")
|
|
42
|
+
_verify_ssl: str | bool | ssl.SSLContext = field(default=True, kw_only=True, alias="verify_ssl")
|
|
43
|
+
_follow_redirects: bool = field(default=False, kw_only=True, alias="follow_redirects")
|
|
44
|
+
_httpx_args: dict[str, Any] = field(factory=dict, kw_only=True, alias="httpx_args")
|
|
45
|
+
_client: httpx.Client | None = field(default=None, init=False)
|
|
46
|
+
_async_client: httpx.AsyncClient | None = field(default=None, init=False)
|
|
47
|
+
|
|
48
|
+
def with_headers(self, headers: dict[str, str]) -> "Client":
|
|
49
|
+
"""Get a new client matching this one with additional headers"""
|
|
50
|
+
if self._client is not None:
|
|
51
|
+
self._client.headers.update(headers)
|
|
52
|
+
if self._async_client is not None:
|
|
53
|
+
self._async_client.headers.update(headers)
|
|
54
|
+
return evolve(self, headers={**self._headers, **headers})
|
|
11
55
|
|
|
12
|
-
|
|
13
|
-
|
|
56
|
+
def with_cookies(self, cookies: dict[str, str]) -> "Client":
|
|
57
|
+
"""Get a new client matching this one with additional cookies"""
|
|
58
|
+
if self._client is not None:
|
|
59
|
+
self._client.cookies.update(cookies)
|
|
60
|
+
if self._async_client is not None:
|
|
61
|
+
self._async_client.cookies.update(cookies)
|
|
62
|
+
return evolve(self, cookies={**self._cookies, **cookies})
|
|
14
63
|
|
|
64
|
+
def with_timeout(self, timeout: httpx.Timeout) -> "Client":
|
|
65
|
+
"""Get a new client matching this one with a new timeout configuration"""
|
|
66
|
+
if self._client is not None:
|
|
67
|
+
self._client.timeout = timeout
|
|
68
|
+
if self._async_client is not None:
|
|
69
|
+
self._async_client.timeout = timeout
|
|
70
|
+
return evolve(self, timeout=timeout)
|
|
15
71
|
|
|
16
|
-
def
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
72
|
+
def set_httpx_client(self, client: httpx.Client) -> "Client":
|
|
73
|
+
"""Manually set the underlying httpx.Client
|
|
74
|
+
|
|
75
|
+
**NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
|
|
76
|
+
"""
|
|
77
|
+
self._client = client
|
|
78
|
+
return self
|
|
79
|
+
|
|
80
|
+
def get_httpx_client(self) -> httpx.Client:
|
|
81
|
+
"""Get the underlying httpx.Client, constructing a new one if not previously set"""
|
|
82
|
+
if self._client is None:
|
|
83
|
+
self._client = httpx.Client(
|
|
84
|
+
base_url=self._base_url,
|
|
85
|
+
cookies=self._cookies,
|
|
86
|
+
headers=self._headers,
|
|
87
|
+
timeout=self._timeout,
|
|
88
|
+
verify=self._verify_ssl,
|
|
89
|
+
follow_redirects=self._follow_redirects,
|
|
90
|
+
**self._httpx_args,
|
|
91
|
+
)
|
|
92
|
+
return self._client
|
|
93
|
+
|
|
94
|
+
def __enter__(self) -> "Client":
|
|
95
|
+
"""Enter a context manager for self.client—you cannot enter twice (see httpx docs)"""
|
|
96
|
+
self.get_httpx_client().__enter__()
|
|
97
|
+
return self
|
|
98
|
+
|
|
99
|
+
def __exit__(self, *args: Any, **kwargs: Any) -> None:
|
|
100
|
+
"""Exit a context manager for internal httpx.Client (see httpx docs)"""
|
|
101
|
+
self.get_httpx_client().__exit__(*args, **kwargs)
|
|
102
|
+
|
|
103
|
+
def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "Client":
|
|
104
|
+
"""Manually set the underlying httpx.AsyncClient
|
|
105
|
+
|
|
106
|
+
**NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
|
|
107
|
+
"""
|
|
108
|
+
self._async_client = async_client
|
|
109
|
+
return self
|
|
110
|
+
|
|
111
|
+
def get_async_httpx_client(self) -> httpx.AsyncClient:
|
|
112
|
+
"""Get the underlying httpx.AsyncClient, constructing a new one if not previously set"""
|
|
113
|
+
if self._async_client is None:
|
|
114
|
+
self._async_client = httpx.AsyncClient(
|
|
115
|
+
base_url=self._base_url,
|
|
116
|
+
cookies=self._cookies,
|
|
117
|
+
headers=self._headers,
|
|
118
|
+
timeout=self._timeout,
|
|
119
|
+
verify=self._verify_ssl,
|
|
120
|
+
follow_redirects=self._follow_redirects,
|
|
121
|
+
**self._httpx_args,
|
|
122
|
+
)
|
|
123
|
+
return self._async_client
|
|
124
|
+
|
|
125
|
+
async def __aenter__(self) -> "Client":
|
|
126
|
+
"""Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)"""
|
|
127
|
+
await self.get_async_httpx_client().__aenter__()
|
|
128
|
+
return self
|
|
129
|
+
|
|
130
|
+
async def __aexit__(self, *args: Any, **kwargs: Any) -> None:
|
|
131
|
+
"""Exit a context manager for underlying httpx.AsyncClient (see httpx docs)"""
|
|
132
|
+
await self.get_async_httpx_client().__aexit__(*args, **kwargs)
|
|
21
133
|
|
|
22
134
|
|
|
23
135
|
@define
|
|
24
|
-
class
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
verify_ssl
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
136
|
+
class AuthenticatedClient:
|
|
137
|
+
"""A Client which has been authenticated for use on secured endpoints
|
|
138
|
+
|
|
139
|
+
The following are accepted as keyword arguments and will be used to construct httpx Clients internally:
|
|
140
|
+
|
|
141
|
+
``base_url``: The base URL for the API, all requests are made to a relative path to this URL
|
|
142
|
+
|
|
143
|
+
``cookies``: A dictionary of cookies to be sent with every request
|
|
144
|
+
|
|
145
|
+
``headers``: A dictionary of headers to be sent with every request
|
|
146
|
+
|
|
147
|
+
``timeout``: The maximum amount of a time a request can take. API functions will raise
|
|
148
|
+
httpx.TimeoutException if this is exceeded.
|
|
149
|
+
|
|
150
|
+
``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production,
|
|
151
|
+
but can be set to False for testing purposes.
|
|
152
|
+
|
|
153
|
+
``follow_redirects``: Whether or not to follow redirects. Default value is False.
|
|
154
|
+
|
|
155
|
+
``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor.
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
Attributes:
|
|
159
|
+
raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a
|
|
160
|
+
status code that was not documented in the source OpenAPI document. Can also be provided as a keyword
|
|
161
|
+
argument to the constructor.
|
|
162
|
+
token: The token to use for authentication
|
|
163
|
+
prefix: The prefix to use for the Authorization header
|
|
164
|
+
auth_header_name: The name of the Authorization header
|
|
42
165
|
"""
|
|
43
166
|
|
|
44
|
-
|
|
45
|
-
_base_url: str
|
|
167
|
+
raise_on_unexpected_status: bool = field(default=False, kw_only=True)
|
|
168
|
+
_base_url: str = field(alias="base_url")
|
|
46
169
|
_cookies: dict[str, str] = field(factory=dict, kw_only=True, alias="cookies")
|
|
47
170
|
_headers: dict[str, str] = field(factory=dict, kw_only=True, alias="headers")
|
|
48
171
|
_timeout: httpx.Timeout | None = field(default=None, kw_only=True, alias="timeout")
|
|
49
172
|
_verify_ssl: str | bool | ssl.SSLContext = field(default=True, kw_only=True, alias="verify_ssl")
|
|
50
173
|
_follow_redirects: bool = field(default=False, kw_only=True, alias="follow_redirects")
|
|
51
174
|
_httpx_args: dict[str, Any] = field(factory=dict, kw_only=True, alias="httpx_args")
|
|
52
|
-
_raise_on_unexpected_status: bool = field(
|
|
53
|
-
default=False, kw_only=True, alias="raise_on_unexpected_status"
|
|
54
|
-
)
|
|
55
175
|
_client: httpx.Client | None = field(default=None, init=False)
|
|
56
176
|
_async_client: httpx.AsyncClient | None = field(default=None, init=False)
|
|
57
177
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return self._raise_on_unexpected_status
|
|
178
|
+
token: str
|
|
179
|
+
prefix: str = "Bearer"
|
|
180
|
+
auth_header_name: str = "Authorization"
|
|
62
181
|
|
|
63
|
-
def with_headers(self, headers: dict[str, str]) -> "
|
|
64
|
-
"""Get a new client matching this one with additional headers
|
|
182
|
+
def with_headers(self, headers: dict[str, str]) -> "AuthenticatedClient":
|
|
183
|
+
"""Get a new client matching this one with additional headers"""
|
|
65
184
|
if self._client is not None:
|
|
66
185
|
self._client.headers.update(headers)
|
|
67
186
|
if self._async_client is not None:
|
|
68
187
|
self._async_client.headers.update(headers)
|
|
69
188
|
return evolve(self, headers={**self._headers, **headers})
|
|
70
189
|
|
|
71
|
-
def with_cookies(self, cookies: dict[str, str]) -> "
|
|
72
|
-
"""Get a new client matching this one with additional cookies
|
|
190
|
+
def with_cookies(self, cookies: dict[str, str]) -> "AuthenticatedClient":
|
|
191
|
+
"""Get a new client matching this one with additional cookies"""
|
|
73
192
|
if self._client is not None:
|
|
74
193
|
self._client.cookies.update(cookies)
|
|
75
194
|
if self._async_client is not None:
|
|
76
195
|
self._async_client.cookies.update(cookies)
|
|
77
196
|
return evolve(self, cookies={**self._cookies, **cookies})
|
|
78
197
|
|
|
79
|
-
def with_timeout(self, timeout: httpx.Timeout) -> "
|
|
80
|
-
"""Get a new client matching this one with a new timeout configuration
|
|
198
|
+
def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient":
|
|
199
|
+
"""Get a new client matching this one with a new timeout configuration"""
|
|
81
200
|
if self._client is not None:
|
|
82
201
|
self._client.timeout = timeout
|
|
83
202
|
if self._async_client is not None:
|
|
84
203
|
self._async_client.timeout = timeout
|
|
85
204
|
return evolve(self, timeout=timeout)
|
|
86
205
|
|
|
87
|
-
|
|
88
|
-
|
|
206
|
+
def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClient":
|
|
207
|
+
"""Manually set the underlying httpx.Client
|
|
89
208
|
|
|
90
|
-
|
|
209
|
+
**NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
|
|
210
|
+
"""
|
|
91
211
|
self._client = client
|
|
92
212
|
return self
|
|
93
213
|
|
|
94
214
|
def get_httpx_client(self) -> httpx.Client:
|
|
215
|
+
"""Get the underlying httpx.Client, constructing a new one if not previously set"""
|
|
95
216
|
if self._client is None:
|
|
96
|
-
|
|
217
|
+
self._headers[self.auth_header_name] = (
|
|
218
|
+
f"{self.prefix} {self.token}" if self.prefix else self.token
|
|
219
|
+
)
|
|
97
220
|
self._client = httpx.Client(
|
|
98
|
-
base_url=
|
|
221
|
+
base_url=self._base_url,
|
|
99
222
|
cookies=self._cookies,
|
|
100
|
-
headers=
|
|
223
|
+
headers=self._headers,
|
|
101
224
|
timeout=self._timeout,
|
|
102
225
|
verify=self._verify_ssl,
|
|
103
226
|
follow_redirects=self._follow_redirects,
|
|
@@ -105,24 +228,33 @@ class Nadeshiko:
|
|
|
105
228
|
)
|
|
106
229
|
return self._client
|
|
107
230
|
|
|
108
|
-
def __enter__(self) -> "
|
|
231
|
+
def __enter__(self) -> "AuthenticatedClient":
|
|
232
|
+
"""Enter a context manager for self.client—you cannot enter twice (see httpx docs)"""
|
|
109
233
|
self.get_httpx_client().__enter__()
|
|
110
234
|
return self
|
|
111
235
|
|
|
112
236
|
def __exit__(self, *args: Any, **kwargs: Any) -> None:
|
|
237
|
+
"""Exit a context manager for internal httpx.Client (see httpx docs)"""
|
|
113
238
|
self.get_httpx_client().__exit__(*args, **kwargs)
|
|
114
239
|
|
|
115
|
-
def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "
|
|
240
|
+
def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient":
|
|
241
|
+
"""Manually set the underlying httpx.AsyncClient
|
|
242
|
+
|
|
243
|
+
**NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
|
|
244
|
+
"""
|
|
116
245
|
self._async_client = async_client
|
|
117
246
|
return self
|
|
118
247
|
|
|
119
248
|
def get_async_httpx_client(self) -> httpx.AsyncClient:
|
|
249
|
+
"""Get the underlying httpx.AsyncClient, constructing a new one if not previously set"""
|
|
120
250
|
if self._async_client is None:
|
|
121
|
-
|
|
251
|
+
self._headers[self.auth_header_name] = (
|
|
252
|
+
f"{self.prefix} {self.token}" if self.prefix else self.token
|
|
253
|
+
)
|
|
122
254
|
self._async_client = httpx.AsyncClient(
|
|
123
|
-
base_url=
|
|
255
|
+
base_url=self._base_url,
|
|
124
256
|
cookies=self._cookies,
|
|
125
|
-
headers=
|
|
257
|
+
headers=self._headers,
|
|
126
258
|
timeout=self._timeout,
|
|
127
259
|
verify=self._verify_ssl,
|
|
128
260
|
follow_redirects=self._follow_redirects,
|
|
@@ -130,9 +262,11 @@ class Nadeshiko:
|
|
|
130
262
|
)
|
|
131
263
|
return self._async_client
|
|
132
264
|
|
|
133
|
-
async def __aenter__(self) -> "
|
|
265
|
+
async def __aenter__(self) -> "AuthenticatedClient":
|
|
266
|
+
"""Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)"""
|
|
134
267
|
await self.get_async_httpx_client().__aenter__()
|
|
135
268
|
return self
|
|
136
269
|
|
|
137
270
|
async def __aexit__(self, *args: Any, **kwargs: Any) -> None:
|
|
271
|
+
"""Exit a context manager for underlying httpx.AsyncClient (see httpx docs)"""
|
|
138
272
|
await self.get_async_httpx_client().__aexit__(*args, **kwargs)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nadeshiko-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Python SDK for Nadeshiko API
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Requires-Dist: attrs>=23.0
|
|
@@ -17,6 +17,9 @@ Description-Content-Type: text/markdown
|
|
|
17
17
|
|
|
18
18
|
# Nadeshiko Python SDK
|
|
19
19
|
|
|
20
|
+
[](https://pypi.org/project/nadeshiko-sdk/)
|
|
21
|
+
|
|
22
|
+
|
|
20
23
|
Python SDK for the [Nadeshiko API](https://nadeshiko.co)
|
|
21
24
|
|
|
22
25
|
## Quick Start
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
nadeshiko/__init__.py,sha256=
|
|
2
|
-
nadeshiko/_version.py,sha256=
|
|
3
|
-
nadeshiko/client.py,sha256=
|
|
1
|
+
nadeshiko/__init__.py,sha256=aeAjSMM5BYro2XyF18xzV3c0AlWyPLxr2iJijsB7Tks,190
|
|
2
|
+
nadeshiko/_version.py,sha256=Zn1KFblwuFHiDRdRAiRnDBRkbPttWh44jKa5zG2ov0E,22
|
|
3
|
+
nadeshiko/client.py,sha256=KI0gSZL9TUd9vfpb6T01eliMBmRbqGv_-Gbmp-E--pg,12448
|
|
4
4
|
nadeshiko/errors.py,sha256=gO8GBmKqmSNgAg-E5oT-oOyxztvp7V_6XG7OUTT15q0,546
|
|
5
5
|
nadeshiko/types.py,sha256=0We4NPvhIYASRpQ3le41nmJeEAVm42-2VKdzlJ4Ogok,1343
|
|
6
6
|
nadeshiko/api/__init__.py,sha256=zTSiG_ujSjAqWPyc435YXaX9XTlpMjiJWBbV-f-YtdA,45
|
|
@@ -162,6 +162,6 @@ nadeshiko/models/user_info_response_user.py,sha256=JTCD9BMIcH1ygWcyB8VfYZjcQwi-w
|
|
|
162
162
|
nadeshiko/models/user_role.py,sha256=je_tlp39e-2jlzwBnmjkr6ymhJ6olWKTPEtFExEsHGE,1811
|
|
163
163
|
nadeshiko/models/word_match.py,sha256=Yaf5_bSK4Dk93EHqOesb9jQ8BlQlX4NUU39GpupEl7A,3285
|
|
164
164
|
nadeshiko/models/word_match_media.py,sha256=6eKrsm3fQHe2mLYNQ4aRQCU7JrMaIoJqw7NTA2o_2-Y,3094
|
|
165
|
-
nadeshiko_sdk-0.
|
|
166
|
-
nadeshiko_sdk-0.
|
|
167
|
-
nadeshiko_sdk-0.
|
|
165
|
+
nadeshiko_sdk-0.2.0.dist-info/METADATA,sha256=gq-rQIr6hh7L4XVDlx1JYweeTCmPNOx5MjOleQUzcl0,4044
|
|
166
|
+
nadeshiko_sdk-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
167
|
+
nadeshiko_sdk-0.2.0.dist-info/RECORD,,
|
|
File without changes
|