rclone-api 1.0.46__py2.py3-none-any.whl → 1.0.48__py2.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/completed_process.py +28 -0
- rclone_api/exec.py +6 -2
- rclone_api/rclone.py +74 -13
- rclone_api/util.py +3 -1
- {rclone_api-1.0.46.dist-info → rclone_api-1.0.48.dist-info}/METADATA +1 -1
- {rclone_api-1.0.46.dist-info → rclone_api-1.0.48.dist-info}/RECORD +10 -10
- {rclone_api-1.0.46.dist-info → rclone_api-1.0.48.dist-info}/LICENSE +0 -0
- {rclone_api-1.0.46.dist-info → rclone_api-1.0.48.dist-info}/WHEEL +0 -0
- {rclone_api-1.0.46.dist-info → rclone_api-1.0.48.dist-info}/entry_points.txt +0 -0
- {rclone_api-1.0.46.dist-info → rclone_api-1.0.48.dist-info}/top_level.txt +0 -0
rclone_api/completed_process.py
CHANGED
@@ -19,3 +19,31 @@ class CompletedProcess:
|
|
19
19
|
|
20
20
|
def successes(self) -> list[subprocess.CompletedProcess]:
|
21
21
|
return [p for p in self.completed if p.returncode == 0]
|
22
|
+
|
23
|
+
@property
|
24
|
+
def stdout(self) -> str:
|
25
|
+
tmp: list[str] = []
|
26
|
+
for cp in self.completed:
|
27
|
+
stdout = cp.stdout
|
28
|
+
if stdout is not None:
|
29
|
+
tmp.append(stdout)
|
30
|
+
return "\n".join(tmp)
|
31
|
+
|
32
|
+
@property
|
33
|
+
def stderr(self) -> str:
|
34
|
+
tmp: list[str] = []
|
35
|
+
for cp in self.completed:
|
36
|
+
stderr = cp.stderr
|
37
|
+
if stderr is not None:
|
38
|
+
tmp.append(stderr)
|
39
|
+
return "\n".join(tmp)
|
40
|
+
|
41
|
+
@property
|
42
|
+
def returncode(self) -> int | None:
|
43
|
+
for cp in self.completed:
|
44
|
+
rtn = cp.returncode
|
45
|
+
if rtn is None:
|
46
|
+
return None
|
47
|
+
if rtn != 0:
|
48
|
+
return rtn
|
49
|
+
return 0
|
rclone_api/exec.py
CHANGED
@@ -13,11 +13,15 @@ class RcloneExec:
|
|
13
13
|
rclone_config: Path | Config
|
14
14
|
rclone_exe: Path
|
15
15
|
|
16
|
-
def execute(
|
16
|
+
def execute(
|
17
|
+
self, cmd: list[str], check: bool, capture: bool | None = None
|
18
|
+
) -> subprocess.CompletedProcess:
|
17
19
|
"""Execute rclone command."""
|
18
20
|
from rclone_api.util import rclone_execute
|
19
21
|
|
20
|
-
return rclone_execute(
|
22
|
+
return rclone_execute(
|
23
|
+
cmd, self.rclone_config, self.rclone_exe, check=check, capture=capture
|
24
|
+
)
|
21
25
|
|
22
26
|
def launch_process(self, cmd: list[str], capture: bool | None) -> Process:
|
23
27
|
"""Launch rclone process."""
|
rclone_api/rclone.py
CHANGED
@@ -57,8 +57,10 @@ class Rclone:
|
|
57
57
|
raise ValueError(f"Rclone config file not found: {rclone_conf}")
|
58
58
|
self._exec = RcloneExec(rclone_conf, get_rclone_exe(rclone_exe))
|
59
59
|
|
60
|
-
def _run(
|
61
|
-
|
60
|
+
def _run(
|
61
|
+
self, cmd: list[str], check: bool = True, capture: bool | None = None
|
62
|
+
) -> subprocess.CompletedProcess:
|
63
|
+
return self._exec.execute(cmd, check=check, capture=capture)
|
62
64
|
|
63
65
|
def _launch_process(self, cmd: list[str], capture: bool | None = None) -> Process:
|
64
66
|
return self._exec.launch_process(cmd, capture=capture)
|
@@ -70,6 +72,47 @@ class Rclone:
|
|
70
72
|
cmd += other_args
|
71
73
|
return self._launch_process(cmd, capture=False)
|
72
74
|
|
75
|
+
def launch_server(
|
76
|
+
self,
|
77
|
+
addr: str | None = None,
|
78
|
+
user: str | None = None,
|
79
|
+
password: str | None = None,
|
80
|
+
other_args: list[str] | None = None,
|
81
|
+
) -> Process:
|
82
|
+
"""Launch the Rclone server so it can receive commands"""
|
83
|
+
cmd = ["rcd"]
|
84
|
+
if addr is not None:
|
85
|
+
cmd += ["--rc-addr", addr]
|
86
|
+
if user is not None:
|
87
|
+
cmd += ["--rc-user", user]
|
88
|
+
if password is not None:
|
89
|
+
cmd += ["--rc-pass", password]
|
90
|
+
if other_args:
|
91
|
+
cmd += other_args
|
92
|
+
out = self._launch_process(cmd, capture=False)
|
93
|
+
time.sleep(1) # Give it some time to launch
|
94
|
+
return out
|
95
|
+
|
96
|
+
def remote_control(
|
97
|
+
self,
|
98
|
+
addr: str,
|
99
|
+
user: str | None = None,
|
100
|
+
password: str | None = None,
|
101
|
+
capture: bool | None = None,
|
102
|
+
other_args: list[str] | None = None,
|
103
|
+
) -> CompletedProcess:
|
104
|
+
cmd = ["rc"]
|
105
|
+
if addr:
|
106
|
+
cmd += ["--rc-addr", addr]
|
107
|
+
if user is not None:
|
108
|
+
cmd += ["--rc-user", user]
|
109
|
+
if password is not None:
|
110
|
+
cmd += ["--rc-pass", password]
|
111
|
+
if other_args:
|
112
|
+
cmd += other_args
|
113
|
+
cp = self._run(cmd, capture=capture)
|
114
|
+
return CompletedProcess.from_subprocess(cp)
|
115
|
+
|
73
116
|
def obscure(self, password: str) -> str:
|
74
117
|
"""Obscure a password for use in rclone config files."""
|
75
118
|
cmd_list: list[str] = ["obscure", password]
|
@@ -218,7 +261,13 @@ class Rclone:
|
|
218
261
|
cmd_list: list[str] = ["copyto", src, dst]
|
219
262
|
self._run(cmd_list)
|
220
263
|
|
221
|
-
def copy_to(
|
264
|
+
def copy_to(
|
265
|
+
self,
|
266
|
+
src: File | str,
|
267
|
+
dst: File | str,
|
268
|
+
check=True,
|
269
|
+
other_args: list[str] | None = None,
|
270
|
+
) -> None:
|
222
271
|
"""Copy multiple files from source to destination.
|
223
272
|
|
224
273
|
Warning - slow.
|
@@ -229,9 +278,16 @@ class Rclone:
|
|
229
278
|
src = str(src)
|
230
279
|
dst = str(dst)
|
231
280
|
cmd_list: list[str] = ["copyto", src, dst]
|
232
|
-
|
281
|
+
if other_args is not None:
|
282
|
+
cmd_list += other_args
|
283
|
+
self._run(cmd_list, check=check)
|
233
284
|
|
234
|
-
def copyfiles(
|
285
|
+
def copyfiles(
|
286
|
+
self,
|
287
|
+
files: str | File | list[str] | list[File],
|
288
|
+
check=True,
|
289
|
+
other_args: list[str] | None = None,
|
290
|
+
) -> list[CompletedProcess]:
|
235
291
|
"""Copy multiple files from source to destination.
|
236
292
|
|
237
293
|
Warning - slow.
|
@@ -241,10 +297,11 @@ class Rclone:
|
|
241
297
|
"""
|
242
298
|
payload: list[str] = convert_to_filestr_list(files)
|
243
299
|
if len(payload) == 0:
|
244
|
-
return
|
300
|
+
return []
|
245
301
|
|
246
302
|
datalists: dict[str, list[str]] = group_files(payload)
|
247
|
-
out: subprocess.CompletedProcess | None = None
|
303
|
+
# out: subprocess.CompletedProcess | None = None
|
304
|
+
out: list[CompletedProcess] = []
|
248
305
|
|
249
306
|
futures: list[Future] = []
|
250
307
|
|
@@ -257,7 +314,7 @@ class Rclone:
|
|
257
314
|
|
258
315
|
# print(include_files_txt)
|
259
316
|
cmd_list: list[str] = [
|
260
|
-
"
|
317
|
+
"copy",
|
261
318
|
remote,
|
262
319
|
"--files-from",
|
263
320
|
str(include_files_txt),
|
@@ -266,19 +323,23 @@ class Rclone:
|
|
266
323
|
"--transfers",
|
267
324
|
"1000",
|
268
325
|
]
|
326
|
+
if other_args is not None:
|
327
|
+
cmd_list += other_args
|
269
328
|
out = self._run(cmd_list)
|
270
329
|
return out
|
271
330
|
|
272
331
|
fut: Future = EXECUTOR.submit(_task)
|
273
332
|
futures.append(fut)
|
274
333
|
for fut in futures:
|
275
|
-
|
276
|
-
assert
|
277
|
-
|
334
|
+
cp: subprocess.CompletedProcess = fut.result()
|
335
|
+
assert cp is not None
|
336
|
+
out.append(CompletedProcess.from_subprocess(cp))
|
337
|
+
if cp.returncode != 0:
|
278
338
|
if check:
|
279
|
-
raise ValueError(f"Error deleting files: {
|
339
|
+
raise ValueError(f"Error deleting files: {cp.stderr}")
|
280
340
|
else:
|
281
|
-
warnings.warn(f"Error deleting files: {
|
341
|
+
warnings.warn(f"Error deleting files: {cp.stderr}")
|
342
|
+
return out
|
282
343
|
|
283
344
|
def copy(self, src: Dir | str, dst: Dir | str) -> CompletedProcess:
|
284
345
|
"""Copy files from source to destination.
|
rclone_api/util.py
CHANGED
@@ -78,10 +78,12 @@ def rclone_execute(
|
|
78
78
|
rclone_conf: Path | Config,
|
79
79
|
rclone_exe: Path,
|
80
80
|
check: bool,
|
81
|
+
capture: bool | None = None,
|
81
82
|
verbose: bool | None = None,
|
82
83
|
) -> subprocess.CompletedProcess:
|
83
84
|
tempdir: TemporaryDirectory | None = None
|
84
85
|
verbose = get_verbose(verbose)
|
86
|
+
capture = capture if isinstance(capture, bool) else True
|
85
87
|
assert verbose is not None
|
86
88
|
|
87
89
|
try:
|
@@ -97,7 +99,7 @@ def rclone_execute(
|
|
97
99
|
cmd_str = subprocess.list2cmdline(cmd)
|
98
100
|
print(f"Running: {cmd_str}")
|
99
101
|
cp = subprocess.run(
|
100
|
-
cmd, capture_output=
|
102
|
+
cmd, capture_output=capture, encoding="utf-8", check=False, shell=False
|
101
103
|
)
|
102
104
|
if cp.returncode != 0:
|
103
105
|
cmd_str = subprocess.list2cmdline(cmd)
|
@@ -1,27 +1,27 @@
|
|
1
1
|
rclone_api/__init__.py,sha256=fvWhio7i71rS5JtIr3l-36F6LRHo0ddpq0VX-6P5ldY,495
|
2
2
|
rclone_api/cli.py,sha256=dibfAZIh0kXWsBbfp3onKLjyZXo54mTzDjUdzJlDlWo,231
|
3
|
-
rclone_api/completed_process.py,sha256=
|
3
|
+
rclone_api/completed_process.py,sha256=Pp-hXnLgej0IGO5ee9Fmx64dGzIofbQFEUyXdFCvO54,1371
|
4
4
|
rclone_api/config.py,sha256=tP6cU9DnCCEIRc_KP9HPur1jFLLg2QGFSxNwFm6_MVw,118
|
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=ELUQD1Mv8qaoAav13sEE-iKynFph70rQHj7-a4Z1pyo,4137
|
8
8
|
rclone_api/dir.py,sha256=vV-bcI2ESijmwF5rPID5WO2K7soAfZa35wv4KRh_GIo,2154
|
9
9
|
rclone_api/dir_listing.py,sha256=9Qqf2SUswrOEkyqmaH23V51I18X6ePiXb9B1vUwRF5o,1571
|
10
|
-
rclone_api/exec.py,sha256=
|
10
|
+
rclone_api/exec.py,sha256=1ovvaMXDEfLiT7BrYZyE85u_yFhEUwUNW3jPOzqknR8,1023
|
11
11
|
rclone_api/file.py,sha256=D02iHJW1LhfOiM_R_yPHP8_ApnDiYrkuraVcrV8-qkw,1246
|
12
12
|
rclone_api/filelist.py,sha256=xbiusvNgaB_b_kQOZoHMJJxn6TWGtPrWd2J042BI28o,767
|
13
13
|
rclone_api/group_files.py,sha256=HxrRUi_kFlMblrCMFyv6rO56tVMEzgU4-vVeB_2-lbc,4606
|
14
14
|
rclone_api/process.py,sha256=RrMfTe0bndmJ6gBK67ioqNvCstJ8aTC8RlGX1XBLlcw,4191
|
15
|
-
rclone_api/rclone.py,sha256=
|
15
|
+
rclone_api/rclone.py,sha256=KBT3mugMPqH1Ftz7aBeu9qwZr2lxRErgCkYNgpgI3KM,23815
|
16
16
|
rclone_api/remote.py,sha256=c9hlRKBCg1BFB9MCINaQIoCg10qyAkeqiS4brl8ce-8,343
|
17
17
|
rclone_api/rpath.py,sha256=8ZA_1wxWtskwcy0I8V2VbjKDmzPkiWd8Q2JQSvh-sYE,2586
|
18
|
-
rclone_api/util.py,sha256=
|
18
|
+
rclone_api/util.py,sha256=IWNOOcPE0xdKvehzXQ9okIppGDBYWJPIfdbUME8BFVM,4015
|
19
19
|
rclone_api/walk.py,sha256=kca0t1GAnF6FLclN01G8NG__Qe-ggodLtAbQSHyVPng,2968
|
20
20
|
rclone_api/assets/example.txt,sha256=lTBovRjiz0_TgtAtbA1C5hNi2ffbqnNPqkKg6UiKCT8,54
|
21
21
|
rclone_api/cmd/list_files.py,sha256=x8FHODEilwKqwdiU1jdkeJbLwOqUkUQuDWPo2u_zpf0,741
|
22
|
-
rclone_api-1.0.
|
23
|
-
rclone_api-1.0.
|
24
|
-
rclone_api-1.0.
|
25
|
-
rclone_api-1.0.
|
26
|
-
rclone_api-1.0.
|
27
|
-
rclone_api-1.0.
|
22
|
+
rclone_api-1.0.48.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
|
23
|
+
rclone_api-1.0.48.dist-info/METADATA,sha256=8dsLu_ibzUt98dEjs_K_hc2oLS8Un8BhJNsaWWKc01I,4489
|
24
|
+
rclone_api-1.0.48.dist-info/WHEEL,sha256=9Hm2OB-j1QcCUq9Jguht7ayGIIZBRTdOXD1qg9cCgPM,109
|
25
|
+
rclone_api-1.0.48.dist-info/entry_points.txt,sha256=XUoTX3m7CWxdj2VAKhEuO0NMOfX2qf-OcEDFwdyk9ZE,72
|
26
|
+
rclone_api-1.0.48.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
|
27
|
+
rclone_api-1.0.48.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|