rclone-api 1.0.35__tar.gz → 1.0.36__tar.gz

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rclone-api might be problematic. Click here for more details.

Files changed (61) hide show
  1. {rclone_api-1.0.35 → rclone_api-1.0.36}/PKG-INFO +1 -1
  2. {rclone_api-1.0.35 → rclone_api-1.0.36}/pyproject.toml +1 -1
  3. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/rclone.py +48 -29
  4. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/util.py +15 -0
  5. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api.egg-info/PKG-INFO +1 -1
  6. {rclone_api-1.0.35 → rclone_api-1.0.36}/tests/test_copy.py +6 -11
  7. {rclone_api-1.0.35 → rclone_api-1.0.36}/.aiderignore +0 -0
  8. {rclone_api-1.0.35 → rclone_api-1.0.36}/.github/workflows/lint.yml +0 -0
  9. {rclone_api-1.0.35 → rclone_api-1.0.36}/.github/workflows/push_macos.yml +0 -0
  10. {rclone_api-1.0.35 → rclone_api-1.0.36}/.github/workflows/push_ubuntu.yml +0 -0
  11. {rclone_api-1.0.35 → rclone_api-1.0.36}/.github/workflows/push_win.yml +0 -0
  12. {rclone_api-1.0.35 → rclone_api-1.0.36}/.gitignore +0 -0
  13. {rclone_api-1.0.35 → rclone_api-1.0.36}/.pylintrc +0 -0
  14. {rclone_api-1.0.35 → rclone_api-1.0.36}/.vscode/launch.json +0 -0
  15. {rclone_api-1.0.35 → rclone_api-1.0.36}/.vscode/settings.json +0 -0
  16. {rclone_api-1.0.35 → rclone_api-1.0.36}/.vscode/tasks.json +0 -0
  17. {rclone_api-1.0.35 → rclone_api-1.0.36}/LICENSE +0 -0
  18. {rclone_api-1.0.35 → rclone_api-1.0.36}/MANIFEST.in +0 -0
  19. {rclone_api-1.0.35 → rclone_api-1.0.36}/README.md +0 -0
  20. {rclone_api-1.0.35 → rclone_api-1.0.36}/clean +0 -0
  21. {rclone_api-1.0.35 → rclone_api-1.0.36}/install +0 -0
  22. {rclone_api-1.0.35 → rclone_api-1.0.36}/lint +0 -0
  23. {rclone_api-1.0.35 → rclone_api-1.0.36}/requirements.testing.txt +0 -0
  24. {rclone_api-1.0.35 → rclone_api-1.0.36}/setup.cfg +0 -0
  25. {rclone_api-1.0.35 → rclone_api-1.0.36}/setup.py +0 -0
  26. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/__init__.py +0 -0
  27. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/assets/example.txt +0 -0
  28. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/cli.py +0 -0
  29. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/cmd/list_files.py +0 -0
  30. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/config.py +0 -0
  31. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/convert.py +0 -0
  32. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/deprecated.py +0 -0
  33. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/diff.py +0 -0
  34. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/dir.py +0 -0
  35. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/dir_listing.py +0 -0
  36. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/exec.py +0 -0
  37. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/file.py +0 -0
  38. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/filelist.py +0 -0
  39. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/process.py +0 -0
  40. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/remote.py +0 -0
  41. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/rpath.py +0 -0
  42. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api/walk.py +0 -0
  43. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api.egg-info/SOURCES.txt +0 -0
  44. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api.egg-info/dependency_links.txt +0 -0
  45. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api.egg-info/entry_points.txt +0 -0
  46. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api.egg-info/requires.txt +0 -0
  47. {rclone_api-1.0.35 → rclone_api-1.0.36}/src/rclone_api.egg-info/top_level.txt +0 -0
  48. {rclone_api-1.0.35 → rclone_api-1.0.36}/test +0 -0
  49. {rclone_api-1.0.35 → rclone_api-1.0.36}/tests/test_cmd_list_files.py +0 -0
  50. {rclone_api-1.0.35 → rclone_api-1.0.36}/tests/test_diff.py +0 -0
  51. {rclone_api-1.0.35 → rclone_api-1.0.36}/tests/test_is_synced.py +0 -0
  52. {rclone_api-1.0.35 → rclone_api-1.0.36}/tests/test_ls.py +0 -0
  53. {rclone_api-1.0.35 → rclone_api-1.0.36}/tests/test_mount.py +0 -0
  54. {rclone_api-1.0.35 → rclone_api-1.0.36}/tests/test_mount_s3.py +0 -0
  55. {rclone_api-1.0.35 → rclone_api-1.0.36}/tests/test_mount_webdav.py +0 -0
  56. {rclone_api-1.0.35 → rclone_api-1.0.36}/tests/test_obscure.py +0 -0
  57. {rclone_api-1.0.35 → rclone_api-1.0.36}/tests/test_remotes.py +0 -0
  58. {rclone_api-1.0.35 → rclone_api-1.0.36}/tests/test_serve_webdav.py +0 -0
  59. {rclone_api-1.0.35 → rclone_api-1.0.36}/tests/test_walk.py +0 -0
  60. {rclone_api-1.0.35 → rclone_api-1.0.36}/tox.ini +0 -0
  61. {rclone_api-1.0.35 → rclone_api-1.0.36}/upload_package.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rclone_api
