18
18
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
19
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20
20
DEALINGS IN THE SOFTWARE.
21
- """
21
+ """ # noqa: A005 # we access this via namespace
22
22
23
23
from __future__ import annotations
24
24
52
52
T = TypeVar ("T" )
53
53
Response = Coroutine [None , None , T ]
54
54
MU = TypeVar ("MU" , bound = "MaybeUnlock" )
55
- BE = TypeVar ("BE" , bound = BaseException )
56
55
from .types .responses import CreatePasteResponse , GetPasteResponse
57
56
58
57
@@ -69,8 +68,14 @@ def _clean_dt(dt: datetime.datetime) -> str:
69
68
return dt .isoformat ()
70
69
71
70
72
- async def json_or_text (response : aiohttp .ClientResponse , / ) -> dict [str , Any ] | str :
73
- """A quick method to parse a `aiohttp.ClientResponse` and test if it's json or text."""
71
+ async def _json_or_text (response : aiohttp .ClientResponse , / ) -> dict [str , Any ] | str :
72
+ """A quick method to parse a `aiohttp.ClientResponse` and test if it's json or text.
73
+
74
+ Returns
75
+ --------
76
+ Union[Dict[:class:`str`, Any], :class:`str`]
77
+ The JSON object, or request text.
78
+ """
74
79
text = await response .text (encoding = "utf-8" )
75
80
try :
76
81
if response .headers ["content-type" ] == "application/json" :
@@ -97,8 +102,8 @@ def defer(self) -> None:
97
102
98
103
def __exit__ (
99
104
self ,
100
- exc_type : type [BE ] | None ,
101
- exc : BE | None ,
105
+ exc_type : type [BaseException ] | None ,
106
+ exc : BaseException | None ,
102
107
traceback : TracebackType | None ,
103
108
) -> None :
104
109
if self ._unlock :
@@ -115,14 +120,14 @@ class Route:
115
120
API_BASE : ClassVar [str ] = "https://mystb.in/api"
116
121
117
122
def __init__ (self , verb : SupportedHTTPVerb , path : str , ** params : Any ) -> None :
118
-
119
123
self .verb : SupportedHTTPVerb = verb
120
124
self .path : str = path
121
125
url = self .API_BASE + path
122
126
if params :
123
127
url = url .format_map ({k : _uriquote (v ) if isinstance (v , str ) else v for k , v in params .items ()})
124
128
self .url : str = url
125
129
130
+
126
131
class HTTPClient :
127
132
__slots__ = (
128
133
"_async" ,
@@ -131,7 +136,7 @@ class HTTPClient:
131
136
"_session" ,
132
137
"_token" ,
133
138
"api_base" ,
134
- "user_agent"
139
+ "user_agent" ,
135
140
)
136
141
137
142
def __init__ (self , * , session : aiohttp .ClientSession | None = None , api_base : str | None = None ) -> None :
@@ -142,12 +147,9 @@ def __init__(self, *, session: aiohttp.ClientSession | None = None, api_base: st
142
147
self .user_agent : str = user_agent .format (__version__ , sys .version_info , aiohttp .__version__ )
143
148
self ._resolve_api (api_base )
144
149
145
- def _resolve_api (self , api : str | None ) -> None :
146
- if api :
147
- Route .API_BASE = api + "api" if api .endswith ("/" ) else api + "/api"
148
- self .api_base = api + ("/" if not api .endswith ("/" ) else "" )
149
- else :
150
- self .api_base = "https://mystb.in/"
150
+ def _resolve_api (self , api_base : str | None , / ) -> None :
151
+ if api_base :
152
+ Route .API_BASE = f"https://{ api_base } /api"
151
153
152
154
async def close (self ) -> None :
153
155
if self ._session and self ._owns_session :
@@ -194,28 +196,28 @@ async def request(self, route: Route, **kwargs: Any) -> Any:
194
196
retry = response .headers .get ("x-ratelimit-retry-after" , None )
195
197
LOGGER .debug ("retry is: %s" , retry )
196
198
if retry is not None :
197
- retry = datetime .datetime .fromtimestamp (int (retry ))
199
+ retry = datetime .datetime .fromtimestamp (int (retry ), tz = datetime . timezone . utc )
198
200
# The total ratelimit session hits
199
201
limit = response .headers .get ("x-ratelimit-limit" , None )
200
202
LOGGER .debug ("limit is: %s" , limit )
201
203
202
204
if remaining == "0" and response .status != 429 :
203
205
assert retry is not None
204
- delta = retry - datetime .datetime .now ()
206
+ delta = retry - datetime .datetime .now (datetime . timezone . utc )
205
207
sleep = delta .total_seconds () + 1
206
208
LOGGER .warning ("A ratelimit has been exhausted, sleeping for: %d" , sleep )
207
209
maybe_lock .defer ()
208
210
loop = asyncio .get_running_loop ()
209
211
loop .call_later (sleep , lock .release )
210
212
211
- data = await json_or_text (response )
213
+ data = await _json_or_text (response )
212
214
213
215
if 300 > response .status >= 200 :
214
216
return data
215
217
216
218
if response .status == 429 :
217
219
assert retry is not None
218
- delta = retry - datetime .datetime .now ()
220
+ delta = retry - datetime .datetime .now (datetime . timezone . utc )
219
221
sleep = delta .total_seconds () + 1
220
222
LOGGER .warning ("A ratelimit has been hit, sleeping for: %d" , sleep )
221
223
await asyncio .sleep (sleep )
@@ -227,15 +229,14 @@ async def request(self, route: Route, **kwargs: Any) -> Any:
227
229
await asyncio .sleep (sleep_ )
228
230
continue
229
231
230
- print (data )
231
232
assert isinstance (data , dict )
232
233
LOGGER .exception ("Unhandled HTTP error occurred: %s -> %s" , response .status , data )
233
234
raise APIException (
234
235
response = response ,
235
236
status_code = response .status ,
236
237
)
237
- except (aiohttp .ServerDisconnectedError , aiohttp .ServerTimeoutError ) as error :
238
- LOGGER .exception ("Network error occurred: %s" , error )
238
+ except (aiohttp .ServerDisconnectedError , aiohttp .ServerTimeoutError ):
239
+ LOGGER .exception ("Network error occurred:" )
239
240
await asyncio .sleep (5 )
240
241
continue
241
242
0 commit comments