rclone-api 1.2.9__py2.py3-none-any.whl → 1.2.11__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/s3/chunk_file.py +4 -4
- rclone_api/s3/chunk_types.py +20 -13
- rclone_api/s3/upload_file_multipart.py +13 -11
- rclone_api/types.py +1 -1
- {rclone_api-1.2.9.dist-info → rclone_api-1.2.11.dist-info}/METADATA +1 -1
- {rclone_api-1.2.9.dist-info → rclone_api-1.2.11.dist-info}/RECORD +10 -10
- {rclone_api-1.2.9.dist-info → rclone_api-1.2.11.dist-info}/LICENSE +0 -0
- {rclone_api-1.2.9.dist-info → rclone_api-1.2.11.dist-info}/WHEEL +0 -0
- {rclone_api-1.2.9.dist-info → rclone_api-1.2.11.dist-info}/entry_points.txt +0 -0
- {rclone_api-1.2.9.dist-info → rclone_api-1.2.11.dist-info}/top_level.txt +0 -0
rclone_api/s3/chunk_file.py
CHANGED
|
@@ -9,7 +9,7 @@ from typing import Any, Callable
|
|
|
9
9
|
|
|
10
10
|
from rclone_api.mount import FilePart
|
|
11
11
|
from rclone_api.s3.chunk_types import UploadState
|
|
12
|
-
from rclone_api.types import
|
|
12
|
+
from rclone_api.types import EndOfStream
|
|
13
13
|
from rclone_api.util import locked_print
|
|
14
14
|
|
|
15
15
|
|
|
@@ -41,7 +41,7 @@ def file_chunker(
|
|
|
41
41
|
fetcher: Callable[[int, int, Any], Future[FilePart]],
|
|
42
42
|
max_chunks: int | None,
|
|
43
43
|
cancel_signal: Event,
|
|
44
|
-
queue_upload: Queue[FilePart |
|
|
44
|
+
queue_upload: Queue[FilePart | EndOfStream],
|
|
45
45
|
) -> None:
|
|
46
46
|
count = 0
|
|
47
47
|
|
|
@@ -63,7 +63,7 @@ def file_chunker(
|
|
|
63
63
|
try:
|
|
64
64
|
part_number = 1
|
|
65
65
|
done_part_numbers: set[int] = {
|
|
66
|
-
p.part_number for p in upload_state.parts if p
|
|
66
|
+
p.part_number for p in upload_state.parts if not isinstance(p, EndOfStream)
|
|
67
67
|
}
|
|
68
68
|
num_parts = upload_info.total_chunks()
|
|
69
69
|
|
|
@@ -133,4 +133,4 @@ def file_chunker(
|
|
|
133
133
|
|
|
134
134
|
warnings.warn(f"Error reading file: {e}")
|
|
135
135
|
finally:
|
|
136
|
-
queue_upload.put(
|
|
136
|
+
queue_upload.put(EndOfStream())
|
rclone_api/s3/chunk_types.py
CHANGED
|
@@ -7,7 +7,7 @@ from threading import Lock
|
|
|
7
7
|
|
|
8
8
|
from botocore.client import BaseClient
|
|
9
9
|
|
|
10
|
-
from rclone_api.types import SizeSuffix
|
|
10
|
+
from rclone_api.types import EndOfStream, SizeSuffix
|
|
11
11
|
from rclone_api.util import locked_print
|
|
12
12
|
|
|
13
13
|
# _MIN_UPLOAD_CHUNK_SIZE = 5 * 1024 * 1024 # 5MB
|
|
@@ -83,27 +83,34 @@ class FinishedPiece:
|
|
|
83
83
|
return json.dumps(self.to_json(), indent=0)
|
|
84
84
|
|
|
85
85
|
@staticmethod
|
|
86
|
-
def to_json_array(parts: list["FinishedPiece |
|
|
87
|
-
non_none: list[FinishedPiece] = [
|
|
86
|
+
def to_json_array(parts: list["FinishedPiece | EndOfStream"]) -> list[dict]:
|
|
87
|
+
non_none: list[FinishedPiece] = []
|
|
88
|
+
for p in parts:
|
|
89
|
+
if not isinstance(p, EndOfStream):
|
|
90
|
+
non_none.append(p)
|
|
88
91
|
non_none.sort(key=lambda x: x.part_number)
|
|
89
|
-
all_nones: list[None] = [None for p in parts if p is None]
|
|
90
|
-
assert len(all_nones) <= 1, "Only one None should be present"
|
|
92
|
+
# all_nones: list[None] = [None for p in parts if p is None]
|
|
93
|
+
# assert len(all_nones) <= 1, "Only one None should be present"
|
|
94
|
+
count_eos = 0
|
|
95
|
+
for p in parts:
|
|
96
|
+
if p is EndOfStream:
|
|
97
|
+
count_eos += 1
|
|
98
|
+
assert count_eos <= 1, "Only one EndOfStream should be present"
|
|
91
99
|
return [p.to_json() for p in non_none]
|
|
92
100
|
|
|
93
101
|
@staticmethod
|
|
94
|
-
def from_json(json: dict | None) -> "FinishedPiece |
|
|
102
|
+
def from_json(json: dict | None) -> "FinishedPiece | EndOfStream":
|
|
95
103
|
if json is None:
|
|
96
|
-
return
|
|
104
|
+
return EndOfStream()
|
|
97
105
|
return FinishedPiece(**json)
|
|
98
106
|
|
|
99
107
|
|
|
100
108
|
@dataclass
|
|
101
109
|
class UploadState:
|
|
102
110
|
upload_info: UploadInfo
|
|
103
|
-
# finished_parts: Queue[FinishedPiece | None]
|
|
104
111
|
peristant: Path | None
|
|
105
112
|
lock: Lock = Lock()
|
|
106
|
-
parts: list[FinishedPiece |
|
|
113
|
+
parts: list[FinishedPiece | EndOfStream] = field(default_factory=list)
|
|
107
114
|
|
|
108
115
|
def update_source_file(self, src_file: Path, known_file_size: int | None) -> None:
|
|
109
116
|
new_file_size = (
|
|
@@ -126,7 +133,7 @@ class UploadState:
|
|
|
126
133
|
num_chunks = self.upload_info.total_chunks()
|
|
127
134
|
count = 0
|
|
128
135
|
for p in self.parts:
|
|
129
|
-
if p
|
|
136
|
+
if not isinstance(p, EndOfStream):
|
|
130
137
|
count += 1
|
|
131
138
|
return count, num_chunks
|
|
132
139
|
|
|
@@ -141,7 +148,7 @@ class UploadState:
|
|
|
141
148
|
), f"Count {count} is greater than num_chunks {num_chunks}"
|
|
142
149
|
return num_chunks - count
|
|
143
150
|
|
|
144
|
-
def add_finished(self, part: FinishedPiece |
|
|
151
|
+
def add_finished(self, part: FinishedPiece | EndOfStream) -> None:
|
|
145
152
|
if part is None:
|
|
146
153
|
return
|
|
147
154
|
with self.lock:
|
|
@@ -195,13 +202,13 @@ class UploadState:
|
|
|
195
202
|
def to_json(self) -> dict:
|
|
196
203
|
# queue -> list
|
|
197
204
|
# parts: list[dict] = [f.to_json() for f in self.parts]
|
|
198
|
-
parts: list[FinishedPiece |
|
|
205
|
+
parts: list[FinishedPiece | EndOfStream] = list(self.parts)
|
|
199
206
|
|
|
200
207
|
parts_json = FinishedPiece.to_json_array(parts)
|
|
201
208
|
is_done = self.is_done()
|
|
202
209
|
count_non_none: int = 0
|
|
203
210
|
for p in parts:
|
|
204
|
-
if p is not
|
|
211
|
+
if p is not EndOfStream:
|
|
205
212
|
count_non_none += 1
|
|
206
213
|
|
|
207
214
|
file_size_bytes = self.upload_info.file_size
|
|
@@ -18,7 +18,7 @@ from rclone_api.s3.chunk_types import (
|
|
|
18
18
|
UploadState,
|
|
19
19
|
)
|
|
20
20
|
from rclone_api.s3.types import MultiUploadResult
|
|
21
|
-
from rclone_api.types import
|
|
21
|
+
from rclone_api.types import EndOfStream
|
|
22
22
|
from rclone_api.util import locked_print
|
|
23
23
|
|
|
24
24
|
_MIN_UPLOAD_CHUNK_SIZE = 5 * 1024 * 1024 # 5MB
|
|
@@ -58,10 +58,10 @@ def upload_task(
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
def handle_upload(
|
|
61
|
-
upload_info: UploadInfo, fp: FilePart
|
|
62
|
-
) -> FinishedPiece | Exception |
|
|
63
|
-
if fp
|
|
64
|
-
return
|
|
61
|
+
upload_info: UploadInfo, fp: FilePart | EndOfStream
|
|
62
|
+
) -> FinishedPiece | Exception | EndOfStream:
|
|
63
|
+
if isinstance(fp, EndOfStream):
|
|
64
|
+
return fp
|
|
65
65
|
assert isinstance(fp.extra, S3FileInfo)
|
|
66
66
|
extra: S3FileInfo = fp.extra
|
|
67
67
|
part_number = extra.part_number
|
|
@@ -222,7 +222,7 @@ def upload_file_multipart(
|
|
|
222
222
|
started_new_upload = finished == 0
|
|
223
223
|
upload_info = upload_state.upload_info
|
|
224
224
|
|
|
225
|
-
queue_upload: Queue[FilePart |
|
|
225
|
+
queue_upload: Queue[FilePart | EndOfStream] = Queue(work_que_max)
|
|
226
226
|
chunker_errors: Queue[Exception] = Queue()
|
|
227
227
|
cancel_chunker_event = Event()
|
|
228
228
|
|
|
@@ -254,11 +254,11 @@ def upload_file_multipart(
|
|
|
254
254
|
with ThreadPoolExecutor(max_workers=upload_threads) as executor:
|
|
255
255
|
try:
|
|
256
256
|
while True:
|
|
257
|
-
file_chunk: FilePart |
|
|
258
|
-
if file_chunk is
|
|
257
|
+
file_chunk: FilePart | EndOfStream = queue_upload.get()
|
|
258
|
+
if file_chunk is EndOfStream:
|
|
259
259
|
break
|
|
260
260
|
|
|
261
|
-
if isinstance(file_chunk,
|
|
261
|
+
if isinstance(file_chunk, EndOfStream):
|
|
262
262
|
break
|
|
263
263
|
|
|
264
264
|
def task(upload_info=upload_info, file_chunk=file_chunk):
|
|
@@ -280,7 +280,7 @@ def upload_file_multipart(
|
|
|
280
280
|
executor.shutdown(wait=False, cancel_futures=True)
|
|
281
281
|
raise
|
|
282
282
|
# upload_state.finished_parts.put(None) # Signal the end of the queue
|
|
283
|
-
upload_state.add_finished(
|
|
283
|
+
upload_state.add_finished(EndOfStream())
|
|
284
284
|
thread_chunker.join()
|
|
285
285
|
|
|
286
286
|
if not chunker_errors.empty():
|
|
@@ -288,7 +288,9 @@ def upload_file_multipart(
|
|
|
288
288
|
if not upload_state.is_done():
|
|
289
289
|
upload_state.save()
|
|
290
290
|
return MultiUploadResult.SUSPENDED
|
|
291
|
-
parts: list[FinishedPiece] = [
|
|
291
|
+
parts: list[FinishedPiece] = [
|
|
292
|
+
p for p in upload_state.parts if not isinstance(p, EndOfStream)
|
|
293
|
+
]
|
|
292
294
|
locked_print(f"Upload complete, sorting {len(parts)} parts to complete upload")
|
|
293
295
|
parts.sort(key=lambda x: x.part_number) # Some backends need this.
|
|
294
296
|
parts_s3: list[dict] = [
|
rclone_api/types.py
CHANGED
|
@@ -17,7 +17,7 @@ rclone_api/rclone.py,sha256=4_eoKkC0eZDT2VnpMlrF5EkDZam5WWaiiWFxNntqs2k,49323
|
|
|
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=XiiWoGXAzNxTEfRcszw3BeRF7ZATXHIAPFg2-aJzUfo,9926
|
|
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
|
|
@@ -28,14 +28,14 @@ rclone_api/experimental/flags_base.py,sha256=ajU_czkTcAxXYU-SlmiCfHY7aCQGHvpCLqJ
|
|
|
28
28
|
rclone_api/profile/mount_copy_bytes.py,sha256=HK11knsykKO1WNi8LYOkQbipQBpZn7uhV5CVEQDRCJs,8558
|
|
29
29
|
rclone_api/s3/api.py,sha256=PafsIEyWDpLWAXsZAjFm9CY14vJpsDr9lOsn0kGRLZ0,4009
|
|
30
30
|
rclone_api/s3/basic_ops.py,sha256=hK3366xhVEzEcjz9Gk_8lFx6MRceAk72cax6mUrr6ko,2104
|
|
31
|
-
rclone_api/s3/chunk_file.py,sha256=
|
|
32
|
-
rclone_api/s3/chunk_types.py,sha256=
|
|
31
|
+
rclone_api/s3/chunk_file.py,sha256=kuLz1hgEydKCQZWFgrfzPtIzjRCbte1eZz5aKe0ubcg,4428
|
|
32
|
+
rclone_api/s3/chunk_types.py,sha256=I0YCWFgxCvmt8cp4tMabiiwiD2yKTcbA6ZL2D3xnn5w,8781
|
|
33
33
|
rclone_api/s3/create.py,sha256=wgfkapv_j904CfKuWyiBIWJVxfAx_ftemFSUV14aT68,3149
|
|
34
34
|
rclone_api/s3/types.py,sha256=FkUNNAk8fjSbLhDA45YgNQk9BTjmJZHT3fExiCKcDt0,1591
|
|
35
|
-
rclone_api/s3/upload_file_multipart.py,sha256=
|
|
36
|
-
rclone_api-1.2.
|
|
37
|
-
rclone_api-1.2.
|
|
38
|
-
rclone_api-1.2.
|
|
39
|
-
rclone_api-1.2.
|
|
40
|
-
rclone_api-1.2.
|
|
41
|
-
rclone_api-1.2.
|
|
35
|
+
rclone_api/s3/upload_file_multipart.py,sha256=Bpkaj4HRNwbmjlWoPXHG9Jtfr4Y3KNnRGtyGnrao70I,11212
|
|
36
|
+
rclone_api-1.2.11.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
|
|
37
|
+
rclone_api-1.2.11.dist-info/METADATA,sha256=tZjLSJOrP_cBKpMLKusuQC51_zdBMg5rEx5QgximXCg,4537
|
|
38
|
+
rclone_api-1.2.11.dist-info/WHEEL,sha256=rF4EZyR2XVS6irmOHQIJx2SUqXLZKRMUrjsg8UwN-XQ,109
|
|
39
|
+
rclone_api-1.2.11.dist-info/entry_points.txt,sha256=TV8kwP3FRzYwUEr0RLC7aJh0W03SAefIJNXTJ-FdMIQ,200
|
|
40
|
+
rclone_api-1.2.11.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
|
|
41
|
+
rclone_api-1.2.11.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|