3
- Version: 1.0.35
3
+ Version: 1.0.36
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.35"
18
+ version = "1.0.36"
19
19
 
20
20
  [tool.setuptools]
21
21
  package-dir = {"" = "src"}
@@ -5,7 +5,6 @@ Unit test file.
5
5
  import subprocess
6
6
  import time
7
7
  import warnings
8
- from concurrent.futures import ThreadPoolExecutor
9
8
  from enum import Enum
10
9
  from fnmatch import fnmatch
11
10
  from pathlib import Path
@@ -23,7 +22,7 @@ from rclone_api.file import File
23
22
  from rclone_api.process import Process
24
23
  from rclone_api.remote import Remote
25
24
  from rclone_api.rpath import RPath
26
- from rclone_api.util import get_rclone_exe, to_path, wait_for_mount
25
+ from rclone_api.util import get_rclone_exe, partition_files, to_path, wait_for_mount
27
26
  from rclone_api.walk import walk
28
27
 
29
28
 
@@ -184,7 +183,7 @@ class Rclone:
184
183
  cmd_list: list[str] = ["copyto", src, dst]
185
184
  self._run(cmd_list)
186
185
 
187
- def copyfiles(self, filelist: dict[File, File] | dict[str, str]) -> None:
186
+ def copy_to(self, src: File | str, dst: File | str) -> None:
188
187
  """Copy multiple files from source to destination.
189
188
 
190
189
  Warning - slow.
@@ -192,17 +191,48 @@ class Rclone:
192
191
  Args:
193
192
  payload: Dictionary of source and destination file paths
194
193
  """
195
- str_dict: dict[str, str] = {}
196
- for src, dst in filelist.items():
197
- src = src if isinstance(src, str) else str(src.path)
198
- dst = dst if isinstance(dst, str) else str(dst.path)
199
- str_dict[src] = dst
200
-
201
- with ThreadPoolExecutor(max_workers=64) as executor:
202
- for src, dst in str_dict.items(): # warning - slow
203
- cmd_list: list[str] = ["copyto", src, dst]
204
- # self._run(cmd_list)
205
- executor.submit(self._run, cmd_list)
194
+ src = str(src)
195
+ dst = str(dst)
196
+ cmd_list: list[str] = ["copyto", src, dst]
197
+ self._run(cmd_list)
198
+
199
+ def copyfiles(self, files: str | File | list[str] | list[File]) -> None:
200
+ """Copy multiple files from source to destination.
201
+
202
+ Warning - slow.
203
+
204
+ Args:
205
+ payload: Dictionary of source and destination file paths
206
+ """
207
+ payload: list[str] = convert_to_filestr_list(files)
208
+ if len(payload) == 0:
209
+ return
210
+
211
+ datalists: dict[str, list[str]] = partition_files(payload)
212
+ out: subprocess.CompletedProcess | None = None
213
+
214
+ for remote, files in datalists.items():
215
+ with TemporaryDirectory() as tmpdir:
216
+ include_files_txt = Path(tmpdir) / "include_files.txt"
217
+ include_files_txt.write_text("\n".join(files), encoding="utf-8")
218
+
219
+ print(include_files_txt)
220
+ cmd_list: list[str] = [
221
+ "delete",
222
+ remote,
223
+ "--files-from",
224
+ str(include_files_txt),
225
+ "--checkers",
226
+ "1000",
227
+ "--transfers",
228
+ "1000",
229
+ ]
230
+ out = self._run(cmd_list)
231
+ if out.returncode != 0:
232
+ print(out)
233
+ raise ValueError(f"Error deleting files: {out.stderr}")
234
+
235
+ assert out is not None
206
236
 
