p115client 0.0.5.10.2__py3-none-any.whl → 0.0.5.10.4__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.
@@ -8,8 +8,8 @@ __all__ = [
8
8
  "iter_nodes_skim", "iter_stared_dirs_raw", "iter_stared_dirs", "ensure_attr_path",
9
9
  "ensure_attr_path_by_category_get", "iterdir_raw", "iterdir", "iterdir_limited",
10
10
  "iter_files_raw", "iter_files", "traverse_files", "iter_dirs", "iter_dupfiles",
11
- "iter_image_files", "share_iterdir", "share_iter_files", "iter_selected_nodes",
12
- "iter_selected_nodes_by_pickcode", "iter_selected_nodes_using_category_get",
11
+ "iter_image_files", "share_iterdir", "share_iter_files", "share_get_id_to_path",
12
+ "iter_selected_nodes", "iter_selected_nodes_by_pickcode", "iter_selected_nodes_using_category_get",
13
13
  "iter_selected_nodes_using_edit", "iter_selected_nodes_using_star_event",
14
14
  "iter_selected_dirs_using_star", "iter_files_with_dirname", "iter_files_with_path",
15
15
  "iter_files_with_path_by_export_dir", "iter_parents_3_level", "iter_dir_nodes",
@@ -104,7 +104,7 @@ class OverviewAttr:
104
104
 
105
105
 
106
106
  #: 用于缓存每个用户(根据用户 id 区别)的每个目录 id 到所对应的 (名称, 父id) 的元组的字典的字典
107
- ID_TO_DIRNODE_CACHE: Final[defaultdict[int, dict[int, tuple[str, int] | DirNode]]] = defaultdict(dict)
107
+ ID_TO_DIRNODE_CACHE: Final[defaultdict[int | tuple[int, str], dict[int, tuple[str, int] | DirNode]]] = defaultdict(dict)
108
108
 
109
109
 
110
110
  def _overview_attr(info: Mapping, /) -> OverviewAttr:
@@ -117,8 +117,8 @@ def _overview_attr(info: Mapping, /) -> OverviewAttr:
117
117
  else:
118
118
  id = int(info["fid"])
119
119
  pid = int(info["cid"])
120
- ctime = int(info["tp"])
121
- mtime = int(info["te"])
120
+ ctime = int(info.get("tp") or info["t"])
121
+ mtime = int(info.get("te") or info["t"])
122
122
  elif "fn" in info:
123
123
  is_dir = info["fc"] == "0"
124
124
  name = info["fn"]
@@ -596,18 +596,18 @@ def get_ancestors_to_cid(
596
596
  return run_gen_step(gen_step, async_=async_)
597
597
 
598
598
 
599
-
600
-
601
599
  # TODO: 使用 search 接口以在特定目录之下搜索某个名字,以便减少风控
602
600
  @overload
603
601
  def get_id_to_path(
604
602
  client: str | P115Client,
605
603
  path: str | Sequence[str],
604
+ parent_id: int = 0,
606
605
  ensure_file: None | bool = None,
607
606
  is_posixpath: bool = False,
608
607
  refresh: bool = False,
609
608
  id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
610
609
  app: str = "web",
610
+ dont_use_getid: bool = False,
611
611
  *,
612
612
  async_: Literal[False] = False,
613
613
  **request_kwargs,
@@ -617,11 +617,13 @@ def get_id_to_path(
617
617
  def get_id_to_path(
618
618
  client: str | P115Client,
619
619
  path: str | Sequence[str],
620
+ parent_id: int = 0,
620
621
  ensure_file: None | bool = None,
621
622
  is_posixpath: bool = False,
622
623
  refresh: bool = False,
623
624
  id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
624
625
  app: str = "web",
626
+ dont_use_getid: bool = False,
625
627
  *,
626
628
  async_: Literal[True],
627
629
  **request_kwargs,
@@ -630,11 +632,13 @@ def get_id_to_path(
630
632
  def get_id_to_path(
631
633
  client: str | P115Client,
632
634
  path: str | Sequence[str],
635
+ parent_id: int = 0,
633
636
  ensure_file: None | bool = None,
634
637
  is_posixpath: bool = False,
635
638
  refresh: bool = False,
636
639
  id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
637
640
  app: str = "web",
641
+ dont_use_getid: bool = False,
638
642
  *,
639
643
  async_: Literal[False, True] = False,
640
644
  **request_kwargs,
@@ -643,6 +647,7 @@ def get_id_to_path(
643
647
 
644
648
  :param client: 115 客户端或 cookies
645
649
  :param path: 路径
650
+ :param parent_id: 上级目录的 id
646
651
  :param ensure_file: 是否确保为文件
647
652
 
648
653
  - True: 必须是文件
@@ -653,6 +658,7 @@ def get_id_to_path(
653
658
  :param refresh: 是否刷新。如果为 True,则会执行网络请求以查询;如果为 False,则直接从 `id_to_dirnode` 中获取
654
659
  :param id_to_dirnode: 字典,保存 id 到对应文件的 `DirNode(name, parent_id)` 命名元组的字典
655
660
  :param app: 使用某个 app (设备)的接口
661
+ :param dont_use_getid: 不要使用 `client.fs_dir_getid` 或 `client.fs_dir_getid_app`,以便 `id_to_dirnode` 有缓存
656
662
  :param async_: 是否异步
657
663
  :param request_kwargs: 其它请求参数
658
664
 
@@ -664,178 +670,124 @@ def get_id_to_path(
664
670
  id_to_dirnode = ID_TO_DIRNODE_CACHE[client.user_id]
665
671
  error = FileNotFoundError(ENOENT, f"no such path: {path!r}")
666
672
  def gen_step():
667
- nonlocal client, ensure_file
668
- if not isinstance(path, str):
669
- patht = ["", *filter(None, path)]
670
- if len(patht) == 1:
671
- return 0
672
- if is_posixpath:
673
- for i in range(1, len(patht)):
674
- patht[i] = patht[i].replace("/", "|")
675
- elif path in (".", "..", "/"):
676
- if ensure_file:
677
- raise error
678
- return 0
679
- elif path.startswith("根目录 > "):
680
- patht = path.split(" > ")
681
- patht[0] = ""
682
- if is_posixpath:
683
- for i in range(1, len(patht)):
684
- patht[i] = patht[i].replace("/", "|")
685
- elif is_posixpath:
686
- if ensure_file is None and path.endswith("/"):
687
- ensure_file = False
688
- patht = ["", *filter(None, path.split("/"))]
673
+ nonlocal ensure_file, parent_id
674
+ if isinstance(path, str):
675
+ if path.startswith("/"):
676
+ parent_id = 0
677
+ if path in (".", "..", "/"):
678
+ if ensure_file:
679
+ raise error
680
+ return parent_id
681
+ elif path.startswith("根目录 > "):
682
+ parent_id = 0
683
+ patht = path.split(" > ")[1:]
684
+ elif is_posixpath:
685
+ if ensure_file is None and path.endswith("/"):
686
+ ensure_file = False
687
+ patht = [p for p in path.split("/") if p]
688
+ else:
689
+ if ensure_file is None and path_is_dir_form(path):
690
+ ensure_file = False
691
+ patht, _ = splits(path.lstrip("/"))
689
692
  else:
690
- if ensure_file is None and path_is_dir_form(path):
691
- ensure_file = False
692
- patht, _ = splits("/" + path)
693
- if len(patht) == 1:
693
+ if path and not path[0]:
694
+ parent_id = 0
695
+ patht = list(path[1:])
696
+ else:
697
+ patht = [p for p in path if p]
698
+ if not patht:
699
+ return parent_id
700
+ if not patht:
694
701
  if ensure_file:
695
702
  raise error
696
- return 0
697
- stop = len(patht) - bool(ensure_file)
698
- obj = "|" if is_posixpath else "/"
699
- for i in range(stop):
700
- if obj in patht[i]:
701
- break
702
- else:
703
- i += 1
704
- j = 1
705
- pid = 0
706
- if stop > 1 and not refresh and id_to_dirnode:
707
- if stop == 2:
708
- if is_posixpath:
709
- needle = (patht[1].replace("/", "|"), pid)
710
- else:
711
- needle = (patht[1], pid)
712
- for k, t in id_to_dirnode.items():
713
- if is_posixpath:
714
- t = (t[0].replace("/", "|"), t[1])
715
- if t == needle:
716
- pid = k
717
- j = 2
718
- else:
719
- if is_posixpath:
720
- table = {(n.replace("/", "|"), pid): k for k, (n, pid) in id_to_dirnode.items()}
703
+ return parent_id
704
+ i = 0
705
+ start_parent_id = parent_id
706
+ if not refresh and id_to_dirnode and id_to_dirnode is not ...:
707
+ if i := len(patht) - bool(ensure_file):
708
+ obj = "|" if is_posixpath else "/"
709
+ for i in range(i):
710
+ if obj in patht[i]:
711
+ break
721
712
  else:
722
- table = {cast(tuple[str, int], tuple(t)): k for k, t in id_to_dirnode.items()}
723
- try:
724
- for j in range(1, stop):
725
- if is_posixpath:
726
- needle = (patht[j].replace("/", "|"), pid)
727
- else:
728
- needle = (patht[j], pid)
729
- pid = table[needle]
730
- j += 1
731
- except KeyError:
732
- pass
733
- if j >= i:
734
- i = j
735
- cid = pid
736
- else:
737
- if ensure_file and len(patht) == i:
738
- i -= 1
739
- if app in ("", "web", "desktop", "harmony"):
740
- fs_dir_getid: Callable = client.fs_dir_getid
741
- else:
742
- fs_dir_getid = partial(client.fs_dir_getid_app, app=app)
743
- cid = 0
744
- while i > 1:
745
- dirname = "/".join(patht[:i])
746
- resp = yield fs_dir_getid(dirname, async_=async_, **request_kwargs)
747
- if not (resp["state"] and (cid := resp["id"])):
748
- if len(patht) == i and ensure_file is None:
749
- ensure_file = True
750
- i -= 1
751
- continue
752
- raise error
753
- cid = int(cid)
754
- if not refresh and cid not in id_to_dirnode:
755
- yield get_path_to_cid(
756
- client,
757
- cid,
758
- id_to_dirnode=id_to_dirnode,
759
- app=app,
760
- async_=async_,
761
- **request_kwargs,
762
- )
763
- break
764
- if len(patht) == i:
765
- return cid
766
- for name in patht[i:-1]:
767
- if async_:
768
- async def request():
769
- nonlocal cid
770
- async for info in iterdir_raw(
771
- client,
772
- cid,
773
- ensure_file=False,
774
- app=app,
775
- id_to_dirnode=id_to_dirnode,
776
- async_=True,
777
- **request_kwargs,
778
- ):
779
- attr = _overview_attr(info)
780
- if (attr.name.replace("/", "|") if is_posixpath else attr.name) == name:
781
- cid = attr.id
713
+ i += 1
714
+ if i:
715
+ for i in range(i):
716
+ needle = (patht[i], parent_id)
717
+ for fid, key in id_to_dirnode.items():
718
+ if needle == key:
719
+ parent_id = fid
782
720
  break
783
721
  else:
784
- raise error
785
- yield request
786
- else:
787
- for info in iterdir_raw(
788
- client,
789
- cid,
790
- ensure_file=False,
791
- app=app,
792
- id_to_dirnode=id_to_dirnode,
793
- **request_kwargs,
794
- ):
795
- attr = _overview_attr(info)
796
- if (attr.name.replace("/", "|") if is_posixpath else attr.name) == name:
797
- cid = attr.id
798
722
  break
799
723
  else:
800
- raise error
801
- name = patht[-1]
802
- if async_:
803
- async def request():
804
- async for info in iterdir_raw(
805
- client,
806
- cid,
807
- app=app,
808
- id_to_dirnode=id_to_dirnode,
809
- async_=True,
810
- **request_kwargs,
811
- ):
812
- attr = _overview_attr(info)
813
- if (attr.name.replace("/", "|") if is_posixpath else attr.name) == name:
814
- if ensure_file:
815
- if not attr.is_dir:
816
- return P115ID(attr.id, info, about="path")
817
- elif attr.is_dir:
818
- return P115ID(attr.id, info, about="path")
724
+ i += 1
725
+ if i == len(patht):
726
+ return parent_id
727
+ if not start_parent_id:
728
+ stop = 0
729
+ if j := len(patht) - bool(ensure_file):
730
+ for stop, part in enumerate(patht[:j]):
731
+ if "/" in part:
732
+ break
819
733
  else:
820
- raise error
821
- return (yield request)
822
- else:
823
- for info in iterdir_raw(
734
+ stop += 1
735
+ if not dont_use_getid:
736
+ while stop > i:
737
+ if app in ("", "web", "desktop", "harmony"):
738
+ fs_dir_getid: Callable = client.fs_dir_getid
739
+ else:
740
+ fs_dir_getid = partial(client.fs_dir_getid_app, app=app)
741
+ dirname = "/".join(patht[:stop])
742
+ resp = yield fs_dir_getid(dirname, async_=async_, **request_kwargs)
743
+ check_response(resp)
744
+ cid = int(resp["id"])
745
+ if not cid:
746
+ if stop == len(patht) and ensure_file is None:
747
+ stop -= 1
748
+ continue
749
+ raise error
750
+ parent_id = cid
751
+ i = stop
752
+ break
753
+ if i == len(patht):
754
+ return parent_id
755
+ for name in patht[i:-1]:
756
+ if is_posixpath:
757
+ name = name.replace("/", "|")
758
+ with with_iter_next(iterdir(
824
759
  client,
825
- cid,
760
+ parent_id,
761
+ ensure_file=False,
826
762
  app=app,
827
763
  id_to_dirnode=id_to_dirnode,
764
+ async_=async_,
828
765
  **request_kwargs,
829
- ):
830
- attr = _overview_attr(info)
831
- if (attr.name.replace("/", "|") if is_posixpath else attr.name) == name:
832
- if ensure_file:
833
- if not attr.is_dir:
834
- return P115ID(attr.id, info, about="path")
835
- elif attr.is_dir:
836
- return P115ID(attr.id, info, about="path")
837
- else:
838
- raise error
766
+ )) as get_next:
767
+ found = False
768
+ while not found:
769
+ attr = yield get_next
770
+ found = (attr["name"].replace("/", "|") if is_posixpath else attr["name"]) == name
771
+ parent_id = attr["id"]
772
+ if not found:
773
+ raise error
774
+ name = patht[-1]
775
+ if is_posixpath:
776
+ name = name.replace("/", "|")
777
+ with with_iter_next(iterdir(
778
+ client,
779
+ parent_id,
780
+ app=app,
781
+ id_to_dirnode=id_to_dirnode,
782
+ async_=async_,
783
+ **request_kwargs,
784
+ )) as get_next:
785
+ while True:
786
+ attr = yield get_next
787
+ if (attr["name"].replace("/", "|") if is_posixpath else attr["name"]) == name:
788
+ if ensure_file is None or ensure_file ^ attr["is_dir"]:
789
+ return P115ID(attr["id"], attr, about="path")
790
+ raise error
839
791
  return run_gen_step(gen_step, async_=async_)
840
792
 
841
793
 
@@ -1135,6 +1087,11 @@ def _iter_fs_files(
1135
1087
  pid, name = int(info["cid"]), info["name"]
1136
1088
  id_to_dirnode[pid] = DirNode(name, int(info["pid"]))
1137
1089
  if ensure_file is None:
1090
+ if id_to_dirnode is not ...:
1091
+ for info in resp["data"]:
1092
+ attr = _overview_attr(info)
1093
+ if attr.is_dir:
1094
+ id_to_dirnode[attr.id] = DirNode(attr.name, attr.parent_id)
1138
1095
  yield YieldFrom(resp["data"], identity=True)
1139
1096
  else:
1140
1097
  for info in resp["data"]:
@@ -3118,6 +3075,7 @@ def share_iterdir(
3118
3075
  order: Literal["file_name", "file_size", "file_type", "user_utime", "user_ptime", "user_otime"] = "user_ptime",
3119
3076
  asc: Literal[0, 1] = 1,
3120
3077
  normalize_attr: None | Callable[[dict], dict] = normalize_attr,
3078
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
3121
3079
  *,
3122
3080
  async_: Literal[False] = False,
3123
3081
  **request_kwargs,
@@ -3133,6 +3091,7 @@ def share_iterdir(
3133
3091
  order: Literal["file_name", "file_size", "file_type", "user_utime", "user_ptime", "user_otime"] = "user_ptime",
3134
3092
  asc: Literal[0, 1] = 1,
3135
3093
  normalize_attr: None | Callable[[dict], dict] = normalize_attr,
3094
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
3136
3095
  *,
3137
3096
  async_: Literal[True],
3138
3097
  **request_kwargs,
@@ -3147,6 +3106,7 @@ def share_iterdir(
3147
3106
  order: Literal["file_name", "file_size", "file_type", "user_utime", "user_ptime", "user_otime"] = "user_ptime",
3148
3107
  asc: Literal[0, 1] = 1,
3149
3108
  normalize_attr: None | Callable[[dict], dict] = normalize_attr,
3109
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
3150
3110
  *,
3151
3111
  async_: Literal[False, True] = False,
3152
3112
  **request_kwargs,
@@ -3169,6 +3129,7 @@ def share_iterdir(
3169
3129
 
3170
3130
  :param asc: 升序排列。0: 否,1: 是
3171
3131
  :param normalize_attr: 把数据进行转换处理,使之便于阅读
3132
+ :param id_to_dirnode: 字典,保存 id 到对应文件的 `DirNode(name, parent_id)` 命名元组的字典
3172
3133
  :param async_: 是否异步
3173
3134
  :param request_kwargs: 其它请求参数
3174
3135
 
@@ -3176,7 +3137,9 @@ def share_iterdir(
3176
3137
  """
3177
3138
  if isinstance(client, str):
3178
3139
  client = P115Client(client, check_for_relogin=True)
3179
- if page_size < 0:
3140
+ if id_to_dirnode is None:
3141
+ id_to_dirnode = ID_TO_DIRNODE_CACHE[(client.user_id, share_code)]
3142
+ if page_size <= 0:
3180
3143
  page_size = 10_000
3181
3144
  def gen_step():
3182
3145
  nonlocal receive_code
@@ -3202,6 +3165,10 @@ def share_iterdir(
3202
3165
  for attr in resp["data"]["list"]:
3203
3166
  attr["share_code"] = share_code
3204
3167
  attr["receive_code"] = receive_code
3168
+ if id_to_dirnode is not ...:
3169
+ oattr = _overview_attr(attr)
3170
+ if oattr.is_dir:
3171
+ id_to_dirnode[oattr.id] = DirNode(oattr.name, oattr.parent_id)
3205
3172
  if normalize_attr is not None:
3206
3173
  attr = normalize_attr(attr)
3207
3174
  yield Yield(attr, identity=True)
@@ -3216,6 +3183,7 @@ def share_iter_files(
3216
3183
  client: str | P115Client,
3217
3184
  share_link: str,
3218
3185
  receive_code: str = "",
3186
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
3219
3187
  *,
3220
3188
  async_: Literal[False] = False,
3221
3189
  **request_kwargs,
@@ -3226,6 +3194,7 @@ def share_iter_files(
3226
3194
  client: str | P115Client,
3227
3195
  share_link: str,
3228
3196
  receive_code: str = "",
3197
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
3229
3198
  *,
3230
3199
  async_: Literal[True],
3231
3200
  **request_kwargs,
@@ -3235,6 +3204,7 @@ def share_iter_files(
3235
3204
  client: str | P115Client,
3236
3205
  share_link: str,
3237
3206
  receive_code: str = "",
3207
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
3238
3208
  *,
3239
3209
  async_: Literal[False, True] = False,
3240
3210
  **request_kwargs,
@@ -3274,6 +3244,7 @@ def share_iter_files(
3274
3244
  if isinstance(client, str):
3275
3245
  client = P115Client(client, check_for_relogin=True)
3276
3246
  def gen_step():
3247
+ nonlocal id_to_dirnode
3277
3248
  payload: dict = cast(dict, share_extract_payload(share_link))
3278
3249
  if receive_code:
3279
3250
  payload["receive_code"] = receive_code
@@ -3281,7 +3252,10 @@ def share_iter_files(
3281
3252
  resp = yield client.share_info(payload["share_code"], async_=async_, **request_kwargs)
3282
3253
  check_response(resp)
3283
3254
  payload["receive_code"] = resp["data"]["receive_code"]
3255
+ if id_to_dirnode is None:
3256
+ id_to_dirnode = ID_TO_DIRNODE_CACHE[(client.user_id, payload["share_code"])]
3284
3257
  payload["cid"] = 0
3258
+ payload["id_to_dirnode"] = id_to_dirnode
3285
3259
  it = share_iterdir(client, **payload, async_=async_, **request_kwargs)
3286
3260
  do_next: Callable = anext if async_ else next
3287
3261
  try:
@@ -3307,6 +3281,176 @@ def share_iter_files(
3307
3281
  return run_gen_step(gen_step, async_=async_)
3308
3282
 
3309
3283
 
3284
+ @overload
3285
+ def share_get_id_to_path(
3286
+ client: str | P115Client,
3287
+ share_code: str,
3288
+ receive_code: str = "",
3289
+ path: str | Sequence[str] = "",
3290
+ parent_id: int = 0,
3291
+ ensure_file: None | bool = None,
3292
+ is_posixpath: bool = False,
3293
+ refresh: bool = False,
3294
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
3295
+ *,
3296
+ async_: Literal[False] = False,
3297
+ **request_kwargs,
3298
+ ) -> int:
3299
+ ...
3300
+ @overload
3301
+ def share_get_id_to_path(
3302
+ client: str | P115Client,
3303
+ share_code: str,
3304
+ receive_code: str = "",
3305
+ path: str | Sequence[str] = "",
3306
+ parent_id: int = 0,
3307
+ ensure_file: None | bool = None,
3308
+ is_posixpath: bool = False,
3309
+ refresh: bool = False,
3310
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
3311
+ *,
3312
+ async_: Literal[True],
3313
+ **request_kwargs,
3314
+ ) -> Coroutine[Any, Any, int]:
3315
+ ...
3316
+ def share_get_id_to_path(
3317
+ client: str | P115Client,
3318
+ share_code: str,
3319
+ receive_code: str = "",
3320
+ path: str | Sequence[str] = "",
3321
+ parent_id: int = 0,
3322
+ ensure_file: None | bool = None,
3323
+ is_posixpath: bool = False,
3324
+ refresh: bool = False,
3325
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
3326
+ *,
3327
+ async_: Literal[False, True] = False,
3328
+ **request_kwargs,
3329
+ ) -> int | Coroutine[Any, Any, int]:
3330
+ """对分享链接,获取路径对应的 id
3331
+
3332
+ :param client: 115 客户端或 cookies
3333
+ :param share_code: 分享码
3334
+ :param receive_code: 密码
3335
+ :param path: 路径
3336
+ :param parent_id: 上级目录的 id
3337
+ :param ensure_file: 是否确保为文件
3338
+
3339
+ - True: 必须是文件
3340
+ - False: 必须是目录
3341
+ - None: 可以是目录或文件
3342
+
3343
+ :param is_posixpath: 使用 posixpath,会把 "/" 转换为 "|",因此解析的时候,会对 "|" 进行特别处理
3344
+ :param refresh: 是否刷新。如果为 True,则会执行网络请求以查询;如果为 False,则直接从 `id_to_dirnode` 中获取
3345
+ :param id_to_dirnode: 字典,保存 id 到对应文件的 `DirNode(name, parent_id)` 命名元组的字典
3346
+ :param async_: 是否异步
3347
+ :param request_kwargs: 其它请求参数
3348
+
3349
+ :return: 文件或目录的 id
3350
+ """
3351
+ if isinstance(client, str):
3352
+ client = P115Client(client, check_for_relogin=True)
3353
+ if id_to_dirnode is None:
3354
+ id_to_dirnode = ID_TO_DIRNODE_CACHE[(client.user_id, share_code)]
3355
+ error = FileNotFoundError(ENOENT, f"no such path: {path!r}")
3356
+ def gen_step():
3357
+ nonlocal ensure_file, parent_id, receive_code
3358
+ if isinstance(path, str):
3359
+ if path.startswith("/"):
3360
+ parent_id = 0
3361
+ if path in (".", "..", "/"):
3362
+ if ensure_file:
3363
+ raise error
3364
+ return parent_id
3365
+ elif path.startswith("根目录 > "):
3366
+ parent_id = 0
3367
+ patht = path.split(" > ")[1:]
3368
+ elif is_posixpath:
3369
+ if ensure_file is None and path.endswith("/"):
3370
+ ensure_file = False
3371
+ patht = [p for p in path.split("/") if p]
3372
+ else:
3373
+ if ensure_file is None and path_is_dir_form(path):
3374
+ ensure_file = False
3375
+ patht, _ = splits(path.lstrip("/"))
3376
+ else:
3377
+ if path and not path[0]:
3378
+ parent_id = 0
3379
+ patht = list(path[1:])
3380
+ else:
3381
+ patht = [p for p in path if p]
3382
+ if not patht:
3383
+ return parent_id
3384
+ if not patht:
3385
+ if ensure_file:
3386
+ raise error
3387
+ return parent_id
3388
+ if not receive_code:
3389
+ resp = yield client.share_info(share_code, async_=async_, **request_kwargs)
3390
+ check_response(resp)
3391
+ receive_code = resp["data"]["receive_code"]
3392
+ i = 0
3393
+ if not refresh and id_to_dirnode and id_to_dirnode is not ...:
3394
+ if i := len(patht) - bool(ensure_file):
3395
+ obj = "|" if is_posixpath else "/"
3396
+ for i in range(i):
3397
+ if obj in patht[i]:
3398
+ break
3399
+ else:
3400
+ i += 1
3401
+ if i:
3402
+ for i in range(i):
3403
+ needle = (patht[i], parent_id)
3404
+ for fid, key in id_to_dirnode.items():
3405
+ if needle == key:
3406
+ parent_id = fid
3407
+ break
3408
+ else:
3409
+ break
3410
+ else:
3411
+ i += 1
3412
+ if i == len(patht):
3413
+ return parent_id
3414
+ for name in patht[i:-1]:
3415
+ if is_posixpath:
3416
+ name = name.replace("/", "|")
3417
+ with with_iter_next(share_iterdir(
3418
+ client,
3419
+ share_code,
3420
+ receive_code=receive_code,
3421
+ cid=parent_id,
3422
+ id_to_dirnode=id_to_dirnode,
3423
+ async_=async_,
3424
+ **request_kwargs,
3425
+ )) as get_next:
3426
+ found = False
3427
+ while not found:
3428
+ attr = yield get_next
3429
+ found = attr["is_dir"] and (attr["name"].replace("/", "|") if is_posixpath else attr["name"]) == name
3430
+ parent_id = attr["id"]
3431
+ if not found:
3432
+ raise error
3433
+ name = patht[-1]
3434
+ if is_posixpath:
3435
+ name = name.replace("/", "|")
3436
+ with with_iter_next(share_iterdir(
3437
+ client,
3438
+ share_code,
3439
+ receive_code=receive_code,
3440
+ cid=parent_id,
3441
+ id_to_dirnode=id_to_dirnode,
3442
+ async_=async_,
3443
+ **request_kwargs,
3444
+ )) as get_next:
3445
+ while True:
3446
+ attr = yield get_next
3447
+ if (attr["name"].replace("/", "|") if is_posixpath else attr["name"]) == name:
3448
+ if ensure_file is None or ensure_file ^ attr["is_dir"]:
3449
+ return P115ID(attr["id"], attr, about="path")
3450
+ raise error
3451
+ return run_gen_step(gen_step, async_=async_)
3452
+
3453
+
3310
3454
  @overload
3311
3455
  def iter_selected_nodes(
3312
3456
  client: str | P115Client,
p115client/tool/pool.py CHANGED
@@ -24,7 +24,7 @@ from p115client import check_response, P115Client
24
24
  from p115client.const import AVAILABLE_APP_IDS
25
25
  from p115client.exception import P115OSError, AuthenticationError, LoginError
26
26
 
27
- from .util import get_status, is_timeouterror
27
+ from .util import get_status_code, is_timeouterror
28
28
 
29
29
 
30
30
  @total_ordering
@@ -374,7 +374,7 @@ def call_wrap_with_pool(get_cert_headers: Callable, /, func: Callable) -> Callab
374
374
  except BaseException as e:
375
375
  if isinstance(e, P115OSError) and e.args[1].get("errno") == 40101004:
376
376
  raise
377
- if not isinstance(e, (AuthenticationError, LoginError)) and get_status(e) != 405:
377
+ if not isinstance(e, (AuthenticationError, LoginError)) and get_status_code(e) != 405:
378
378
  revert()
379
379
  raise
380
380
  return run_gen_step(gen_step, async_=async_)
p115client/tool/util.py CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
5
5
  __all__ = [
6
- "get_status", "is_timeouterror", "posix_escape_name", "reduce_image_url_layers",
6
+ "get_status_code", "is_timeouterror", "posix_escape_name", "reduce_image_url_layers",
7
7
  "share_extract_payload", "unescape_115_charref",
8
8
  ]
9
9
  __doc__ = "这个模块提供了一些工具函数"
@@ -23,7 +23,7 @@ class SharePayload(TypedDict):
23
23
  receive_code: None | str
24
24
 
25
25
 
26
- def get_status(e: BaseException, /) -> None | int:
26
+ def get_status_code(e: BaseException, /) -> None | int:
27
27
  """获取 HTTP 请求异常的状态码(如果有的话)
28
28
  """
29
29
  status = (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: p115client
3
- Version: 0.0.5.10.2
3
+ Version: 0.0.5.10.4
4
4
  Summary: Python 115 webdisk client.
5
5
  Home-page: https://github.com/ChenyangGao/p115client
6
6
  License: MIT
@@ -12,15 +12,15 @@ p115client/tool/edit.py,sha256=eRlR1UZMpfGnoetpqSAAx5bPBOEiSlx7HPkpOSs5agk,17739
12
12
  p115client/tool/export_dir.py,sha256=iMnKtnESi8HKvW9WhIvOdEoMXSBpAnhFlGeyKXHpQbE,24545
13
13
  p115client/tool/fs_files.py,sha256=jY57L4nhB9t-2kT_1j3mdiwOdPZKsimN3eN5mUJAqMI,15745
14
14
  p115client/tool/history.py,sha256=2S26BH7uBNfVHlbYFNy-aNOLMcM-HrlR7TLHAZacUJI,7458
15
- p115client/tool/iterdir.py,sha256=6-ke9yNY3mqHmzEapXk3lYwl3XRkWLH2D_nqJ1nq8Tk,186120
15
+ p115client/tool/iterdir.py,sha256=Qgs1fHwfgCXb-9T_1WQfyhnfXe8LZYwZY7oMTnCz3tQ,192038
16
16
  p115client/tool/life.py,sha256=X6Bp0GYKwnZeWlttE2DIVw5iOCXM5QzIkM6Zuj24c5Y,17323
17
- p115client/tool/pool.py,sha256=zftRR74IR_5zHigJtaImxGYt81rqCAn_V5Nm7HBMj68,13943
17
+ p115client/tool/pool.py,sha256=K-ALC-JEwik3DYCr5Eckok15oQnHRe6yznKIuJ9jyyM,13953
18
18
  p115client/tool/request.py,sha256=rjXuQwRganE5Z-4rfgnyPFjE4jzdQSLdIs9s0cIDshU,7043
19
19
  p115client/tool/upload.py,sha256=qK1OQYxP-Faq2eMDhc5sBXJiSr8m8EZ_gb0O_iA2TrI,15915
20
- p115client/tool/util.py,sha256=QrB4CIvIBEhl_MGSPSAenkY76WjEUHdcUjpccdc8x_A,3347
20
+ p115client/tool/util.py,sha256=0o9TrXdoPcljgxDDRdxRon41bq1OjuUYCWsR0XLfmPo,3357
21
21
  p115client/tool/xys.py,sha256=WMTisCyN4eYyv4A14yYOpjud2mBhQvBcUHOp6pJUQeA,10140
22
22
  p115client/type.py,sha256=7kOp98uLaYqcTTCgCrb3DRcl8ukMpn7ibsnVvtw2nG8,6250
23
- p115client-0.0.5.10.2.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
24
- p115client-0.0.5.10.2.dist-info/METADATA,sha256=C-Qh-vXqaJgXYsfdNs17Mm1jM_xuVm1FWPvGhqumlPo,8276
25
- p115client-0.0.5.10.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
26
- p115client-0.0.5.10.2.dist-info/RECORD,,
23
+ p115client-0.0.5.10.4.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
24
+ p115client-0.0.5.10.4.dist-info/METADATA,sha256=-zPTpPGe0IpuPfetzVHdvKDXQ9PGxPIu--dw7MFJxns,8276
25
+ p115client-0.0.5.10.4.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
26
+ p115client-0.0.5.10.4.dist-info/RECORD,,