rclone-api 1.2.9__py2.py3-none-any.whl → 1.2.12__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 +10 -4
- rclone_api/s3/chunk_types.py +20 -13
- rclone_api/s3/upload_file_multipart.py +16 -11
- rclone_api/types.py +1 -1
- {rclone_api-1.2.9.dist-info → rclone_api-1.2.12.dist-info}/METADATA +1 -1
- {rclone_api-1.2.9.dist-info → rclone_api-1.2.12.dist-info}/RECORD +10 -10
- {rclone_api-1.2.9.dist-info → rclone_api-1.2.12.dist-info}/LICENSE +0 -0
- {rclone_api-1.2.9.dist-info → rclone_api-1.2.12.dist-info}/WHEEL +0 -0
- {rclone_api-1.2.9.dist-info → rclone_api-1.2.12.dist-info}/entry_points.txt +0 -0
- {rclone_api-1.2.9.dist-info → rclone_api-1.2.12.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
|
|
|
@@ -51,6 +51,9 @@ def file_chunker(
|
|
|
51
51
|
if max_chunks is None:
|
|
52
52
|
return False
|
|
53
53
|
if count >= max_chunks:
|
|
54
|
+
print(
|
|
55
|
+
f"Stopping file chunker after {count} chunks because it exceeded max_chunks {max_chunks}"
|
|
56
|
+
)
|
|
54
57
|
return True
|
|
55
58
|
count += 1
|
|
56
59
|
return False
|
|
@@ -63,7 +66,7 @@ def file_chunker(
|
|
|
63
66
|
try:
|
|
64
67
|
part_number = 1
|
|
65
68
|
done_part_numbers: set[int] = {
|
|
66
|
-
p.part_number for p in upload_state.parts if p
|
|
69
|
+
p.part_number for p in upload_state.parts if not isinstance(p, EndOfStream)
|
|
67
70
|
}
|
|
68
71
|
num_parts = upload_info.total_chunks()
|
|
69
72
|
|
|
@@ -133,4 +136,7 @@ def file_chunker(
|
|
|
133
136
|
|
|
134
137
|
warnings.warn(f"Error reading file: {e}")
|
|
135
138
|
finally:
|
|
136
|
-
|
|
139
|
+
print("#############################################################")
|
|
140
|
+
print(f"Finishing FILE CHUNKER for {file_path} and adding EndOfStream")
|
|
141
|
+
print("#############################################################")
|
|
142
|
+
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
|
|
|
@@ -246,6 +246,9 @@ def upload_file_multipart(
|
|
|
246
246
|
queue_errors.put(e)
|
|
247
247
|
_thread.interrupt_main()
|
|
248
248
|
raise
|
|
249
|
+
print("#########################################")
|
|
250
|
+
print("# CHUNKER TASK COMPLETED")
|
|
251
|
+
print("#########################################")
|
|
249
252
|
|
|
250
253
|
try:
|
|
251
254
|
thread_chunker = Thread(target=chunker_task, daemon=True)
|
|
@@ -254,11 +257,11 @@ def upload_file_multipart(
|
|
|
254
257
|
with ThreadPoolExecutor(max_workers=upload_threads) as executor:
|
|
255
258
|
try:
|
|
256
259
|
while True:
|
|
257
|
-
file_chunk: FilePart |
|
|
258
|
-
if file_chunk is
|
|
260
|
+
file_chunk: FilePart | EndOfStream = queue_upload.get()
|
|
261
|
+
if file_chunk is EndOfStream:
|
|
259
262
|
break
|
|
260
263
|
|
|
261
|
-
if isinstance(file_chunk,
|
|
264
|
+
if isinstance(file_chunk, EndOfStream):
|
|
262
265
|
break
|
|
263
266
|
|
|
264
267
|
def task(upload_info=upload_info, file_chunk=file_chunk):
|
|
@@ -280,7 +283,7 @@ def upload_file_multipart(
|
|
|
280
283
|
executor.shutdown(wait=False, cancel_futures=True)
|
|
281
284
|
raise
|
|
282
285
|
# upload_state.finished_parts.put(None) # Signal the end of the queue
|
|
283
|
-
upload_state.add_finished(
|
|
286
|
+
upload_state.add_finished(EndOfStream())
|
|
284
287
|
thread_chunker.join()
|
|
285
288
|
|
|
286
289
|
if not chunker_errors.empty():
|
|
@@ -288,7 +291,9 @@ def upload_file_multipart(
|
|
|
288
291
|
if not upload_state.is_done():
|
|
289
292
|
upload_state.save()
|
|
290
293
|
return MultiUploadResult.SUSPENDED
|
|
291
|
-
parts: list[FinishedPiece] = [
|
|
294
|
+
parts: list[FinishedPiece] = [
|
|
295
|
+
p for p in upload_state.parts if not isinstance(p, EndOfStream)
|
|
296
|
+
]
|
|
292
297
|
locked_print(f"Upload complete, sorting {len(parts)} parts to complete upload")
|
|
293
298
|
parts.sort(key=lambda x: x.part_number) # Some backends need this.
|
|
294
299
|
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=mk0koNiohOTJIp3nor2Lg-KlfbHeetC6GM4HVzkmEGY,4805
|
|
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=TrhrYeRkpQRzmn8x_RR59ww3GXA3Wd95pCKI-Bhu9_0,11372
|
|
36
|
+
rclone_api-1.2.12.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
|
|
37
|
+
rclone_api-1.2.12.dist-info/METADATA,sha256=47ATkIGrPGHwqK9hqVVJifxeli3iwGFnvusvIbS0_ms,4537
|
|
38
|
+
rclone_api-1.2.12.dist-info/WHEEL,sha256=rF4EZyR2XVS6irmOHQIJx2SUqXLZKRMUrjsg8UwN-XQ,109
|
|
39
|
+
rclone_api-1.2.12.dist-info/entry_points.txt,sha256=TV8kwP3FRzYwUEr0RLC7aJh0W03SAefIJNXTJ-FdMIQ,200
|
|
40
|
+
rclone_api-1.2.12.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
|
|
41
|
+
rclone_api-1.2.12.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|