rclone-api 1.1.83__tar.gz → 1.1.85__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. {rclone_api-1.1.83 → rclone_api-1.1.85}/PKG-INFO +1 -1
  2. {rclone_api-1.1.83 → rclone_api-1.1.85}/pyproject.toml +1 -1
  3. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/cmd/copy_large_s3.py +2 -2
  4. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/mount.py +19 -12
  5. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/profile/mount_copy_bytes.py +21 -4
  6. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/rclone.py +2 -1
  7. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/types.py +8 -9
  8. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api.egg-info/PKG-INFO +1 -1
  9. {rclone_api-1.1.83 → rclone_api-1.1.85}/.aiderignore +0 -0
  10. {rclone_api-1.1.83 → rclone_api-1.1.85}/.github/workflows/lint.yml +0 -0
  11. {rclone_api-1.1.83 → rclone_api-1.1.85}/.github/workflows/push_macos.yml +0 -0
  12. {rclone_api-1.1.83 → rclone_api-1.1.85}/.github/workflows/push_ubuntu.yml +0 -0
  13. {rclone_api-1.1.83 → rclone_api-1.1.85}/.github/workflows/push_win.yml +0 -0
  14. {rclone_api-1.1.83 → rclone_api-1.1.85}/.gitignore +0 -0
  15. {rclone_api-1.1.83 → rclone_api-1.1.85}/.pylintrc +0 -0
  16. {rclone_api-1.1.83 → rclone_api-1.1.85}/.vscode/launch.json +0 -0
  17. {rclone_api-1.1.83 → rclone_api-1.1.85}/.vscode/settings.json +0 -0
  18. {rclone_api-1.1.83 → rclone_api-1.1.85}/.vscode/tasks.json +0 -0
  19. {rclone_api-1.1.83 → rclone_api-1.1.85}/LICENSE +0 -0
  20. {rclone_api-1.1.83 → rclone_api-1.1.85}/MANIFEST.in +0 -0
  21. {rclone_api-1.1.83 → rclone_api-1.1.85}/README.md +0 -0
  22. {rclone_api-1.1.83 → rclone_api-1.1.85}/clean +0 -0
  23. {rclone_api-1.1.83 → rclone_api-1.1.85}/install +0 -0
  24. {rclone_api-1.1.83 → rclone_api-1.1.85}/lint +0 -0
  25. {rclone_api-1.1.83 → rclone_api-1.1.85}/requirements.testing.txt +0 -0
  26. {rclone_api-1.1.83 → rclone_api-1.1.85}/setup.cfg +0 -0
  27. {rclone_api-1.1.83 → rclone_api-1.1.85}/setup.py +0 -0
  28. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/__init__.py +0 -0
  29. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/assets/example.txt +0 -0
  30. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/cli.py +0 -0
  31. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/cmd/list_files.py +0 -0
  32. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/completed_process.py +0 -0
  33. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/config.py +0 -0
  34. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/convert.py +0 -0
  35. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/deprecated.py +0 -0
  36. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/diff.py +0 -0
  37. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/dir.py +0 -0
  38. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/dir_listing.py +0 -0
  39. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/exec.py +0 -0
  40. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/experimental/flags.py +0 -0
  41. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/experimental/flags_base.py +0 -0
  42. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/file.py +0 -0
  43. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/filelist.py +0 -0
  44. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/group_files.py +0 -0
  45. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/process.py +0 -0
  46. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/remote.py +0 -0
  47. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/rpath.py +0 -0
  48. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/s3/api.py +0 -0
  49. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/s3/basic_ops.py +0 -0
  50. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/s3/chunk_file.py +0 -0
  51. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/s3/chunk_types.py +0 -0
  52. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/s3/create.py +0 -0
  53. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/s3/types.py +0 -0
  54. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/s3/upload_file_multipart.py +0 -0
  55. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/scan_missing_folders.py +0 -0
  56. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/util.py +0 -0
  57. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api/walk.py +0 -0
  58. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api.egg-info/SOURCES.txt +0 -0
  59. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api.egg-info/dependency_links.txt +0 -0
  60. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api.egg-info/entry_points.txt +0 -0
  61. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api.egg-info/requires.txt +0 -0
  62. {rclone_api-1.1.83 → rclone_api-1.1.85}/src/rclone_api.egg-info/top_level.txt +0 -0
  63. {rclone_api-1.1.83 → rclone_api-1.1.85}/test +0 -0
  64. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/archive/test_paramiko.py.disabled +0 -0
  65. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_cmd_list_files.py +0 -0
  66. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_copy.py +0 -0
  67. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_copy_bytes.py +0 -0
  68. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_copy_file_resumable_s3.py +0 -0
  69. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_copy_files.py +0 -0
  70. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_diff.py +0 -0
  71. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_group_files.py +0 -0
  72. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_is_synced.py +0 -0
  73. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_ls.py +0 -0
  74. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_mount.py +0 -0
  75. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_mount_s3.py +0 -0
  76. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_obscure.py +0 -0
  77. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_rclone_config.py +0 -0
  78. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_remote_control.py +0 -0
  79. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_remotes.py +0 -0
  80. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_s3.py +0 -0
  81. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_scan_missing_folders.py +0 -0
  82. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_size_files.py +0 -0
  83. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_size_suffix.py +0 -0
  84. {rclone_api-1.1.83 → rclone_api-1.1.85}/tests/test_walk.py +0 -0
  85. {rclone_api-1.1.83 → rclone_api-1.1.85}/tox.ini +0 -0
  86. {rclone_api-1.1.83 → rclone_api-1.1.85}/upload_package.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rclone_api
