p115client 0.0.5.8.5__tar.gz → 0.0.5.8.7__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 (22) hide show
  1. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/PKG-INFO +1 -1
  2. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/client.py +34 -14
  3. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/tool/download.py +28 -25
  4. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/tool/iterdir.py +101 -6
  5. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/pyproject.toml +1 -1
  6. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/LICENSE +0 -0
  7. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/__init__.py +0 -0
  8. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/_upload.py +0 -0
  9. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/const.py +0 -0
  10. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/exception.py +0 -0
  11. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/py.typed +0 -0
  12. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/tool/__init__.py +0 -0
  13. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/tool/edit.py +0 -0
  14. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/tool/export_dir.py +0 -0
  15. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/tool/fs_files.py +0 -0
  16. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/tool/life.py +0 -0
  17. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/tool/pool.py +0 -0
  18. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/tool/request.py +0 -0
  19. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/tool/upload.py +0 -0
  20. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/tool/xys.py +0 -0
  21. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/p115client/type.py +0 -0
  22. {p115client-0.0.5.8.5 → p115client-0.0.5.8.7}/readme.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: p115client
3
- Version: 0.0.5.8.5
3
+ Version: 0.0.5.8.7
4
4
  Summary: Python 115 webdisk client.
5
5
  Home-page: https://github.com/ChenyangGao/p115client
6
6
  License: MIT
@@ -1022,6 +1022,12 @@ class ClientRequestMixin:
1022
1022
  for cookie in cookies:
1023
1023
  set_cookie(create_cookie("", cookie))
1024
1024
 
1025
+ @cookies.deleter
1026
+ def cookies(self, /):
1027
+ """请求所用的 Cookies 对象(同步和异步共用)
1028
+ """
1029
+ self.cookies = None
1030
+
1025
1031
  @property
1026
1032
  def cookiejar(self, /) -> CookieJar:
