aioqzone 1.9.9.dev1__tar.gz → 1.10.2.dev1__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.
Files changed (54) hide show
  1. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/PKG-INFO +3 -3
  2. aioqzone-1.10.2.dev1/pyproject.toml +102 -0
  3. aioqzone-1.9.9.dev1/pyproject.toml → aioqzone-1.10.2.dev1/pyproject.toml.orig +5 -6
  4. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/api/login/__init__.py +23 -2
  5. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/utils/jsjson.py +4 -3
  6. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/README.md +0 -0
  7. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/__init__.py +0 -0
  8. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/api/__init__.py +0 -0
  9. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/api/h5/__init__.py +0 -0
  10. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/api/h5/model.py +0 -0
  11. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/api/login/_base.py +0 -0
  12. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/exception.py +0 -0
  13. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/message.py +0 -0
  14. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/model/__init__.py +0 -0
  15. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/model/api/__init__.py +0 -0
  16. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/model/api/feed.py +0 -0
  17. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/model/api/profile.py +0 -0
  18. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/model/api/request.py +0 -0
  19. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/model/api/response.py +0 -0
  20. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/model/protocol/__init__.py +0 -0
  21. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/model/protocol/config.py +0 -0
  22. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/model/protocol/entity.py +0 -0
  23. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/utils/__init__.py +0 -0
  24. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/utils/entity.py +0 -0
  25. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/utils/regex.py +0 -0
  26. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/utils/retry.py +0 -0
  27. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/aioqzone/utils/time.py +0 -0
  28. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/__init__.py +0 -0
  29. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/base.py +0 -0
  30. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/constant.py +0 -0
  31. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/exception.py +0 -0
  32. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/message.py +0 -0
  33. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/py.typed +0 -0
  34. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/qr/__init__.py +0 -0
  35. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/qr/type.py +0 -0
  36. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/type.py +0 -0
  37. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/up/__init__.py +0 -0
  38. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/up/_model.py +0 -0
  39. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/up/captcha/__init__.py +0 -0
  40. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/up/captcha/_model.py +0 -0
  41. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/up/captcha/capsess.py +0 -0
  42. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/up/captcha/click/__init__.py +0 -0
  43. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/up/captcha/click/_types.py +0 -0
  44. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/up/captcha/pil_utils.py +0 -0
  45. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/up/captcha/select/__init__.py +0 -0
  46. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/up/captcha/select/_types.py +0 -0
  47. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/up/captcha/slide/__init__.py +0 -0
  48. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/up/captcha/slide/_types.py +0 -0
  49. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/up/encrypt.py +0 -0
  50. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/up/h5.py +0 -0
  51. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/up/web.py +0 -0
  52. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/utils/encrypt.py +0 -0
  53. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/utils/iter.py +0 -0
  54. {aioqzone-1.9.9.dev1 → aioqzone-1.10.2.dev1}/src/qqqr/utils/net.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aioqzone
3
- Version: 1.9.9.dev1
3
+ Version: 1.10.2.dev1
4
4
  Summary: A Python wrapper for Qzone login and H5 APIs.
5
5
  Keywords: qzone-api,autologin,asyncio-spider
6
6
  Author: aioqzone
@@ -15,12 +15,12 @@ Requires-Dist: pydantic-settings>=2.9.0
15
15
  Requires-Dist: rsa>=4.9.1
16
16
  Requires-Dist: tenacity>=8.2.3,<10.0.0
17
17
  Requires-Dist: tylisten>=2.2.1
18
- Requires-Dist: pillow>=11.3.0
18
+ Requires-Dist: pillow>=13.0.0
19
19
  Requires-Dist: pychaosvm~=0.5.4
20
20
  Requires-Dist: slide-tc~=0.1.4 ; extra == 'slide-captcha'
21
21
  Maintainer: JamzumSum
22
22
  Maintainer-email: JamzumSum <22952836+JamzumSum@users.noreply.github.com>
23
- Requires-Python: >=3.10
23
+ Requires-Python: >=3.11
24
24
  Project-URL: Homepage, https://github.com/aioqzone/aioqzone
25
25
  Project-URL: Repository, https://github.com/aioqzone/aioqzone
26
26
  Project-URL: Documentation, https://aioqzone.github.io/aioqzone
