rclone-api 1.0.59__tar.gz → 1.0.61__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {rclone_api-1.0.59 → rclone_api-1.0.61}/PKG-INFO +1 -1
- {rclone_api-1.0.59 → rclone_api-1.0.61}/pyproject.toml +1 -1
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/diff.py +4 -3
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/rclone.py +37 -13
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/util.py +7 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api.egg-info/PKG-INFO +1 -1
- {rclone_api-1.0.59 → rclone_api-1.0.61}/tests/test_diff.py +0 -12
- {rclone_api-1.0.59 → rclone_api-1.0.61}/tests/test_is_synced.py +1 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/.aiderignore +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/.github/workflows/lint.yml +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/.github/workflows/push_macos.yml +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/.github/workflows/push_ubuntu.yml +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/.github/workflows/push_win.yml +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/.gitignore +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/.pylintrc +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/.vscode/launch.json +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/.vscode/settings.json +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/.vscode/tasks.json +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/LICENSE +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/MANIFEST.in +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/README.md +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/clean +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/install +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/lint +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/requirements.testing.txt +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/setup.cfg +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/setup.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/__init__.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/assets/example.txt +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/cli.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/cmd/list_files.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/completed_process.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/config.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/convert.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/deprecated.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/dir.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/dir_listing.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/exec.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/file.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/filelist.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/group_files.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/process.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/remote.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/rpath.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api/walk.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api.egg-info/SOURCES.txt +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api.egg-info/dependency_links.txt +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api.egg-info/entry_points.txt +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api.egg-info/requires.txt +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/src/rclone_api.egg-info/top_level.txt +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/test +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/tests/test_cmd_list_files.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/tests/test_copy.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/tests/test_copy_files.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/tests/test_group_files.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/tests/test_ls.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/tests/test_mount.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/tests/test_mount_s3.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/tests/test_mount_webdav.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/tests/test_obscure.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/tests/test_remote_control.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/tests/test_remotes.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/tests/test_serve_webdav.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/tests/test_walk.py +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/tox.ini +0 -0
- {rclone_api-1.0.59 → rclone_api-1.0.61}/upload_package.sh +0 -0
@@ -1,3 +1,4 @@
|
|
1
|
+
import warnings
|
1
2
|
from dataclasses import dataclass
|
2
3
|
from enum import Enum
|
3
4
|
from queue import Queue
|
@@ -104,9 +105,9 @@ def _async_diff_stream_from_running_process(
|
|
104
105
|
_thread.interrupt_main()
|
105
106
|
if count == 0 and check:
|
106
107
|
first_lines_str = "\n".join(first_few_lines)
|
107
|
-
|
108
|
-
|
109
|
-
)
|
108
|
+
warning_msg = f"No output from rclone check, first few lines: {first_lines_str}"
|
109
|
+
warnings.warn(warning_msg)
|
110
|
+
raise ValueError(warning_msg)
|
110
111
|
|
111
112
|
|
112
113
|
def diff_stream_from_running_process(
|
@@ -27,6 +27,7 @@ from rclone_api.process import Process
|
|
27
27
|
from rclone_api.remote import Remote
|
28
28
|
from rclone_api.rpath import RPath
|
29
29
|
from rclone_api.util import (
|
30
|
+
get_check,
|
30
31
|
get_rclone_exe,
|
31
32
|
get_verbose,
|
32
33
|
to_path,
|
@@ -56,7 +57,7 @@ class Rclone:
|
|
56
57
|
self._exec = RcloneExec(rclone_conf, get_rclone_exe(rclone_exe))
|
57
58
|
|
58
59
|
def _run(
|
59
|
-
self, cmd: list[str], check: bool =
|
60
|
+
self, cmd: list[str], check: bool = False, capture: bool | None = None
|
60
61
|
) -> subprocess.CompletedProcess:
|
61
62
|
return self._exec.execute(cmd, check=check, capture=capture)
|
62
63
|
|
@@ -276,7 +277,7 @@ class Rclone:
|
|
276
277
|
self,
|
277
278
|
src: File | str,
|
278
279
|
dst: File | str,
|
279
|
-
check=
|
280
|
+
check: bool | None = None,
|
280
281
|
other_args: list[str] | None = None,
|
281
282
|
) -> None:
|
282
283
|
"""Copy multiple files from source to destination.
|
@@ -286,6 +287,7 @@ class Rclone:
|
|
286
287
|
Args:
|
287
288
|
payload: Dictionary of source and destination file paths
|
288
289
|
"""
|
290
|
+
check = get_check(check)
|
289
291
|
src = src if isinstance(src, str) else str(src.path)
|
290
292
|
dst = dst if isinstance(dst, str) else str(dst.path)
|
291
293
|
cmd_list: list[str] = ["copyto", src, dst]
|
@@ -297,8 +299,8 @@ class Rclone:
|
|
297
299
|
self,
|
298
300
|
src: str,
|
299
301
|
dst: str,
|
300
|
-
files: list[str],
|
301
|
-
check=
|
302
|
+
files: list[str] | Path,
|
303
|
+
check: bool | None = None,
|
302
304
|
verbose: bool | None = None,
|
303
305
|
checkers: int | None = None,
|
304
306
|
transfers: int | None = None,
|
@@ -312,6 +314,7 @@ class Rclone:
|
|
312
314
|
Args:
|
313
315
|
payload: Dictionary of source and destination file paths
|
314
316
|
"""
|
317
|
+
check = get_check(check)
|
315
318
|
max_partition_workers = max_partition_workers or 1
|
316
319
|
low_level_retries = low_level_retries or 10
|
317
320
|
retries = retries or 3
|
@@ -319,7 +322,11 @@ class Rclone:
|
|
319
322
|
checkers = checkers or 1000
|
320
323
|
transfers = transfers or 32
|
321
324
|
verbose = get_verbose(verbose)
|
322
|
-
payload: list[str] =
|
325
|
+
payload: list[str] = (
|
326
|
+
files
|
327
|
+
if isinstance(files, list)
|
328
|
+
else [f.strip() for f in files.read_text().splitlines() if f.strip()]
|
329
|
+
)
|
323
330
|
if len(payload) == 0:
|
324
331
|
return []
|
325
332
|
|
@@ -338,10 +345,26 @@ class Rclone:
|
|
338
345
|
with ThreadPoolExecutor(max_workers=max_partition_workers) as executor:
|
339
346
|
for common_prefix, files in datalists.items():
|
340
347
|
|
341
|
-
def _task(
|
348
|
+
def _task(
|
349
|
+
files: list[str] | Path = files,
|
350
|
+
) -> subprocess.CompletedProcess:
|
342
351
|
with TemporaryDirectory() as tmpdir:
|
343
|
-
|
344
|
-
|
352
|
+
filelist: list[str] = []
|
353
|
+
filepath: Path
|
354
|
+
if isinstance(files, list):
|
355
|
+
include_files_txt = Path(tmpdir) / "include_files.txt"
|
356
|
+
include_files_txt.write_text(
|
357
|
+
"\n".join(files), encoding="utf-8"
|
358
|
+
)
|
359
|
+
filelist = list(files)
|
360
|
+
filepath = Path(include_files_txt)
|
361
|
+
elif isinstance(files, Path):
|
362
|
+
filelist = [
|
363
|
+
f.strip()
|
364
|
+
for f in files.read_text().splitlines()
|
365
|
+
if f.strip()
|
366
|
+
]
|
367
|
+
filepath = files
|
345
368
|
if common_prefix:
|
346
369
|
src_path = f"{src}/{common_prefix}"
|
347
370
|
dst_path = f"{dst}/{common_prefix}"
|
@@ -350,8 +373,8 @@ class Rclone:
|
|
350
373
|
dst_path = dst
|
351
374
|
|
352
375
|
if verbose:
|
353
|
-
nfiles = len(
|
354
|
-
files_fqdn = [f" {src_path}/{f}" for f in
|
376
|
+
nfiles = len(filelist)
|
377
|
+
files_fqdn = [f" {src_path}/{f}" for f in filelist]
|
355
378
|
print(f"Copying {nfiles} files:")
|
356
379
|
chunk_size = 100
|
357
380
|
for i in range(0, nfiles, chunk_size):
|
@@ -367,7 +390,7 @@ class Rclone:
|
|
367
390
|
src_path,
|
368
391
|
dst_path,
|
369
392
|
"--files-from",
|
370
|
-
str(
|
393
|
+
str(filepath),
|
371
394
|
"--checkers",
|
372
395
|
str(checkers),
|
373
396
|
"--transfers",
|
@@ -426,13 +449,14 @@ class Rclone:
|
|
426
449
|
def delete_files(
|
427
450
|
self,
|
428
451
|
files: str | File | list[str] | list[File],
|
429
|
-
check=
|
452
|
+
check: bool | None = None,
|
430
453
|
rmdirs=False,
|
431
454
|
verbose: bool | None = None,
|
432
455
|
max_partition_workers: int | None = None,
|
433
456
|
other_args: list[str] | None = None,
|
434
457
|
) -> CompletedProcess:
|
435
458
|
"""Delete a directory"""
|
459
|
+
check = get_check(check)
|
436
460
|
verbose = get_verbose(verbose)
|
437
461
|
payload: list[str] = convert_to_filestr_list(files)
|
438
462
|
if len(payload) == 0:
|
@@ -522,7 +546,7 @@ class Rclone:
|
|
522
546
|
dst = convert_to_str(dst)
|
523
547
|
cmd_list: list[str] = ["check", str(src), str(dst)]
|
524
548
|
try:
|
525
|
-
self._run(cmd_list)
|
549
|
+
self._run(cmd_list, check=True)
|
526
550
|
return True
|
527
551
|
except subprocess.CalledProcessError:
|
528
552
|
return False
|
@@ -63,6 +63,13 @@ def get_verbose(verbose: bool | None) -> bool:
|
|
63
63
|
return bool(int(os.getenv("RCLONE_API_VERBOSE", "0")))
|
64
64
|
|
65
65
|
|
66
|
+
def get_check(check: bool | None) -> bool:
|
67
|
+
if check is not None:
|
68
|
+
return check
|
69
|
+
# get it from the environment
|
70
|
+
return bool(int(os.getenv("RCLONE_API_CHECK", "1")))
|
71
|
+
|
72
|
+
|
66
73
|
def get_rclone_exe(rclone_exe: Path | None) -> Path:
|
67
74
|
if rclone_exe is None:
|
68
75
|
|
@@ -70,18 +70,6 @@ class RcloneDiffTests(unittest.TestCase):
|
|
70
70
|
msg = "\n".join([str(item) for item in all])
|
71
71
|
print(msg)
|
72
72
|
|
73
|
-
all.clear()
|
74
|
-
for item in rclone.diff(
|
75
|
-
"dst:rclone-api-unit-test/test", "dst:rclone-api-unit-test/test"
|
76
|
-
):
|
77
|
-
self.assertEqual(item.type, DiffType.EQUAL)
|
78
|
-
print(item)
|
79
|
-
all.append(item)
|
80
|
-
|
81
|
-
msg = "\n".join([str(item) for item in all])
|
82
|
-
print(msg)
|
83
|
-
print("done")
|
84
|
-
|
85
73
|
|
86
74
|
if __name__ == "__main__":
|
87
75
|
unittest.main()
|
@@ -62,6 +62,7 @@ class RcloneIsSyncedTests(unittest.TestCase):
|
|
62
62
|
listing: DirListing = rclone.ls(path)
|
63
63
|
self.assertGreater(len(listing.dirs), 0)
|
64
64
|
src_dir = listing.dirs[0]
|
65
|
+
src_dir = src_dir
|
65
66
|
dst_dir = f"dst:{BUCKET_NAME}/test"
|
66
67
|
rclone.purge(dst_dir)
|
67
68
|
is_synced = rclone.is_synced(src_dir, dst_dir)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|