rclone-api 1.1.59__py2.py3-none-any.whl → 1.1.61__py2.py3-none-any.whl
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.
- rclone_api/profile/mount_copy_bytes.py +23 -14
- rclone_api/rclone.py +60 -2
- rclone_api/types.py +8 -0
- {rclone_api-1.1.59.dist-info → rclone_api-1.1.61.dist-info}/METADATA +1 -1
- {rclone_api-1.1.59.dist-info → rclone_api-1.1.61.dist-info}/RECORD +9 -9
- {rclone_api-1.1.59.dist-info → rclone_api-1.1.61.dist-info}/LICENSE +0 -0
- {rclone_api-1.1.59.dist-info → rclone_api-1.1.61.dist-info}/WHEEL +0 -0
- {rclone_api-1.1.59.dist-info → rclone_api-1.1.61.dist-info}/entry_points.txt +0 -0
- {rclone_api-1.1.59.dist-info → rclone_api-1.1.61.dist-info}/top_level.txt +0 -0
|
@@ -6,7 +6,6 @@ import argparse
|
|
|
6
6
|
import os
|
|
7
7
|
import shutil
|
|
8
8
|
import time
|
|
9
|
-
from concurrent.futures import Future, ThreadPoolExecutor
|
|
10
9
|
from dataclasses import dataclass
|
|
11
10
|
from pathlib import Path
|
|
12
11
|
|
|
@@ -108,7 +107,8 @@ def _run_profile(
|
|
|
108
107
|
offset: SizeSuffix,
|
|
109
108
|
size: SizeSuffix,
|
|
110
109
|
log_dir: Path,
|
|
111
|
-
|
|
110
|
+
num: int,
|
|
111
|
+
direct_io: bool,
|
|
112
112
|
) -> None:
|
|
113
113
|
|
|
114
114
|
mount_log = log_dir / f"mount_{SizeSuffix(size)}_threads_{transfers}.log"
|
|
@@ -118,12 +118,14 @@ def _run_profile(
|
|
|
118
118
|
print("#" * 80)
|
|
119
119
|
net_io_start = psutil.net_io_counters()
|
|
120
120
|
start = time.time()
|
|
121
|
+
chunk_size = size // transfers
|
|
121
122
|
bytes_or_err: bytes | Exception = rclone.copy_bytes(
|
|
122
123
|
src=src_file,
|
|
123
124
|
offset=offset.as_int(),
|
|
124
125
|
length=size.as_int(),
|
|
126
|
+
chunk_size=chunk_size,
|
|
125
127
|
direct_io=direct_io,
|
|
126
|
-
|
|
128
|
+
max_threads=transfers,
|
|
127
129
|
mount_log=mount_log,
|
|
128
130
|
)
|
|
129
131
|
diff = time.time() - start
|
|
@@ -137,9 +139,11 @@ def _run_profile(
|
|
|
137
139
|
assert len(bytes_or_err) == size.as_int(), f"Length: {len(bytes_or_err)} != {size}"
|
|
138
140
|
|
|
139
141
|
# print io stats
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
142
|
+
# disabling num for now
|
|
143
|
+
num = 1
|
|
144
|
+
bytes_sent = (net_io_end.bytes_sent - net_io_start.bytes_sent) // num
|
|
145
|
+
bytes_recv = (net_io_end.bytes_recv - net_io_start.bytes_recv) // num
|
|
146
|
+
packets_sent = (net_io_end.packets_sent - net_io_start.packets_sent) // num
|
|
143
147
|
efficiency = size.as_int() / (bytes_recv)
|
|
144
148
|
efficiency_100 = efficiency * 100
|
|
145
149
|
efficiency_str = f"{efficiency_100:.2f}"
|
|
@@ -164,6 +168,7 @@ def test_profile_copy_bytes(
|
|
|
164
168
|
transfer_list: list[int] | None,
|
|
165
169
|
mount_root_path: Path,
|
|
166
170
|
size: SizeSuffix | None,
|
|
171
|
+
num: int,
|
|
167
172
|
) -> None:
|
|
168
173
|
|
|
169
174
|
if size:
|
|
@@ -197,6 +202,7 @@ def test_profile_copy_bytes(
|
|
|
197
202
|
size=SizeSuffix(sz),
|
|
198
203
|
direct_io=args.direct_io,
|
|
199
204
|
log_dir=mount_root_path,
|
|
205
|
+
num=num,
|
|
200
206
|
)
|
|
201
207
|
print("done")
|
|
202
208
|
|
|
@@ -227,8 +233,8 @@ def main() -> None:
|
|
|
227
233
|
shutil.rmtree(mount_root_path)
|
|
228
234
|
|
|
229
235
|
args = _parse_args()
|
|
230
|
-
transfer_list = [
|
|
231
|
-
parallel_workers = args.num
|
|
236
|
+
transfer_list = [args.num]
|
|
237
|
+
# parallel_workers = args.num
|
|
232
238
|
|
|
233
239
|
def task(
|
|
234
240
|
offset: SizeSuffix,
|
|
@@ -244,14 +250,17 @@ def main() -> None:
|
|
|
244
250
|
mount_root_path=mount_root_path,
|
|
245
251
|
transfer_list=transfer_list,
|
|
246
252
|
size=args.size,
|
|
253
|
+
num=args.num,
|
|
247
254
|
)
|
|
248
255
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
256
|
+
task(SizeSuffix(0))
|
|
257
|
+
|
|
258
|
+
# with ThreadPoolExecutor(max_workers=parallel_workers) as _:
|
|
259
|
+
# tasks: list[Future] = []
|
|
260
|
+
# for i in range(parallel_workers):
|
|
261
|
+
# offset = SizeSuffix(i * 1024 * 1024 * 256)
|
|
262
|
+
# future = ThreadPoolExecutor().submit(lambda: task(offset=offset))
|
|
263
|
+
# tasks.append(future)
|
|
255
264
|
|
|
256
265
|
|
|
257
266
|
if __name__ == "__main__":
|
rclone_api/rclone.py
CHANGED
|
@@ -815,7 +815,7 @@ class Rclone:
|
|
|
815
815
|
)
|
|
816
816
|
return out
|
|
817
817
|
|
|
818
|
-
def
|
|
818
|
+
def _copy_bytes(
|
|
819
819
|
self,
|
|
820
820
|
src: str,
|
|
821
821
|
offset: int,
|
|
@@ -844,7 +844,7 @@ class Rclone:
|
|
|
844
844
|
max_read_ahead = SizeSuffix(vfs_read_chunk_size.as_int())
|
|
845
845
|
|
|
846
846
|
# other_args += ["--vfs-read-chunk-size", str(vfs_read_chunk_size)]
|
|
847
|
-
other_args += ["--vfs-read-chunk-size", str(
|
|
847
|
+
other_args += ["--vfs-read-chunk-size", str(vfs_read_chunk_size)]
|
|
848
848
|
other_args += ["--vfs-read-chunk-size-limit", str(vfs_read_chunk_size_limit)]
|
|
849
849
|
other_args += ["--vfs-read-chunk-streams", str(vfs_read_chunk_streams)]
|
|
850
850
|
other_args += ["--vfs-disk-space-total-size", str(vfs_disk_space_total_size)]
|
|
@@ -883,6 +883,64 @@ class Rclone:
|
|
|
883
883
|
except Exception as e:
|
|
884
884
|
return e
|
|
885
885
|
|
|
886
|
+
def copy_bytes(
|
|
887
|
+
self,
|
|
888
|
+
src: str,
|
|
889
|
+
offset: int,
|
|
890
|
+
length: int,
|
|
891
|
+
chunk_size: SizeSuffix,
|
|
892
|
+
max_threads: int = 1,
|
|
893
|
+
# If outfile is supplied then bytes are written to this file and success returns bytes(0)
|
|
894
|
+
outfile: Path | None = None,
|
|
895
|
+
mount_log: Path | None = None,
|
|
896
|
+
direct_io: bool = True,
|
|
897
|
+
) -> bytes | Exception:
|
|
898
|
+
"""Copy bytes from a file to another file."""
|
|
899
|
+
# determine number of threads from chunk size
|
|
900
|
+
threads = min(max_threads, length // chunk_size.as_int())
|
|
901
|
+
|
|
902
|
+
if threads == 1:
|
|
903
|
+
return self._copy_bytes(
|
|
904
|
+
src,
|
|
905
|
+
offset,
|
|
906
|
+
length,
|
|
907
|
+
transfers=1,
|
|
908
|
+
outfile=outfile,
|
|
909
|
+
mount_log=mount_log,
|
|
910
|
+
direct_io=direct_io,
|
|
911
|
+
)
|
|
912
|
+
else:
|
|
913
|
+
futures: list[Future] = []
|
|
914
|
+
with ThreadPoolExecutor(max_workers=threads) as executor:
|
|
915
|
+
for i in range(threads):
|
|
916
|
+
start = i * chunk_size.as_int()
|
|
917
|
+
end = start + chunk_size.as_int()
|
|
918
|
+
if i == threads - 1:
|
|
919
|
+
end = length
|
|
920
|
+
future = executor.submit(
|
|
921
|
+
self._copy_bytes,
|
|
922
|
+
src,
|
|
923
|
+
offset + start,
|
|
924
|
+
end - start,
|
|
925
|
+
transfers=1,
|
|
926
|
+
outfile=None,
|
|
927
|
+
mount_log=mount_log,
|
|
928
|
+
direct_io=direct_io,
|
|
929
|
+
)
|
|
930
|
+
futures.append(future)
|
|
931
|
+
data: bytes = b""
|
|
932
|
+
for future in futures:
|
|
933
|
+
chunk: bytes | Exception = future.result()
|
|
934
|
+
if isinstance(chunk, Exception):
|
|
935
|
+
return chunk
|
|
936
|
+
data += chunk
|
|
937
|
+
if outfile is not None:
|
|
938
|
+
with open(outfile, "wb") as out:
|
|
939
|
+
out.write(data)
|
|
940
|
+
del data
|
|
941
|
+
return bytes(0)
|
|
942
|
+
return data
|
|
943
|
+
|
|
886
944
|
def copy_dir(
|
|
887
945
|
self, src: str | Dir, dst: str | Dir, args: list[str] | None = None
|
|
888
946
|
) -> CompletedProcess:
|
rclone_api/types.py
CHANGED
|
@@ -170,3 +170,11 @@ class SizeSuffix:
|
|
|
170
170
|
raise ZeroDivisionError("Division by zero is undefined")
|
|
171
171
|
# Use floor division to maintain integer arithmetic.
|
|
172
172
|
return SizeSuffix(self._size // other_int._size)
|
|
173
|
+
|
|
174
|
+
# support / division
|
|
175
|
+
def __floordiv__(self, other: "int | SizeSuffix") -> "SizeSuffix":
|
|
176
|
+
other_int = SizeSuffix(other)
|
|
177
|
+
if other_int._size == 0:
|
|
178
|
+
raise ZeroDivisionError("Division by zero is undefined")
|
|
179
|
+
# Use floor division to maintain integer arithmetic.
|
|
180
|
+
return SizeSuffix(self._size // other_int._size)
|
|
@@ -13,11 +13,11 @@ rclone_api/filelist.py,sha256=xbiusvNgaB_b_kQOZoHMJJxn6TWGtPrWd2J042BI28o,767
|
|
|
13
13
|
rclone_api/group_files.py,sha256=H92xPW9lQnbNw5KbtZCl00bD6iRh9yRbCuxku4j_3dg,8036
|
|
14
14
|
rclone_api/mount.py,sha256=5XiFwP7tst4h8cGQstZMJ0u5VzqFQ4YehnDl2AFP11A,10057
|
|
15
15
|
rclone_api/process.py,sha256=rBj_S86jC6nqCYop-jq8r9eMSteKeObxUrJMgH8LZvI,5084
|
|
16
|
-
rclone_api/rclone.py,sha256=
|
|
16
|
+
rclone_api/rclone.py,sha256=_bXkNBKeAVfjEOmX7bEwpxlXaJURJ3RguY1TJzwIBzM,46038
|
|
17
17
|
rclone_api/remote.py,sha256=O9WDUFQy9f6oT1HdUbTixK2eg0xtBBm8k4Xl6aa6K00,431
|
|
18
18
|
rclone_api/rpath.py,sha256=8ZA_1wxWtskwcy0I8V2VbjKDmzPkiWd8Q2JQSvh-sYE,2586
|
|
19
19
|
rclone_api/scan_missing_folders.py,sha256=Kulca2Q6WZodt00ATFHkmqqInuoPvBkhTcS9703y6po,4740
|
|
20
|
-
rclone_api/types.py,sha256=
|
|
20
|
+
rclone_api/types.py,sha256=2x9APG861HFrMwt5AIpxYI_ahDY09vUjGMtTE5xHlEs,5085
|
|
21
21
|
rclone_api/util.py,sha256=_Z-GUMVXnHYOGdo2dy2ie2P5fGgyg8KdGjHKicx68Ko,4573
|
|
22
22
|
rclone_api/walk.py,sha256=-54NVE8EJcCstwDoaC_UtHm73R2HrZwVwQmsnv55xNU,3369
|
|
23
23
|
rclone_api/assets/example.txt,sha256=lTBovRjiz0_TgtAtbA1C5hNi2ffbqnNPqkKg6UiKCT8,54
|
|
@@ -25,7 +25,7 @@ rclone_api/cmd/copy_large_s3.py,sha256=-rfedi-ZzPUdCSP8ai9LRL0y1xVkvN-viQQlk8HVU
|
|
|
25
25
|
rclone_api/cmd/list_files.py,sha256=x8FHODEilwKqwdiU1jdkeJbLwOqUkUQuDWPo2u_zpf0,741
|
|
26
26
|
rclone_api/experimental/flags.py,sha256=qCVD--fSTmzlk9hloRLr0q9elzAOFzPsvVpKM3aB1Mk,2739
|
|
27
27
|
rclone_api/experimental/flags_base.py,sha256=ajU_czkTcAxXYU-SlmiCfHY7aCQGHvpCLqJ-Z8uZLk0,2102
|
|
28
|
-
rclone_api/profile/mount_copy_bytes.py,sha256=
|
|
28
|
+
rclone_api/profile/mount_copy_bytes.py,sha256=KJhn2ufpRwT9c9bH_q2RWvklw5x63nvI-UMtv9O8CPg,7717
|
|
29
29
|
rclone_api/s3/api.py,sha256=qxtRDUpHYqJ7StJRtP8U_PbF_BvYRg705568SyvF-R0,3770
|
|
30
30
|
rclone_api/s3/basic_ops.py,sha256=hK3366xhVEzEcjz9Gk_8lFx6MRceAk72cax6mUrr6ko,2104
|
|
31
31
|
rclone_api/s3/chunk_file.py,sha256=D6wM9Nuu73LNGC8JCCfevqjF3qdZ21mQxYQClFLZLMU,3726
|
|
@@ -33,9 +33,9 @@ rclone_api/s3/chunk_types.py,sha256=LbXayXY1KgVU1LkdbASD_BQ7TpVpwVnzMjtz--8LBaE,
|
|
|
33
33
|
rclone_api/s3/create.py,sha256=wgfkapv_j904CfKuWyiBIWJVxfAx_ftemFSUV14aT68,3149
|
|
34
34
|
rclone_api/s3/types.py,sha256=yBnJ38Tjk6RlydJ-sqZ7DSfyFloy8KDYJ0mv3vlOzLE,1388
|
|
35
35
|
rclone_api/s3/upload_file_multipart.py,sha256=y9azNAU8QH5Ovwz33V2HZwNmJdlFjJg-jrXLZ1gtMds,10364
|
|
36
|
-
rclone_api-1.1.
|
|
37
|
-
rclone_api-1.1.
|
|
38
|
-
rclone_api-1.1.
|
|
39
|
-
rclone_api-1.1.
|
|
40
|
-
rclone_api-1.1.
|
|
41
|
-
rclone_api-1.1.
|
|
36
|
+
rclone_api-1.1.61.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
|
|
37
|
+
rclone_api-1.1.61.dist-info/METADATA,sha256=K94aUUT1DvHqha4sUrmbKR18VbBosxwPVUW0tQLAKqU,4537
|
|
38
|
+
rclone_api-1.1.61.dist-info/WHEEL,sha256=rF4EZyR2XVS6irmOHQIJx2SUqXLZKRMUrjsg8UwN-XQ,109
|
|
39
|
+
rclone_api-1.1.61.dist-info/entry_points.txt,sha256=TV8kwP3FRzYwUEr0RLC7aJh0W03SAefIJNXTJ-FdMIQ,200
|
|
40
|
+
rclone_api-1.1.61.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
|
|
41
|
+
rclone_api-1.1.61.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|