rclone-api 1.5.36__py3-none-any.whl → 1.5.38__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.
- rclone_api/fs.py +19 -11
- rclone_api/http_server.py +19 -5
- {rclone_api-1.5.36.dist-info → rclone_api-1.5.38.dist-info}/METADATA +1 -1
- {rclone_api-1.5.36.dist-info → rclone_api-1.5.38.dist-info}/RECORD +8 -8
- {rclone_api-1.5.36.dist-info → rclone_api-1.5.38.dist-info}/WHEEL +0 -0
- {rclone_api-1.5.36.dist-info → rclone_api-1.5.38.dist-info}/entry_points.txt +0 -0
- {rclone_api-1.5.36.dist-info → rclone_api-1.5.38.dist-info}/licenses/LICENSE +0 -0
- {rclone_api-1.5.36.dist-info → rclone_api-1.5.38.dist-info}/top_level.txt +0 -0
rclone_api/fs.py
CHANGED
@@ -31,7 +31,8 @@ class FS(abc.ABC):
|
|
31
31
|
pass
|
32
32
|
|
33
33
|
@abc.abstractmethod
|
34
|
-
def ls(self, path: Path | str) -> list[str]:
|
34
|
+
def ls(self, path: Path | str) -> tuple[list[str], list[str]]:
|
35
|
+
"""First is files and second is directories."""
|
35
36
|
pass
|
36
37
|
|
37
38
|
@abc.abstractmethod
|
@@ -57,8 +58,11 @@ class RealFS(FS):
|
|
57
58
|
def __init__(self) -> None:
|
58
59
|
super().__init__()
|
59
60
|
|
60
|
-
def ls(self, path: Path | str) -> list[str]:
|
61
|
-
|
61
|
+
def ls(self, path: Path | str) -> tuple[list[str], list[str]]:
|
62
|
+
files_and_dirs = [str(p) for p in Path(path).iterdir()]
|
63
|
+
files = [f for f in files_and_dirs if Path(f).is_file()]
|
64
|
+
dirs = [d for d in files_and_dirs if Path(d).is_dir()]
|
65
|
+
return files, dirs
|
62
66
|
|
63
67
|
def cwd(self) -> "FSPath":
|
64
68
|
return RealFS.from_path(Path.cwd())
|
@@ -176,7 +180,7 @@ class RemoteFS(FS):
|
|
176
180
|
# Make faster.
|
177
181
|
return isinstance(err, Exception) and self.exists(path)
|
178
182
|
|
179
|
-
def ls(self, path: Path | str) -> list[str]:
|
183
|
+
def ls(self, path: Path | str) -> tuple[list[str], list[str]]:
|
180
184
|
from rclone_api.http_server import HttpServer
|
181
185
|
|
182
186
|
assert isinstance(self.server, HttpServer)
|
@@ -259,13 +263,17 @@ class FSPath:
|
|
259
263
|
assert isinstance(self.fs, RealFS)
|
260
264
|
shutil.rmtree(self.path, ignore_errors=ignore_errors)
|
261
265
|
|
262
|
-
def lspaths(self) -> "list[FSPath]":
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
266
|
+
def lspaths(self) -> "tuple[list[FSPath], list[FSPath]]":
|
267
|
+
filenames, dirnames = self.ls()
|
268
|
+
fpaths: list[FSPath] = [self / name for name in filenames]
|
269
|
+
dpaths: list[FSPath] = [self / name for name in dirnames]
|
270
|
+
return fpaths, dpaths
|
271
|
+
|
272
|
+
def ls(self) -> tuple[list[str], list[str]]:
|
273
|
+
filenames: list[str]
|
274
|
+
dirnames: list[str]
|
275
|
+
filenames, dirnames = self.fs.ls(self.path)
|
276
|
+
return filenames, dirnames
|
269
277
|
|
270
278
|
@property
|
271
279
|
def name(self) -> str:
|
rclone_api/http_server.py
CHANGED
@@ -6,6 +6,7 @@ import tempfile
|
|
6
6
|
import time
|
7
7
|
import warnings
|
8
8
|
from concurrent.futures import Future, ThreadPoolExecutor
|
9
|
+
from dataclasses import dataclass
|
9
10
|
from pathlib import Path
|
10
11
|
from threading import Semaphore
|
11
12
|
from typing import Any
|
@@ -24,9 +25,16 @@ _PUT_WARNED = False
|
|
24
25
|
_range = range
|
25
26
|
|
26
27
|
|
27
|
-
|
28
|
+
@dataclass
|
29
|
+
class FileList:
|
30
|
+
dirs: list[str]
|
31
|
+
files: list[str]
|
32
|
+
|
33
|
+
|
34
|
+
def _parse_files_and_dirs(html: str) -> FileList:
|
28
35
|
soup = BeautifulSoup(html, "html.parser")
|
29
36
|
files = []
|
37
|
+
dirs = []
|
30
38
|
# Find each table row with class "file"
|
31
39
|
for tr in soup.find_all("tr", class_="file"):
|
32
40
|
name_span = tr.find("span", class_="name") # type: ignore
|
@@ -38,9 +46,14 @@ def _parse_files(html: str) -> list[str]:
|
|
38
46
|
# Get the text from the <a> tag
|
39
47
|
file_name = a_tag.get_text(strip=True) # type: ignore
|
40
48
|
# Skip directories (they end with a slash)
|
41
|
-
if not file_name.endswith("/"):
|
49
|
+
# if not file_name.endswith("/"):
|
50
|
+
# files.append(file_name)
|
51
|
+
# files.append(file_name)
|
52
|
+
if file_name.endswith("/"):
|
53
|
+
dirs.append(file_name)
|
54
|
+
else:
|
42
55
|
files.append(file_name)
|
43
|
-
return files
|
56
|
+
return FileList(dirs=dirs, files=files)
|
44
57
|
|
45
58
|
|
46
59
|
class HttpServer:
|
@@ -125,7 +138,7 @@ class HttpServer:
|
|
125
138
|
|
126
139
|
# curl "http://localhost:5572/?list"
|
127
140
|
|
128
|
-
def list(self, path: str) -> list[str] | Exception:
|
141
|
+
def list(self, path: str) -> tuple[list[str], list[str]] | Exception:
|
129
142
|
"""List files on the server."""
|
130
143
|
|
131
144
|
try:
|
@@ -136,7 +149,8 @@ class HttpServer:
|
|
136
149
|
url += "/?list"
|
137
150
|
response = httpx.get(url, timeout=_TIMEOUT)
|
138
151
|
response.raise_for_status()
|
139
|
-
|
152
|
+
files_and_dirs = _parse_files_and_dirs(response.content.decode())
|
153
|
+
return files_and_dirs.files, files_and_dirs.dirs
|
140
154
|
except Exception as e:
|
141
155
|
warnings.warn(f"Failed to list files on {self.url}: {e}")
|
142
156
|
return e
|
@@ -13,9 +13,9 @@ rclone_api/file_item.py,sha256=cH-AQYsxedhNPp4c8NHY1ad4Z7St4yf_VGbmiGD59no,1770
|
|
13
13
|
rclone_api/file_part.py,sha256=i6ByS5_sae8Eba-4imBVTxd-xKC8ExWy7NR8QGr0ors,6155
|
14
14
|
rclone_api/file_stream.py,sha256=_W3qnwCuigqA0hzXl2q5pAxSZDRaUSwet4BkT0lpnzs,1431
|
15
15
|
rclone_api/filelist.py,sha256=xbiusvNgaB_b_kQOZoHMJJxn6TWGtPrWd2J042BI28o,767
|
16
|
-
rclone_api/fs.py,sha256=
|
16
|
+
rclone_api/fs.py,sha256=ldXOBsPg5I36FFUrEwFN1KbpVge5C4OywtoRTgBUfVw,8893
|
17
17
|
rclone_api/group_files.py,sha256=H92xPW9lQnbNw5KbtZCl00bD6iRh9yRbCuxku4j_3dg,8036
|
18
|
-
rclone_api/http_server.py,sha256=
|
18
|
+
rclone_api/http_server.py,sha256=P-LT2GqCEM9tGbyzzr-CrSOc3FyCw1qXUSQ5bY2KBHU,12113
|
19
19
|
rclone_api/install.py,sha256=Xb1BRn8rQcSpSd4dzmvIOELP2zM2DytUeIZ6jzv738A,2893
|
20
20
|
rclone_api/log.py,sha256=VZHM7pNSXip2ZLBKMP7M1u-rp_F7zoafFDuR8CPUoKI,1271
|
21
21
|
rclone_api/mount.py,sha256=LZqEhuKZunbWVqmsOIqkkCotaxWJpdFRS1InXveoU5E,1428
|
@@ -54,9 +54,9 @@ rclone_api/s3/multipart/upload_parts_inline.py,sha256=V7syKjFyVIe4U9Ahl5XgqVTzt9
|
|
54
54
|
rclone_api/s3/multipart/upload_parts_resumable.py,sha256=6-nlMclS8jyVvMvFbQDcZOX9MY1WbCcKA_s9bwuYxnk,9793
|
55
55
|
rclone_api/s3/multipart/upload_parts_server_side_merge.py,sha256=Fp2pdrs5dONQI9LkfNolgAGj1-Z2V1SsRd0r0sreuXI,18040
|
56
56
|
rclone_api/s3/multipart/upload_state.py,sha256=f-Aq2NqtAaMUMhYitlICSNIxCKurWAl2gDEUVizLIqw,6019
|
57
|
-
rclone_api-1.5.
|
58
|
-
rclone_api-1.5.
|
59
|
-
rclone_api-1.5.
|
60
|
-
rclone_api-1.5.
|
61
|
-
rclone_api-1.5.
|
62
|
-
rclone_api-1.5.
|
57
|
+
rclone_api-1.5.38.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
|
58
|
+
rclone_api-1.5.38.dist-info/METADATA,sha256=XDpdSE4QLUjHXPagSiqgSXZBK4Pc_ducVr-xpsUHa1I,37155
|
59
|
+
rclone_api-1.5.38.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
|
60
|
+
rclone_api-1.5.38.dist-info/entry_points.txt,sha256=fJteOlYVwgX3UbNuL9jJ0zUTuX2O79JFAeNgK7Sw7EQ,255
|
61
|
+
rclone_api-1.5.38.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
|
62
|
+
rclone_api-1.5.38.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|