rclone-api 1.0.58__tar.gz → 1.0.60__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. {rclone_api-1.0.58 → rclone_api-1.0.60}/PKG-INFO +1 -1
  2. {rclone_api-1.0.58 → rclone_api-1.0.60}/pyproject.toml +1 -1
  3. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/diff.py +4 -3
  4. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/dir.py +2 -2
  5. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/rclone.py +41 -9
  6. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/util.py +7 -0
  7. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/walk.py +14 -8
  8. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api.egg-info/PKG-INFO +1 -1
  9. {rclone_api-1.0.58 → rclone_api-1.0.60}/tests/test_diff.py +0 -12
  10. {rclone_api-1.0.58 → rclone_api-1.0.60}/tests/test_is_synced.py +1 -0
  11. {rclone_api-1.0.58 → rclone_api-1.0.60}/.aiderignore +0 -0
  12. {rclone_api-1.0.58 → rclone_api-1.0.60}/.github/workflows/lint.yml +0 -0
  13. {rclone_api-1.0.58 → rclone_api-1.0.60}/.github/workflows/push_macos.yml +0 -0
  14. {rclone_api-1.0.58 → rclone_api-1.0.60}/.github/workflows/push_ubuntu.yml +0 -0
  15. {rclone_api-1.0.58 → rclone_api-1.0.60}/.github/workflows/push_win.yml +0 -0
  16. {rclone_api-1.0.58 → rclone_api-1.0.60}/.gitignore +0 -0
  17. {rclone_api-1.0.58 → rclone_api-1.0.60}/.pylintrc +0 -0
  18. {rclone_api-1.0.58 → rclone_api-1.0.60}/.vscode/launch.json +0 -0
  19. {rclone_api-1.0.58 → rclone_api-1.0.60}/.vscode/settings.json +0 -0
  20. {rclone_api-1.0.58 → rclone_api-1.0.60}/.vscode/tasks.json +0 -0
  21. {rclone_api-1.0.58 → rclone_api-1.0.60}/LICENSE +0 -0
  22. {rclone_api-1.0.58 → rclone_api-1.0.60}/MANIFEST.in +0 -0
  23. {rclone_api-1.0.58 → rclone_api-1.0.60}/README.md +0 -0
  24. {rclone_api-1.0.58 → rclone_api-1.0.60}/clean +0 -0
  25. {rclone_api-1.0.58 → rclone_api-1.0.60}/install +0 -0
  26. {rclone_api-1.0.58 → rclone_api-1.0.60}/lint +0 -0
  27. {rclone_api-1.0.58 → rclone_api-1.0.60}/requirements.testing.txt +0 -0
  28. {rclone_api-1.0.58 → rclone_api-1.0.60}/setup.cfg +0 -0
  29. {rclone_api-1.0.58 → rclone_api-1.0.60}/setup.py +0 -0
  30. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/__init__.py +0 -0
  31. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/assets/example.txt +0 -0
  32. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/cli.py +0 -0
  33. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/cmd/list_files.py +0 -0
  34. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/completed_process.py +0 -0
  35. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/config.py +0 -0
  36. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/convert.py +0 -0
  37. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/deprecated.py +0 -0
  38. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/dir_listing.py +0 -0
  39. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/exec.py +0 -0
  40. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/file.py +0 -0
  41. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/filelist.py +0 -0
  42. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/group_files.py +0 -0
  43. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/process.py +0 -0
  44. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/remote.py +0 -0
  45. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api/rpath.py +0 -0
  46. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api.egg-info/SOURCES.txt +0 -0
  47. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api.egg-info/dependency_links.txt +0 -0
  48. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api.egg-info/entry_points.txt +0 -0
  49. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api.egg-info/requires.txt +0 -0
  50. {rclone_api-1.0.58 → rclone_api-1.0.60}/src/rclone_api.egg-info/top_level.txt +0 -0
  51. {rclone_api-1.0.58 → rclone_api-1.0.60}/test +0 -0
  52. {rclone_api-1.0.58 → rclone_api-1.0.60}/tests/test_cmd_list_files.py +0 -0
  53. {rclone_api-1.0.58 → rclone_api-1.0.60}/tests/test_copy.py +0 -0
  54. {rclone_api-1.0.58 → rclone_api-1.0.60}/tests/test_copy_files.py +0 -0
  55. {rclone_api-1.0.58 → rclone_api-1.0.60}/tests/test_group_files.py +0 -0
  56. {rclone_api-1.0.58 → rclone_api-1.0.60}/tests/test_ls.py +0 -0
  57. {rclone_api-1.0.58 → rclone_api-1.0.60}/tests/test_mount.py +0 -0
  58. {rclone_api-1.0.58 → rclone_api-1.0.60}/tests/test_mount_s3.py +0 -0
  59. {rclone_api-1.0.58 → rclone_api-1.0.60}/tests/test_mount_webdav.py +0 -0
  60. {rclone_api-1.0.58 → rclone_api-1.0.60}/tests/test_obscure.py +0 -0
  61. {rclone_api-1.0.58 → rclone_api-1.0.60}/tests/test_remote_control.py +0 -0
  62. {rclone_api-1.0.58 → rclone_api-1.0.60}/tests/test_remotes.py +0 -0
  63. {rclone_api-1.0.58 → rclone_api-1.0.60}/tests/test_serve_webdav.py +0 -0
  64. {rclone_api-1.0.58 → rclone_api-1.0.60}/tests/test_walk.py +0 -0
  65. {rclone_api-1.0.58 → rclone_api-1.0.60}/tox.ini +0 -0
  66. {rclone_api-1.0.58 → rclone_api-1.0.60}/upload_package.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rclone_api
