p115client 0.0.5.11.11__py3-none-any.whl → 0.0.5.12.1__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.
p115client/const.py CHANGED
@@ -5,8 +5,8 @@ from __future__ import annotations
5
5
 
6
6
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
7
7
  __all__ = [
8
- "AVAILABLE_APPS", "APP_TO_SSOENT", "SSOENT_TO_APP", "CLIENT_API_MAP",
9
- "CLASS_TO_TYPE", "SUFFIX_TO_TYPE", "errno",
8
+ "AVAILABLE_APPS", "APP_TO_SSOENT", "SSOENT_TO_APP", "CLIENT_METHOD_API_MAP",
9
+ "CLIENT_API_METHODS_MAP", "CLASS_TO_TYPE", "SUFFIX_TO_TYPE", "errno",
10
10
  ]
11
11
 
12
12
  from enum import IntEnum
@@ -69,8 +69,11 @@ SSOENT_TO_APP: Final[dict[str, str]] = {
69
69
  "S1": "harmony",
70
70
  }
71
71
 
72
- #: 所有已封装的 115 接口以及对应的方法名
73
- CLIENT_API_MAP: Final[dict[str, str]] = {}
72
+ #: 所有已封装的方法名和对应的 115 接口
73
+ CLIENT_METHOD_API_MAP: Final[dict[str, str]] = {}
74
+
75
+ #: 所有已封装的 115 接口和对应的方法名
76
+ CLIENT_API_METHODS_MAP: Final[dict[str, list[str]]] = {}
74
77
 
75
78
  #: 文件的 class 属性对应的所属类型的整数代码
