rclone-api 1.5.59__py3-none-any.whl → 1.5.61__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/config.py +4 -2
- rclone_api/exec.py +1 -1
- rclone_api/http_server.py +7 -9
- rclone_api/process.py +7 -10
- rclone_api/rclone_impl.py +9 -6
- rclone_api/util.py +5 -5
- {rclone_api-1.5.59.dist-info → rclone_api-1.5.61.dist-info}/METADATA +1 -1
- {rclone_api-1.5.59.dist-info → rclone_api-1.5.61.dist-info}/RECORD +12 -12
- {rclone_api-1.5.59.dist-info → rclone_api-1.5.61.dist-info}/WHEEL +0 -0
- {rclone_api-1.5.59.dist-info → rclone_api-1.5.61.dist-info}/entry_points.txt +0 -0
- {rclone_api-1.5.59.dist-info → rclone_api-1.5.61.dist-info}/licenses/LICENSE +0 -0
- {rclone_api-1.5.59.dist-info → rclone_api-1.5.61.dist-info}/top_level.txt +0 -0
rclone_api/config.py
CHANGED
@@ -52,9 +52,11 @@ class Config:
|
|
52
52
|
"""Rclone configuration dataclass."""
|
53
53
|
|
54
54
|
# text: str
|
55
|
-
def __init__(self, text: str | dict) -> None:
|
55
|
+
def __init__(self, text: str | dict | None) -> None:
|
56
56
|
self.text: str
|
57
|
-
if
|
57
|
+
if text is None:
|
58
|
+
self.text = ""
|
59
|
+
elif isinstance(text, dict):
|
58
60
|
self.text = _json_to_rclone_config_str_or_raise(text)
|
59
61
|
else:
|
60
62
|
self.text = text
|
rclone_api/exec.py
CHANGED
rclone_api/http_server.py
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
Unit test file for testing rclone mount functionality.
|
3
3
|
"""
|
4
4
|
|
5
|
+
import logging
|
5
6
|
import tempfile
|
6
7
|
import time
|
7
8
|
import warnings
|
@@ -21,6 +22,7 @@ from rclone_api.types import Range, SizeSuffix, get_chunk_tmpdir
|
|
21
22
|
_TIMEOUT = 10 * 60 # 10 minutes
|
22
23
|
_PUT_WARNED = False
|
23
24
|
|
25
|
+
logger = logging.getLogger(__name__)
|
24
26
|
|
25
27
|
_range = range
|
26
28
|
|
@@ -84,7 +86,6 @@ class HttpServer:
|
|
84
86
|
"""Check if the file exists on the server."""
|
85
87
|
try:
|
86
88
|
assert self.process is not None
|
87
|
-
# response = httpx.head(f"{self.url}/{path}")
|
88
89
|
url = self._get_file_url(path)
|
89
90
|
response = httpx.head(url)
|
90
91
|
return response.status_code == 200
|
@@ -96,7 +97,6 @@ class HttpServer:
|
|
96
97
|
"""Get size of the file from the server."""
|
97
98
|
try:
|
98
99
|
assert self.process is not None
|
99
|
-
# response = httpx.head(f"{self.url}/{path}")
|
100
100
|
url = self._get_file_url(path)
|
101
101
|
response = httpx.head(url)
|
102
102
|
response.raise_for_status()
|
@@ -117,7 +117,7 @@ class HttpServer:
|
|
117
117
|
url = self._get_file_url(path)
|
118
118
|
headers = {"Content-Type": "application/octet-stream"}
|
119
119
|
response = httpx.post(url, content=data, timeout=_TIMEOUT, headers=headers)
|
120
|
-
|
120
|
+
logger.info(f"Allowed methods: {response.headers.get('Allow')}")
|
121
121
|
response.raise_for_status()
|
122
122
|
return None
|
123
123
|
except Exception as e:
|
@@ -179,15 +179,14 @@ class HttpServer:
|
|
179
179
|
file.write(chunk)
|
180
180
|
else:
|
181
181
|
assert response.is_closed
|
182
|
-
# print(f"Downloaded bytes {start}-{end} to {dst}")
|
183
182
|
if range:
|
184
183
|
length = range.end - range.start
|
185
|
-
|
184
|
+
logger.info(
|
186
185
|
f"Downloaded bytes starting at {range.start} with size {length} to {dst}"
|
187
186
|
)
|
188
187
|
else:
|
189
188
|
size = dst.stat().st_size
|
190
|
-
|
189
|
+
logger.info(f"Downloaded {size} bytes to {dst}")
|
191
190
|
return dst
|
192
191
|
except Exception as e:
|
193
192
|
warnings.warn(f"Failed to download {url} to {dst}: {e}")
|
@@ -263,7 +262,7 @@ class HttpServer:
|
|
263
262
|
count = 0
|
264
263
|
with open(dst_path, "wb") as file:
|
265
264
|
for f in finished:
|
266
|
-
|
265
|
+
logger.info(f"Appending {f} to {dst_path}")
|
267
266
|
with open(f, "rb") as part:
|
268
267
|
# chunk = part.read(8192 * 4)
|
269
268
|
while chunk := part.read(8192 * 4):
|
@@ -271,9 +270,8 @@ class HttpServer:
|
|
271
270
|
break
|
272
271
|
count += len(chunk)
|
273
272
|
file.write(chunk)
|
274
|
-
|
273
|
+
logger.info(f"Removing {f}")
|
275
274
|
f.unlink()
|
276
|
-
# print(f"Downloaded {count} bytes to {dst_path}")
|
277
275
|
return dst_path
|
278
276
|
except Exception as e:
|
279
277
|
warnings.warn(f"Failed to copy chunked: {e}")
|
rclone_api/process.py
CHANGED
@@ -15,7 +15,7 @@ from rclone_api.util import clear_temp_config_file, get_verbose, make_temp_confi
|
|
15
15
|
@dataclass
|
16
16
|
class ProcessArgs:
|
17
17
|
cmd: list[str]
|
18
|
-
rclone_conf: Path | Config
|
18
|
+
rclone_conf: Path | Config | None
|
19
19
|
rclone_exe: Path
|
20
20
|
cmd_list: list[str]
|
21
21
|
verbose: bool | None = None
|
@@ -32,7 +32,7 @@ class Process:
|
|
32
32
|
self.log = args.log
|
33
33
|
self.cleaned_up = False
|
34
34
|
self.tempfile: Path | None = None
|
35
|
-
|
35
|
+
rclone_conf: Path | None = None
|
36
36
|
verbose = get_verbose(args.verbose)
|
37
37
|
# Create a temporary config file if needed.
|
38
38
|
if isinstance(args.rclone_conf, Config):
|
@@ -41,15 +41,12 @@ class Process:
|
|
41
41
|
rclone_conf = self.tempfile
|
42
42
|
else:
|
43
43
|
rclone_conf = args.rclone_conf
|
44
|
-
|
45
|
-
assert rclone_conf.exists(), f"rclone config not found: {rclone_conf}"
|
46
|
-
|
44
|
+
# assert rclone_conf.exists(), f"rclone config not found: {rclone_conf}"
|
47
45
|
# Build the command.
|
48
|
-
self.cmd = (
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
)
|
46
|
+
self.cmd = [str(args.rclone_exe.resolve())]
|
47
|
+
if rclone_conf:
|
48
|
+
self.cmd += ["--config", str(rclone_conf.resolve())]
|
49
|
+
self.cmd += args.cmd_list
|
53
50
|
if self.args.log:
|
54
51
|
self.args.log.parent.mkdir(parents=True, exist_ok=True)
|
55
52
|
self.cmd += ["--log-file", str(self.args.log)]
|
rclone_api/rclone_impl.py
CHANGED
@@ -67,8 +67,10 @@ def rclone_verbose(verbose: bool | None) -> bool:
|
|
67
67
|
return bool(int(os.getenv("RCLONE_API_VERBOSE", "0")))
|
68
68
|
|
69
69
|
|
70
|
-
def _to_rclone_conf(config: Config | Path) -> Config:
|
71
|
-
if
|
70
|
+
def _to_rclone_conf(config: Config | Path | None) -> Config:
|
71
|
+
if config is None:
|
72
|
+
return Config(None)
|
73
|
+
elif isinstance(config, Path):
|
72
74
|
content = config.read_text(encoding="utf-8")
|
73
75
|
return Config(content)
|
74
76
|
else:
|
@@ -100,13 +102,17 @@ class RcloneImpl:
|
|
100
102
|
if isinstance(rclone_conf, Path):
|
101
103
|
if not rclone_conf.exists():
|
102
104
|
raise ValueError(f"Rclone config file not found: {rclone_conf}")
|
105
|
+
rclone_exe = get_rclone_exe(rclone_exe)
|
106
|
+
# Not fully constructed version of ._exec, which can be used to find a config file from default paths.
|
107
|
+
self._exec = RcloneExec(None, get_rclone_exe(rclone_exe))
|
103
108
|
if rclone_conf is None:
|
104
109
|
from rclone_api.config import find_conf_file
|
105
110
|
|
106
111
|
maybe_path = find_conf_file(self)
|
107
112
|
if not isinstance(maybe_path, Path):
|
108
|
-
|
113
|
+
warnings.warn("Rclone config file not found")
|
109
114
|
rclone_conf = _to_rclone_conf(maybe_path)
|
115
|
+
# replace self._exec with one that has the config
|
110
116
|
self._exec = RcloneExec(rclone_conf, get_rclone_exe(rclone_exe))
|
111
117
|
self.config: Config = _to_rclone_conf(rclone_conf)
|
112
118
|
|
@@ -1334,9 +1340,6 @@ class RcloneImpl:
|
|
1334
1340
|
if obscure:
|
1335
1341
|
cmd_list.append("--obscure")
|
1336
1342
|
|
1337
|
-
if no_obscure:
|
1338
|
-
cmd_list.append("--no-obscure")
|
1339
|
-
|
1340
1343
|
try:
|
1341
1344
|
cp = self._run(cmd_list, capture=True, check=True)
|
1342
1345
|
stdout: str | bytes = cp.stdout
|
rclone_api/util.py
CHANGED
@@ -178,7 +178,7 @@ def upgrade_rclone() -> Path:
|
|
178
178
|
|
179
179
|
def rclone_execute(
|
180
180
|
cmd: list[str],
|
181
|
-
rclone_conf: Path | Config,
|
181
|
+
rclone_conf: Path | Config | None,
|
182
182
|
rclone_exe: Path,
|
183
183
|
check: bool,
|
184
184
|
capture: bool | Path | None = None,
|
@@ -202,10 +202,10 @@ def rclone_execute(
|
|
202
202
|
tmpfile.write_text(rclone_conf.text, encoding="utf-8")
|
203
203
|
rclone_conf = tmpfile
|
204
204
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
205
|
+
full_cmd = [str(rclone_exe.resolve())]
|
206
|
+
if rclone_conf:
|
207
|
+
full_cmd += ["--config", str(rclone_conf.resolve())]
|
208
|
+
full_cmd += cmd
|
209
209
|
if verbose:
|
210
210
|
cmd_str = subprocess.list2cmdline(full_cmd)
|
211
211
|
print(f"\nRunning: {cmd_str}")
|
@@ -1,31 +1,31 @@
|
|
1
1
|
rclone_api/__init__.py,sha256=M3-jlyxhO7Md3FGMO8qBJ1Z7oLcbOjWshCHh2-CqKG4,34885
|
2
2
|
rclone_api/cli.py,sha256=dibfAZIh0kXWsBbfp3onKLjyZXo54mTzDjUdzJlDlWo,231
|
3
3
|
rclone_api/completed_process.py,sha256=_IZ8IWK7DM1_tsbDEkH6wPZ-bbcrgf7A7smls854pmg,1775
|
4
|
-
rclone_api/config.py,sha256=
|
4
|
+
rclone_api/config.py,sha256=URZwMME01f0EZymprCESuZ5dk4IuUSKbHhwIeTHrn7A,6131
|
5
5
|
rclone_api/convert.py,sha256=Mx9Qo7zhkOedJd8LdhPvNGHp8znJzOk4f_2KWnoGc78,1012
|
6
6
|
rclone_api/deprecated.py,sha256=qWKpnZdYcBK7YQZKuVoWWXDwi-uqiAtbjgPcci_efow,590
|
7
7
|
rclone_api/diff.py,sha256=tMoJMAGmLSE6Q_7QhPf6PnCzb840djxMZtDmhc2GlGQ,5227
|
8
8
|
rclone_api/dir.py,sha256=_9o-_5tbWVJkL1Vf_Yb8aiQV3xAqvUq5bk3zoJblvEg,3547
|
9
9
|
rclone_api/dir_listing.py,sha256=bSmd8yZtSeyVaDRw2JPB4bCpbCeDzhoa_pomgdJp44c,1884
|
10
|
-
rclone_api/exec.py,sha256=
|
10
|
+
rclone_api/exec.py,sha256=3x2FOrh_3Ml23sW_5fry3dmlKyHtq3iYKByLeZtbNcg,1090
|
11
11
|
rclone_api/file.py,sha256=JLPqjUcW_YVb4UQjX6FQ7PABJqhchFUXVy1W-X9rJLk,5659
|
12
12
|
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
16
|
rclone_api/group_files.py,sha256=H92xPW9lQnbNw5KbtZCl00bD6iRh9yRbCuxku4j_3dg,8036
|
17
|
-
rclone_api/http_server.py,sha256=
|
17
|
+
rclone_api/http_server.py,sha256=ZzDVfuRtHBihxdVLUIHNvIZMixyYPm6N2iPHkfWx5eE,11942
|
18
18
|
rclone_api/install.py,sha256=ZDG8QNj1JciS_DSqYnMTECwhJksUPAoqZQxtX804TDk,5679
|
19
19
|
rclone_api/log.py,sha256=VZHM7pNSXip2ZLBKMP7M1u-rp_F7zoafFDuR8CPUoKI,1271
|
20
20
|
rclone_api/mount.py,sha256=LZqEhuKZunbWVqmsOIqkkCotaxWJpdFRS1InXveoU5E,1428
|
21
21
|
rclone_api/mount_util.py,sha256=jqhJEVTHV6c6lOOzUYb4FLMbqDMHdz7-QRcdH-IobFc,10154
|
22
|
-
rclone_api/process.py,sha256=
|
23
|
-
rclone_api/rclone_impl.py,sha256=
|
22
|
+
rclone_api/process.py,sha256=V4Ax9AyNdC3m4O6gjWSbIJyCQCMhT-t0f-K8z6xux7Q,5946
|
23
|
+
rclone_api/rclone_impl.py,sha256=FXIkDOGnqp7zN9pks3WXoruIJki9M2sJd0-QX5cMQgg,52603
|
24
24
|
rclone_api/remote.py,sha256=mTgMTQTwxUmbLjTpr-AGTId2ycXKI9mLX5L7PPpDIoc,520
|
25
25
|
rclone_api/rpath.py,sha256=Y1JjQWcie39EgQrq-UtbfDz5yDLCwwfu27W7AQXllSE,2860
|
26
26
|
rclone_api/scan_missing_folders.py,sha256=-8NCwpCaHeHrX-IepCoAEsX1rl8S-GOCxcIhTr_w3gA,4747
|
27
27
|
rclone_api/types.py,sha256=59Rw7NdHw35X6iiWMemO61IzCbrjgfNHUlzY3Dq0wdM,12303
|
28
|
-
rclone_api/util.py,sha256=
|
28
|
+
rclone_api/util.py,sha256=NIWU1YLGWyNhICwXCpmAw0AgCXkOYG6BO6m1mTNQwzY,9559
|
29
29
|
rclone_api/assets/example.txt,sha256=lTBovRjiz0_TgtAtbA1C5hNi2ffbqnNPqkKg6UiKCT8,54
|
30
30
|
rclone_api/cmd/analyze.py,sha256=RHbvk1G5ZUc3qLqlm1AZEyQzd_W_ZjcbCNDvW4YpTKQ,1252
|
31
31
|
rclone_api/cmd/copy_large_s3.py,sha256=E0B7P-JJTuOM7wMZtwQHJCpoLhccJleh0mnMq8ZiSUo,3234
|
@@ -58,9 +58,9 @@ rclone_api/s3/multipart/upload_parts_inline.py,sha256=V7syKjFyVIe4U9Ahl5XgqVTzt9
|
|
58
58
|
rclone_api/s3/multipart/upload_parts_resumable.py,sha256=6-nlMclS8jyVvMvFbQDcZOX9MY1WbCcKA_s9bwuYxnk,9793
|
59
59
|
rclone_api/s3/multipart/upload_parts_server_side_merge.py,sha256=Fp2pdrs5dONQI9LkfNolgAGj1-Z2V1SsRd0r0sreuXI,18040
|
60
60
|
rclone_api/s3/multipart/upload_state.py,sha256=f-Aq2NqtAaMUMhYitlICSNIxCKurWAl2gDEUVizLIqw,6019
|
61
|
-
rclone_api-1.5.
|
62
|
-
rclone_api-1.5.
|
63
|
-
rclone_api-1.5.
|
64
|
-
rclone_api-1.5.
|
65
|
-
rclone_api-1.5.
|
66
|
-
rclone_api-1.5.
|
61
|
+
rclone_api-1.5.61.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
|
62
|
+
rclone_api-1.5.61.dist-info/METADATA,sha256=6euBxBpkAYSnNXNCu_JDaYOiTIDW6vzyzHxpx09u-0g,37305
|
63
|
+
rclone_api-1.5.61.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
64
|
+
rclone_api-1.5.61.dist-info/entry_points.txt,sha256=ognh2e11HTjn73_KL5MWI67pBKS2jekBi-QTiRXySXA,316
|
65
|
+
rclone_api-1.5.61.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
|
66
|
+
rclone_api-1.5.61.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|