rclone-api 1.0.34__py2.py3-none-any.whl → 1.0.36__py2.py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
rclone_api/rclone.py CHANGED
@@ -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
 
rclone_api/util.py CHANGED
@@ -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
@@ -2,6 +2,7 @@ rclone_api/__init__.py,sha256=L_ulzYG9WmQqmrVANt-Omi1FJUQVTkXA7SVZx9QH_9M,457
2
2
  rclone_api/cli.py,sha256=dibfAZIh0kXWsBbfp3onKLjyZXo54mTzDjUdzJlDlWo,231
3
3
  rclone_api/config.py,sha256=tP6cU9DnCCEIRc_KP9HPur1jFLLg2QGFSxNwFm6_MVw,118
4
4
  rclone_api/convert.py,sha256=Mx9Qo7zhkOedJd8LdhPvNGHp8znJzOk4f_2KWnoGc78,1012
5
+ rclone_api/deprecated.py,sha256=qWKpnZdYcBK7YQZKuVoWWXDwi-uqiAtbjgPcci_efow,590
5
6
  rclone_api/diff.py,sha256=UqAiWJjAeTTy2ewH6idYKt92Y_JltGAWvrZuE9RNKX8,4159
6
7
  rclone_api/dir.py,sha256=vV-bcI2ESijmwF5rPID5WO2K7soAfZa35wv4KRh_GIo,2154
7
8
  rclone_api/dir_listing.py,sha256=9Qqf2SUswrOEkyqmaH23V51I18X6ePiXb9B1vUwRF5o,1571
@@ -9,16 +10,16 @@ rclone_api/exec.py,sha256=HWmnU2Jwb-3EttSbAJSaLloYA7YI2mHTzRJ5VEri9aM,941
9
10
  rclone_api/file.py,sha256=D02iHJW1LhfOiM_R_yPHP8_ApnDiYrkuraVcrV8-qkw,1246
10
11
  rclone_api/filelist.py,sha256=xbiusvNgaB_b_kQOZoHMJJxn6TWGtPrWd2J042BI28o,767
11
12
  rclone_api/process.py,sha256=RrMfTe0bndmJ6gBK67ioqNvCstJ8aTC8RlGX1XBLlcw,4191
12
- rclone_api/rclone.py,sha256=jthwnD974eaSBwrgXlQJu_cJpvohxce80BITKhfMYWI,18145
13
+ rclone_api/rclone.py,sha256=XWk3aIyEqIQHv7Oq7z8W2wt7kxiypO6KHCVA_lnXV7Y,19038
13
14
  rclone_api/remote.py,sha256=c9hlRKBCg1BFB9MCINaQIoCg10qyAkeqiS4brl8ce-8,343
14
15
  rclone_api/rpath.py,sha256=8ZA_1wxWtskwcy0I8V2VbjKDmzPkiWd8Q2JQSvh-sYE,2586
15
- rclone_api/util.py,sha256=sUjH5NmsawmNbPMY7V6hD8vFJXCwbl44XM1kuij3tA0,3918
16
+ rclone_api/util.py,sha256=N1n2Fxt-pU_xKwQdwXM3zAThBHG0zwDQY30s0iQao-0,4374
16
17
  rclone_api/walk.py,sha256=kca0t1GAnF6FLclN01G8NG__Qe-ggodLtAbQSHyVPng,2968
17
18
  rclone_api/assets/example.txt,sha256=lTBovRjiz0_TgtAtbA1C5hNi2ffbqnNPqkKg6UiKCT8,54
18
19
  rclone_api/cmd/list_files.py,sha256=x8FHODEilwKqwdiU1jdkeJbLwOqUkUQuDWPo2u_zpf0,741
19
- rclone_api-1.0.34.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
20
- rclone_api-1.0.34.dist-info/METADATA,sha256=mPuGlvje_1-t2WhXPpcRmcEnildFVqil-F8QgAtsZyE,4488
21
- rclone_api-1.0.34.dist-info/WHEEL,sha256=9Hm2OB-j1QcCUq9Jguht7ayGIIZBRTdOXD1qg9cCgPM,109
22
- rclone_api-1.0.34.dist-info/entry_points.txt,sha256=XUoTX3m7CWxdj2VAKhEuO0NMOfX2qf-OcEDFwdyk9ZE,72
23
- rclone_api-1.0.34.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
24
- rclone_api-1.0.34.dist-info/RECORD,,
20
+ rclone_api-1.0.36.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
21
+ rclone_api-1.0.36.dist-info/METADATA,sha256=dRfp6LOgaS5s_QIrSN_JoD2V8CLHDMWH9QApRvsCJjc,4489
22
+ rclone_api-1.0.36.dist-info/WHEEL,sha256=9Hm2OB-j1QcCUq9Jguht7ayGIIZBRTdOXD1qg9cCgPM,109
23
+ rclone_api-1.0.36.dist-info/entry_points.txt,sha256=XUoTX3m7CWxdj2VAKhEuO0NMOfX2qf-OcEDFwdyk9ZE,72
24
+ rclone_api-1.0.36.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
25
+ rclone_api-1.0.36.dist-info/RECORD,,