aioqzone 1.8.1.dev1__tar.gz → 1.8.2.dev3__tar.gz
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.
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/PKG-INFO +3 -3
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/README.md +1 -1
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/pyproject.toml +4 -4
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/api/h5/model.py +1 -1
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/api/login/__init__.py +1 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/model/api/__init__.py +2 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/model/api/profile.py +1 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/model/protocol/__init__.py +1 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/model/protocol/config.py +9 -2
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/utils/regex.py +1 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/utils/retry.py +1 -2
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/qr/__init__.py +10 -6
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/up/captcha/__init__.py +9 -2
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/up/captcha/capsess.py +5 -4
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/up/web.py +5 -2
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/utils/iter.py +4 -4
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/utils/jsjson.py +11 -7
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/utils/net.py +2 -2
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/LICENSE +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/__init__.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/api/__init__.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/api/h5/__init__.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/api/login/_base.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/exception.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/message.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/model/__init__.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/model/api/feed.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/model/api/request.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/model/api/response.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/model/protocol/entity.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/utils/__init__.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/utils/entity.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/aioqzone/utils/time.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/__init__.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/base.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/constant.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/exception.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/message.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/py.typed +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/qr/type.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/type.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/up/__init__.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/up/_model.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/up/captcha/_model.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/up/captcha/pil_utils.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/up/captcha/select/__init__.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/up/captcha/select/_types.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/up/captcha/slide/__init__.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/up/captcha/slide/_types.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/up/encrypt.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/up/h5.py +0 -0
- {aioqzone-1.8.1.dev1 → aioqzone-1.8.2.dev3}/src/qqqr/utils/encrypt.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: aioqzone
|
|
3
|
-
Version: 1.8.
|
|
3
|
+
Version: 1.8.2.dev3
|
|
4
4
|
Summary: A Python wrapper for Qzone login and H5 APIs.
|
|
5
5
|
Home-page: https://github.com/aioqzone/aioqzone
|
|
6
6
|
License: AGPL-3.0
|
|
@@ -23,7 +23,7 @@ Provides-Extra: slide-captcha
|
|
|
23
23
|
Requires-Dist: aiohttp (>=3.8.5,<4.0.0)
|
|
24
24
|
Requires-Dist: exceptiongroup (>=1.1.1,<2.0.0)
|
|
25
25
|
Requires-Dist: pillow (>=10.0.1,<11.0.0)
|
|
26
|
-
Requires-Dist: pychaosvm (>=0.3.
|
|
26
|
+
Requires-Dist: pychaosvm (>=0.3.4,<0.5.0)
|
|
27
27
|
Requires-Dist: pydantic (>=2.0.3,<3.0.0)
|
|
28
28
|
Requires-Dist: pydantic-settings (>=2.0.2,<3.0.0)
|
|
29
29
|
Requires-Dist: rsa (>=4.8,<5.0)
|
|
@@ -43,7 +43,7 @@ aioqzone封装了一些Qzone接口。
|
|
|
43
43
|
[][home]
|
|
44
44
|
[][pypi]
|
|
45
45
|
[](https://github.com/psf/black)
|
|
46
|
-
[](https://t.me/
|
|
46
|
+
[](https://t.me/aioqzone_chatroom)
|
|
47
47
|
|
|
48
48
|
[English](README_en.md) | 简体中文
|
|
49
49
|
|
|
@@ -5,7 +5,7 @@ aioqzone封装了一些Qzone接口。
|
|
|
5
5
|
[][home]
|
|
6
6
|
[][pypi]
|
|
7
7
|
[](https://github.com/psf/black)
|
|
8
|
-
[](https://t.me/
|
|
8
|
+
[](https://t.me/aioqzone_chatroom)
|
|
9
9
|
|
|
10
10
|
[English](README_en.md) | 简体中文
|
|
11
11
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "aioqzone"
|
|
3
|
-
version = "1.8.
|
|
3
|
+
version = "1.8.2.dev3"
|
|
4
4
|
description = "A Python wrapper for Qzone login and H5 APIs."
|
|
5
5
|
authors = ["aioqzone <zzzzss990315@gmail.com>"]
|
|
6
6
|
license = "AGPL-3.0"
|
|
@@ -36,7 +36,7 @@ tenacity = "^8.2.3"
|
|
|
36
36
|
exceptiongroup = "^1.1.1"
|
|
37
37
|
tylisten = "^2.1.3"
|
|
38
38
|
pillow = "^10.0.1"
|
|
39
|
-
pychaosvm = { version = "
|
|
39
|
+
pychaosvm = { version = ">=0.3.4,<0.5.0", source = "aioqzone-index" }
|
|
40
40
|
slide-tc = {version = "~0.1.1", optional = true, source = "aioqzone-index" }
|
|
41
41
|
|
|
42
42
|
[tool.poetry.extras]
|
|
@@ -47,8 +47,8 @@ slide-captcha = ["slide-tc"]
|
|
|
47
47
|
optional = false
|
|
48
48
|
|
|
49
49
|
[tool.poetry.group.test.dependencies]
|
|
50
|
-
pytest = "^
|
|
51
|
-
pytest-asyncio = "~0.21.
|
|
50
|
+
pytest = "^8.2.0"
|
|
51
|
+
pytest-asyncio = "~0.21.2"
|
|
52
52
|
|
|
53
53
|
[tool.poetry.group.dev]
|
|
54
54
|
optional = true
|
|
@@ -61,7 +61,7 @@ class QzoneH5API:
|
|
|
61
61
|
async for attempt in self._relogin_retry:
|
|
62
62
|
with attempt:
|
|
63
63
|
if (gtk := self.login.gtk) == 0:
|
|
64
|
-
raise TryAgain
|
|
64
|
+
raise TryAgain("no login state")
|
|
65
65
|
if api.attach_token:
|
|
66
66
|
params["g_tk"] = gtk
|
|
67
67
|
hostuin: int = getattr(api.params, "hostuin", self.login.uin)
|
|
@@ -118,6 +118,7 @@ class UpLoginManager(Loginable):
|
|
|
118
118
|
client=self.client,
|
|
119
119
|
uin=self.config.uin,
|
|
120
120
|
pwd=self.config.pwd.get_secret_value(),
|
|
121
|
+
fake_ip=self.config.fake_ip and str(self.config.fake_ip),
|
|
121
122
|
h5=enable,
|
|
122
123
|
)
|
|
123
124
|
self.sms_code_input = self.uplogin.sms_code_input
|
|
@@ -12,6 +12,8 @@ TyHttpMethod = t.Union[t.Literal["GET"], t.Literal["POST"]]
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class QzoneApi(BaseModel, t.Generic[TyRequest, TyResponse]):
|
|
15
|
+
"""The base class for all Qzone APIs below."""
|
|
16
|
+
|
|
15
17
|
host: t.ClassVar[str] = "https://h5.qzone.qq.com"
|
|
16
18
|
http_method: t.ClassVar[TyHttpMethod]
|
|
17
19
|
path: t.ClassVar[str]
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import typing as t
|
|
2
|
+
from ipaddress import IPv4Address
|
|
2
3
|
|
|
3
|
-
from pydantic import Field, SecretStr
|
|
4
|
+
from pydantic import AnyUrl, Field, SecretStr
|
|
4
5
|
from pydantic_settings import BaseSettings
|
|
5
6
|
|
|
6
7
|
|
|
@@ -13,6 +14,12 @@ class UpLoginConfig(LoginConfig):
|
|
|
13
14
|
pwd: SecretStr = Field(default="")
|
|
14
15
|
"""User password."""
|
|
15
16
|
|
|
17
|
+
fake_ip: t.Optional[IPv4Address] = None
|
|
18
|
+
"""Fake IP used when collecting network environment.
|
|
19
|
+
|
|
20
|
+
.. versionadded:: 1.8.2
|
|
21
|
+
"""
|
|
22
|
+
|
|
16
23
|
|
|
17
24
|
class QrLoginConfig(LoginConfig):
|
|
18
25
|
max_refresh_times: int = 6
|
|
@@ -14,8 +14,7 @@ class RetryIfCode(retry_if_exception, Generic[_E]):
|
|
|
14
14
|
|
|
15
15
|
@classmethod
|
|
16
16
|
@abstractmethod
|
|
17
|
-
def get_code(cls, exc: _E) -> int:
|
|
18
|
-
...
|
|
17
|
+
def get_code(cls, exc: _E) -> int: ...
|
|
19
18
|
|
|
20
19
|
def __init__(self, *code: int) -> None:
|
|
21
20
|
super().__init__(lambda exc: isinstance(exc, self._exc_cls) and self.get_code(exc) in code)
|
|
@@ -88,6 +88,10 @@ class QrLogin(LoginBase[QrSession], _QrHookMixin):
|
|
|
88
88
|
return QrSession(await self.show(push_qr), login_sig=login_sig)
|
|
89
89
|
|
|
90
90
|
async def show(self, push_qr=False) -> QR:
|
|
91
|
+
"""``ptqrshow`` api.
|
|
92
|
+
|
|
93
|
+
:param push_qr: push QR to mobile client.
|
|
94
|
+
"""
|
|
91
95
|
data = {
|
|
92
96
|
"appid": self.app.appid,
|
|
93
97
|
"daid": self.app.daid,
|
|
@@ -125,7 +129,7 @@ class QrLogin(LoginBase[QrSession], _QrHookMixin):
|
|
|
125
129
|
async def poll(self, sess: QrSession) -> PollResp:
|
|
126
130
|
"""Poll QR status.
|
|
127
131
|
|
|
128
|
-
:raise `
|
|
132
|
+
:raise `aiohttp.ClientResponseError`: if response status code != 200
|
|
129
133
|
|
|
130
134
|
:return: a poll response object
|
|
131
135
|
"""
|
|
@@ -168,17 +172,17 @@ class QrLogin(LoginBase[QrSession], _QrHookMixin):
|
|
|
168
172
|
poll_freq: float = 3,
|
|
169
173
|
):
|
|
170
174
|
"""Loop until cookie is returned or max `refresh_times` exceeds.
|
|
171
|
-
- This method will emit :
|
|
172
|
-
- If qr is not scanned after `refresh_times`, it will raise :exc:`
|
|
173
|
-
- If :obj
|
|
174
|
-
- If :obj
|
|
175
|
+
- This method will emit :obj:`.qr_fetched` event if a new qrcode is fetched.
|
|
176
|
+
- If qr is not scanned after `refresh_times`, it will raise :exc:`UserTimeout`.
|
|
177
|
+
- If :obj:`.refresh` is set, it will refresh qrcode at once without increasing expire counter.
|
|
178
|
+
- If :obj:`.cancel` is set, it will raise :exc:`UserBreak` before next polling.
|
|
175
179
|
|
|
176
180
|
:meta public:
|
|
177
181
|
:param refresh_times: max qr expire times.
|
|
178
182
|
:param poll_freq: interval between two status polling, in seconds, default as 3.
|
|
179
183
|
|
|
180
184
|
:raise `UserTimeout`: if qr is not scanned after `refresh_times` expires.
|
|
181
|
-
:raise `UserBreak`: if :obj
|
|
185
|
+
:raise `UserBreak`: if :obj:`.cancel` is set.
|
|
182
186
|
"""
|
|
183
187
|
self.refresh.clear()
|
|
184
188
|
self.cancel.clear()
|
|
@@ -52,7 +52,13 @@ class Captcha(_CaptchaHookMixin):
|
|
|
52
52
|
solve_select_captcha: solve_select_captcha.TyInst
|
|
53
53
|
solve_slide_captcha: solve_slide_captcha.TyInst
|
|
54
54
|
|
|
55
|
-
def __init__(
|
|
55
|
+
def __init__(
|
|
56
|
+
self,
|
|
57
|
+
client: ClientAdapter,
|
|
58
|
+
appid: int,
|
|
59
|
+
xlogin_url: str,
|
|
60
|
+
fake_ip: t.Optional[str] = None,
|
|
61
|
+
):
|
|
56
62
|
"""
|
|
57
63
|
:param client: network client
|
|
58
64
|
:param appid: Specify the appid of the application
|
|
@@ -64,6 +70,7 @@ class Captcha(_CaptchaHookMixin):
|
|
|
64
70
|
self.appid = appid
|
|
65
71
|
self.xlogin_url = xlogin_url
|
|
66
72
|
self.client.headers["Referer"] = "https://xui.ptlogin2.qq.com/"
|
|
73
|
+
self.fake_ip = fake_ip
|
|
67
74
|
|
|
68
75
|
@property
|
|
69
76
|
def base64_ua(self):
|
|
@@ -149,7 +156,7 @@ class Captcha(_CaptchaHookMixin):
|
|
|
149
156
|
return await sess.solve_captcha()
|
|
150
157
|
|
|
151
158
|
async def get_tdc_collect(client: ClientAdapter) -> str:
|
|
152
|
-
await sess.get_tdc(client)
|
|
159
|
+
await sess.get_tdc(client, ip=self.fake_ip)
|
|
153
160
|
return unquote(str(sess.tdc.getData(None, True)))
|
|
154
161
|
|
|
155
162
|
ans, collect, _ = await asyncio.gather(
|
|
@@ -70,7 +70,9 @@ class BaseTcaptchaSession(ABC):
|
|
|
70
70
|
def _vmslide_js_url(self):
|
|
71
71
|
raise NotImplementedError
|
|
72
72
|
|
|
73
|
-
async def get_tdc(
|
|
73
|
+
async def get_tdc(
|
|
74
|
+
self, client: ClientAdapter, ua: t.Optional[str] = None, ip: t.Optional[str] = None
|
|
75
|
+
):
|
|
74
76
|
"""
|
|
75
77
|
.. note:: If :obj:`.mouse_track` should be set, set it before calling this method.
|
|
76
78
|
"""
|
|
@@ -80,14 +82,13 @@ class BaseTcaptchaSession(ABC):
|
|
|
80
82
|
r.raise_for_status()
|
|
81
83
|
self.tdc = prepare(
|
|
82
84
|
await r.text("utf8"),
|
|
83
|
-
ip=self.prehandle.uip,
|
|
85
|
+
ip=ip or self.prehandle.uip,
|
|
84
86
|
ua=ua or client.headers["User-Agent"],
|
|
85
87
|
mouse_track=await self.mouse_track,
|
|
86
88
|
)
|
|
87
89
|
|
|
88
90
|
@abstractmethod
|
|
89
|
-
async def get_captcha_problem(self, client: ClientAdapter):
|
|
90
|
-
...
|
|
91
|
+
async def get_captcha_problem(self, client: ClientAdapter): ...
|
|
91
92
|
|
|
92
93
|
@abstractmethod
|
|
93
94
|
async def solve_captcha(self) -> str:
|
|
@@ -123,17 +123,20 @@ class UpWebLogin(LoginBase[UpWebSession], _UpHookMixin):
|
|
|
123
123
|
app: t.Optional[APPID] = None,
|
|
124
124
|
proxy: t.Optional[Proxy] = None,
|
|
125
125
|
info: t.Optional[PT_QR_APP] = None,
|
|
126
|
+
fake_ip: t.Optional[str] = None,
|
|
126
127
|
):
|
|
127
128
|
super().__init__(client, uin=uin, h5=h5, app=app, proxy=proxy, info=info)
|
|
128
129
|
self.pwd = pwd
|
|
129
130
|
self.pwder = TeaEncoder(pwd)
|
|
130
|
-
self.captcha = Captcha(
|
|
131
|
+
self.captcha = Captcha(
|
|
132
|
+
self.client, self.app.appid, str(self.login_page_url), fake_ip=fake_ip
|
|
133
|
+
)
|
|
131
134
|
|
|
132
135
|
async def new(self):
|
|
133
136
|
"""Create a :class:`UpWebSession`. This will call `check` api of Qzone, and receive result
|
|
134
137
|
about whether this login needs a captcha, sms verification, etc.
|
|
135
138
|
|
|
136
|
-
:raise `
|
|
139
|
+
:raise `aiohttp.ClientResponseError`: if response status != 200
|
|
137
140
|
|
|
138
141
|
:return: a up login session
|
|
139
142
|
"""
|
|
@@ -5,8 +5,9 @@ D = t.TypeVar("D")
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
@t.overload
|
|
8
|
-
def first(
|
|
9
|
-
|
|
8
|
+
def first(
|
|
9
|
+
it: t.Iterable[T], pred: t.Optional[t.Callable[[T], t.Optional[object]]] = None
|
|
10
|
+
) -> T: ...
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
@t.overload
|
|
@@ -15,8 +16,7 @@ def first(
|
|
|
15
16
|
pred: t.Optional[t.Callable[[T], t.Optional[object]]] = None,
|
|
16
17
|
*,
|
|
17
18
|
default: D,
|
|
18
|
-
) -> t.Union[T, D]:
|
|
19
|
-
...
|
|
19
|
+
) -> t.Union[T, D]: ...
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def first(
|
|
@@ -10,9 +10,13 @@ JsonValue = Union[bool, int, str, JsonDict, JsonList]
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class AstLoader:
|
|
13
|
-
"""
|
|
13
|
+
""":class:`AstLoader` uses standard :mod:`ast` module to parse the js/json"""
|
|
14
14
|
|
|
15
15
|
class RewriteUndef(ast.NodeTransformer):
|
|
16
|
+
"""
|
|
17
|
+
:meta private:
|
|
18
|
+
"""
|
|
19
|
+
|
|
16
20
|
const = {
|
|
17
21
|
"undefined": ast.Constant(value=None),
|
|
18
22
|
"null": ast.Constant(value=None),
|
|
@@ -28,12 +32,12 @@ class AstLoader:
|
|
|
28
32
|
@classmethod
|
|
29
33
|
def json_loads(cls, js: str, filename: str = "stdin") -> JsonValue:
|
|
30
34
|
"""
|
|
31
|
-
The json_loads function loads a JSON object from a js/json string. It uses standard
|
|
35
|
+
The :meth:`~AstLoader.json_loads` function loads a JSON object from a js/json string. It uses standard
|
|
32
36
|
:mod:`ast` module to parse the js/json.
|
|
33
37
|
|
|
34
38
|
:param js: Used to Pass the js/json string to be parsed.
|
|
35
39
|
:param filename: Used to Specify the name of the file that is being read. This is only for debug use.
|
|
36
|
-
:return: A
|
|
40
|
+
:return: A :obj:`JsonValue` object.
|
|
37
41
|
"""
|
|
38
42
|
js = dedent(js).replace(r"\/", "/")
|
|
39
43
|
node = ast.parse(js, mode="eval")
|
|
@@ -43,14 +47,14 @@ class AstLoader:
|
|
|
43
47
|
|
|
44
48
|
|
|
45
49
|
def json_loads(js: str) -> JsonValue:
|
|
46
|
-
"""The json_loads function converts a string representation of JS/JSON data into a Python object.
|
|
50
|
+
"""The :meth:`json_loads` function converts a string representation of JS/JSON data into a Python object.
|
|
47
51
|
Current implementation is using :external+python:mod:`ast`.
|
|
48
52
|
|
|
49
|
-
If you need more parameters or another implementation, call `xxxLoader.json_loads` instead.
|
|
50
|
-
|
|
51
53
|
.. seealso:: :meth:`.AstLoader.json_loads`
|
|
52
54
|
|
|
55
|
+
If you need more parameters or another implementation, call ``xxxLoader.json_loads`` instead.
|
|
56
|
+
|
|
53
57
|
:param js: Used to Pass the JS/JSON string.
|
|
54
|
-
:return: A
|
|
58
|
+
:return: A :obj:`JsonValue` object.
|
|
55
59
|
"""
|
|
56
60
|
return AstLoader.json_loads(js)
|
|
@@ -9,12 +9,12 @@ __all__ = ["raise_for_status", "get_all_cookie", "ClientAdapter"]
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def raise_for_status(response: Response, *accept_code: int):
|
|
12
|
-
"""A checker more strict than :meth:`~
|
|
12
|
+
"""A checker more strict than :meth:`~aiohttp.ClientResponse.raise_for_status`.
|
|
13
13
|
|
|
14
14
|
:param response: Client response to check.
|
|
15
15
|
:param accept_code: Overwrite codes that can be accepted, If not given, default is `(200, )`
|
|
16
16
|
|
|
17
|
-
:raise `
|
|
17
|
+
:raise `aiohttp.ClientResponseError`: if status not in :obj:`accept_code`
|
|
18
18
|
"""
|
|
19
19
|
response.raise_for_status
|
|
20
20
|
accept_code = accept_code or (200,)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|