207
237
  def copy(self, src: Dir | str, dst: Dir | str) -> subprocess.CompletedProcess:
208
238
  """Copy files from source to destination.
@@ -238,19 +268,7 @@ class Rclone:
238
268
  stderr="",
239
269
  )
240
270
 
241
- datalists: dict[str, list[str]] = {}
242
-
243
- for f in payload:
244
- remote, path = f.split(":", 1)
245
- if "/" in path:
246
- bucket, path = path.split("/", 1)
247
- remote = f"{remote}:{bucket}"
248
- else:
249
- remote = f"{remote}:"
250
- if remote not in datalists:
251
- datalists[remote] = []
252
- datalists[remote].append(path)
253
-
271
+ datalists: dict[str, list[str]] = partition_files(payload)
254
272
  out: subprocess.CompletedProcess | None = None
255
273
 
256
274
  for remote, files in datalists.items():
@@ -288,8 +306,9 @@ class Rclone:
288
306
  arg: str = convert_to_str(path)
289
307
  assert isinstance(arg, str)
290
308
  try:
291
- self.ls(arg)
292
- return True
309
+ dir_listing = self.ls(arg)
310
+ # print(dir_listing)
311
+ return len(dir_listing.dirs) > 0 or len(dir_listing.files) > 0
293
312
  except subprocess.CalledProcessError:
294
313
  return False
295
314
 
@@ -129,3 +129,18 @@ def wait_for_mount(path: Path, mount_process: Any, timeout: int = 60) -> None:
129
129
  if path.exists():
130
130
  return
131
131
  raise TimeoutError(f"Path {path} did not exist after {timeout} seconds")
132
+
133
+
134
+ def partition_files(files: list[str]) -> dict[str, list[str]]:
135
+ datalists: dict[str, list[str]] = {}
136
+ for f in files:
137
+ remote, path = f.split(":", 1)
138
+ if "/" in path:
139
+ bucket, path = path.split("/", 1)
140
+ remote = f"{remote}:{bucket}"
141
+ else:
142
+ remote = f"{remote}:"
143
+ if remote not in datalists:
144
+ datalists[remote] = []
145
+ datalists[remote].append(path)
146
+ return datalists
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rclone_api
3
- Version: 1.0.35
3
+ Version: 1.0.36
4
4
  Summary: rclone api in python
5
5
  Home-page: https://github.com/zackees/rclone-api
6
6
  Maintainer: Zachary Vorhies
@@ -83,22 +83,17 @@ class RcloneCopyTests(unittest.TestCase):
83
83
  first_file = str(listing.files[0])
84
84
  dest_file = first_file + "_copy"
85
85
 
86
- # Copy the files to the same location with different names
87
- filelist: dict[str, str] = {
88
- first_file: dest_file,
89
- }
90
- # warning slow.
91
- rclone.copyfiles(filelist)
92
-
93
- delete_list: list[str] = []
94
- for _, dst in filelist.items():
95
- delete_list.append(dst)
86
+ # Copy the file to the same location with different names
87
+ rclone.copy_to(first_file, dest_file)
96
88
 
97
89
  # now test that the new file exists
98
90
  exists = rclone.exists(dest_file)
99
91
  self.assertTrue(exists)
100
92
 
101
- rclone.delete_files(delete_list)
93
+ rclone.delete_files(dest_file)
94
+ print(f"Checking that {dest_file} was deleted")
95
+ deleted = rclone.exists(dest_file)
96
+ self.assertFalse(deleted)
102
97
  print("done")
103
98
 
104
99
 
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