3
- Version: 1.0.58
3
+ Version: 1.0.60
4
4
  Summary: rclone api in python
5
5
  Home-page: https://github.com/zackees/rclone-api
6
6
  Maintainer: Zachary Vorhies
@@ -15,7 +15,7 @@ dependencies = [
15
15
  "python-dotenv>=1.0.0",
16
16
  ]
17
17
  # Change this with the version number bump.
18
- version = "1.0.58"
18
+ version = "1.0.60"
19
19
 
20
20
  [tool.setuptools]
21
21
  package-dir = {"" = "src"}
@@ -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
- raise ValueError(
108
- f"No output from rclone check, first few lines: {first_lines_str}"
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(
@@ -41,11 +41,11 @@ class Dir:
41
41
  # self.path.set_rclone(self.path.remote.rclone)
42
42
  assert self.path.rclone is not None
43
43
 
44
- def ls(self, max_depth: int = 0) -> DirListing:
44
+ def ls(self, max_depth: int = 0, reverse: bool = False) -> DirListing:
45
45
  """List files and directories in the given path."""
46
46
  assert self.path.rclone is not None
47
47
  dir = Dir(self.path)
48
- return self.path.rclone.ls(dir, max_depth=max_depth)
48
+ return self.path.rclone.ls(dir, max_depth=max_depth, reverse=reverse)
49
49
 
50
50
  def walk(
51
51
  self, breadth_first: bool, max_depth: int = -1
@@ -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 = True, capture: bool | None = None
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
 
@@ -72,7 +73,7 @@ class Rclone:
72
73
 
73
74
  def launch_server(
74
75
  self,
75
- addr: str | None = None,
76
+ addr: str,
76
77
  user: str | None = None,
77
78
  password: str | None = None,
78
79
  other_args: list[str] | None = None,
@@ -122,6 +123,7 @@ class Rclone:
122
123
  path: Dir | Remote | str,
123
124
  max_depth: int | None = None,
124
125
  glob: str | None = None,
126
+ reverse: bool = False,
125
127
  ) -> DirListing:
126
128
  """List files in the given path.
127
129
 
@@ -162,6 +164,9 @@ class Rclone:
162
164
  # do we have a glob pattern?
163
165
  if glob is not None:
164
166
  paths = [p for p in paths if fnmatch(p.path, glob)]
167
+
168
+ if reverse:
169
+ paths.reverse()
165
170
  return DirListing(paths)
166
171
 
167
172
  def listremotes(self) -> list[Remote]:
@@ -175,9 +180,21 @@ class Rclone:
175
180
  out = [Remote(name=t, rclone=self) for t in tmp]
176
181
  return out
177
182
 
178
- def diff(self, src: str, dst: str) -> Generator[DiffItem, None, None]:
183
+ def diff(
184
+ self,
185
+ src: str,
186
+ dst: str,
187
+ min_size: (
188
+ str | None
189
+ ) = None, # e. g. "1MB" - see rclone documentation: https://rclone.org/commands/rclone_check/
190
+ max_size: (
191
+ str | None
192
+ ) = None, # e. g. "1GB" - see rclone documentation: https://rclone.org/commands/rclone_check/
193
+ other_args: list[str] | None = None,
194
+ ) -> Generator[DiffItem, None, None]:
179
195
  """Be extra careful with the src and dst values. If you are off by one
180
196
  parent directory, you will get a huge amount of false diffs."""
197
+ other_args = other_args or []
181
198
  cmd = [
182
199
  "check",
183
200
  src,
@@ -189,6 +206,12 @@ class Rclone:
189
206
  "--combined",
190
207
  "-",
191
208
  ]
209
+ if min_size:
210
+ cmd += ["--min-size", min_size]
211
+ if max_size:
212
+ cmd += ["--max-size", max_size]
213
+ if other_args:
214
+ cmd += other_args
192
215
  proc = self._launch_process(cmd, capture=True)
193
216
  item: DiffItem
194
217
  for item in diff_stream_from_running_process(proc, src_slug=src, dst_slug=dst):
@@ -197,7 +220,11 @@ class Rclone:
197
220
  yield item
198
221
 
199
222
  def walk(
200
- self, path: Dir | Remote | str, max_depth: int = -1, breadth_first: bool = True
223
+ self,
224
+ path: Dir | Remote | str,
225
+ max_depth: int = -1,
226
+ breadth_first: bool = True,
227
+ reverse: bool = False,
201
228
  ) -> Generator[DirListing, None, None]:
202
229
  """Walk through the given path recursively.
203
230
 
@@ -231,7 +258,9 @@ class Rclone:
231
258
  dir_obj = Dir(path) # shut up pyright
232
259
  assert f"Invalid type for path: {type(path)}"
233
260
 
234
- yield from walk(dir_obj, max_depth=max_depth, breadth_first=breadth_first)
261
+ yield from walk(
262
+ dir_obj, max_depth=max_depth, breadth_first=breadth_first, reverse=reverse
263
+ )
235
264
 
236
265
  def cleanup(
237
266
  self, path: str, other_args: list[str] | None = None
@@ -248,7 +277,7 @@ class Rclone:
248
277
  self,
249
278
  src: File | str,
250
279
  dst: File | str,
251
- check=True,
280
+ check: bool | None = None,
252
281
  other_args: list[str] | None = None,
253
282
  ) -> None:
254
283
  """Copy multiple files from source to destination.
@@ -258,6 +287,7 @@ class Rclone:
258
287
  Args:
259
288
  payload: Dictionary of source and destination file paths
260
289
  """
290
+ check = get_check(check)
261
291
  src = src if isinstance(src, str) else str(src.path)
262
292
  dst = dst if isinstance(dst, str) else str(dst.path)
263
293
  cmd_list: list[str] = ["copyto", src, dst]
@@ -270,7 +300,7 @@ class Rclone:
270
300
  src: str,
271
301
  dst: str,
272
302
  files: list[str],
273
- check=True,
303
+ check: bool | None = None,
274
304
  verbose: bool | None = None,
275
305
  checkers: int | None = None,
276
306
  transfers: int | None = None,
@@ -284,6 +314,7 @@ class Rclone:
284
314
  Args:
285
315
  payload: Dictionary of source and destination file paths
286
316
  """
317
+ check = get_check(check)
287
318
  max_partition_workers = max_partition_workers or 1
288
319
  low_level_retries = low_level_retries or 10
289
320
  retries = retries or 3
@@ -398,13 +429,14 @@ class Rclone:
398
429
  def delete_files(
399
430
  self,
400
431
  files: str | File | list[str] | list[File],
401
- check=True,
432
+ check: bool | None = None,
402
433
  rmdirs=False,
403
434
  verbose: bool | None = None,
404
435
  max_partition_workers: int | None = None,
405
436
  other_args: list[str] | None = None,
406
437
  ) -> CompletedProcess:
407
438
  """Delete a directory"""
439
+ check = get_check(check)
408
440
  verbose = get_verbose(verbose)
409
441
  payload: list[str] = convert_to_filestr_list(files)
410
442
  if len(payload) == 0:
@@ -494,7 +526,7 @@ class Rclone:
494
526
  dst = convert_to_str(dst)
495
527
  cmd_list: list[str] = ["check", str(src), str(dst)]
496
528
  try:
497
- self._run(cmd_list)
529
+ self._run(cmd_list, check=True)
498
530
  return True
499
531
  except subprocess.CalledProcessError:
500
532
  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
 
@@ -10,14 +10,17 @@ _MAX_OUT_QUEUE_SIZE = 50
10
10
 
11
11
 
12
12
  def _walk_runner_breadth_first(
13
- dir: Dir, max_depth: int, out_queue: Queue[DirListing | None]
13
+ dir: Dir,
14
+ max_depth: int,
15
+ out_queue: Queue[DirListing | None],
16
+ reverse: bool = False,
14
17
  ) -> None:
15
18
  queue: Queue[Dir] = Queue()
16
19
  queue.put(dir)
17
20
  try:
18
21
  while not queue.empty():
19
22
  current_dir = queue.get()
20
- dirlisting = current_dir.ls()
23
+ dirlisting = current_dir.ls(max_depth=0, reverse=reverse)
21
24
  out_queue.put(dirlisting)
22
25
  dirs = dirlisting.dirs
23
26
 
@@ -38,20 +41,22 @@ def _walk_runner_breadth_first(
38
41
 
39
42
 
40
43
  def _walk_runner_depth_first(
41
- dir: Dir, max_depth: int, out_queue: Queue[DirListing | None]
44
+ dir: Dir, max_depth: int, out_queue: Queue[DirListing | None], reverse=False
42
45
  ) -> None:
43
46
  try:
44
47
  stack = [(dir, max_depth)]
45
48
  while stack:
46
49
  current_dir, depth = stack.pop()
47
50
  dirlisting = current_dir.ls()
51
+ if reverse:
52
+ dirlisting.dirs.reverse()
48
53
  if depth != 0:
49
- for subdir in reversed(
50
- dirlisting.dirs
51
- ): # Process deeper directories first
54
+ for subdir in dirlisting.dirs: # Process deeper directories first
52
55
  # stack.append((child, depth - 1 if depth > 0 else depth))
53
56
  next_depth = depth - 1 if depth > 0 else depth
54
- _walk_runner_depth_first(subdir, next_depth, out_queue)
57
+ _walk_runner_depth_first(
58
+ subdir, next_depth, out_queue, reverse=reverse
59
+ )
55
60
  out_queue.put(dirlisting)
56
61
  out_queue.put(None)
57
62
  except KeyboardInterrupt:
@@ -65,6 +70,7 @@ def walk(
65
70
  dir: Dir | Remote,
66
71
  breadth_first: bool,
67
72
  max_depth: int = -1,
73
+ reverse: bool = False,
68
74
  ) -> Generator[DirListing, None, None]:
69
75
  """Walk through the given directory recursively.
70
76
 
@@ -88,7 +94,7 @@ def walk(
88
94
  # Start worker thread
89
95
  worker = Thread(
90
96
  target=strategy,
91
- args=(dir, max_depth, out_queue),
97
+ args=(dir, max_depth, out_queue, reverse),
92
98
  daemon=True,
93
99
  )
94
100
  worker.start()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rclone_api
3
- Version: 1.0.58
3
+ Version: 1.0.60
4
4
  Summary: rclone api in python
5
5
  Home-page: https://github.com/zackees/rclone-api
6
6
  Maintainer: Zachary Vorhies
@@ -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