@@ -0,0 +1,102 @@
1
+ [project]
2
+ name = "aioqzone"
3
+ version = "1.10.2.dev1"
4
+ description = "A Python wrapper for Qzone login and H5 APIs."
5
+ license = "AGPL-3.0-or-later"
6
+ readme = "README.md"
7
+ requires-python = ">=3.11"
8
+ keywords = [
9
+ "qzone-api",
10
+ "autologin",
11
+ "asyncio-spider",
12
+ ]
13
+ classifiers = [
14
+ "Development Status :: 4 - Beta",
15
+ "Intended Audience :: Developers",
16
+ "Topic :: Software Development :: Libraries :: Python Modules",
17
+ "Typing :: Typed",
18
+ ]
19
+ dependencies = [
20
+ "aiohttp~=3.14",
21
+ "pydantic~=2.12",
22
+ "pydantic-settings>=2.9.0",
23
+ "rsa>=4.9.1",
24
+ "tenacity>=8.2.3,<10.0.0",
25
+ "tylisten>=2.2.1",
26
+ "pillow>=13.0.0",
27
+ "pychaosvm~=0.5.4",
28
+ ]
29
+
30
+ [[project.authors]]
31
+ name = "aioqzone"
32
+
33
+ [[project.maintainers]]
34
+ name = "JamzumSum"
35
+ email = "22952836+JamzumSum@users.noreply.github.com"
36
+
37
+ [project.urls]
38
+ Homepage = "https://github.com/aioqzone/aioqzone"
39
+ Repository = "https://github.com/aioqzone/aioqzone"
40
+ Documentation = "https://aioqzone.github.io/aioqzone"
41
+ "Bug Tracker" = "https://github.com/aioqzone/aioqzone/issues"
42
+ Discussion = "https://t.me/aioqzone_chatroom"
43
+
44
+ [project.optional-dependencies]
45
+ slide-captcha = ["slide-tc~=0.1.4"]
46
+
47
+ [dependency-groups]
48
+ test = [
49
+ "pytest>=9.0.3",
50
+ "pytest-asyncio~=1.1",
51
+ ]
52
+ dev = [
53
+ "pre-commit",
54
+ "ruff",
55
+ "ty",
56
+ ]
57
+ doc = [
58
+ "Sphinx~=9.0",
59
+ "autodoc-pydantic>=2.2.0",
60
+ "sphinx-autodoc-typehints~=3.0",
61
+ "furo",
62
+ "sphinx-intl",
63
+ "sphinx-inline-tabs",
64
+ ]
65
+
66
+ [tool.uv]
67
+ prerelease = "if-necessary-or-explicit"
68
+
69
+ [tool.uv.sources.pychaosvm]
70
+ index = "aioqzone-index"
71
+
72
+ [tool.uv.sources.slide-tc]
73
+ index = "aioqzone-index"
74
+
75
+ [[tool.uv.index]]
76
+ name = "aioqzone-index"
77
+ url = "https://aioqzone.github.io/aioqzone-index/simple/"
78
+
79
+ [tool.uv.build-backend]
80
+ module-name = [
81
+ "aioqzone",
82
+ "qqqr",
83
+ ]
84
+
85
+ [tool.pytest.ini_options]
86
+ pythonpath = "src"
87
+ log_cli = true
88
+ log_cli_level = "WARNING"
89
+ asyncio_default_fixture_loop_scope = "module"
90
+
91
+ [tool.ruff]
92
+ line-length = 99
93
+
94
+ [tool.ruff.lint]
95
+ ignore = [
96
+ "F403",
97
+ "F405",
98
+ ]
99
+
100
+ [build-system]
101
+ requires = ["uv_build"]
102
+ build-backend = "uv_build"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "aioqzone"
3
- version = "1.9.9.dev1"
3
+ version = "1.10.2.dev1"
4
4
  description = "A Python wrapper for Qzone login and H5 APIs."
5
5
  authors = [{ name = "aioqzone" }]
