p115client 0.0.5.11.6__tar.gz → 0.0.5.11.7.1__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 (25) hide show
  1. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/PKG-INFO +2 -2
  2. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/client.py +83 -28
  3. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/const.py +2 -6
  4. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/tool/attr.py +2 -2
  5. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/tool/download.py +16 -16
  6. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/tool/iterdir.py +86 -86
  7. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/tool/pool.py +2 -3
  8. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/pyproject.toml +1 -1
  9. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/readme.md +1 -1
  10. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/LICENSE +0 -0
  11. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/__init__.py +0 -0
  12. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/_upload.py +0 -0
  13. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/exception.py +0 -0
  14. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/py.typed +0 -0
  15. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/tool/__init__.py +0 -0
  16. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/tool/edit.py +0 -0
  17. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/tool/export_dir.py +0 -0
  18. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/tool/fs_files.py +0 -0
  19. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/tool/history.py +0 -0
  20. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/tool/life.py +0 -0
  21. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/tool/request.py +0 -0
  22. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/tool/upload.py +0 -0
  23. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/tool/util.py +0 -0
  24. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/tool/xys.py +0 -0
  25. {p115client-0.0.5.11.6 → p115client-0.0.5.11.7.1}/p115client/type.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: p115client
3
- Version: 0.0.5.11.6
3
+ Version: 0.0.5.11.7.1
4
4
  Summary: Python 115 webdisk client.
5
5
  Home-page: https://github.com/ChenyangGao/p115client
6
6
  License: MIT
