rclone-api 1.3.28__py2.py3-none-any.whl → 1.4.1__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 +491 -4
- rclone_api/cmd/copy_large_s3.py +17 -10
- rclone_api/db/db.py +3 -3
- rclone_api/detail/copy_file_parts.py +382 -0
- rclone_api/dir.py +1 -1
- rclone_api/dir_listing.py +1 -1
- rclone_api/file.py +8 -0
- rclone_api/file_part.py +198 -0
- rclone_api/file_stream.py +52 -0
- rclone_api/http_server.py +15 -21
- rclone_api/{rclone.py → rclone_impl.py} +153 -321
- rclone_api/remote.py +3 -3
- rclone_api/rpath.py +11 -4
- rclone_api/s3/chunk_task.py +3 -19
- rclone_api/s3/multipart/file_info.py +7 -0
- rclone_api/s3/multipart/finished_piece.py +38 -0
- rclone_api/s3/multipart/upload_info.py +62 -0
- rclone_api/s3/{chunk_types.py → multipart/upload_state.py} +3 -99
- rclone_api/s3/s3_multipart_uploader.py +138 -28
- rclone_api/s3/types.py +1 -1
- rclone_api/s3/upload_file_multipart.py +6 -13
- rclone_api/scan_missing_folders.py +1 -1
- rclone_api/types.py +136 -165
- rclone_api/util.py +22 -2
- {rclone_api-1.3.28.dist-info → rclone_api-1.4.1.dist-info}/METADATA +1 -1
- rclone_api-1.4.1.dist-info/RECORD +55 -0
- rclone_api/mount_read_chunker.py +0 -130
- rclone_api/profile/mount_copy_bytes.py +0 -311
- rclone_api-1.3.28.dist-info/RECORD +0 -51
- /rclone_api/{walk.py → detail/walk.py} +0 -0
- {rclone_api-1.3.28.dist-info → rclone_api-1.4.1.dist-info}/LICENSE +0 -0
- {rclone_api-1.3.28.dist-info → rclone_api-1.4.1.dist-info}/WHEEL +0 -0
- {rclone_api-1.3.28.dist-info → rclone_api-1.4.1.dist-info}/entry_points.txt +0 -0
- {rclone_api-1.3.28.dist-info → rclone_api-1.4.1.dist-info}/top_level.txt +0 -0
rclone_api/http_server.py
CHANGED
@@ -5,30 +5,19 @@ Unit test file for testing rclone mount functionality.
|
|
5
5
|
import tempfile
|
6
6
|
import warnings
|
7
7
|
from concurrent.futures import Future, ThreadPoolExecutor
|
8
|
-
from dataclasses import dataclass
|
9
8
|
from pathlib import Path
|
9
|
+
from threading import Semaphore
|
10
10
|
from typing import Any
|
11
11
|
|
12
12
|
import httpx
|
13
13
|
|
14
|
+
from rclone_api.file_part import FilePart
|
14
15
|
from rclone_api.process import Process
|
15
|
-
from rclone_api.types import
|
16
|
+
from rclone_api.types import Range, SizeSuffix, get_chunk_tmpdir
|
16
17
|
|
17
18
|
_TIMEOUT = 10 * 60 # 10 minutes
|
18
19
|
|
19
20
|
|
20
|
-
@dataclass
|
21
|
-
class Range:
|
22
|
-
start: int
|
23
|
-
end: int
|
24
|
-
|
25
|
-
def to_header(self) -> dict[str, str]:
|
26
|
-
val = f"bytes={self.start}-{self.end-1}"
|
27
|
-
return {
|
28
|
-
"Range": val,
|
29
|
-
}
|
30
|
-
|
31
|
-
|
32
21
|
_range = range
|
33
22
|
|
34
23
|
|
@@ -49,10 +38,10 @@ class HttpServer:
|
|
49
38
|
def get_fetcher(self, path: str, n_threads: int = 16) -> "HttpFetcher":
|
50
39
|
return HttpFetcher(self, path, n_threads=n_threads)
|
51
40
|
|
52
|
-
def get(self, path: str) -> bytes | Exception:
|
41
|
+
def get(self, path: str, range: Range | None = None) -> bytes | Exception:
|
53
42
|
"""Get bytes from the server."""
|
54
43
|
with tempfile.TemporaryFile() as file:
|
55
|
-
self.download(path, Path(file.name),
|
44
|
+
self.download(path, Path(file.name), range)
|
56
45
|
file.seek(0)
|
57
46
|
return file.read()
|
58
47
|
|
@@ -124,8 +113,13 @@ class HttpServer:
|
|
124
113
|
with ThreadPoolExecutor(max_workers=n_threads) as executor:
|
125
114
|
try:
|
126
115
|
futures: list[Future[Path | Exception]] = []
|
127
|
-
|
128
|
-
|
116
|
+
start: int
|
117
|
+
for start in _range(
|
118
|
+
range.start.as_int(), range.end.as_int(), chunk_size
|
119
|
+
):
|
120
|
+
end = min(
|
121
|
+
SizeSuffix(start + chunk_size).as_int(), range.end.as_int()
|
122
|
+
)
|
129
123
|
r = Range(start=start, end=end)
|
130
124
|
|
131
125
|
def task(r: Range = r) -> Path | Exception:
|
@@ -200,11 +194,11 @@ class HttpFetcher:
|
|
200
194
|
self.server = server
|
201
195
|
self.path = path
|
202
196
|
self.executor = ThreadPoolExecutor(max_workers=n_threads)
|
203
|
-
|
204
|
-
|
197
|
+
# Semaphore throttles the number of concurrent fetches
|
198
|
+
# TODO this is kind of a hack.
|
205
199
|
self.semaphore = Semaphore(n_threads)
|
206
200
|
|
207
|
-
def
|
201
|
+
def bytes_fetcher(
|
208
202
|
self, offset: int | SizeSuffix, size: int | SizeSuffix, extra: Any
|
209
203
|
) -> Future[FilePart]:
|
210
204
|
if isinstance(offset, SizeSuffix):
|