rclone-api 1.0.34__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.34 → rclone_api-1.0.36}/PKG-INFO +2 -2
  2. {rclone_api-1.0.34 → rclone_api-1.0.36}/README.md +1 -1
  3. {rclone_api-1.0.34 → rclone_api-1.0.36}/pyproject.toml +1 -1
  4. rclone_api-1.0.36/src/rclone_api/deprecated.py +24 -0
  5. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/rclone.py +56 -30
  6. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/util.py +15 -0
  7. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api.egg-info/PKG-INFO +2 -2
  8. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api.egg-info/SOURCES.txt +1 -0
  9. {rclone_api-1.0.34 → rclone_api-1.0.36}/tests/test_copy.py +7 -12
  10. {rclone_api-1.0.34 → rclone_api-1.0.36}/.aiderignore +0 -0
  11. {rclone_api-1.0.34 → rclone_api-1.0.36}/.github/workflows/lint.yml +0 -0
  12. {rclone_api-1.0.34 → rclone_api-1.0.36}/.github/workflows/push_macos.yml +0 -0
  13. {rclone_api-1.0.34 → rclone_api-1.0.36}/.github/workflows/push_ubuntu.yml +0 -0
  14. {rclone_api-1.0.34 → rclone_api-1.0.36}/.github/workflows/push_win.yml +0 -0
  15. {rclone_api-1.0.34 → rclone_api-1.0.36}/.gitignore +0 -0
  16. {rclone_api-1.0.34 → rclone_api-1.0.36}/.pylintrc +0 -0
  17. {rclone_api-1.0.34 → rclone_api-1.0.36}/.vscode/launch.json +0 -0
  18. {rclone_api-1.0.34 → rclone_api-1.0.36}/.vscode/settings.json +0 -0
  19. {rclone_api-1.0.34 → rclone_api-1.0.36}/.vscode/tasks.json +0 -0
  20. {rclone_api-1.0.34 → rclone_api-1.0.36}/LICENSE +0 -0
  21. {rclone_api-1.0.34 → rclone_api-1.0.36}/MANIFEST.in +0 -0
  22. {rclone_api-1.0.34 → rclone_api-1.0.36}/clean +0 -0
  23. {rclone_api-1.0.34 → rclone_api-1.0.36}/install +0 -0
  24. {rclone_api-1.0.34 → rclone_api-1.0.36}/lint +0 -0
  25. {rclone_api-1.0.34 → rclone_api-1.0.36}/requirements.testing.txt +0 -0
  26. {rclone_api-1.0.34 → rclone_api-1.0.36}/setup.cfg +0 -0
  27. {rclone_api-1.0.34 → rclone_api-1.0.36}/setup.py +0 -0
  28. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/__init__.py +0 -0
  29. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/assets/example.txt +0 -0
  30. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/cli.py +0 -0
  31. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/cmd/list_files.py +0 -0
  32. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/config.py +0 -0
  33. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/convert.py +0 -0
  34. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/diff.py +0 -0
  35. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/dir.py +0 -0
  36. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/dir_listing.py +0 -0
  37. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/exec.py +0 -0
  38. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/file.py +0 -0
  39. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/filelist.py +0 -0
  40. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/process.py +0 -0
  41. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/remote.py +0 -0
  42. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/rpath.py +0 -0
  43. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api/walk.py +0 -0
  44. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api.egg-info/dependency_links.txt +0 -0
  45. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api.egg-info/entry_points.txt +0 -0
  46. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api.egg-info/requires.txt +0 -0
  47. {rclone_api-1.0.34 → rclone_api-1.0.36}/src/rclone_api.egg-info/top_level.txt +0 -0
  48. {rclone_api-1.0.34 → rclone_api-1.0.36}/test +0 -0
  49. {rclone_api-1.0.34 → rclone_api-1.0.36}/tests/test_cmd_list_files.py +0 -0
  50. {rclone_api-1.0.34 → rclone_api-1.0.36}/tests/test_diff.py +0 -0
  51. {rclone_api-1.0.34 → rclone_api-1.0.36}/tests/test_is_synced.py +0 -0
  52. {rclone_api-1.0.34 → rclone_api-1.0.36}/tests/test_ls.py +0 -0
  53. {rclone_api-1.0.34 → rclone_api-1.0.36}/tests/test_mount.py +0 -0
  54. {rclone_api-1.0.34 → rclone_api-1.0.36}/tests/test_mount_s3.py +0 -0
  55. {rclone_api-1.0.34 → rclone_api-1.0.36}/tests/test_mount_webdav.py +0 -0
  56. {rclone_api-1.0.34 → rclone_api-1.0.36}/tests/test_obscure.py +0 -0
  57. {rclone_api-1.0.34 → rclone_api-1.0.36}/tests/test_remotes.py +0 -0
  58. {rclone_api-1.0.34 → rclone_api-1.0.36}/tests/test_serve_webdav.py +0 -0
  59. {rclone_api-1.0.34 → rclone_api-1.0.36}/tests/test_walk.py +0 -0
  60. {rclone_api-1.0.34 → rclone_api-1.0.36}/tox.ini +0 -0
  61. {rclone_api-1.0.34 → 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.34
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
@@ -127,7 +127,7 @@ if listing.files:
127
127
  # Delete a File
128
128
  print("\n=== Deleting a File ===")
129
129
  file_to_delete = f"dst:{BUCKET_NAME}/zachs_video/sample.png_copy"
130
- rclone.deletefiles([file_to_delete])
130
+ rclone.delete_files([file_to_delete])
131
131
  print(f"Deleted {file_to_delete}")
132
132
 
133
133
  # Walk Through a Directory
@@ -110,7 +110,7 @@ if listing.files:
110
110
  # Delete a File
111
111
  print("\n=== Deleting a File ===")
112
112
  file_to_delete = f"dst:{BUCKET_NAME}/zachs_video/sample.png_copy"
113
- rclone.deletefiles([file_to_delete])
113
+ rclone.delete_files([file_to_delete])
114
114
  print(f"Deleted {file_to_delete}")
115
115
 
116
116
  # Walk Through a Directory
@@ -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.34"
18
+ version = "1.0.36"
19
19
 
20
20
  [tool.setuptools]
21
21
  package-dir = {"" = "src"}
@@ -0,0 +1,24 @@
1
+ import functools
2
+ import warnings
3
+
4
+
5
+ def deprecated(new_func_name: str):
6
+ """Decorator to mark functions as deprecated.
7
+
8
+ Args:
9
+ new_func_name: The name of the function that should be used instead.
10
+ """
11
+
12
+ def decorator(func):
13
+ @functools.wraps(func)
14
+ def wrapper(*args, **kwargs):
15
+ warnings.warn(
16
+ f"{func.__name__}() is deprecated; use {new_func_name}() instead.",
17
+ DeprecationWarning,
18
+ stacklevel=2,
19
+ )
20
+ return func(*args, **kwargs)
21
+
22
+ return wrapper
23
+
24
+ return decorator
@@ -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
@@ -15,6 +14,7 @@ from typing import Generator
15
14
  from rclone_api import Dir
16
15
  from rclone_api.config import Config
17
16
  from rclone_api.convert import convert_to_filestr_list, convert_to_str
17
+ from rclone_api.deprecated import deprecated
18
18
  from rclone_api.diff import DiffItem, diff_stream_from_running_process
19
19
  from rclone_api.dir_listing import DirListing
20
20
  from rclone_api.exec import RcloneExec
@@ -22,7 +22,7 @@ from rclone_api.file import File
22
22
  from rclone_api.process import Process
23
23
  from rclone_api.remote import Remote
24
24
  from rclone_api.rpath import RPath
25
- 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
26
26
  from rclone_api.walk import walk
27
27
 
28
28
 
@@ -183,7 +183,7 @@ class Rclone:
183
183
  cmd_list: list[str] = ["copyto", src, dst]
184
184
  self._run(cmd_list)
185
185
 
186
- def copyfiles(self, filelist: dict[File, File] | dict[str, str]) -> None:
186
+ def copy_to(self, src: File | str, dst: File | str) -> None:
187
187
  """Copy multiple files from source to destination.
188
188
 
189
189
  Warning - slow.
@@ -191,17 +191,48 @@ class Rclone:
191
191
  Args:
192
192
  payload: Dictionary of source and destination file paths
193
193
  """
194
- str_dict: dict[str, str] = {}
195
- for src, dst in filelist.items():
196
- src = src if isinstance(src, str) else str(src.path)
197
- dst = dst if isinstance(dst, str) else str(dst.path)
198
- str_dict[src] = dst
199
-
200
- with ThreadPoolExecutor(max_workers=64) as executor:
201
- for src, dst in str_dict.items(): # warning - slow
202
- cmd_list: list[str] = ["copyto", src, dst]
203
- # self._run(cmd_list)
204
- 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
205
236
 
206
237
  def copy(self, src: Dir | str, dst: Dir | str) -> subprocess.CompletedProcess:
207
238
  """Copy files from source to destination.
@@ -224,7 +255,7 @@ class Rclone:
224
255
  cmd_list: list[str] = ["purge", str(path)]
225
256
  return self._run(cmd_list)
226
257
 
227
- def deletefiles(
258
+ def delete_files(
228
259
  self, files: str | File | list[str] | list[File]
229
260
  ) -> subprocess.CompletedProcess:
230
261
  """Delete a directory"""
@@ -237,19 +268,7 @@ class Rclone:
237
268
  stderr="",
238
269
  )
239
270
 
240
- datalists: dict[str, list[str]] = {}
241
-
242
- for f in payload:
243
- remote, path = f.split(":", 1)
244
- if "/" in path:
245
- bucket, path = path.split("/", 1)
246
- remote = f"{remote}:{bucket}"
247
- else:
248
- remote = f"{remote}:"
249
- if remote not in datalists:
250
- datalists[remote] = []
251
- datalists[remote].append(path)
252
-
271
+ datalists: dict[str, list[str]] = partition_files(payload)
253
272
  out: subprocess.CompletedProcess | None = None
254
273
 
255
274
  for remote, files in datalists.items():
@@ -276,13 +295,20 @@ class Rclone:
276
295
  assert out is not None
277
296
  return out
278
297
 
298
+ @deprecated("delete_files")
299
+ def deletefiles(
300
+ self, files: str | File | list[str] | list[File]
301
+ ) -> subprocess.CompletedProcess:
302
+ return self.delete_files(files)
303
+
279
304
  def exists(self, path: Dir | Remote | str | File) -> bool:
280
305
  """Check if a file or directory exists."""
281
306
  arg: str = convert_to_str(path)
282
307
  assert isinstance(arg, str)
283
308
  try:
284
- self.ls(arg)
285
- 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
286
312
  except subprocess.CalledProcessError:
287
313
  return False
288
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.34
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
@@ -127,7 +127,7 @@ if listing.files:
127
127
  # Delete a File
128
128
  print("\n=== Deleting a File ===")
129
129
  file_to_delete = f"dst:{BUCKET_NAME}/zachs_video/sample.png_copy"
130
- rclone.deletefiles([file_to_delete])
130
+ rclone.delete_files([file_to_delete])
131
131
  print(f"Deleted {file_to_delete}")
132
132
 
133
133
  # Walk Through a Directory
@@ -24,6 +24,7 @@ src/rclone_api/__init__.py
24
24
  src/rclone_api/cli.py
25
25
  src/rclone_api/config.py
26
26
  src/rclone_api/convert.py
27
+ src/rclone_api/deprecated.py
27
28
  src/rclone_api/diff.py
28
29
  src/rclone_api/dir.py
29
30
  src/rclone_api/dir_listing.py
@@ -71,7 +71,7 @@ class RcloneCopyTests(unittest.TestCase):
71
71
  listing = rclone.ls(f"dst:{BUCKET_NAME}/zachs_video/", glob=f"*{new_name}")
72
72
  self.assertEqual(len(listing.files), 1)
73
73
  self.assertEqual(listing.dirs, [])
74
- rclone.deletefiles([new_path])
74
+ rclone.delete_files([new_path])
75
75
  print("done")
76
76
 
77
77
  def test_copyfiles(self) -> None:
@@ -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.deletefiles(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