6
6
  maintainers = [
@@ -8,7 +8,7 @@ maintainers = [
8
8
  ]
9
9
  license = "AGPL-3.0-or-later"
10
10
  readme = "README.md"
11
- requires-python = ">=3.10"
11
+ requires-python = ">=3.11"
12
12
  keywords = ["qzone-api", "autologin", "asyncio-spider"]
13
13
  classifiers = [
14
14
  "Development Status :: 4 - Beta",
@@ -25,7 +25,7 @@ dependencies = [
25
25
  "tenacity>=8.2.3,<10.0.0",
26
26
  # "exceptiongroup>=1.1.1",
27
27
  "tylisten>=2.2.1",
28
- "pillow>=11.3.0",
28
+ "pillow>=13.0.0",
29
29
  "pychaosvm~=0.5.4",
30
30
  ]
31
31
 
@@ -37,15 +37,14 @@ Documentation = "https://aioqzone.github.io/aioqzone"
37
37
  "Discussion" = "https://t.me/aioqzone_chatroom"
38
38
 
39
39
  [dependency-groups]
40
- test = ["pytest>=9.0.3", "pytest-asyncio>=1.1,<1.4"]
40
+ test = ["pytest>=9.0.3", "pytest-asyncio~=1.1"]
41
41
  dev = [
42
42
  "pre-commit",
43
43
  "ruff",
44
44
  "ty",
45
45
  ]
46
46
  doc = [
47
- "Sphinx>=8.1.3; python_version=='3.10'",
48
- "Sphinx~=9.0; python_version>='3.11'",
47
+ "Sphinx~=9.0",
49
48
  "autodoc-pydantic>=2.2.0",
50
49
  "sphinx-autodoc-typehints~=3.0",
51
50
  "furo",
@@ -8,7 +8,14 @@ import logging
8
8
  import typing as t
9
9
 
10
10
  from aiohttp import ClientError
11
- from tenacity import TryAgain, retry, retry_if_exception_type, stop_after_attempt, wait_exponential
11
+ from tenacity import (
12
+ RetryCallState,
13
+ TryAgain,
14
+ retry,
15
+ retry_if_exception_type,
16
+ stop_after_attempt,
17
+ wait_exponential,
18
+ )
12
19
  from tylisten import FutureStore
13
20
  from typing_extensions import Self
14
21
 
@@ -31,6 +38,20 @@ __all__ = [
31
38
  ]
32
39
 
33
40
 
41
+ def _reraise_last_attempt(retry_state: RetryCallState) -> t.NoReturn:
42
+ """Re-raise the last attempt exception instead of tenacity's ``RetryError``.
43
+
44
+ tenacity >= 9.2.1 unwraps ``TryAgain`` to its cause when ``reraise=True``,
45
+ which would surface the underlying ``ClientError`` (or ``GeneratorExit``)
46
+ rather than the documented :exc:`TryAgain`. Re-raising the attempt's own
47
+ exception keeps the public contract stable across tenacity versions.
48
+ """
49
+ outcome = retry_state.outcome
50
+ if outcome is None:
51
+ raise RuntimeError("retry outcome is unexpectedly None")
52
+ raise outcome.result()
53
+
54
+
34
55
  @t.final
35
56
  class ConstLoginMan(Loginable):
36
57
  """A basic login manager which uses external provided cookie."""
@@ -99,7 +120,7 @@ class UpLoginManager(Loginable):
99
120
  stop=stop_after_attempt(2),
100
121
  wait=wait_exponential(min=1, max=6),
101
122
  retry=retry_if_exception_type(TryAgain),
102
- reraise=True,
123
+ retry_error_callback=_reraise_last_attempt,
103
124
  )
104
125
  async def _new_cookie(self) -> t.Dict[str, str]:
105
126
  """
@@ -41,10 +41,11 @@ class AstLoader:
41
41
  :return: A :obj:`JsonValue` object.
42
42
  """
43
43
  js = dedent(js).replace(r"\/", "/")
44
- node = ast.parse(js, mode="eval")
44
+ node = ast.parse(js, filename=filename, mode="eval")
45
45
  node = ast.fix_missing_locations(cls.RewriteUndef().visit(node))
46
- code = compile(node, filename, mode="eval")
47
- return eval(code)
46
+ # Parse as a data literal only. Never compile/eval the input: it comes from
47
+ # remote responses and must not be executed as Python code.
48
+ return ast.literal_eval(node)
48
49
 
49
50
 
50
51
  def json_loads(js: str) -> JsonValue:
File without changes