76
79
  CLASS_TO_TYPE: Final[dict[str, int]] = {
@@ -7,12 +7,14 @@ __doc__ = "这个模块提供了一些和离线下载有关的函数"
7
7
 
8
8
  from asyncio import sleep as async_sleep
9
9
  from collections.abc import AsyncIterator, Callable, Iterable, Iterator
10
+ from errno import EBUSY
10
11
  from itertools import count
11
12
  from time import sleep, time
12
13
  from typing import overload, Literal
13
14
 
14
15
  from iterutils import run_gen_step_iter, with_iter_next, Yield, YieldFrom
15
16
  from p115client import check_response, P115Client, P115OpenClient
17
+ from p115client.exception import BusyOSError
16
18
 
17
19
 
18
20
  @overload
@@ -22,7 +24,8 @@ def offline_iter(
22
24
  page_start: int = 1,
23
25
  page_stop: int = -1,
24
26
  cooldown: float = 0,
25
- use_open_api: bool = False,
27
+ raise_for_update: bool = False,
28
+ use_open_api: bool = False,
26
29
  *,
27
30
  async_: Literal[False] = False,
28
31
  **request_kwargs,
@@ -35,6 +38,7 @@ def offline_iter(
35
38
  page_start: int = 1,
36
39
  page_stop: int = -1,
37
40
  cooldown: float = 0,
41
+ raise_for_update: bool = False,
38
42
  use_open_api: bool = False,
39
43
  *,
40
44
  async_: Literal[True],
@@ -47,6 +51,7 @@ def offline_iter(
47
51
  page_start: int = 1,
48
52
  page_stop: int = -1,
49
53
  cooldown: float = 0,
54
+ raise_for_update: bool = False,
50
55
  use_open_api: bool = False,
51
56
  *,
52
57
  async_: Literal[False, True] = False,
@@ -54,10 +59,18 @@ def offline_iter(
54
59
  ) -> Iterator[dict] | AsyncIterator[dict]:
55
60
  """遍历任务列表,获取任务信息
56
61
 
62
+ .. tip::
63
+ 在逐页拉取的间隔期间,任务列表可能发生变化,可能导致重复和遗漏:
64
+
65
+ 1. 新增任务,特别是状态为进行中
66
+ 2. 删除任务
67
+ 3. 曾经取得的进行中的任务,变为完成
68
+
57
69
  :param client: 115 客户端或 cookies
58
70
  :param page_start: 开始页数
59
71
  :param page_stop: 结束页数(不含),如果 <= 0,则不限
60
72
  :param cooldown: 接口调用冷却时间,单位:秒
73
+ :param raise_for_update: 当列表发生更新时,是否报错退出
61
74
  :param use_open_api: 是否使用 open api
62
75
  :param async_: 是否异步
63
76
  :param request_kwargs: 其它请求参数
@@ -79,21 +92,40 @@ def offline_iter(
79
92
  offline_list = client.offline_list_open
80
93
  else:
81
94
  offline_list = client.offline_list
82
- if cooldown > 0:
95
+ may_sleep = cooldown > 0
96
+ if may_sleep:
83
97
  do_sleep = async_sleep if async_ else sleep
84
- last_t: float = 0
98
+ last_t: float = 0
99
+ if raise_for_update:
100
+ count = -1
101
+ seen: set[str] = set()
102
+ add_info_hash = seen.add
85
103
  for page in pages:
86
- if last_t and (diff := last_t + cooldown - time()) > 0:
87
- yield do_sleep(diff)
88
- last_t = time()
104
+ if may_sleep:
105
+ if last_t and (diff := last_t + cooldown - time()) > 0:
106
+ yield do_sleep(diff)
107
+ last_t = time()
89
108
  resp = yield offline_list(page, async_=async_, **request_kwargs)
90
109
  check_response(resp)
91
110
  if use_open_api:
92
111
  resp = resp["data"]
112
+ if raise_for_update:
113
+ if count < 0:
114
+ count = resp["count"]
115
+ elif count != resp["count"]:
116
+ raise BusyOSError(EBUSY, f"detected count changes: {count} != {resp['count']}")
93
117
  tasks = resp["tasks"]
94
118
  if not tasks:
95
119
  break
96
- yield YieldFrom(resp["tasks"])
120
+ if raise_for_update:
121
+ for task in tasks:
122
+ info_hash = task["info_hash"]
123
+ if info_hash in seen:
124
+ raise BusyOSError(EBUSY, f"detected duplicate task: info_hash={info_hash!r}")
125
+ add_info_hash(info_hash)
126
+ yield Yield(task)
127
+ else:
128
+ yield YieldFrom(resp["tasks"])
97
129
  if len(tasks) < 30 or page >= resp["page_count"]:
98
130
  break
99
131
  return run_gen_step_iter(gen_step, async_=async_)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: p115client
3
- Version: 0.0.5.11.11
3
+ Version: 0.0.5.12.1
4
4
  Summary: Python 115 webdisk client.
5
5
  Home-page: https://github.com/ChenyangGao/p115client
6
6
  License: MIT
@@ -1,8 +1,8 @@
1
1
  LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
2
2
  p115client/__init__.py,sha256=1mx7njuAlqcuEWONTjSiiGnXyyNyqOcJyNX1FMHqQ-4,214
3
3
  p115client/_upload.py,sha256=3uXwgFsXkZ4X5hjL1N2mx0y8tA8MjVxe49N0BoyYyno,31253
4
- p115client/client.py,sha256=sXqO2jxXtP58r4xyoYzcfJ3eu4zTvMy7EbUBLca8Cp4,784167
5
- p115client/const.py,sha256=KqDGr9KsOnSkNVM3RIdQGptCMHbidMmZ_ffyFPiniww,7654
4
+ p115client/client.py,sha256=h62_xx1z-F5TeqQn55ugUUcJuAbVRV1mIfXsI1_rO6s,794996
5
+ p115client/const.py,sha256=ZYtBtTFB0eljIR0tze21_52Gl0pQxvyqMmDwgB1bqNU,7803
6
6
  p115client/exception.py,sha256=4SZ8ubOLMRxtcqc0u1kNzXqH1a6wwXJFwGnRDURoEgQ,3708
7
7
  p115client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  p115client/tool/__init__.py,sha256=IwwzbCQ7jpRoFGTQUCfGBx8zvjqjgSFs98yKpYyI46s,429
@@ -15,14 +15,14 @@ p115client/tool/fs_files.py,sha256=cRUa-GNjoOMoLtLJxG-Zp6C6QFoM1Au0B_Z19KhLzn8,1
15
15
  p115client/tool/history.py,sha256=qquCiiOIRpxOqmyXbmdwS_qpfPkduJilM6AGuOufrYU,7462
16
16
  p115client/tool/iterdir.py,sha256=dXBMPfxPzRcFhBpnBT3X1LYkhc3l31rYCLRKRFbggSk,200498
17
17
  p115client/tool/life.py,sha256=ceweN2uNKYxigSOaBQ4Abo5u05zqppRm_P7k-_rHjcA,17301
18
- p115client/tool/offline.py,sha256=5I7ooTaxB3bGncfNtTnBNGDmErjCJae6Q9jkLAS34Is,4978
18
+ p115client/tool/offline.py,sha256=iEpC4e71Pmz1j7NTlXUgJLKUSf_wcPxVZ9ciqURoXcA,6305
19
19
  p115client/tool/pool.py,sha256=H65VhoNxQC6xWSL1THq_PximWnBOqB4EfU6kWBTAnlA,13946
20
20
  p115client/tool/request.py,sha256=rjXuQwRganE5Z-4rfgnyPFjE4jzdQSLdIs9s0cIDshU,7043
21
21
  p115client/tool/upload.py,sha256=D2TPJlS--bGX-oHgTm6ktoqnX1_gwOMwxwMkiOwGuIY,32695
22
22
  p115client/tool/util.py,sha256=pAa8gc4BcnVTpNcXbNZU4tBUMjSB04DGOpzDdzfbto8,3934
23
23
  p115client/tool/xys.py,sha256=vU28Px2yeQzIxxGkopJIpvV6TdOnWJ5xB6NPXpTgM0Y,10306
24
24
  p115client/type.py,sha256=7kOp98uLaYqcTTCgCrb3DRcl8ukMpn7ibsnVvtw2nG8,6250
25
- p115client-0.0.5.11.11.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
26
- p115client-0.0.5.11.11.dist-info/METADATA,sha256=wOD1JB3jSbUZi0McSiXPL98BiBtZd019jevjlL0hdD8,8193
27
- p115client-0.0.5.11.11.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
28
- p115client-0.0.5.11.11.dist-info/RECORD,,
25
+ p115client-0.0.5.12.1.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
26
+ p115client-0.0.5.12.1.dist-info/METADATA,sha256=wDdhSFRIxbvM_XKquuiBNf2rVWkLPHtCUiEn1U88Ro0,8192
27
+ p115client-0.0.5.12.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
28
+ p115client-0.0.5.12.1.dist-info/RECORD,,