@@ -108,7 +108,7 @@ client = P115Client(Path("~/115-cookies.txt").expanduser(), check_for_relogin=Tr
108
108
 
109
109
  如果你有一个申请通过的开放接口的应用,则可以创建开放接口的客户端实例
110
110
 
111
- 你可以直接从一个 `P115Client` 实例拿到授权(自动扫码登录并授权),如果不提供 `app_id`,则使用默认值
111
+ 你可以直接从一个 `P115Client` 实例拿到授权(自动扫码登录并授权)
112
112
 
113
113
  ```python
114
114
  app_id = <开放接口应用的 AppID>
@@ -766,7 +766,7 @@ def normalize_attr_app[D: dict[str, Any]](
766
766
  simple: bool = False,
767
767
  keep_raw: bool = False,
768
768
  *,
769
- dict_cls: None | type[D] = None,
769
+ dict_cls: type[D],
770
770
  ) -> D:
771
771
  ...
772
772
  def normalize_attr_app[D: dict[str, Any]](
@@ -896,7 +896,7 @@ def normalize_attr_app2[D: dict[str, Any]](
896
896
  simple: bool = False,
897
897
  keep_raw: bool = False,
898
898
  *,
899
- dict_cls: None | type[D] = None,
899
+ dict_cls: type[D],
900
900
  ) -> D:
901
901
  ...
902
902
  def normalize_attr_app2[D: dict[str, Any]](
@@ -1082,7 +1082,7 @@ def normalize_attr_simple(
1082
1082
  /,
1083
1083
  keep_raw: bool = False,
1084
1084
  *,
1085
- dict_cls: None = None,
1085
+ dict_cls: None,
1086
1086
  ) -> dict[str, Any]:
1087
1087
  ...
1088
1088
  @overload
@@ -1091,7 +1091,7 @@ def normalize_attr_simple[D: dict[str, Any]](
1091
1091
  /,
1092
1092
  keep_raw: bool = False,
1093
1093
  *,
1094
- dict_cls: type[D],
1094
+ dict_cls: type[D] = AttrDict, # type: ignore
1095
1095
  ) -> D:
1096
1096
  ...
1097
1097
  def normalize_attr_simple[D: dict[str, Any]](
@@ -1099,7 +1099,7 @@ def normalize_attr_simple[D: dict[str, Any]](
1099
1099
  /,
1100
1100
  keep_raw: bool = False,
1101
1101
  *,
1102
- dict_cls: None | type[D] = None,
1102
+ dict_cls: None | type[D] = AttrDict, # type: ignore
1103
1103
  ) -> dict[str, Any] | D:
1104
1104
  return normalize_attr(
1105
1105
  info,
@@ -1138,7 +1138,7 @@ class IgnoreCaseDict[V](dict[str, V]):
1138
1138
  return cls(zip(map(str.lower, iterable), repeat(value)))
1139
1139
 
1140
1140
  @overload
1141
- def get(self, key: str) -> None | V:
1141
+ def get(self, key: str, default: None = None) -> None | V:
1142
1142
  ...
1143
1143
  @overload
1144
1144
  def get[T](self, key: str, default: T) -> V | T:
@@ -2329,7 +2329,7 @@ class ClientRequestMixin:
2329
2329
  def login_with_app_id(
2330
2330
  cls,
2331
2331
  /,
2332
- app_id: int | str = 100195993,
2332
+ app_id: int | str,
2333
2333
  console_qrcode: bool = True,
2334
2334
  base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
2335
2335
  *,
@@ -2342,7 +2342,7 @@ class ClientRequestMixin:
2342
2342
  def login_with_app_id(
2343
2343
  cls,
2344
2344
  /,
2345
- app_id: int | str = 100195993,
2345
+ app_id: int | str,
2346
2346
  console_qrcode: bool = True,
2347
2347
  base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
2348
2348
  *,
@@ -2354,7 +2354,7 @@ class ClientRequestMixin:
2354
2354
  def login_with_app_id(
2355
2355
  cls,
2356
2356
  /,
2357
- app_id: int | str = 100195993,
2357
+ app_id: int | str,
2358
2358
  console_qrcode: bool = True,
2359
2359
  base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
2360
2360
  *,
@@ -4994,7 +4994,7 @@ class P115OpenClient(ClientRequestMixin):
4994
4994
  else:
4995
4995
  filesize, filesha1_obj = file_digest(file, "sha1")
4996
4996
  finally:
4997
- yield seek(curpos)
4997
+ yield cast(Callable, seek)(curpos)
4998
4998
  filesha1 = filesha1_obj.hexdigest()
4999
4999
  if filesize < 0:
5000
5000
  try:
@@ -5006,9 +5006,9 @@ class P115OpenClient(ClientRequestMixin):
5006
5006
  except TypeError:
5007
5007
  if seekable:
5008
5008
  try:
5009
- filesize = (yield seek(0, 2)) - curpos
5009
+ filesize = (yield cast(Callable, seek)(0, 2)) - curpos
5010
5010
  finally:
5011
- yield seek(curpos)
5011
+ yield cast(Callable, seek)(curpos)
5012
5012
  if filesize == 0:
5013
5013
  filesha1 = "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"
5014
5014
  elif multipart_resume_data is None and filesize >= 1 << 20:
@@ -5018,13 +5018,13 @@ class P115OpenClient(ClientRequestMixin):
5018
5018
  async_read = ensure_async(file.read, threaded=True)
5019
5019
  async def read_range_bytes_or_hash(sign_check: str, /):
5020
5020
  start, end = map(int, sign_check.split("-"))
5021
- await seek(curpos + start)
5021
+ await cast(Callable, seek)(curpos + start)
5022
5022
  return await async_read(end - start + 1)
5023
5023
  else:
5024
5024
  read = cast(Callable[[int], Buffer], file.read)
5025
5025
  def read_range_bytes_or_hash(sign_check: str, /):
5026
5026
  start, end = map(int, sign_check.split("-"))
5027
- seek(curpos + start)
5027
+ cast(Callable, seek)(curpos + start)
5028
5028
  return read(end - start + 1)
5029
5029
  elif isinstance(file, (URL, SupportsGeturl)):
5030
5030
  if isinstance(file, URL):
@@ -5194,6 +5194,60 @@ class P115OpenClient(ClientRequestMixin):
5194
5194
  api = complete_proapi("/open/user/info", base_url)
5195
5195
  return self.request(url=api, async_=async_, **request_kwargs)
5196
5196
 
5197
+ @overload
5198
+ def vip_qr_url(
5199
+ self,
5200
+ payload: int | dict,
5201
+ /,
5202
+ base_url: bool | str | Callable[[], str] = False,
5203
+ *,
5204
+ async_: Literal[False] = False,
5205
+ **request_kwargs,
5206
+ ) -> dict:
5207
+ ...
5208
+ @overload
5209
+ def vip_qr_url(
5210
+ self,
5211
+ payload: int | dict,
5212
+ /,
5213
+ base_url: bool | str | Callable[[], str] = False,
5214
+ *,
5215
+ async_: Literal[True],
5216
+ **request_kwargs,
5217
+ ) -> Coroutine[Any, Any, dict]:
5218
+ ...
5219
+ def vip_qr_url(
5220
+ self,
5221
+ payload: int | dict,
5222
+ /,
5223
+ base_url: bool | str | Callable[[], str] = False,
5224
+ *,
5225
+ async_: Literal[False, True] = False,
5226
+ **request_kwargs,
5227
+ ) -> dict | Coroutine[Any, Any, dict]:
5228
+ """获取产品列表地址(即引导用户扫码购买 115 的 VIP 服务,以获取提成)
5229
+
5230
+ GET https://proapi.115.com/open/open/vip/qr_url
5231
+
5232
+ .. admonition:: Reference
5233
+
5234
+ https://www.yuque.com/115yun/open/cguk6qshgapwg4qn#oByvI
5235
+
5236
+ :payload:
5237
+ - open_device: int
5238
+ - default_product_id: int = <default> 💡 打开产品列表默认选中的产品对应的产品id,如果没有则使用默认的产品顺序。
5239
+
5240
+ - 月费: 5
5241
+ - 年费: 1
5242
+ - 尝鲜1天: 101
5243
+ - 长期VIP(长期): 24072401
5244
+ - 超级VIP: 24072402
5245
+ """
5246
+ api = complete_proapi("/open/vip/qr_url", base_url)
5247
+ if not isinstance(payload, dict):
5248
+ payload = {"open_device": payload}
5249
+ return self.request(url=api, params=payload, async_=async_, **request_kwargs)
5250
+
5197
5251
  download_url_open = download_url
5198
5252
  download_url_info_open = download_url_info
5199
5253
  fs_copy_open = fs_copy
@@ -5226,6 +5280,7 @@ class P115OpenClient(ClientRequestMixin):
5226
5280
  user_info_open = user_info
5227
5281
  upload_file_init_open = upload_file_init
5228
5282
  upload_file_open = upload_file
5283
+ vip_qr_url_open = vip_qr_url
5229
5284
 
5230
5285
 
5231
5286
  class P115Client(P115OpenClient):
@@ -5902,7 +5957,7 @@ class P115Client(P115OpenClient):
5902
5957
  def login_with_open(
5903
5958
  self,
5904
5959
  /,
5905
- app_id: int | str = 100195993,
5960
+ app_id: int | str,
5906
5961
  *,
5907
5962
  show_warning: bool = False,
5908
5963
  async_: Literal[False] = False,
@@ -5913,7 +5968,7 @@ class P115Client(P115OpenClient):
5913
5968
  def login_with_open(
5914
5969
  self,
5915
5970
  /,
5916
- app_id: int | str = 100195993,
5971
+ app_id: int | str,
5917
5972
  *,
5918
5973
  show_warning: bool = False,
5919
5974
  async_: Literal[True],
@@ -5923,7 +5978,7 @@ class P115Client(P115OpenClient):
5923
5978
  def login_with_open(
5924
5979
  self,
5925
5980
  /,
5926
- app_id: int | str = 100195993,
5981
+ app_id: int | str,
5927
5982
  *,
5928
5983
  show_warning: bool = False,
5929
5984
  async_: Literal[False, True] = False,
@@ -6098,7 +6153,7 @@ class P115Client(P115OpenClient):
6098
6153
  def login_another_open(
6099
6154
  self,
6100
6155
  /,
6101
- app_id: int | str = 100195993,
6156
+ app_id: int | str,
6102
6157
  *,
6103
6158
  replace: Literal[True] | Self,
6104
6159
  show_warning: bool = False,
@@ -6110,7 +6165,7 @@ class P115Client(P115OpenClient):
6110
6165
  def login_another_open(
6111
6166
  self,
6112
6167
  /,
6113
- app_id: int | str = 100195993,
6168
+ app_id: int | str,
6114
6169
  *,
6115
6170
  replace: Literal[True] | Self,
6116
6171
  show_warning: bool = False,
@@ -6122,7 +6177,7 @@ class P115Client(P115OpenClient):
6122
6177
  def login_another_open(
6123
6178
  self,
6124
6179
  /,
6125
- app_id: int | str = 100195993,
6180
+ app_id: int | str,
6126
6181
  *,
6127
6182
  replace: Literal[False] = False,
6128
6183
  show_warning: bool = False,
@@ -6134,7 +6189,7 @@ class P115Client(P115OpenClient):
6134
6189
  def login_another_open(
6135
6190
  self,
6136
6191
  /,
6137
- app_id: int | str = 100195993,
6192
+ app_id: int | str,
6138
6193
  *,
6139
6194
  replace: Literal[False] = False,
6140
6195
  show_warning: bool = False,
@@ -6145,7 +6200,7 @@ class P115Client(P115OpenClient):
6145
6200
  def login_another_open(
6146
6201
  self,
6147
6202
  /,
6148
- app_id: int | str = 100195993,
6203
+ app_id: int | str,
6149
6204
  *,
6150
6205
  replace: bool | Self = False,
6151
6206
  show_warning: bool = False,
@@ -6540,7 +6595,7 @@ class P115Client(P115OpenClient):
6540
6595
  continue
6541
6596
  if i or is_auth_error:
6542
6597
  raise
6543
- app_id = getattr(self, "app_id", 100195993)
6598
+ app_id = getattr(self, "app_id")
6544
6599
  yield self.login_another_open(
6545
6600
  app_id,
6546
6601
  replace=True,
@@ -21125,7 +21180,7 @@ class P115Client(P115OpenClient):
21125
21180
  else:
21126
21181
  filesize, filesha1_obj = file_digest(file, "sha1")
21127
21182
  finally:
21128
- yield seek(curpos)
21183
+ yield cast(Callable, seek)(curpos)
21129
21184
  filesha1 = filesha1_obj.hexdigest()
21130
21185
  if filesize < 0:
21131
21186
  try:
@@ -21137,9 +21192,9 @@ class P115Client(P115OpenClient):
21137
21192
  except TypeError:
21138
21193
  if seekable:
21139
21194
  try:
21140
- filesize = (yield seek(0, 2)) - curpos
21195
+ filesize = (yield cast(Callable, seek)(0, 2)) - curpos
21141
21196
  finally:
21142
- yield seek(curpos)
21197
+ yield cast(Callable, seek)(curpos)
21143
21198
  if filesize == 0:
21144
21199
  filesha1 = "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"
21145
21200
  elif not upload_directly and multipart_resume_data is None and filesize >= 1 << 20:
@@ -21149,13 +21204,13 @@ class P115Client(P115OpenClient):
21149
21204
  async_read = ensure_async(file.read, threaded=True)
21150
21205
  async def read_range_bytes_or_hash(sign_check: str, /):
21151
21206
  start, end = map(int, sign_check.split("-"))
21152
- await seek(curpos + start)
21207
+ await cast(Callable, seek)(curpos + start)
21153
21208
  return await async_read(end - start + 1)
21154
21209
  else:
21155
21210
  read = cast(Callable[[int], Buffer], file.read)
21156
21211
  def read_range_bytes_or_hash(sign_check: str, /):
21157
21212
  start, end = map(int, sign_check.split("-"))
21158
- seek(curpos + start)
21213
+ cast(Callable, seek)(curpos + start)
21159
21214
  return read(end - start + 1)
21160
21215
  elif isinstance(file, (URL, SupportsGeturl)):
21161
21216
  if isinstance(file, URL):
@@ -5,18 +5,14 @@ from __future__ import annotations
5
5
 
6
6
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
7
7
  __all__ = [
8
- "AVAILABLE_APP_IDS", "AVAILABLE_APPS", "APP_TO_SSOENT", "SSOENT_TO_APP",
9
- "CLIENT_API_MAP", "CLASS_TO_TYPE", "SUFFIX_TO_TYPE", "errno",
8
+ "AVAILABLE_APPS", "APP_TO_SSOENT", "SSOENT_TO_APP", "CLIENT_API_MAP",
9
+ "CLASS_TO_TYPE", "SUFFIX_TO_TYPE", "errno",
10
10
  ]
11
11
 
12
12
  from enum import IntEnum
13
13
  from typing import Final
14
14
 
15
15
 
16
- #: 可用的 AppID 列表
17
- AVAILABLE_APP_IDS = range(100195123, 100196845, 2)
18
-
19
-
20
16
  #: 目前可用的登录设备
21
17
  AVAILABLE_APPS: Final[tuple[str, ...]] = (
22
18
  "web", "ios", "115ios", "android", "115android", "115ipad", "tv", "qandroid",
@@ -55,8 +55,8 @@ def get_attr(
55
55
  if isinstance(client, str):
56
56
  client = P115Client(client, check_for_relogin=True)
57
57
  def gen_step():
58
+ from dictattr import AttrDict
58
59
  if skim:
59
- from dictattr import AttrDict
60
60
  resp = yield client.fs_file_skim(id, async_=async_, **request_kwargs)
61
61
  check_response(resp)
62
62
  info = resp["data"][0]
@@ -71,7 +71,7 @@ def get_attr(
71
71
  else:
72
72
  resp = yield client.fs_file(id, async_=async_, **request_kwargs)
73
73
  check_response(resp)
74
- return normalize_attr_web(resp["data"][0])
74
+ return normalize_attr_web(resp["data"][0], dict_cls=AttrDict)
75
75
  return run_gen_step(gen_step, may_call=False, async_=async_)
76
76
 
77
77
 
@@ -10,7 +10,7 @@ __all__ = [
10
10
  __doc__ = "这个模块提供了一些和下载有关的函数"
11
11
 
12
12
  from asyncio import create_task, to_thread, Queue as AsyncQueue, TaskGroup
13
- from collections.abc import AsyncIterator, Callable, Coroutine, Iterable, Iterator
13
+ from collections.abc import AsyncIterator, Callable, Coroutine, Iterable, Iterator, MutableMapping
14
14
  from concurrent.futures import ThreadPoolExecutor
15
15
  from errno import ENOTDIR
16
16
  from functools import partial
@@ -243,7 +243,7 @@ def iter_files_with_url(
243
243
  use_star: None | bool = False,
244
244
  escape: None | bool | Callable[[str], str] = True,
245
245
  normalize_attr: Callable[[dict], dict] = normalize_attr,
246
- id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
246
+ id_to_dirnode: None | EllipsisType | MutableMapping[int, tuple[str, int] | DirNode] = None,
247
247
  app: str = "web",
248
248
  raise_for_changed_count: bool = False,
249
249
  user_agent: str = "",
@@ -264,7 +264,7 @@ def iter_files_with_url(
264
264
  use_star: None | bool = False,
265
265
  escape: None | bool | Callable[[str], str] = True,
266
266
  normalize_attr: Callable[[dict], dict] = normalize_attr,
267
- id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
267
+ id_to_dirnode: None | EllipsisType | MutableMapping[int, tuple[str, int] | DirNode] = None,
268
268
  app: str = "web",
269
269
  raise_for_changed_count: bool = False,
270
270
  user_agent: str = "",
@@ -284,7 +284,7 @@ def iter_files_with_url(
284
284
  use_star: None | bool = False,
285
285
  escape: None | bool | Callable[[str], str] = True,
286
286
  normalize_attr: Callable[[dict], dict] = normalize_attr,
287
- id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
287
+ id_to_dirnode: None | EllipsisType | MutableMapping[int, tuple[str, int] | DirNode] = None,
288
288
  app: str = "web",
289
289
  raise_for_changed_count: bool = False,
290
290
  user_agent: str = "",
@@ -417,7 +417,7 @@ def iter_images_with_url(
417
417
  use_star: None | bool = False,
418
418
  escape: None | bool | Callable[[str], str] = True,
419
419
  normalize_attr: Callable[[dict], dict] = normalize_attr,
420
- id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
420
+ id_to_dirnode: None | EllipsisType | MutableMapping[int, tuple[str, int] | DirNode] = None,
421
421
  app: str = "web",
422
422
  raise_for_changed_count: bool = False,
423
423
  *,
@@ -436,7 +436,7 @@ def iter_images_with_url(
436
436
  use_star: None | bool = False,
437
437
  escape: None | bool | Callable[[str], str] = True,
438
438
  normalize_attr: Callable[[dict], dict] = normalize_attr,
439
- id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
439
+ id_to_dirnode: None | EllipsisType | MutableMapping[int, tuple[str, int] | DirNode] = None,
440
440
  app: str = "web",
441
441
  raise_for_changed_count: bool = False,
442
442
  *,
@@ -454,7 +454,7 @@ def iter_images_with_url(
454
454
  use_star: None | bool = False,
455
455
  escape: None | bool | Callable[[str], str] = True,
456
456
  normalize_attr: Callable[[dict], dict] = normalize_attr,
457
- id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
457
+ id_to_dirnode: None | EllipsisType | MutableMapping[int, tuple[str, int] | DirNode] = None,
458
458
  app: str = "web",
459
459
  raise_for_changed_count: bool = False,
460
460
  *,
@@ -575,7 +575,7 @@ def iter_subtitles_with_url(
575
575
  use_star: None | bool = False,
576
576
  escape: None | bool | Callable[[str], str] = True,
577
577
  normalize_attr: Callable[[dict], dict] = normalize_attr,
578
- id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
578
+ id_to_dirnode: None | EllipsisType | MutableMapping[int, tuple[str, int] | DirNode] = None,
579
579
  app: str = "web",
580
580
  raise_for_changed_count: bool = False,
581
581
  *,
@@ -594,7 +594,7 @@ def iter_subtitles_with_url(
594
594
  use_star: None | bool = False,
595
595
  escape: None | bool | Callable[[str], str] = True,
596
596
  normalize_attr: Callable[[dict], dict] = normalize_attr,
597
- id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
597
+ id_to_dirnode: None | EllipsisType | MutableMapping[int, tuple[str, int] | DirNode] = None,
598
598
  app: str = "web",
599
599
  raise_for_changed_count: bool = False,
600
600
  *,
@@ -612,7 +612,7 @@ def iter_subtitles_with_url(
612
612
  use_star: None | bool = False,
613
613
  escape: None | bool | Callable[[str], str] = True,
614
614
  normalize_attr: Callable[[dict], dict] = normalize_attr,
615
- id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
615
+ id_to_dirnode: None | EllipsisType | MutableMapping[int, tuple[str, int] | DirNode] = None,
616
616
  app: str = "web",
617
617
  raise_for_changed_count: bool = False,
618
618
  *,
@@ -855,7 +855,7 @@ def make_strm(
855
855
  suffix: str = "",
856
856
  type: Literal[1, 2, 3, 4, 5, 6, 7, 99] = 4,
857
857
  max_workers: None | int = None,
858
- id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
858
+ id_to_dirnode: None | EllipsisType | MutableMapping[int, tuple[str, int] | DirNode] = None,
859
859
  path_already: bool = False,
860
860
  app: str = "android",
861
861
  fs_files_cooldown: int | float = 0.5,
@@ -881,7 +881,7 @@ def make_strm(
881
881
  suffix: str = "",
882
882
  type: Literal[1, 2, 3, 4, 5, 6, 7, 99] = 4,
883
883
  max_workers: None | int = None,
884
- id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
884
+ id_to_dirnode: None | EllipsisType | MutableMapping[int, tuple[str, int] | DirNode] = None,
885
885
  path_already: bool = False,
886
886
  app: str = "android",
887
887
  fs_files_cooldown: int | float = 0.5,
@@ -906,7 +906,7 @@ def make_strm(
906
906
  suffix: str = "",
907
907
  type: Literal[1, 2, 3, 4, 5, 6, 7, 99] = 4,
908
908
  max_workers: None | int = None,
909
- id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
909
+ id_to_dirnode: None | EllipsisType | MutableMapping[int, tuple[str, int] | DirNode] = None,
910
910
  path_already: bool = False,
911
911
  app: str = "android",
912
912
  fs_files_cooldown: int | float = 0.5,
@@ -1295,7 +1295,7 @@ def iter_download_nodes(
1295
1295
  def iter_download_files(
1296
1296
  client: str | P115Client,
1297
1297
  cid: int = 0,
1298
- id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
1298
+ id_to_dirnode: None | EllipsisType | MutableMapping[int, tuple[str, int] | DirNode] = None,
1299
1299
  escape: None | bool | Callable[[str], str] = True,
1300
1300
  with_ancestors: bool = True,
1301
1301
  max_workers: None | int = None,
@@ -1309,7 +1309,7 @@ def iter_download_files(
1309
1309
  def iter_download_files(
1310
1310
  client: str | P115Client,
1311
1311
  cid: int = 0,
1312
- id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
1312
+ id_to_dirnode: None | EllipsisType | MutableMapping[int, tuple[str, int] | DirNode] = None,
1313
1313
  escape: None | bool | Callable[[str], str] = True,
1314
1314
  with_ancestors: bool = True,
1315
1315
  max_workers: None | int = None,
@@ -1322,7 +1322,7 @@ def iter_download_files(
1322
1322
  def iter_download_files(
1323
1323
  client: str | P115Client,
1324
1324
  cid: int = 0,
1325
- id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
1325
+ id_to_dirnode: None | EllipsisType | MutableMapping[int, tuple[str, int] | DirNode] = None,
1326
1326
  escape: None | bool | Callable[[str], str] = True,
1327
1327
  with_ancestors: bool = True,
1328
1328
  max_workers: None | int = None,