rclone-api 1.1.25__py2.py3-none-any.whl → 1.1.28__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/cmd/copy_large_s3.py +9 -12
- rclone_api/s3/api.py +1 -1
- rclone_api/types.py +52 -25
- {rclone_api-1.1.25.dist-info → rclone_api-1.1.28.dist-info}/METADATA +1 -1
- {rclone_api-1.1.25.dist-info → rclone_api-1.1.28.dist-info}/RECORD +10 -10
- /rclone_api/s3/{chunk_uploader.py → upload_file_multipart.py} +0 -0
- {rclone_api-1.1.25.dist-info → rclone_api-1.1.28.dist-info}/LICENSE +0 -0
- {rclone_api-1.1.25.dist-info → rclone_api-1.1.28.dist-info}/WHEEL +0 -0
- {rclone_api-1.1.25.dist-info → rclone_api-1.1.28.dist-info}/entry_points.txt +0 -0
- {rclone_api-1.1.25.dist-info → rclone_api-1.1.28.dist-info}/top_level.txt +0 -0
rclone_api/cmd/copy_large_s3.py
CHANGED
|
@@ -13,7 +13,7 @@ class Args:
|
|
|
13
13
|
src: str
|
|
14
14
|
dst: str
|
|
15
15
|
chunk_size: SizeSuffix
|
|
16
|
-
|
|
16
|
+
read_threads: int
|
|
17
17
|
write_threads: int
|
|
18
18
|
retries: int
|
|
19
19
|
save_state_json: Path
|
|
@@ -37,19 +37,19 @@ def _parse_args() -> Args:
|
|
|
37
37
|
)
|
|
38
38
|
parser.add_argument(
|
|
39
39
|
"--chunk-size",
|
|
40
|
-
help="Chunk size that will be read and uploaded in
|
|
40
|
+
help="Chunk size that will be read and uploaded in SizeSuffix form, too low or too high will cause issues",
|
|
41
41
|
type=str,
|
|
42
|
-
default="64MB",
|
|
42
|
+
default="64MB", # if this is too low or too high an s3 service
|
|
43
43
|
)
|
|
44
44
|
parser.add_argument(
|
|
45
|
-
"--threads",
|
|
46
|
-
help="Number of
|
|
45
|
+
"--read-threads",
|
|
46
|
+
help="Number of concurrent read threads per chunk, only one chunk will be read at a time",
|
|
47
47
|
type=int,
|
|
48
|
-
default=
|
|
48
|
+
default=32,
|
|
49
49
|
)
|
|
50
50
|
parser.add_argument(
|
|
51
51
|
"--write-threads",
|
|
52
|
-
help="Max number of chunks to upload in parallel to the destination",
|
|
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
54
|
default=64,
|
|
55
55
|
)
|
|
@@ -67,7 +67,7 @@ def _parse_args() -> Args:
|
|
|
67
67
|
src=args.src,
|
|
68
68
|
dst=args.dst,
|
|
69
69
|
chunk_size=SizeSuffix(args.chunk_size),
|
|
70
|
-
|
|
70
|
+
read_threads=args.read_threads,
|
|
71
71
|
write_threads=args.write_threads,
|
|
72
72
|
retries=args.retries,
|
|
73
73
|
save_state_json=args.resume_json,
|
|
@@ -85,11 +85,8 @@ def main() -> int:
|
|
|
85
85
|
src=args.src,
|
|
86
86
|
dst=args.dst,
|
|
87
87
|
chunk_size=args.chunk_size,
|
|
88
|
-
read_threads=args.
|
|
88
|
+
read_threads=args.read_threads,
|
|
89
89
|
write_threads=args.write_threads,
|
|
90
|
-
# vfs_read_chunk_size=unit_chunk,
|
|
91
|
-
# vfs_read_chunk_size_limit=args.chunk_size,
|
|
92
|
-
# vfs_read_chunk_streams=args.threads,
|
|
93
90
|
retries=args.retries,
|
|
94
91
|
save_state_json=args.save_state_json,
|
|
95
92
|
verbose=args.verbose,
|
rclone_api/s3/api.py
CHANGED
|
@@ -9,9 +9,9 @@ from rclone_api.s3.basic_ops import (
|
|
|
9
9
|
list_bucket_contents,
|
|
10
10
|
upload_file,
|
|
11
11
|
)
|
|
12
|
-
from rclone_api.s3.chunk_uploader import MultiUploadResult, upload_file_multipart
|
|
13
12
|
from rclone_api.s3.create import create_s3_client
|
|
14
13
|
from rclone_api.s3.types import S3Credentials, S3MutliPartUploadConfig, S3UploadTarget
|
|
14
|
+
from rclone_api.s3.upload_file_multipart import MultiUploadResult, upload_file_multipart
|
|
15
15
|
|
|
16
16
|
_MIN_THRESHOLD_FOR_CHUNKING = 5 * 1024 * 1024
|
|
17
17
|
|
rclone_api/types.py
CHANGED
|
@@ -37,41 +37,68 @@ class SizeResult:
|
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
def _to_size_suffix(size: int) -> str:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
40
|
+
def _convert(size: int) -> tuple[float, str]:
|
|
41
|
+
val: float
|
|
42
|
+
unit: str
|
|
43
|
+
if size < 1024:
|
|
44
|
+
val = size
|
|
45
|
+
unit = "B"
|
|
46
|
+
elif size < 1024**2:
|
|
47
|
+
val = size / 1024
|
|
48
|
+
unit = "K"
|
|
49
|
+
elif size < 1024**3:
|
|
50
|
+
val = size / (1024**2)
|
|
51
|
+
unit = "M"
|
|
52
|
+
elif size < 1024**4:
|
|
53
|
+
val = size / (1024**3)
|
|
54
|
+
unit = "G"
|
|
55
|
+
elif size < 1024**5:
|
|
56
|
+
val = size / (1024**4)
|
|
57
|
+
unit = "T"
|
|
58
|
+
elif size < 1024**6:
|
|
59
|
+
val = size / (1024**5)
|
|
60
|
+
unit = "P"
|
|
61
|
+
else:
|
|
62
|
+
raise ValueError(f"Invalid size: {size}")
|
|
63
|
+
|
|
64
|
+
return val, unit
|
|
65
|
+
|
|
66
|
+
def _fmt(_val: float | int, _unit: str) -> str:
|
|
67
|
+
# If the float is an integer, drop the decimal, otherwise format with one decimal.
|
|
68
|
+
val_str: str = str(_val)
|
|
69
|
+
if not val_str.endswith(".0"):
|
|
70
|
+
first_str: str = f"{_val:.1f}"
|
|
71
|
+
else:
|
|
72
|
+
first_str = str(int(_val))
|
|
73
|
+
return first_str + _unit
|
|
74
|
+
|
|
75
|
+
val, unit = _convert(size)
|
|
76
|
+
out = _fmt(val, unit)
|
|
77
|
+
# Now round trip the value to fix floating point issues via rounding.
|
|
78
|
+
int_val = _from_size_suffix(out)
|
|
79
|
+
val, unit = _convert(int_val)
|
|
80
|
+
out = _fmt(val, unit)
|
|
81
|
+
return out
|
|
62
82
|
|
|
63
83
|
|
|
64
84
|
# Update regex to allow decimals (e.g., 16.5MB)
|
|
65
85
|
_PATTERN_SIZE_SUFFIX = re.compile(r"^(\d+(?:\.\d+)?)([A-Za-z]+)$")
|
|
66
86
|
|
|
67
87
|
|
|
88
|
+
def _parse_elements(value: str) -> tuple[str, str] | None:
|
|
89
|
+
match = _PATTERN_SIZE_SUFFIX.match(value)
|
|
90
|
+
if match is None:
|
|
91
|
+
return None
|
|
92
|
+
return match.group(1), match.group(2)
|
|
93
|
+
|
|
94
|
+
|
|
68
95
|
def _from_size_suffix(size: str) -> int:
|
|
69
96
|
if size == "0":
|
|
70
97
|
return 0
|
|
71
|
-
|
|
72
|
-
if
|
|
98
|
+
pair = _parse_elements(size)
|
|
99
|
+
if pair is None:
|
|
73
100
|
raise ValueError(f"Invalid size suffix: {size}")
|
|
74
|
-
num_str, suffix =
|
|
101
|
+
num_str, suffix = pair
|
|
75
102
|
n = float(num_str)
|
|
76
103
|
# Determine the unit from the first letter (e.g., "M" from "MB")
|
|
77
104
|
unit = suffix[0].upper()
|
|
@@ -17,24 +17,24 @@ rclone_api/rclone.py,sha256=gszjs6MJFoT5tKmBB06sd0OjbtZZAtRdjvha4RrE-lI,40252
|
|
|
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=AWVIoCaRkUBCXOQffxdkFCOeUhPwolQh9d2albyAGHc,4730
|
|
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
|
|
24
|
-
rclone_api/cmd/copy_large_s3.py,sha256
|
|
24
|
+
rclone_api/cmd/copy_large_s3.py,sha256=-rfedi-ZzPUdCSP8ai9LRL0y1xVkvN-viQQlk8HVUWw,3389
|
|
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/s3/api.py,sha256=
|
|
28
|
+
rclone_api/s3/api.py,sha256=qxtRDUpHYqJ7StJRtP8U_PbF_BvYRg705568SyvF-R0,3770
|
|
29
29
|
rclone_api/s3/basic_ops.py,sha256=hK3366xhVEzEcjz9Gk_8lFx6MRceAk72cax6mUrr6ko,2104
|
|
30
30
|
rclone_api/s3/chunk_file.py,sha256=YELR-EzR7RHpzCDGpYdzlwu21NZW5wttIDvLoONI4aU,3477
|
|
31
31
|
rclone_api/s3/chunk_types.py,sha256=LbXayXY1KgVU1LkdbASD_BQ7TpVpwVnzMjtz--8LBaE,10316
|
|
32
|
-
rclone_api/s3/chunk_uploader.py,sha256=1jQAdk35Fa9Tcq36bS65262cs7AcNG2DAFQ-NdYlWSw,9961
|
|
33
32
|
rclone_api/s3/create.py,sha256=wgfkapv_j904CfKuWyiBIWJVxfAx_ftemFSUV14aT68,3149
|
|
34
33
|
rclone_api/s3/types.py,sha256=yBnJ38Tjk6RlydJ-sqZ7DSfyFloy8KDYJ0mv3vlOzLE,1388
|
|
35
|
-
rclone_api
|
|
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.
|
|
34
|
+
rclone_api/s3/upload_file_multipart.py,sha256=1jQAdk35Fa9Tcq36bS65262cs7AcNG2DAFQ-NdYlWSw,9961
|
|
35
|
+
rclone_api-1.1.28.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
|
|
36
|
+
rclone_api-1.1.28.dist-info/METADATA,sha256=oYARfyAum3DsSyUi9eSCthPsskeXoo7-exERXB_gAAA,4514
|
|
37
|
+
rclone_api-1.1.28.dist-info/WHEEL,sha256=rF4EZyR2XVS6irmOHQIJx2SUqXLZKRMUrjsg8UwN-XQ,109
|
|
38
|
+
rclone_api-1.1.28.dist-info/entry_points.txt,sha256=6eNqTRXKhVf8CpWNjXiOa_0Du9tHiW_HD2iQSXRsUg8,132
|
|
39
|
+
rclone_api-1.1.28.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
|
|
40
|
+
rclone_api-1.1.28.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|