3
- Version: 1.1.83
3
+ Version: 1.1.85
4
4
  Summary: rclone api in python
5
5
  Home-page: https://github.com/zackees/rclone-api
6
6
  License: BSD 3-Clause License
@@ -23,7 +23,7 @@ dependencies = [
23
23
  ]
24
24
 
25
25
  # Change this with the version number bump.
26
- version = "1.1.83"
26
+ version = "1.1.85"
27
27
 
28
28
  [tool.setuptools]
29
29
  package-dir = {"" = "src"}
@@ -45,13 +45,13 @@ def _parse_args() -> Args:
45
45
  "--read-threads",
46
46
  help="Number of concurrent read threads per chunk, only one chunk will be read at a time",
47
47
  type=int,
48
- default=32,
48
+ default=1,
49
49
  )
50
50
  parser.add_argument(
51
51
  "--write-threads",
52
52
  help="Max number of chunks to upload in parallel to the destination, each chunk is uploaded in a separate thread",
53
53
  type=int,
54
- default=64,
54
+ default=4,
55
55
  )
56
56
  parser.add_argument("--retries", help="Number of retries", type=int, default=3)
57
57
  parser.add_argument(
@@ -313,7 +313,7 @@ class MultiMountFileChunker:
313
313
  for mount in self.mounts_processing:
314
314
  executor.submit(lambda: mount.close())
315
315
 
316
- def fetch(self, offset: int, size: int) -> bytes | Exception:
316
+ def fetch(self, offset: int, size: int) -> Future[bytes | Exception]:
317
317
  if self.verbose:
318
318
  print(f"Fetching data range: offset={offset}, size={size}")
319
319
  try:
@@ -325,7 +325,10 @@ class MultiMountFileChunker:
325
325
  assert offset >= 0, f"Invalid offset: {offset}"
326
326
  except AssertionError as e:
327
327
  warnings.warn(f"Invalid chunk request: {e}")
328
- return ValueError(e)
328
+ # return ValueError(e)
329
+ # return self.executor.submit(lambda: Exception(e))
330
+ err = Exception(e)
331
+ return self.executor.submit(lambda: err)
329
332
 
330
333
  chunks: list[tuple[int, int]] = []
331
334
  start = offset
@@ -375,15 +378,19 @@ class MultiMountFileChunker:
375
378
  fut = self.executor.submit(task)
376
379
  futures.append(fut)
377
380
 
378
- out: bytes = b""
379
- for fut in futures:
380
- chunk: bytes | Exception = fut.result()
381
- if isinstance(chunk, Exception):
382
- return chunk
383
- else:
384
- out += chunk
385
- del chunk
386
- return out
381
+ def combine(futs: list[Future[bytes | Exception]]) -> bytes | Exception:
382
+ finished_list: list[bytes | Exception] = [f.result() for f in futs]
383
+ bytes_list = [f for f in finished_list if isinstance(f, bytes)]
384
+ if len(bytes_list) != len(finished_list):
385
+ exceptions = [f for f in finished_list if isinstance(f, Exception)]
386
+ return Exception(f"Error fetching file chunk: {exceptions}")
387
+ return b"".join(bytes_list)
388
+
389
+ if len(futures) == 1:
390
+ return futures[0]
391
+ fut = self.executor.submit(combine, futures)
392
+ return fut
387
393
  except Exception as e:
388
394
  warnings.warn(f"Error fetching file chunk: {e}")
389
- return e
395
+ err = Exception(e)
396
+ return self.executor.submit(lambda: err)
@@ -6,6 +6,7 @@ import argparse
6
6
  import os
7
7
  import shutil
8
8
  import time
9
+ from concurrent.futures import Future
9
10
  from dataclasses import dataclass
10
11
  from pathlib import Path
11
12
 
@@ -117,7 +118,7 @@ def _run_profile(
117
118
  print("#" * 80)
118
119
  print(f"# Started test download of {SizeSuffix(size)} with {transfers} transfers")
119
120
  print("#" * 80)
120
- net_io_start = psutil.net_io_counters()
121
+
121
122
  chunk_size = size // transfers
122
123
 
123
124
  filechunker: MultiMountFileChunker = rclone.get_multi_mount_file_chunker(
@@ -128,9 +129,10 @@ def _run_profile(
128
129
  mount_log=mount_log,
129
130
  )
130
131
 
131
- bytes_or_err = filechunker.fetch(offset.as_int(), size.as_int())
132
-
132
+ bytes_or_err = filechunker.fetch(offset.as_int(), size.as_int()).result()
133
+
133
134
  start = time.time()
135
+ net_io_start = psutil.net_io_counters()
134
136
 
135
137
  # bytes_or_err: bytes | Exception = rclone.copy_bytes(
136
138
  # src=src_file,
@@ -142,7 +144,22 @@ def _run_profile(
142
144
  # mount_log=mount_log,
143
145
  # )
144
146
 
145
- bytes_or_err = filechunker.fetch((offset + SizeSuffix("1G")).as_int(), size.as_int())
147
+ # bytes_or_err = filechunker.fetch(
148
+ # (offset + SizeSuffix("1G")).as_int(), size.as_int()
149
+ # )
150
+
151
+ offset = SizeSuffix("1G")
152
+
153
+ futures: list[Future[bytes | Exception]] = []
154
+ for i in range(num):
155
+ offset = SizeSuffix(i * chunk_size.as_int()) + offset
156
+ future = filechunker.fetch(offset.as_int(), size.as_int())
157
+ futures.append(future)
158
+
159
+ for future in futures:
160
+ bytes_or_err = future.result()
161
+ if isinstance(bytes_or_err, Exception):
162
+ assert False, f"Error: {bytes_or_err}"
146
163
 
147
164
  diff = time.time() - start
148
165
  net_io_end = psutil.net_io_counters()
@@ -993,7 +993,8 @@ class Rclone:
993
993
  direct_io=direct_io,
994
994
  )
995
995
  try:
996
- data = filechunker.fetch(offset, length)
996
+ fut = filechunker.fetch(offset, length)
997
+ data = fut.result()
997
998
  if isinstance(data, Exception):
998
999
  warnings.warn(f"Error copying bytes: {data}")
999
1000
  raise data
@@ -178,40 +178,39 @@ class SizeSuffix:
178
178
  raise ZeroDivisionError("Division by zero is undefined")
179
179
  # Use floor division to maintain integer arithmetic.
180
180
  return SizeSuffix(self._size // other_int._size)
181
-
181
+
182
182
  def __eq__(self, other: object) -> bool:
183
183
  if not isinstance(other, SizeSuffix):
184
184
  return False
185
185
  return self._size == other._size
186
-
186
+
187
187
  def __ne__(self, other: object) -> bool:
188
188
  if not isinstance(other, SizeSuffix):
189
189
  return True
190
190
  return self._size != other._size
191
-
191
+
192
192
  def __lt__(self, other: object) -> bool:
193
193
  if not isinstance(other, SizeSuffix):
194
194
  return False
195
195
  return self._size < other._size
196
-
196
+
197
197
  def __le__(self, other: object) -> bool:
198
198
  if not isinstance(other, SizeSuffix):
199
199
  return False
200
200
  return self._size <= other._size
201
-
201
+
202
202
  def __gt__(self, other: object) -> bool:
203
203
  if not isinstance(other, SizeSuffix):
204
204
  return False
205
205
  return self._size > other._size
206
-
206
+
207
207
  def __ge__(self, other: object) -> bool:
208
208
  if not isinstance(other, SizeSuffix):
209
209
  return False
210
210
  return self._size >= other._size
211
-
211
+
212
212
  def __hash__(self) -> int:
213
213
  return hash(self._size)
214
-
214
+
215
215
  def __int__(self) -> int:
216
216
  return self._size
217
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rclone_api
3
- Version: 1.1.83
3
+ Version: 1.1.85
4
4
  Summary: rclone api in python
5
5
  Home-page: https://github.com/zackees/rclone-api
6
6
  License: BSD 3-Clause License
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