rclone-api 1.4.12__py2.py3-none-any.whl → 1.4.14__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/__init__.py +4 -0
- rclone_api/cmd/copy_large_s3_finish.py +27 -3
- rclone_api/s3/api.py +4 -2
- rclone_api/s3/create.py +36 -11
- {rclone_api-1.4.12.dist-info → rclone_api-1.4.14.dist-info}/METADATA +1 -1
- {rclone_api-1.4.12.dist-info → rclone_api-1.4.14.dist-info}/RECORD +10 -10
- {rclone_api-1.4.12.dist-info → rclone_api-1.4.14.dist-info}/LICENSE +0 -0
- {rclone_api-1.4.12.dist-info → rclone_api-1.4.14.dist-info}/WHEEL +0 -0
- {rclone_api-1.4.12.dist-info → rclone_api-1.4.14.dist-info}/entry_points.txt +0 -0
- {rclone_api-1.4.12.dist-info → rclone_api-1.4.14.dist-info}/top_level.txt +0 -0
rclone_api/__init__.py
CHANGED
@@ -51,10 +51,17 @@ def _parse_args() -> Args:
|
|
51
51
|
|
52
52
|
|
53
53
|
def do_finish_part(rclone: Rclone, info: InfoJson, dst: str) -> None:
|
54
|
-
from rclone_api.s3.create import
|
54
|
+
from rclone_api.s3.create import (
|
55
|
+
BaseClient,
|
56
|
+
S3Config,
|
57
|
+
S3Credentials,
|
58
|
+
create_s3_client,
|
59
|
+
)
|
55
60
|
|
56
61
|
s3_creds: S3Credentials = rclone.impl.get_s3_credentials(remote=dst)
|
57
|
-
s3_client: BaseClient = create_s3_client(
|
62
|
+
s3_client: BaseClient = create_s3_client(
|
63
|
+
s3_creds, S3Config(verbose=False, timeout_read=5 * 60)
|
64
|
+
)
|
58
65
|
s3_bucket = s3_creds.bucket_name
|
59
66
|
is_done = info.fetch_is_done()
|
60
67
|
assert is_done, f"Upload is not done: {info}"
|
@@ -112,6 +119,20 @@ def do_finish_part(rclone: Rclone, info: InfoJson, dst: str) -> None:
|
|
112
119
|
retries=3,
|
113
120
|
)
|
114
121
|
|
122
|
+
# now check if the dst now exists, if so, delete the parts folder.
|
123
|
+
# if rclone.exists(dst):
|
124
|
+
# rclone.purge(parts_dir)
|
125
|
+
|
126
|
+
if not rclone.exists(dst):
|
127
|
+
raise FileNotFoundError(f"Destination file not found: {dst}")
|
128
|
+
|
129
|
+
write_size = rclone.size_file(dst)
|
130
|
+
if write_size != size:
|
131
|
+
raise ValueError(f"Size mismatch: {write_size} != {size}")
|
132
|
+
|
133
|
+
print(f"Upload complete: {dst}")
|
134
|
+
rclone.purge(parts_dir)
|
135
|
+
|
115
136
|
|
116
137
|
def main() -> int:
|
117
138
|
"""Main entry point."""
|
@@ -120,7 +141,10 @@ def main() -> int:
|
|
120
141
|
info_json = f"{args.src}/info.json".replace("//", "/")
|
121
142
|
info = InfoJson(rclone.impl, src=None, src_info=info_json)
|
122
143
|
loaded = info.load()
|
123
|
-
|
144
|
+
if not loaded:
|
145
|
+
raise FileNotFoundError(
|
146
|
+
f"Info file not found, has the upload finished? {info_json}"
|
147
|
+
)
|
124
148
|
print(info)
|
125
149
|
do_finish_part(rclone=rclone, info=info, dst=args.dst)
|
126
150
|
return 0
|
rclone_api/s3/api.py
CHANGED
@@ -9,7 +9,7 @@ from rclone_api.s3.basic_ops import (
|
|
9
9
|
list_bucket_contents,
|
10
10
|
upload_file,
|
11
11
|
)
|
12
|
-
from rclone_api.s3.create import create_s3_client
|
12
|
+
from rclone_api.s3.create import S3Config, create_s3_client
|
13
13
|
from rclone_api.s3.types import S3Credentials, S3MutliPartUploadConfig, S3UploadTarget
|
14
14
|
from rclone_api.s3.upload_file_multipart import (
|
15
15
|
MultiUploadResult,
|
@@ -23,7 +23,9 @@ class S3Client:
|
|
23
23
|
def __init__(self, credentials: S3Credentials, verbose: bool = False) -> None:
|
24
24
|
self.verbose = verbose
|
25
25
|
self.credentials: S3Credentials = credentials
|
26
|
-
self.client: BaseClient = create_s3_client(
|
26
|
+
self.client: BaseClient = create_s3_client(
|
27
|
+
credentials, config=S3Config(verbose=verbose)
|
28
|
+
)
|
27
29
|
|
28
30
|
def list_bucket_contents(self, bucket_name: str) -> None:
|
29
31
|
list_bucket_contents(self.client, bucket_name)
|
rclone_api/s3/create.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import warnings
|
2
|
+
from dataclasses import dataclass
|
2
3
|
|
3
4
|
import boto3
|
4
5
|
from botocore.client import BaseClient
|
@@ -8,18 +9,35 @@ from rclone_api.s3.types import S3Credentials, S3Provider
|
|
8
9
|
|
9
10
|
_DEFAULT_BACKBLAZE_ENDPOINT = "https://s3.us-west-002.backblazeb2.com"
|
10
11
|
_MAX_CONNECTIONS = 50
|
12
|
+
_TIMEOUT_READ = 120
|
13
|
+
_TIMEOUT_CONNECT = 60
|
14
|
+
|
15
|
+
|
16
|
+
@dataclass
|
17
|
+
class S3Config:
|
18
|
+
max_pool_connections: int | None = None
|
19
|
+
timeout_connection: int | None = None
|
20
|
+
timeout_read: int | None = None
|
21
|
+
verbose: bool | None = None
|
22
|
+
|
23
|
+
def resolve_defaults(self) -> None:
|
24
|
+
self.max_pool_connections = self.max_pool_connections or _MAX_CONNECTIONS
|
25
|
+
self.timeout_connection = self.timeout_connection or _TIMEOUT_CONNECT
|
26
|
+
self.timeout_read = self.timeout_read or _TIMEOUT_READ
|
27
|
+
self.verbose = self.verbose or False
|
11
28
|
|
12
29
|
|
13
30
|
# Create a Boto3 session and S3 client, this is back blaze specific.
|
14
31
|
# Add a function if you want to use a different S3 provider.
|
15
32
|
# If AWS support is added in a fork then please merge it back here.
|
16
|
-
def _create_backblaze_s3_client(creds: S3Credentials,
|
33
|
+
def _create_backblaze_s3_client(creds: S3Credentials, config: S3Config) -> BaseClient:
|
17
34
|
"""Create and return an S3 client."""
|
18
35
|
region_name = creds.region_name
|
19
36
|
access_key = creds.access_key_id
|
20
37
|
secret_key = creds.secret_access_key
|
21
38
|
endpoint_url = creds.endpoint_url
|
22
39
|
endpoint_url = endpoint_url or _DEFAULT_BACKBLAZE_ENDPOINT
|
40
|
+
config.resolve_defaults()
|
23
41
|
session = boto3.session.Session() # type: ignore
|
24
42
|
return session.client(
|
25
43
|
service_name="s3",
|
@@ -30,7 +48,9 @@ def _create_backblaze_s3_client(creds: S3Credentials, verbose: bool) -> BaseClie
|
|
30
48
|
config=Config(
|
31
49
|
signature_version="s3v4",
|
32
50
|
region_name=region_name,
|
33
|
-
max_pool_connections=
|
51
|
+
max_pool_connections=config.max_pool_connections,
|
52
|
+
read_timeout=config.timeout_read,
|
53
|
+
connect_timeout=config.timeout_connection,
|
34
54
|
# Note that BackBlase has a boko3 bug where it doesn't support the new
|
35
55
|
# checksum header, the following line was an attempt of fix it on the newest
|
36
56
|
# version of boto3, but it didn't work.
|
@@ -39,18 +59,18 @@ def _create_backblaze_s3_client(creds: S3Credentials, verbose: bool) -> BaseClie
|
|
39
59
|
)
|
40
60
|
|
41
61
|
|
42
|
-
def _create_unknown_s3_client(creds: S3Credentials,
|
62
|
+
def _create_unknown_s3_client(creds: S3Credentials, config: S3Config) -> BaseClient:
|
43
63
|
"""Create and return an S3 client."""
|
44
64
|
access_key = creds.access_key_id
|
45
65
|
secret_key = creds.secret_access_key
|
46
66
|
endpoint_url = creds.endpoint_url
|
47
67
|
if (endpoint_url is not None) and not (endpoint_url.startswith("http")):
|
48
|
-
if verbose:
|
68
|
+
if config.verbose:
|
49
69
|
warnings.warn(
|
50
70
|
f"Endpoint URL is schema naive: {endpoint_url}, assuming HTTPS"
|
51
71
|
)
|
52
72
|
endpoint_url = f"https://{endpoint_url}"
|
53
|
-
|
73
|
+
config.resolve_defaults()
|
54
74
|
session = boto3.session.Session() # type: ignore
|
55
75
|
return session.client(
|
56
76
|
service_name="s3",
|
@@ -60,19 +80,24 @@ def _create_unknown_s3_client(creds: S3Credentials, verbose: bool) -> BaseClient
|
|
60
80
|
config=Config(
|
61
81
|
signature_version="s3v4",
|
62
82
|
region_name=creds.region_name,
|
63
|
-
max_pool_connections=
|
83
|
+
max_pool_connections=config.max_pool_connections,
|
84
|
+
read_timeout=config.timeout_read,
|
85
|
+
connect_timeout=config.timeout_connection,
|
64
86
|
),
|
65
87
|
)
|
66
88
|
|
67
89
|
|
68
|
-
def create_s3_client(
|
90
|
+
def create_s3_client(
|
91
|
+
credentials: S3Credentials, config: S3Config | None = None
|
92
|
+
) -> BaseClient:
|
69
93
|
"""Create and return an S3 client."""
|
94
|
+
config = config or S3Config()
|
70
95
|
provider = credentials.provider
|
71
96
|
if provider == S3Provider.BACKBLAZE:
|
72
|
-
if verbose:
|
97
|
+
if config.verbose:
|
73
98
|
print("Creating BackBlaze S3 client")
|
74
|
-
return _create_backblaze_s3_client(creds=credentials,
|
99
|
+
return _create_backblaze_s3_client(creds=credentials, config=config)
|
75
100
|
else:
|
76
|
-
if verbose:
|
101
|
+
if config.verbose:
|
77
102
|
print("Creating generic/unknown S3 client")
|
78
|
-
return _create_unknown_s3_client(creds=credentials,
|
103
|
+
return _create_unknown_s3_client(creds=credentials, config=config)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
rclone_api/__init__.py,sha256=
|
1
|
+
rclone_api/__init__.py,sha256=gsYL3jaqMgHbJ6mnLxNttuaKltUBXNuvpz7C6fF8_8w,17678
|
2
2
|
rclone_api/cli.py,sha256=dibfAZIh0kXWsBbfp3onKLjyZXo54mTzDjUdzJlDlWo,231
|
3
3
|
rclone_api/completed_process.py,sha256=_IZ8IWK7DM1_tsbDEkH6wPZ-bbcrgf7A7smls854pmg,1775
|
4
4
|
rclone_api/config.py,sha256=f6jEAxVorGFr31oHfcsu5AJTtOJj2wR5tTSsbGGZuIw,2558
|
@@ -27,7 +27,7 @@ rclone_api/util.py,sha256=9w_m6W62l_X42Jw5q8p_p30h-QoxAqufvnCLI4PTMOE,7056
|
|
27
27
|
rclone_api/assets/example.txt,sha256=lTBovRjiz0_TgtAtbA1C5hNi2ffbqnNPqkKg6UiKCT8,54
|
28
28
|
rclone_api/cmd/analyze.py,sha256=RHbvk1G5ZUc3qLqlm1AZEyQzd_W_ZjcbCNDvW4YpTKQ,1252
|
29
29
|
rclone_api/cmd/copy_large_s3.py,sha256=B17GliDQyAauNglJCpsey0d3eArT2DAcT9g684TMQk8,3514
|
30
|
-
rclone_api/cmd/copy_large_s3_finish.py,sha256=
|
30
|
+
rclone_api/cmd/copy_large_s3_finish.py,sha256=7bDaUZ0forOqR4JOT1eoMBF_2qtifM9GcLK_he53cw4,4877
|
31
31
|
rclone_api/cmd/list_files.py,sha256=x8FHODEilwKqwdiU1jdkeJbLwOqUkUQuDWPo2u_zpf0,741
|
32
32
|
rclone_api/cmd/save_to_db.py,sha256=ylvnhg_yzexM-m6Zr7XDiswvoDVSl56ELuFAdb9gqBY,1957
|
33
33
|
rclone_api/db/__init__.py,sha256=OSRUdnSWUlDTOHmjdjVmxYTUNpTbtaJ5Ll9sl-PfZg0,40
|
@@ -37,10 +37,10 @@ rclone_api/detail/copy_file_parts.py,sha256=dpqZ0d7l195dZg6Vob2Ty43Uah1v0ozQu5kM
|
|
37
37
|
rclone_api/detail/walk.py,sha256=-54NVE8EJcCstwDoaC_UtHm73R2HrZwVwQmsnv55xNU,3369
|
38
38
|
rclone_api/experimental/flags.py,sha256=qCVD--fSTmzlk9hloRLr0q9elzAOFzPsvVpKM3aB1Mk,2739
|
39
39
|
rclone_api/experimental/flags_base.py,sha256=ajU_czkTcAxXYU-SlmiCfHY7aCQGHvpCLqJ-Z8uZLk0,2102
|
40
|
-
rclone_api/s3/api.py,sha256=
|
40
|
+
rclone_api/s3/api.py,sha256=nIjOskTgTlbksbBHgF27ExFEYheCT_OvcdYl6FqRAto,4058
|
41
41
|
rclone_api/s3/basic_ops.py,sha256=hK3366xhVEzEcjz9Gk_8lFx6MRceAk72cax6mUrr6ko,2104
|
42
42
|
rclone_api/s3/chunk_task.py,sha256=waEYe-iYQ1_BR3NCS4BrzVrK9UANvH1EcbXx2I6Z_NM,6839
|
43
|
-
rclone_api/s3/create.py,sha256=
|
43
|
+
rclone_api/s3/create.py,sha256=NinodMsVPtNXWOM_hlMJWWl-tOj6gV4BcOxEnXFGRWE,3902
|
44
44
|
rclone_api/s3/s3_multipart_uploader_by_copy.py,sha256=KNEWG3CrM8lVWd2b0dA6WT5LO3gEEXNk2tA6Uk9Vi7I,8701
|
45
45
|
rclone_api/s3/types.py,sha256=cYI5MbXRNdT-ps5kGIRQaYrseHyx_ozT4AcwBABTKwk,1616
|
46
46
|
rclone_api/s3/upload_file_multipart.py,sha256=V7syKjFyVIe4U9Ahl5XgqVTzt9akiew3MFjGmufLo2w,12503
|
@@ -48,9 +48,9 @@ rclone_api/s3/multipart/file_info.py,sha256=8v_07_eADo0K-Nsv7F0Ac1wcv3lkIsrR3MaR
|
|
48
48
|
rclone_api/s3/multipart/finished_piece.py,sha256=9nMWnVZ8S99wi2VFQsm1h1ZHqmebkhMGgd2s56wNj9w,1331
|
49
49
|
rclone_api/s3/multipart/upload_info.py,sha256=d6_OfzFR_vtDzCEegFfzCfWi2kUBUV4aXZzqAEVp1c4,1874
|
50
50
|
rclone_api/s3/multipart/upload_state.py,sha256=f-Aq2NqtAaMUMhYitlICSNIxCKurWAl2gDEUVizLIqw,6019
|
51
|
-
rclone_api-1.4.
|
52
|
-
rclone_api-1.4.
|
53
|
-
rclone_api-1.4.
|
54
|
-
rclone_api-1.4.
|
55
|
-
rclone_api-1.4.
|
56
|
-
rclone_api-1.4.
|
51
|
+
rclone_api-1.4.14.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
|
52
|
+
rclone_api-1.4.14.dist-info/METADATA,sha256=w_EeXXSG4Z-yWrXBFz3kKPRtXh4oMZH2kTrrfko7eos,4628
|
53
|
+
rclone_api-1.4.14.dist-info/WHEEL,sha256=rF4EZyR2XVS6irmOHQIJx2SUqXLZKRMUrjsg8UwN-XQ,109
|
54
|
+
rclone_api-1.4.14.dist-info/entry_points.txt,sha256=fJteOlYVwgX3UbNuL9jJ0zUTuX2O79JFAeNgK7Sw7EQ,255
|
55
|
+
rclone_api-1.4.14.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
|
56
|
+
rclone_api-1.4.14.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|