1027
1033
  """请求所用的 CookieJar 对象(同步和异步共用)
@@ -1765,7 +1771,7 @@ class ClientRequestMixin:
1765
1771
  def login_with_open(
1766
1772
  cls,
1767
1773
  /,
1768
- app_id: int | str,
1774
+ app_id: int | str = 100195993,
1769
1775
  console_qrcode: bool = True,
1770
1776
  *,
1771
1777
  async_: Literal[False] = False,
@@ -1777,7 +1783,7 @@ class ClientRequestMixin:
1777
1783
  def login_with_open(
1778
1784
  cls,
1779
1785
  /,
1780
- app_id: int | str,
1786
+ app_id: int | str = 100195993,
1781
1787
  console_qrcode: bool = True,
1782
1788
  *,
1783
1789
  async_: Literal[True],
@@ -1788,7 +1794,7 @@ class ClientRequestMixin:
1788
1794
  def login_with_open(
1789
1795
  cls,
1790
1796
  /,
1791
- app_id: int | str,
1797
+ app_id: int | str = 100195993,
1792
1798
  console_qrcode: bool = True,
1793
1799
  *,
1794
1800
  async_: Literal[False, True] = False,
@@ -2458,7 +2464,7 @@ class P115OpenClient(ClientRequestMixin):
2458
2464
 
2459
2465
  @access_token.setter
2460
2466
  def access_token(self, token, /):
2461
- self.headers["Authorization"] = "Bearer " + token
2467
+ self.headers["authorization"] = "Bearer " + token
2462
2468
  self.__dict__["access_token"] = token
2463
2469
 
2464
2470
  @property
@@ -2470,6 +2476,11 @@ class P115OpenClient(ClientRequestMixin):
2470
2476
  token = self.__dict__["upload_token"] = resp["data"]
2471
2477
  return token
2472
2478
 
2479
+ @locked_cacheproperty
2480
+ def user_id(self, /) -> int:
2481
+ resp = check_response(self.user_info_open())
2482
+ return int(resp["data"]["user_id"])
2483
+
2473
2484
  @overload
2474
2485
  def refresh_access_token(
2475
2486
  self,
@@ -4220,11 +4231,20 @@ class P115Client(P115OpenClient):
4220
4231
  if not cookies_equal(cookies_old, cookies_new):
4221
4232
  self._write_cookies(cookies_new)
4222
4233
 
4234
+ @cookies.deleter
4235
+ def cookies(self, /):
4236
+ """请求所用的 Cookies 对象(同步和异步共用)
4237
+ """
4238
+ self.cookies = None
4239
+
4223
4240
  @locked_cacheproperty
4224
4241
  def user_id(self, /) -> int:
4225
4242
  cookie_uid = self.cookies.get("UID")
4226
4243
  if cookie_uid:
4227
4244
  return int(cookie_uid.split("_")[0])
4245
+ elif "authorization" in self.headers:
4246
+ resp = check_response(self.user_info_open())
4247
+ return int(resp["data"]["user_id"])
4228
4248
  else:
4229
4249
  return 0
4230
4250
 
@@ -4914,9 +4934,9 @@ class P115Client(P115OpenClient):
4914
4934
  def login_another_open(
4915
4935
  self,
4916
4936
  /,
4917
- app_id: int | str,
4918
- replace: Literal[True] | Self,
4937
+ app_id: int | str = 100195993,
4919
4938
  *,
4939
+ replace: Literal[True] | Self,
4920
4940
  async_: Literal[False] = False,
4921
4941
  **request_kwargs,
4922
4942
  ) -> Self:
@@ -4925,9 +4945,9 @@ class P115Client(P115OpenClient):
4925
4945
  def login_another_open(
4926
4946
  self,
4927
4947
  /,
4928
- app_id: int | str,
4929
- replace: Literal[True] | Self,
4948
+ app_id: int | str = 100195993,
4930
4949
  *,
4950
+ replace: Literal[True] | Self,
4931
4951
  async_: Literal[True],
4932
4952
  **request_kwargs,
4933
4953
  ) -> Coroutine[Any, Any, Self]:
@@ -4936,9 +4956,9 @@ class P115Client(P115OpenClient):
4936
4956
  def login_another_open(
4937
4957
  self,
4938
4958
  /,
4939
- app_id: int | str,
4940
- replace: Literal[False] = False,
4959
+ app_id: int | str = 100195993,
4941
4960
  *,
4961
+ replace: Literal[False] = False,
4942
4962
  async_: Literal[False] = False,
4943
4963
  **request_kwargs,
4944
4964
  ) -> P115OpenClient:
@@ -4947,9 +4967,9 @@ class P115Client(P115OpenClient):
4947
4967
  def login_another_open(
4948
4968
  self,
4949
4969
  /,
4950
- app_id: int | str,
4951
- replace: Literal[False] = False,
4970
+ app_id: int | str = 100195993,
4952
4971
  *,
4972
+ replace: Literal[False] = False,
4953
4973
  async_: Literal[True],
4954
4974
  **request_kwargs,
4955
4975
  ) -> Coroutine[Any, Any, P115OpenClient]:
@@ -4957,9 +4977,9 @@ class P115Client(P115OpenClient):
4957
4977
  def login_another_open(
4958
4978
  self,
4959
4979
  /,
4960
- app_id: int | str,
4961
- replace: bool | Self = False,
4980
+ app_id: int | str = 100195993,
4962
4981
  *,
4982
+ replace: bool | Self = False,
4963
4983
  async_: Literal[False, True] = False,
4964
4984
  **request_kwargs,
4965
4985
  ) -> P115OpenClient | Coroutine[Any, Any, P115OpenClient] | Self | Coroutine[Any, Any, Self]:
@@ -25,6 +25,7 @@ from shutil import rmtree
25
25
  from threading import Lock
26
26
  from time import time
27
27
  from typing import cast, overload, Any, Final, Literal, TypedDict
28
+ from types import EllipsisType
28
29
  from urllib.parse import quote, urlsplit
29
30
  from urllib.request import urlopen, Request
30
31
  from uuid import uuid4
@@ -257,7 +258,7 @@ def iter_files_with_url(
257
258
  use_star: None | bool = False,
258
259
  escape: None | bool | Callable[[str], str] = True,
259
260
  normalize_attr: Callable[[dict], dict] = normalize_attr,
260
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
261
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
261
262
  app: str = "web",
262
263
  raise_for_changed_count: bool = False,
263
264
  user_agent: str = "",
@@ -278,7 +279,7 @@ def iter_files_with_url(
278
279
  use_star: None | bool = False,
279
280
  escape: None | bool | Callable[[str], str] = True,
280
281
  normalize_attr: Callable[[dict], dict] = normalize_attr,
281
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
282
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
282
283
  app: str = "web",
283
284
  raise_for_changed_count: bool = False,
284
285
  user_agent: str = "",
@@ -298,7 +299,7 @@ def iter_files_with_url(
298
299
  use_star: None | bool = False,
299
300
  escape: None | bool | Callable[[str], str] = True,
300
301
  normalize_attr: Callable[[dict], dict] = normalize_attr,
301
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
302
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
302
303
  app: str = "web",
303
304
  raise_for_changed_count: bool = False,
304
305
  user_agent: str = "",
@@ -423,7 +424,7 @@ def iter_images_with_url(
423
424
  use_star: None | bool = False,
424
425
  escape: None | bool | Callable[[str], str] = True,
425
426
  normalize_attr: Callable[[dict], dict] = normalize_attr,
426
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
427
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
427
428
  app: str = "web",
428
429
  raise_for_changed_count: bool = False,
429
430
  *,
@@ -442,7 +443,7 @@ def iter_images_with_url(
442
443
  use_star: None | bool = False,
443
444
  escape: None | bool | Callable[[str], str] = True,
444
445
  normalize_attr: Callable[[dict], dict] = normalize_attr,
445
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
446
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
446
447
  app: str = "web",
447
448
  raise_for_changed_count: bool = False,
448
449
  *,
@@ -460,7 +461,7 @@ def iter_images_with_url(
460
461
  use_star: None | bool = False,
461
462
  escape: None | bool | Callable[[str], str] = True,
462
463
  normalize_attr: Callable[[dict], dict] = normalize_attr,
463
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
464
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
464
465
  app: str = "web",
465
466
  raise_for_changed_count: bool = False,
466
467
  *,
@@ -578,7 +579,7 @@ def iter_subtitles_with_url(
578
579
  use_star: None | bool = False,
579
580
  escape: None | bool | Callable[[str], str] = True,
580
581
  normalize_attr: Callable[[dict], dict] = normalize_attr,
581
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
582
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
582
583
  app: str = "web",
583
584
  raise_for_changed_count: bool = False,
584
585
  *,
@@ -597,7 +598,7 @@ def iter_subtitles_with_url(
597
598
  use_star: None | bool = False,
598
599
  escape: None | bool | Callable[[str], str] = True,
599
600
  normalize_attr: Callable[[dict], dict] = normalize_attr,
600
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
601
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
601
602
  app: str = "web",
602
603
  raise_for_changed_count: bool = False,
603
604
  *,
@@ -615,7 +616,7 @@ def iter_subtitles_with_url(
615
616
  use_star: None | bool = False,
616
617
  escape: None | bool | Callable[[str], str] = True,
617
618
  normalize_attr: Callable[[dict], dict] = normalize_attr,
618
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
619
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
619
620
  app: str = "web",
620
621
  raise_for_changed_count: bool = False,
621
622
  *,
@@ -855,7 +856,7 @@ def make_strm(
855
856
  suffix: str = "",
856
857
  type: Literal[1, 2, 3, 4, 5, 6, 7, 99] = 4,
857
858
  max_workers: None | int = None,
858
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
859
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
859
860
  path_already: bool = False,
860
861
  app: str = "android",
861
862
  fs_files_cooldown: int | float = 0.5,
@@ -881,7 +882,7 @@ def make_strm(
881
882
  suffix: str = "",
882
883
  type: Literal[1, 2, 3, 4, 5, 6, 7, 99] = 4,
883
884
  max_workers: None | int = None,
884
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
885
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
885
886
  path_already: bool = False,
886
887
  app: str = "android",
887
888
  fs_files_cooldown: int | float = 0.5,
@@ -906,7 +907,7 @@ def make_strm(
906
907
  suffix: str = "",
907
908
  type: Literal[1, 2, 3, 4, 5, 6, 7, 99] = 4,
908
909
  max_workers: None | int = None,
909
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
910
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
910
911
  path_already: bool = False,
911
912
  app: str = "android",
912
913
  fs_files_cooldown: int | float = 0.5,
@@ -1170,40 +1171,36 @@ def iter_download_nodes(
1170
1171
  method = client.download_files
1171
1172
  else:
1172
1173
  method = client.download_folders
1174
+ get_nodes = partial(method, async_=async_, **{"base_url": get_base_url, **request_kwargs})
1173
1175
  if max_workers == 1:
1174
1176
  def gen_step(pickcode):
1175
1177
  if isinstance(pickcode, int):
1176
1178
  resp = yield client.fs_file_skim(pickcode, async_=async_, **request_kwargs)
1177
1179
  check_response(resp)
1178
1180
  pickcode = resp["data"][0]["pick_code"]
1179
- request_kwargs.setdefault("base_url", get_base_url)
1180
1181
  for i in count(1):
1181
1182
  payload = {"pickcode": pickcode, "page": i}
1182
- resp = yield method(payload, async_=async_, **request_kwargs)
1183
+ resp = yield get_nodes(payload)
1183
1184
  check_response(resp)
1184
1185
  data = resp["data"]
1185
1186
  yield YieldFrom(data["list"], identity=True)
1186
1187
  if not data["has_next_page"]:
1187
1188
  break
1188
1189
  else:
1190
+ max_page = 0
1189
1191
  get_next_page = count(1).__next__
1190
1192
  if async_:
1191
1193
  q: Any = AsyncQueue()
1192
1194
  else:
1193
1195
  q = SimpleQueue()
1194
1196
  get, put = q.get, q.put_nowait
1195
- max_page = 0
1196
1197
  def request(pickcode):
1197
1198
  nonlocal max_page
1198
1199
  while True:
1199
1200
  page = get_next_page()
1200
1201
  if max_page and page > max_page:
1201
1202
  return
1202
- resp: dict = yield method(
1203
- {"pickcode": pickcode, "page": page},
1204
- async_=async_, # type: ignore
1205
- **request_kwargs,
1206
- )
1203
+ resp: dict = yield get_nodes({"pickcode": pickcode, "page": page})
1207
1204
  try:
1208
1205
  check_response(resp)
1209
1206
  except BaseException as e:
@@ -1214,7 +1211,9 @@ def iter_download_nodes(
1214
1211
  if not data["has_next_page"]:
1215
1212
  max_page = page
1216
1213
  def gen_step(pickcode):
1217
- nonlocal max_workers
1214
+ nonlocal max_workers, max_page, get_next_page
1215
+ max_page = 0
1216
+ get_next_page = count(1).__next__
1218
1217
  if async_:
1219
1218
  if max_workers is None or max_workers <= 0:
1220
1219
  max_workers = 20
@@ -1239,7 +1238,6 @@ def iter_download_nodes(
1239
1238
  )
1240
1239
  check_response(resp)
1241
1240
  pickcode = resp["data"][0]["pick_code"]
1242
- request_kwargs.setdefault("base_url", cycle(("http://proapi.115.com", "https://proapi.115.com")).__next__)
1243
1241
  try:
1244
1242
  sentinel = object()
1245
1243
  countdown: Callable
@@ -1282,6 +1280,11 @@ def iter_download_nodes(
1282
1280
  )) as get_next:
1283
1281
  while True:
1284
1282
  attr = yield get_next
1283
+ if not files:
1284
+ yield Yield(
1285
+ {"fid": str(attr["id"]), "pid": "0", "fn": attr["name"]},
1286
+ identity=True,
1287
+ )
1285
1288
  yield YieldFrom(
1286
1289
  run_gen_step_iter(gen_step(attr["pickcode"]), async_=async_),
1287
1290
  identity=True,
@@ -1293,7 +1296,7 @@ def iter_download_nodes(
1293
1296
  def iter_download_files(
1294
1297
  client: str | P115Client,
1295
1298
  cid: int = 0,
1296
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
1299
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
1297
1300
  escape: None | bool | Callable[[str], str] = True,
1298
1301
  with_ancestors: bool = True,
1299
1302
  max_workers: None | int = None,
@@ -1307,7 +1310,7 @@ def iter_download_files(
1307
1310
  def iter_download_files(
1308
1311
  client: str | P115Client,
1309
1312
  cid: int = 0,
1310
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
1313
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
1311
1314
  escape: None | bool | Callable[[str], str] = True,
1312
1315
  with_ancestors: bool = True,
1313
1316
  max_workers: None | int = None,
@@ -1320,7 +1323,7 @@ def iter_download_files(
1320
1323
  def iter_download_files(
1321
1324
  client: str | P115Client,
1322
1325
  cid: int = 0,
1323
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
1326
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
1324
1327
  escape: None | bool | Callable[[str], str] = True,
1325
1328
  with_ancestors: bool = True,
1326
1329
  max_workers: None | int = None,
@@ -8,9 +8,9 @@ __all__ = [
8
8
  "get_ancestors_to_cid", "get_id_to_path", "get_id_to_sha1", "get_id_to_pickcode",
9
9
  "iter_nodes_skim", "iter_stared_dirs_raw", "iter_stared_dirs", "ensure_attr_path",
10
10
  "ensure_attr_path_by_category_get", "iterdir_raw", "iterdir", "iterdir_limited",
11
- "iter_files_raw", "iter_files", "traverse_files", "iter_dupfiles", "iter_image_files",
12
- "share_extract_payload", "share_iterdir", "share_iter_files", "iter_selected_nodes",
13
- "iter_selected_nodes_by_pickcode", "iter_selected_nodes_using_category_get",
11
+ "iter_files_raw", "iter_files", "traverse_files", "iter_dirs", "iter_dupfiles",
12
+ "iter_image_files", "share_extract_payload", "share_iterdir", "share_iter_files",
13
+ "iter_selected_nodes", "iter_selected_nodes_by_pickcode", "iter_selected_nodes_using_category_get",
14
14
  "iter_selected_nodes_using_edit", "iter_selected_nodes_using_star_event",
15
15
  "iter_selected_dirs_using_star", "iter_files_with_dirname", "iter_files_with_path",
16
16
  "iter_files_with_path_by_export_dir", "iter_parents_3_level", "iter_dir_nodes",
@@ -41,9 +41,9 @@ from weakref import WeakValueDictionary
41
41
  from asynctools import async_chain, async_filter, async_map, to_list
42
42
  from concurrenttools import run_as_thread, taskgroup_map, threadpool_map
43
43
  from iterutils import (
44
- bfs_gen, chunked, async_foreach, ensure_aiter, foreach, flatten,
45
- iter_unique, run_gen_step, run_gen_step_iter, through, async_through,
46
- with_iter_next, Yield, YieldFrom,
44
+ as_gen_step, bfs_gen, chunked, async_foreach, ensure_aiter, foreach,
45
+ flatten, iter_unique, run_gen_step, run_gen_step_iter, through,
46
+ async_through, with_iter_next, Yield, YieldFrom,
47
47
  )
48
48
  from iter_collect import iter_keyed_dups, SupportsLT
49
49
  from orjson import loads
@@ -2789,6 +2789,101 @@ def traverse_files(
2789
2789
  return run_gen_step_iter(gen_step, async_=async_)
2790
2790
 
2791
2791
 
2792
+ @overload
2793
+ def iter_dirs(
2794
+ client: str | P115Client,
2795
+ cid: int | str = 0,
2796
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
2797
+ with_pickcode: bool = False,
2798
+ max_workers: None | int = None,
2799
+ *,
2800
+ async_: Literal[False] = False,
2801
+ **request_kwargs,
2802
+ ) -> Iterator[dict]:
2803
+ ...
2804
+ @overload
2805
+ def iter_dirs(
2806
+ client: str | P115Client,
2807
+ cid: int | str = 0,
2808
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
2809
+ with_pickcode: bool = False,
2810
+ max_workers: None | int = None,
2811
+ *,
2812
+ async_: Literal[True],
2813
+ **request_kwargs,
2814
+ ) -> AsyncIterator[dict]:
2815
+ ...
2816
+ def iter_dirs(
2817
+ client: str | P115Client,
2818
+ cid: int | str = 0,
2819
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
2820
+ with_pickcode: bool = False,
2821
+ max_workers: None | int = None,
2822
+ *,
2823
+ async_: Literal[False, True] = False,
2824
+ **request_kwargs,
2825
+ ) -> Iterator[dict] | AsyncIterator[dict]:
2826
+ """遍历目录树,获取目录信息
2827
+
2828
+ :param client: 115 客户端或 cookies
2829
+ :param cid: 目录 id(如果是 int) 或者 pickcode(如果是 str)
2830
+ :param id_to_dirnode: 字典,保存 id 到对应文件的 `DirNode(name, parent_id)` 命名元组的字典
2831
+ :param with_pickcode: 是否需要包含提取码
2832
+ :param max_workers: 最大并发数
2833
+ :param async_: 是否异步
2834
+ :param request_kwargs: 其它请求参数
2835
+
2836
+ :return: 迭代器,返回此目录内的(仅目录)文件信息
2837
+ """
2838
+ from .download import iter_download_nodes
2839
+ if isinstance(client, str):
2840
+ client = P115Client(client, check_for_relogin=True)
2841
+ if id_to_dirnode is None:
2842
+ id_to_dirnode = ID_TO_DIRNODE_CACHE[client.user_id]
2843
+ it = iter_download_nodes(
2844
+ client,
2845
+ cid,
2846
+ files=False,
2847
+ max_workers=max_workers,
2848
+ async_=async_, # type: ignore
2849
+ **request_kwargs,
2850
+ )
2851
+ do_map: Callable = async_map if async_ else map
2852
+ def project(info: dict, /) -> dict:
2853
+ attr = {"id": int(info["fid"]), "parent_id": int(info["pid"]), "name": info["fn"]}
2854
+ if id_to_dirnode is not ...:
2855
+ id_to_dirnode[attr["id"]] = DirNode(attr["name"], attr["parent_id"])
2856
+ return attr
2857
+ it = do_map(project, it)
2858
+ if with_pickcode:
2859
+ file_skim = client.fs_file_skim
2860
+ @as_gen_step(async_=async_)
2861
+ def batch_load_pickcode(batch: Sequence[dict], /):
2862
+ resp = yield file_skim(
2863
+ (a["id"] for a in batch),
2864
+ method="POST",
2865
+ async_=async_,
2866
+ **request_kwargs,
2867
+ )
2868
+ check_response(resp)
2869
+ maps = {int(a["file_id"]): a["pick_code"] for a in resp["data"]}
2870
+ for attr in batch:
2871
+ attr["pickcode"] = maps[attr["id"]]
2872
+ return batch
2873
+ def gen_step(iterable):
2874
+ batch_map = taskgroup_map if async_ else threadpool_map
2875
+ with with_iter_next(batch_map(
2876
+ batch_load_pickcode,
2877
+ chunked(iterable, 3000),
2878
+ max_workers=max_workers,
2879
+ )) as get_next:
2880
+ while True:
2881
+ batch = yield get_next
2882
+ yield YieldFrom(batch, identity=True)
2883
+ it = run_gen_step_iter(gen_step(it), async_=async_)
2884
+ return it
2885
+
2886
+
2792
2887
  @overload
2793
2888
  def iter_dupfiles[K](
2794
2889
  client: str | P115Client,
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "p115client"
3
- version = "0.0.5.8.5"
3
+ version = "0.0.5.8.7"
4
4
  description = "Python 115 webdisk client."
5
5
  authors = ["ChenyangGao <wosiwujm@gmail.com>"]
6
6
  license = "MIT"
File without changes
File without changes