rclone-api 1.0.65__py2.py3-none-any.whl → 1.0.67__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/__init__.py +2 -1
- rclone_api/diff.py +59 -22
- rclone_api/rclone.py +12 -9
- {rclone_api-1.0.65.dist-info → rclone_api-1.0.67.dist-info}/METADATA +1 -1
- {rclone_api-1.0.65.dist-info → rclone_api-1.0.67.dist-info}/RECORD +9 -9
- {rclone_api-1.0.65.dist-info → rclone_api-1.0.67.dist-info}/LICENSE +0 -0
- {rclone_api-1.0.65.dist-info → rclone_api-1.0.67.dist-info}/WHEEL +0 -0
- {rclone_api-1.0.65.dist-info → rclone_api-1.0.67.dist-info}/entry_points.txt +0 -0
- {rclone_api-1.0.65.dist-info → rclone_api-1.0.67.dist-info}/top_level.txt +0 -0
rclone_api/__init__.py
CHANGED
@@ -6,7 +6,7 @@ from .dir_listing import DirListing
|
|
6
6
|
from .file import File
|
7
7
|
from .filelist import FileList
|
8
8
|
from .process import Process
|
9
|
-
from .rclone import DiffOption, Rclone, rclone_verbose
|
9
|
+
from .rclone import DiffOption, ListingOption, Rclone, rclone_verbose
|
10
10
|
from .remote import Remote
|
11
11
|
from .rpath import RPath
|
12
12
|
|
@@ -25,4 +25,5 @@ __all__ = [
|
|
25
25
|
"rclone_verbose",
|
26
26
|
"CompletedProcess",
|
27
27
|
"DiffOption",
|
28
|
+
"ListingOption",
|
28
29
|
]
|
rclone_api/diff.py
CHANGED
@@ -19,6 +19,15 @@ class DiffType(Enum):
|
|
19
19
|
ERROR = "!" # means there was an error
|
20
20
|
|
21
21
|
|
22
|
+
class DiffOption(Enum):
|
23
|
+
COMBINED = "combined"
|
24
|
+
MISSING_ON_SRC = "missing-on-src"
|
25
|
+
MISSING_ON_DST = "missing-on-dst"
|
26
|
+
DIFFER = "differ"
|
27
|
+
MATCH = "match"
|
28
|
+
ERROR = "error"
|
29
|
+
|
30
|
+
|
22
31
|
@dataclass
|
23
32
|
class DiffItem:
|
24
33
|
type: DiffType
|
@@ -42,31 +51,56 @@ class DiffItem:
|
|
42
51
|
return f"{self.src_prefix}/{self.path}"
|
43
52
|
|
44
53
|
|
45
|
-
def
|
54
|
+
def _parse_missing_on_src_dst(line: str) -> str | None:
|
55
|
+
if line.endswith("does-not-exist"):
|
56
|
+
# 2025/02/17 14:43:38 ERROR : zachs_video/breaking_ai_mind.mp4: file not in S3 bucket rclone-api-unit-test path does-not-exist
|
57
|
+
parts = line.split(" : ", 1)
|
58
|
+
if len(parts) < 1:
|
59
|
+
return None
|
60
|
+
right = parts[1]
|
61
|
+
file_path = right.split(":", 1)[0]
|
62
|
+
return file_path.strip()
|
63
|
+
return None
|
64
|
+
|
65
|
+
|
66
|
+
def _classify_diff(
|
67
|
+
line: str, src_slug: str, dst_slug: str, diff_option: DiffOption
|
68
|
+
) -> DiffItem | None:
|
46
69
|
def _new(type: DiffType, path: str) -> DiffItem:
|
47
70
|
return DiffItem(type, path, src_prefix=src_slug, dst_prefix=dst_slug)
|
48
71
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
72
|
+
if diff_option == DiffOption.COMBINED:
|
73
|
+
suffix = line[1:].strip() if len(line) > 0 else ""
|
74
|
+
if line.startswith(DiffType.EQUAL.value):
|
75
|
+
return _new(DiffType.EQUAL, suffix)
|
76
|
+
if line.startswith(DiffType.MISSING_ON_SRC.value):
|
77
|
+
return _new(DiffType.MISSING_ON_SRC, suffix)
|
78
|
+
if line.startswith(DiffType.MISSING_ON_DST.value):
|
79
|
+
return _new(DiffType.MISSING_ON_DST, suffix)
|
80
|
+
if line.startswith(DiffType.DIFFERENT.value):
|
81
|
+
return _new(DiffType.DIFFERENT, suffix)
|
82
|
+
if line.startswith(DiffType.ERROR.value):
|
83
|
+
return _new(DiffType.ERROR, suffix)
|
84
|
+
return None
|
85
|
+
if diff_option == DiffOption.MISSING_ON_SRC:
|
86
|
+
filename_src: str | None = _parse_missing_on_src_dst(line)
|
87
|
+
if filename_src is not None:
|
88
|
+
return _new(DiffType.MISSING_ON_SRC, filename_src)
|
89
|
+
return None
|
90
|
+
if diff_option == DiffOption.MISSING_ON_DST:
|
91
|
+
filename_dst: str | None = _parse_missing_on_src_dst(line)
|
92
|
+
if filename_dst is not None:
|
93
|
+
return _new(DiffType.MISSING_ON_DST, filename_dst)
|
94
|
+
return None
|
95
|
+
else:
|
96
|
+
raise ValueError(f"Unknown diff_option: {diff_option}")
|
64
97
|
|
65
98
|
|
66
99
|
def _async_diff_stream_from_running_process(
|
67
100
|
running_process: Process,
|
68
101
|
src_slug: str,
|
69
102
|
dst_slug: str,
|
103
|
+
diff_option: DiffOption,
|
70
104
|
output: Queue[DiffItem | None],
|
71
105
|
) -> None:
|
72
106
|
count = 0
|
@@ -81,7 +115,7 @@ def _async_diff_stream_from_running_process(
|
|
81
115
|
first_few_lines.append(line_str)
|
82
116
|
# _classify_line_type
|
83
117
|
diff_item: DiffItem | None = _classify_diff(
|
84
|
-
line_str, src_slug, dst_slug
|
118
|
+
line_str, src_slug, dst_slug, diff_option
|
85
119
|
)
|
86
120
|
if diff_item is None:
|
87
121
|
# Some other output that we don't care about, debug print etc.
|
@@ -111,14 +145,17 @@ def diff_stream_from_running_process(
|
|
111
145
|
running_process: Process,
|
112
146
|
src_slug: str,
|
113
147
|
dst_slug: str,
|
148
|
+
diff_option: DiffOption,
|
114
149
|
) -> Generator[DiffItem, None, None]:
|
115
150
|
output: Queue[DiffItem | None] = Queue()
|
116
151
|
# process_output_to_diff_stream(running_process, src_slug, dst_slug, output)
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
152
|
+
|
153
|
+
def _task() -> None:
|
154
|
+
_async_diff_stream_from_running_process(
|
155
|
+
running_process, src_slug, dst_slug, diff_option, output
|
156
|
+
)
|
157
|
+
|
158
|
+
thread = Thread(target=_task, daemon=True)
|
122
159
|
thread.start()
|
123
160
|
while True:
|
124
161
|
item = output.get()
|
rclone_api/rclone.py
CHANGED
@@ -18,7 +18,7 @@ from rclone_api.completed_process import CompletedProcess
|
|
18
18
|
from rclone_api.config import Config
|
19
19
|
from rclone_api.convert import convert_to_filestr_list, convert_to_str
|
20
20
|
from rclone_api.deprecated import deprecated
|
21
|
-
from rclone_api.diff import DiffItem, diff_stream_from_running_process
|
21
|
+
from rclone_api.diff import DiffItem, DiffOption, diff_stream_from_running_process
|
22
22
|
from rclone_api.dir_listing import DirListing
|
23
23
|
from rclone_api.exec import RcloneExec
|
24
24
|
from rclone_api.file import File
|
@@ -47,13 +47,10 @@ class ModTimeStrategy(Enum):
|
|
47
47
|
NO_MODTIME = "no-modtime"
|
48
48
|
|
49
49
|
|
50
|
-
class
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
DIFFER = "differ"
|
55
|
-
MATCH = "match"
|
56
|
-
ERROR = "error"
|
50
|
+
class ListingOption(Enum):
|
51
|
+
DIRS_ONLY = "dirs-only"
|
52
|
+
FILES_ONLY = "files-only"
|
53
|
+
ALL = "all"
|
57
54
|
|
58
55
|
|
59
56
|
class Rclone:
|
@@ -133,6 +130,7 @@ class Rclone:
|
|
133
130
|
max_depth: int | None = None,
|
134
131
|
glob: str | None = None,
|
135
132
|
reverse: bool = False,
|
133
|
+
listing_option: ListingOption = ListingOption.ALL,
|
136
134
|
) -> DirListing:
|
137
135
|
"""List files in the given path.
|
138
136
|
|
@@ -156,6 +154,9 @@ class Rclone:
|
|
156
154
|
if max_depth > 0:
|
157
155
|
cmd.append("--max-depth")
|
158
156
|
cmd.append(str(max_depth))
|
157
|
+
if listing_option != ListingOption.ALL:
|
158
|
+
cmd.append(f"--{listing_option.value}")
|
159
|
+
|
159
160
|
cmd.append(str(path))
|
160
161
|
remote = path.remote if isinstance(path, Dir) else path
|
161
162
|
assert isinstance(remote, Remote)
|
@@ -235,7 +236,9 @@ class Rclone:
|
|
235
236
|
cmd += other_args
|
236
237
|
proc = self._launch_process(cmd, capture=True)
|
237
238
|
item: DiffItem
|
238
|
-
for item in diff_stream_from_running_process(
|
239
|
+
for item in diff_stream_from_running_process(
|
240
|
+
running_process=proc, src_slug=src, dst_slug=dst, diff_option=diff_option
|
241
|
+
):
|
239
242
|
if item is None:
|
240
243
|
break
|
241
244
|
yield item
|
@@ -1,10 +1,10 @@
|
|
1
|
-
rclone_api/__init__.py,sha256=
|
1
|
+
rclone_api/__init__.py,sha256=B9q_4JU5Myh0DN-wqr_IgF5hZeAvszrGcqs2x-3hq-Q,633
|
2
2
|
rclone_api/cli.py,sha256=dibfAZIh0kXWsBbfp3onKLjyZXo54mTzDjUdzJlDlWo,231
|
3
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
|
-
rclone_api/diff.py,sha256=
|
7
|
+
rclone_api/diff.py,sha256=ggdDLUZxa13jMcPzKBcwAElmPCNWMOSR89D4yhpO74M,5264
|
8
8
|
rclone_api/dir.py,sha256=2-PFaDpjEs28z82DQ-TyaCgrm_OgpwlkwfTnx1-Wwpk,2194
|
9
9
|
rclone_api/dir_listing.py,sha256=9Qqf2SUswrOEkyqmaH23V51I18X6ePiXb9B1vUwRF5o,1571
|
10
10
|
rclone_api/exec.py,sha256=1ovvaMXDEfLiT7BrYZyE85u_yFhEUwUNW3jPOzqknR8,1023
|
@@ -12,16 +12,16 @@ rclone_api/file.py,sha256=YtR5Y6c0YfXTS-sReOy2UgiSnafcAeO6b2hnbojBQD4,1423
|
|
12
12
|
rclone_api/filelist.py,sha256=xbiusvNgaB_b_kQOZoHMJJxn6TWGtPrWd2J042BI28o,767
|
13
13
|
rclone_api/group_files.py,sha256=kOHh6ysFDkxjldSwvW6KqmiADUC1yFCdrZRY57TvbGY,5328
|
14
14
|
rclone_api/process.py,sha256=RrMfTe0bndmJ6gBK67ioqNvCstJ8aTC8RlGX1XBLlcw,4191
|
15
|
-
rclone_api/rclone.py,sha256=
|
15
|
+
rclone_api/rclone.py,sha256=CLjyQXRt-YaWwEOKZ2G1LACxUprtG8eLGAcNkVywxh8,27985
|
16
16
|
rclone_api/remote.py,sha256=c9hlRKBCg1BFB9MCINaQIoCg10qyAkeqiS4brl8ce-8,343
|
17
17
|
rclone_api/rpath.py,sha256=8ZA_1wxWtskwcy0I8V2VbjKDmzPkiWd8Q2JQSvh-sYE,2586
|
18
18
|
rclone_api/util.py,sha256=_cvmHcJPRl2yXw4zgZiop3z-riA_8Ek6S5NDPw8cqSY,4198
|
19
19
|
rclone_api/walk.py,sha256=UaNOE3ICd8k5ouSFZvkVEH4r2GnnrD9TxfwkFcQnayo,3170
|
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.67.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
|
23
|
+
rclone_api-1.0.67.dist-info/METADATA,sha256=H866NatSXqCR0niXYtEebKY14_byytSoF1jZ1HHab1s,4489
|
24
|
+
rclone_api-1.0.67.dist-info/WHEEL,sha256=9Hm2OB-j1QcCUq9Jguht7ayGIIZBRTdOXD1qg9cCgPM,109
|
25
|
+
rclone_api-1.0.67.dist-info/entry_points.txt,sha256=XUoTX3m7CWxdj2VAKhEuO0NMOfX2qf-OcEDFwdyk9ZE,72
|
26
|
+
rclone_api-1.0.67.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
|
27
|
+
rclone_api-1.0.67.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|