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 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 _classify_diff(line: str, src_slug: str, dst_slug: str) -> DiffItem | None:
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
- suffix = line[1:].strip() if len(line) > 0 else ""
50
- if line.startswith(DiffType.EQUAL.value):
51
- return _new(DiffType.EQUAL, suffix)
52
- if line.startswith(DiffType.MISSING_ON_SRC.value):
53
- return _new(DiffType.MISSING_ON_SRC, suffix)
54
- if line.startswith(DiffType.MISSING_ON_DST.value):
55
- # return DiffItem(DiffType.MISSING_ON_DST, f"{src_slug}/{suffix}")
56
- return _new(DiffType.MISSING_ON_DST, suffix)
57
- if line.startswith(DiffType.DIFFERENT.value):
58
- # return DiffItem(DiffType.DIFFERENT, suffix)
59
- return _new(DiffType.DIFFERENT, suffix)
60
- if line.startswith(DiffType.ERROR.value):
61
- # return DiffItem(DiffType.ERROR, suffix)
62
- return _new(DiffType.ERROR, suffix)
63
- return None
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
- thread = Thread(
118
- target=_async_diff_stream_from_running_process,
119
- args=(running_process, src_slug, dst_slug, output),
120
- daemon=True,
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 DiffOption(Enum):
51
- COMBINED = "combined"
52
- MISSING_ON_SRC = "missing-on-src"
53
- MISSING_ON_DST = "missing-on-dst"
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(proc, src_slug=src, dst_slug=dst):
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,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rclone_api
3
- Version: 1.0.65
3
+ Version: 1.0.67
4
4
  Summary: rclone api in python
5
5
  Home-page: https://github.com/zackees/rclone-api
6
6
  Maintainer: Zachary Vorhies
@@ -1,10 +1,10 @@
1
- rclone_api/__init__.py,sha256=M9JDm9dhkEUUxnTdfLVzMUJUZdIDWuvTbEoCN_HU_iE,597
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=HVt246BMXR6jrc_RgywC5HLbdbELls1OLrse6kcT-Ak,4038
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=4YNHRuc11oqMVtN7SbuX0cylasWoWkua7UGefrhYGGM,27837
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.65.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
23
- rclone_api-1.0.65.dist-info/METADATA,sha256=Chedoc_vmPbywO4y6TdJeBwwcI6a8UcSrSvI2S7wf_I,4489
24
- rclone_api-1.0.65.dist-info/WHEEL,sha256=9Hm2OB-j1QcCUq9Jguht7ayGIIZBRTdOXD1qg9cCgPM,109
25
- rclone_api-1.0.65.dist-info/entry_points.txt,sha256=XUoTX3m7CWxdj2VAKhEuO0NMOfX2qf-OcEDFwdyk9ZE,72
26
- rclone_api-1.0.65.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
27
- rclone_api-1.0.65.dist-info/RECORD,,
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,,