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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. {rclone_api-1.0.35 → rclone_api-1.0.37}/PKG-INFO +1 -1
  2. {rclone_api-1.0.35 → rclone_api-1.0.37}/pyproject.toml +1 -1
  3. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/diff.py +0 -1
  4. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/rclone.py +58 -33
  5. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/util.py +15 -0
  6. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api.egg-info/PKG-INFO +1 -1
  7. {rclone_api-1.0.35 → rclone_api-1.0.37}/tests/test_copy.py +6 -11
  8. {rclone_api-1.0.35 → rclone_api-1.0.37}/.aiderignore +0 -0
  9. {rclone_api-1.0.35 → rclone_api-1.0.37}/.github/workflows/lint.yml +0 -0
  10. {rclone_api-1.0.35 → rclone_api-1.0.37}/.github/workflows/push_macos.yml +0 -0
  11. {rclone_api-1.0.35 → rclone_api-1.0.37}/.github/workflows/push_ubuntu.yml +0 -0
  12. {rclone_api-1.0.35 → rclone_api-1.0.37}/.github/workflows/push_win.yml +0 -0
  13. {rclone_api-1.0.35 → rclone_api-1.0.37}/.gitignore +0 -0
  14. {rclone_api-1.0.35 → rclone_api-1.0.37}/.pylintrc +0 -0
  15. {rclone_api-1.0.35 → rclone_api-1.0.37}/.vscode/launch.json +0 -0
  16. {rclone_api-1.0.35 → rclone_api-1.0.37}/.vscode/settings.json +0 -0
  17. {rclone_api-1.0.35 → rclone_api-1.0.37}/.vscode/tasks.json +0 -0
  18. {rclone_api-1.0.35 → rclone_api-1.0.37}/LICENSE +0 -0
  19. {rclone_api-1.0.35 → rclone_api-1.0.37}/MANIFEST.in +0 -0
  20. {rclone_api-1.0.35 → rclone_api-1.0.37}/README.md +0 -0
  21. {rclone_api-1.0.35 → rclone_api-1.0.37}/clean +0 -0
  22. {rclone_api-1.0.35 → rclone_api-1.0.37}/install +0 -0
  23. {rclone_api-1.0.35 → rclone_api-1.0.37}/lint +0 -0
  24. {rclone_api-1.0.35 → rclone_api-1.0.37}/requirements.testing.txt +0 -0
  25. {rclone_api-1.0.35 → rclone_api-1.0.37}/setup.cfg +0 -0
  26. {rclone_api-1.0.35 → rclone_api-1.0.37}/setup.py +0 -0
  27. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/__init__.py +0 -0
  28. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/assets/example.txt +0 -0
  29. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/cli.py +0 -0
  30. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/cmd/list_files.py +0 -0
  31. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/config.py +0 -0
  32. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/convert.py +0 -0
  33. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/deprecated.py +0 -0
  34. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/dir.py +0 -0
  35. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/dir_listing.py +0 -0
  36. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/exec.py +0 -0
  37. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/file.py +0 -0
  38. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/filelist.py +0 -0
  39. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/process.py +0 -0
  40. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/remote.py +0 -0
  41. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/rpath.py +0 -0
  42. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api/walk.py +0 -0
  43. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api.egg-info/SOURCES.txt +0 -0
  44. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api.egg-info/dependency_links.txt +0 -0
  45. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api.egg-info/entry_points.txt +0 -0
  46. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api.egg-info/requires.txt +0 -0
  47. {rclone_api-1.0.35 → rclone_api-1.0.37}/src/rclone_api.egg-info/top_level.txt +0 -0
  48. {rclone_api-1.0.35 → rclone_api-1.0.37}/test +0 -0
  49. {rclone_api-1.0.35 → rclone_api-1.0.37}/tests/test_cmd_list_files.py +0 -0
  50. {rclone_api-1.0.35 → rclone_api-1.0.37}/tests/test_diff.py +0 -0
  51. {rclone_api-1.0.35 → rclone_api-1.0.37}/tests/test_is_synced.py +0 -0
  52. {rclone_api-1.0.35 → rclone_api-1.0.37}/tests/test_ls.py +0 -0
  53. {rclone_api-1.0.35 → rclone_api-1.0.37}/tests/test_mount.py +0 -0
  54. {rclone_api-1.0.35 → rclone_api-1.0.37}/tests/test_mount_s3.py +0 -0
  55. {rclone_api-1.0.35 → rclone_api-1.0.37}/tests/test_mount_webdav.py +0 -0
  56. {rclone_api-1.0.35 → rclone_api-1.0.37}/tests/test_obscure.py +0 -0
  57. {rclone_api-1.0.35 → rclone_api-1.0.37}/tests/test_remotes.py +0 -0
  58. {rclone_api-1.0.35 → rclone_api-1.0.37}/tests/test_serve_webdav.py +0 -0
  59. {rclone_api-1.0.35 → rclone_api-1.0.37}/tests/test_walk.py +0 -0
  60. {rclone_api-1.0.35 → rclone_api-1.0.37}/tox.ini +0 -0
  61. {rclone_api-1.0.35 → rclone_api-1.0.37}/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.37
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.37"
19
19
 
20
20
  [tool.setuptools]
21
21
  package-dir = {"" = "src"}
@@ -94,7 +94,6 @@ def _async_diff_stream_from_running_process(
94
94
  print("UnicodeDecodeError")
95
95
  continue
96
96
  output.put(None)
97
- print("done")
98
97
  except KeyboardInterrupt:
99
98
  import _thread
100
99
 
@@ -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.
@@ -226,7 +256,7 @@ class Rclone:
226
256
  return self._run(cmd_list)
227
257
 
228
258
  def delete_files(
229
- self, files: str | File | list[str] | list[File]
259
+ self, files: str | File | list[str] | list[File], check=True
230
260
  ) -> subprocess.CompletedProcess:
231
261
  """Delete a directory"""
232
262
  payload: list[str] = convert_to_filestr_list(files)
@@ -238,27 +268,17 @@ 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
 
274
+ completed_processes: list[subprocess.CompletedProcess] = []
275
+
256
276
  for remote, files in datalists.items():
257
277
  with TemporaryDirectory() as tmpdir:
258
278
  include_files_txt = Path(tmpdir) / "include_files.txt"
259
279
  include_files_txt.write_text("\n".join(files), encoding="utf-8")
260
280
 
261
- print(include_files_txt)
281
+ # print(include_files_txt)
262
282
  cmd_list: list[str] = [
263
283
  "delete",
264
284
  remote,
@@ -270,9 +290,13 @@ class Rclone:
270
290
  "1000",
271
291
  ]
272
292
  out = self._run(cmd_list)
293
+ completed_processes.append(out)
273
294
  if out.returncode != 0:
274
- print(out)
275
- raise ValueError(f"Error deleting files: {out.stderr}")
295
+ if check:
296
+ completed_processes.append(out)
297
+ raise ValueError(f"Error deleting files: {out}")
298
+ else:
299
+ warnings.warn(f"Error deleting files: {out}")
276
300
 
277
301
  assert out is not None
278
302
  return out
@@ -288,8 +312,9 @@ class Rclone:
288
312
  arg: str = convert_to_str(path)
289
313
  assert isinstance(arg, str)
290
314
  try:
291
- self.ls(arg)
292
- return True
315
+ dir_listing = self.ls(arg)
316
+ # print(dir_listing)
317
+ return len(dir_listing.dirs) > 0 or len(dir_listing.files) > 0
293
318
  except subprocess.CalledProcessError:
294
319
  return False
295
320
 
@@ -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.37
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