tosnativeclient 1.0.0__tar.gz → 1.0.2__tar.gz
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.
Potentially problematic release.
This version of tosnativeclient might be problematic. Click here for more details.
- {tosnativeclient-1.0.0 → tosnativeclient-1.0.2}/Cargo.lock +20 -1
- {tosnativeclient-1.0.0 → tosnativeclient-1.0.2}/Cargo.toml +3 -2
- {tosnativeclient-1.0.0 → tosnativeclient-1.0.2}/PKG-INFO +2 -1
- {tosnativeclient-1.0.0 → tosnativeclient-1.0.2}/pyproject.toml +1 -0
- tosnativeclient-1.0.2/python/tosnativeclient/__init__.py +25 -0
- tosnativeclient-1.0.2/python/tosnativeclient/tosnativeclient.pyi +211 -0
- {tosnativeclient-1.0.0 → tosnativeclient-1.0.2}/src/lib.rs +16 -0
- {tosnativeclient-1.0.0 → tosnativeclient-1.0.2}/src/list_stream.rs +27 -44
- {tosnativeclient-1.0.0 → tosnativeclient-1.0.2}/src/read_stream.rs +2 -2
- {tosnativeclient-1.0.0 → tosnativeclient-1.0.2}/src/tos_client.rs +23 -18
- {tosnativeclient-1.0.0 → tosnativeclient-1.0.2}/src/tos_error.rs +6 -1
- tosnativeclient-1.0.2/src/tos_raw_client.rs +436 -0
- {tosnativeclient-1.0.0 → tosnativeclient-1.0.2}/src/write_stream.rs +6 -8
- tosnativeclient-1.0.0/python/tosnativeclient/__init__.py +0 -4
- tosnativeclient-1.0.0/python/tosnativeclient/tosnativeclient.pyi +0 -91
- {tosnativeclient-1.0.0 → tosnativeclient-1.0.2}/.github/workflows/CI.yml +0 -0
- {tosnativeclient-1.0.0 → tosnativeclient-1.0.2}/.gitignore +0 -0
- {tosnativeclient-1.0.0 → tosnativeclient-1.0.2}/build.sh +0 -0
- {tosnativeclient-1.0.0 → tosnativeclient-1.0.2}/src/tos_model.rs +0 -0
|
@@ -472,6 +472,12 @@ version = "0.5.0"
|
|
|
472
472
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
473
473
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
474
474
|
|
|
475
|
+
[[package]]
|
|
476
|
+
name = "hermit-abi"
|
|
477
|
+
version = "0.5.2"
|
|
478
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
479
|
+
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
|
|
480
|
+
|
|
475
481
|
[[package]]
|
|
476
482
|
name = "hex"
|
|
477
483
|
version = "0.4.3"
|
|
@@ -859,6 +865,16 @@ dependencies = [
|
|
|
859
865
|
"autocfg",
|
|
860
866
|
]
|
|
861
867
|
|
|
868
|
+
[[package]]
|
|
869
|
+
name = "num_cpus"
|
|
870
|
+
version = "1.17.0"
|
|
871
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
872
|
+
checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
|
|
873
|
+
dependencies = [
|
|
874
|
+
"hermit-abi",
|
|
875
|
+
"libc",
|
|
876
|
+
]
|
|
877
|
+
|
|
862
878
|
[[package]]
|
|
863
879
|
name = "object"
|
|
864
880
|
version = "0.36.7"
|
|
@@ -1505,13 +1521,14 @@ dependencies = [
|
|
|
1505
1521
|
|
|
1506
1522
|
[[package]]
|
|
1507
1523
|
name = "tosnativeclient"
|
|
1508
|
-
version = "1.0.
|
|
1524
|
+
version = "1.0.2"
|
|
1509
1525
|
dependencies = [
|
|
1510
1526
|
"arc-swap",
|
|
1511
1527
|
"async-channel",
|
|
1512
1528
|
"async-trait",
|
|
1513
1529
|
"bytes",
|
|
1514
1530
|
"futures-util",
|
|
1531
|
+
"num_cpus",
|
|
1515
1532
|
"pyo3",
|
|
1516
1533
|
"tokio",
|
|
1517
1534
|
"tracing",
|
|
@@ -1704,6 +1721,8 @@ dependencies = [
|
|
|
1704
1721
|
"serde",
|
|
1705
1722
|
"serde_json",
|
|
1706
1723
|
"sha2",
|
|
1724
|
+
"tokio",
|
|
1725
|
+
"tokio-util",
|
|
1707
1726
|
"tracing",
|
|
1708
1727
|
"tracing-appender",
|
|
1709
1728
|
"tracing-subscriber",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "tosnativeclient"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.2"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
publish = false
|
|
6
6
|
authors = ["xiangshijian"]
|
|
@@ -15,7 +15,7 @@ crate-type = ["cdylib"]
|
|
|
15
15
|
[dependencies]
|
|
16
16
|
arc-swap = "1.7.1"
|
|
17
17
|
pyo3 = { version = "0.25.0", features = ["extension-module"] }
|
|
18
|
-
ve-tos-rust-sdk = "2.3.0"
|
|
18
|
+
ve-tos-rust-sdk = { version = "2.3.0", features = ["async-file"] }
|
|
19
19
|
tracing-appender = "0.2.3"
|
|
20
20
|
bytes = "1.10.1"
|
|
21
21
|
tokio = { version = "1.36.0", features = ["rt-multi-thread"] }
|
|
@@ -23,3 +23,4 @@ async-trait = "0.1.88"
|
|
|
23
23
|
futures-util = "0.3.30"
|
|
24
24
|
async-channel = "2.3.1"
|
|
25
25
|
tracing = { version = "0.1.41", features = ["log"] }
|
|
26
|
+
num_cpus = "1.17.0"
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tosnativeclient
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
6
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
7
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
7
8
|
Summary: python native client for tos
|
|
8
9
|
Author: xiangshijian
|
|
9
10
|
License: Apache-2.0
|
|
@@ -10,6 +10,7 @@ classifiers = [
|
|
|
10
10
|
"Programming Language :: Rust",
|
|
11
11
|
"Programming Language :: Python :: Implementation :: CPython",
|
|
12
12
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
13
|
+
"License :: OSI Approved :: Apache Software License",
|
|
13
14
|
]
|
|
14
15
|
dynamic = ["version"]
|
|
15
16
|
[tool.maturin]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from .tosnativeclient import TosClient, ListStream, ListObjectsResult, TosObject, ReadStream, WriteStream, TosError, \
|
|
2
|
+
TosException, TosRawClient, \
|
|
3
|
+
HeadObjectInput, HeadObjectOutput, GetObjectOutput, DeleteObjectInput, DeleteObjectOutput, GetObjectInput, \
|
|
4
|
+
PutObjectFromBufferInput, PutObjectFromFileInput, PutObjectOutput
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
'TosError',
|
|
8
|
+
'TosException',
|
|
9
|
+
'TosClient',
|
|
10
|
+
'ListStream',
|
|
11
|
+
'ListObjectsResult',
|
|
12
|
+
'TosObject',
|
|
13
|
+
'ReadStream',
|
|
14
|
+
'WriteStream',
|
|
15
|
+
'TosRawClient',
|
|
16
|
+
'HeadObjectInput',
|
|
17
|
+
'HeadObjectOutput',
|
|
18
|
+
'DeleteObjectInput',
|
|
19
|
+
'DeleteObjectOutput',
|
|
20
|
+
'GetObjectInput',
|
|
21
|
+
'GetObjectOutput',
|
|
22
|
+
'PutObjectFromBufferInput',
|
|
23
|
+
'PutObjectFromFileInput',
|
|
24
|
+
'PutObjectOutput'
|
|
25
|
+
]
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
from typing import List, Dict
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TosError(object):
|
|
7
|
+
message: str
|
|
8
|
+
status_code: Optional[int]
|
|
9
|
+
ec: str
|
|
10
|
+
request_id: str
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TosException(Exception):
|
|
14
|
+
args: List[TosError]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TosObject(object):
|
|
18
|
+
bucket: str
|
|
19
|
+
key: str
|
|
20
|
+
size: int
|
|
21
|
+
etag: str
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ListObjectsResult(object):
|
|
25
|
+
contents: List[TosObject]
|
|
26
|
+
common_prefixes: List[str]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ListStream(object):
|
|
30
|
+
bucket: str
|
|
31
|
+
prefix: str
|
|
32
|
+
delimiter: str
|
|
33
|
+
max_keys: int
|
|
34
|
+
|
|
35
|
+
def __iter__(self) -> ListStream: ...
|
|
36
|
+
|
|
37
|
+
def __next__(self) -> ListObjectsResult: ...
|
|
38
|
+
|
|
39
|
+
def close(self) -> None: ...
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class ReadStream(object):
|
|
43
|
+
bucket: str
|
|
44
|
+
key: str
|
|
45
|
+
size: int
|
|
46
|
+
etag: str
|
|
47
|
+
|
|
48
|
+
def read(self, offset: int, length: int) -> bytes:
|
|
49
|
+
...
|
|
50
|
+
|
|
51
|
+
def close(self) -> None:
|
|
52
|
+
...
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class WriteStream(object):
|
|
56
|
+
bucket: str
|
|
57
|
+
key: str
|
|
58
|
+
storage_class: Optional[str]
|
|
59
|
+
|
|
60
|
+
def write(self, data: bytes) -> int:
|
|
61
|
+
...
|
|
62
|
+
|
|
63
|
+
def close(self) -> None:
|
|
64
|
+
...
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class TosClient(object):
|
|
68
|
+
region: str
|
|
69
|
+
endpoint: str
|
|
70
|
+
ak: str
|
|
71
|
+
sk: str
|
|
72
|
+
part_size: int
|
|
73
|
+
max_retry_count: int
|
|
74
|
+
max_prefetch_tasks: int
|
|
75
|
+
|
|
76
|
+
def __init__(self, region: str, endpoint: str, ak: str = '', sk: str = '', part_size: int = 8388608,
|
|
77
|
+
max_retry_count: int = 3, max_prefetch_tasks: int = 3, directives: str = '', directory: str = '',
|
|
78
|
+
file_name_prefix: str = '', shared_prefetch_tasks: int = 20):
|
|
79
|
+
...
|
|
80
|
+
|
|
81
|
+
def list_objects(self, bucket: str, prefix: str = '', max_keys: int = 1000, delimiter: str = '') -> ListStream:
|
|
82
|
+
...
|
|
83
|
+
|
|
84
|
+
def head_object(self, bucket: str, key: str) -> TosObject:
|
|
85
|
+
...
|
|
86
|
+
|
|
87
|
+
def get_object(self, bucket: str, key: str, etag: str, size: int) -> ReadStream:
|
|
88
|
+
...
|
|
89
|
+
|
|
90
|
+
def put_object(self, bucket: str, key: str, storage_class: Optional[str] = '') -> WriteStream:
|
|
91
|
+
...
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class HeadObjectInput(object):
|
|
95
|
+
bucket: str
|
|
96
|
+
key: str
|
|
97
|
+
version_id: str
|
|
98
|
+
|
|
99
|
+
def __init__(self, bucket: str, key: str, version_id: str = ''):
|
|
100
|
+
...
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class HeadObjectOutput(object):
|
|
104
|
+
request_id: str
|
|
105
|
+
status_code: int
|
|
106
|
+
header: Dict[str, str]
|
|
107
|
+
content_length: int
|
|
108
|
+
etag: str
|
|
109
|
+
version_id: str
|
|
110
|
+
hash_crc64ecma: int
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class DeleteObjectInput(object):
|
|
114
|
+
bucket: str
|
|
115
|
+
key: str
|
|
116
|
+
version_id: str
|
|
117
|
+
|
|
118
|
+
def __init__(self, bucket: str, key: str, version_id: str = ''):
|
|
119
|
+
...
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class DeleteObjectOutput(object):
|
|
123
|
+
request_id: str
|
|
124
|
+
status_code: int
|
|
125
|
+
header: Dict[str, str]
|
|
126
|
+
delete_marker: bool
|
|
127
|
+
version_id: str
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class GetObjectInput(object):
|
|
131
|
+
bucket: str
|
|
132
|
+
key: str
|
|
133
|
+
version_id: str
|
|
134
|
+
range: str
|
|
135
|
+
|
|
136
|
+
def __init__(self, bucket: str, key: str, version_id: str = '', range: str = ''):
|
|
137
|
+
...
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class GetObjectOutput(object):
|
|
141
|
+
request_id: str
|
|
142
|
+
status_code: int
|
|
143
|
+
header: Dict[str, str]
|
|
144
|
+
content_length: int
|
|
145
|
+
etag: str
|
|
146
|
+
version_id: str
|
|
147
|
+
content_range: str
|
|
148
|
+
hash_crc64ecma: int
|
|
149
|
+
|
|
150
|
+
def read_all(self) -> bytes:
|
|
151
|
+
...
|
|
152
|
+
|
|
153
|
+
def read(self) -> bytes:
|
|
154
|
+
...
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class PutObjectFromBufferInput(object):
|
|
158
|
+
bucket: str
|
|
159
|
+
key: str
|
|
160
|
+
content: bytes
|
|
161
|
+
|
|
162
|
+
def __init__(self, bucket: str, key: str, content: bytes):
|
|
163
|
+
...
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class PutObjectFromFileInput(object):
|
|
167
|
+
bucket: str
|
|
168
|
+
key: str
|
|
169
|
+
file_path: str
|
|
170
|
+
|
|
171
|
+
def __init__(self, bucket: str, key: str, file_path: str):
|
|
172
|
+
...
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class PutObjectOutput(object):
|
|
176
|
+
request_id: str
|
|
177
|
+
status_code: int
|
|
178
|
+
header: Dict[str, str]
|
|
179
|
+
etag: str
|
|
180
|
+
version_id: str
|
|
181
|
+
hash_crc64ecma: int
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class TosRawClient(object):
|
|
185
|
+
region: str
|
|
186
|
+
endpoint: str
|
|
187
|
+
ak: str
|
|
188
|
+
sk: str
|
|
189
|
+
connection_timeout: int
|
|
190
|
+
request_timeout: int
|
|
191
|
+
max_connections: int
|
|
192
|
+
max_retry_count: int
|
|
193
|
+
|
|
194
|
+
def __init__(self, region: str, endpoint: str, ak: str = '', sk: str = '', connection_timeout: int = 10000,
|
|
195
|
+
request_timeout: int = 120000, max_connections: int = 1024, max_retry_count: int = 3):
|
|
196
|
+
...
|
|
197
|
+
|
|
198
|
+
def head_object(self, input: HeadObjectInput) -> HeadObjectOutput:
|
|
199
|
+
...
|
|
200
|
+
|
|
201
|
+
def delete_object(self, input: DeleteObjectInput) -> DeleteObjectOutput:
|
|
202
|
+
...
|
|
203
|
+
|
|
204
|
+
def get_object(self, input: GetObjectInput) -> GetObjectOutput:
|
|
205
|
+
...
|
|
206
|
+
|
|
207
|
+
def put_object_from_buffer(self, input: PutObjectFromBufferInput) -> PutObjectOutput:
|
|
208
|
+
...
|
|
209
|
+
|
|
210
|
+
def put_object_from_file(self, input: PutObjectFromFileInput) -> PutObjectOutput:
|
|
211
|
+
...
|
|
@@ -3,6 +3,11 @@ use crate::read_stream::ReadStream;
|
|
|
3
3
|
use crate::tos_client::TosClient;
|
|
4
4
|
use crate::tos_error::{TosError, TosException};
|
|
5
5
|
use crate::tos_model::{ListObjectsResult, TosObject};
|
|
6
|
+
use crate::tos_raw_client::{
|
|
7
|
+
DeleteObjectInput, DeleteObjectOutput, GetObjectInput, GetObjectOutput, HeadObjectInput,
|
|
8
|
+
HeadObjectOutput, PutObjectFromBufferInput, PutObjectFromFileInput, PutObjectOutput,
|
|
9
|
+
TosRawClient,
|
|
10
|
+
};
|
|
6
11
|
use crate::write_stream::WriteStream;
|
|
7
12
|
use pyo3::prelude::*;
|
|
8
13
|
|
|
@@ -11,11 +16,22 @@ mod read_stream;
|
|
|
11
16
|
mod tos_client;
|
|
12
17
|
mod tos_error;
|
|
13
18
|
mod tos_model;
|
|
19
|
+
mod tos_raw_client;
|
|
14
20
|
mod write_stream;
|
|
15
21
|
|
|
16
22
|
#[pymodule]
|
|
17
23
|
#[pyo3(name = "tosnativeclient")]
|
|
18
24
|
fn main(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
25
|
+
m.add_class::<TosRawClient>()?;
|
|
26
|
+
m.add_class::<HeadObjectInput>()?;
|
|
27
|
+
m.add_class::<HeadObjectOutput>()?;
|
|
28
|
+
m.add_class::<DeleteObjectInput>()?;
|
|
29
|
+
m.add_class::<DeleteObjectOutput>()?;
|
|
30
|
+
m.add_class::<GetObjectInput>()?;
|
|
31
|
+
m.add_class::<GetObjectOutput>()?;
|
|
32
|
+
m.add_class::<PutObjectFromBufferInput>()?;
|
|
33
|
+
m.add_class::<PutObjectFromFileInput>()?;
|
|
34
|
+
m.add_class::<PutObjectOutput>()?;
|
|
19
35
|
m.add_class::<TosClient>()?;
|
|
20
36
|
m.add_class::<ListStream>()?;
|
|
21
37
|
m.add_class::<ListObjectsResult>()?;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
use crate::tos_client::InnerTosClient;
|
|
2
|
-
use crate::tos_error::{
|
|
2
|
+
use crate::tos_error::{map_error_from_string, map_tos_error};
|
|
3
3
|
use crate::tos_model::ListObjectsResult;
|
|
4
4
|
use arc_swap::ArcSwap;
|
|
5
5
|
use async_channel::Receiver;
|
|
@@ -46,14 +46,11 @@ impl ListStream {
|
|
|
46
46
|
return Err(map_error_from_string("ListStream is closed"));
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
*pg = slf.list_background(slf.py());
|
|
53
|
-
}
|
|
49
|
+
let mut pg = slf.paginator.write().unwrap();
|
|
50
|
+
if pg.is_none() {
|
|
51
|
+
*pg = slf.list_background(slf.py());
|
|
54
52
|
}
|
|
55
|
-
|
|
56
|
-
slf.next_page(slf.paginator.read().unwrap().as_ref(), slf.py())
|
|
53
|
+
slf.next_page(pg.as_ref(), slf.py())
|
|
57
54
|
}
|
|
58
55
|
|
|
59
56
|
pub fn close(&self) {
|
|
@@ -100,67 +97,54 @@ impl ListStream {
|
|
|
100
97
|
py.allow_threads(|| {
|
|
101
98
|
self.runtime.spawn(async move {
|
|
102
99
|
let mut need_break = false;
|
|
103
|
-
if input.delimiter() == "
|
|
104
|
-
let mut prefixes = Vec::with_capacity(16);
|
|
105
|
-
let mut last_page_end = false;
|
|
100
|
+
if input.delimiter() == "" {
|
|
106
101
|
loop {
|
|
107
|
-
if last_page_end {
|
|
108
|
-
if prefixes.is_empty() {
|
|
109
|
-
let _ = sender
|
|
110
|
-
.send((
|
|
111
|
-
true,
|
|
112
|
-
Err(TosError::TosClientError {
|
|
113
|
-
message: "invalid status error".to_string(),
|
|
114
|
-
cause: None,
|
|
115
|
-
}),
|
|
116
|
-
))
|
|
117
|
-
.await;
|
|
118
|
-
break;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
let prefix = prefixes.remove(0);
|
|
122
|
-
input.set_prefix(prefix);
|
|
123
|
-
input.set_start_after("");
|
|
124
|
-
input.set_continuation_token("");
|
|
125
|
-
last_page_end = false;
|
|
126
|
-
}
|
|
127
102
|
let result = client.list_objects_type2(&input).await;
|
|
128
103
|
if let Ok(ref o) = result {
|
|
129
104
|
if o.is_truncated() {
|
|
130
105
|
input.set_continuation_token(o.next_continuation_token());
|
|
131
106
|
} else {
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
for cp in o.common_prefixes() {
|
|
136
|
-
prefixes.push(cp.prefix().to_string());
|
|
107
|
+
need_break = true;
|
|
137
108
|
}
|
|
138
|
-
need_break = last_page_end && prefixes.is_empty();
|
|
139
109
|
} else {
|
|
140
110
|
need_break = true;
|
|
141
111
|
}
|
|
142
|
-
|
|
143
112
|
if let Err(_) = sender.send((need_break, result)).await {
|
|
144
|
-
need_break = true
|
|
113
|
+
need_break = true
|
|
145
114
|
}
|
|
146
115
|
if need_break {
|
|
147
116
|
break;
|
|
148
117
|
}
|
|
149
118
|
}
|
|
150
119
|
} else {
|
|
120
|
+
let mut prefixes = Vec::with_capacity(16);
|
|
121
|
+
let mut last_page_end = false;
|
|
151
122
|
loop {
|
|
123
|
+
if last_page_end {
|
|
124
|
+
let prefix = prefixes.remove(0);
|
|
125
|
+
input.set_prefix(prefix);
|
|
126
|
+
input.set_start_after("");
|
|
127
|
+
input.set_continuation_token("");
|
|
128
|
+
last_page_end = false;
|
|
129
|
+
}
|
|
152
130
|
let result = client.list_objects_type2(&input).await;
|
|
153
131
|
if let Ok(ref o) = result {
|
|
154
132
|
if o.is_truncated() {
|
|
155
133
|
input.set_continuation_token(o.next_continuation_token());
|
|
156
134
|
} else {
|
|
157
|
-
|
|
135
|
+
last_page_end = true;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
for cp in o.common_prefixes() {
|
|
139
|
+
prefixes.push(cp.prefix().to_string());
|
|
158
140
|
}
|
|
141
|
+
need_break = last_page_end && prefixes.is_empty();
|
|
159
142
|
} else {
|
|
160
143
|
need_break = true;
|
|
161
144
|
}
|
|
145
|
+
|
|
162
146
|
if let Err(_) = sender.send((need_break, result)).await {
|
|
163
|
-
need_break = true
|
|
147
|
+
need_break = true;
|
|
164
148
|
}
|
|
165
149
|
if need_break {
|
|
166
150
|
break;
|
|
@@ -169,7 +153,6 @@ impl ListStream {
|
|
|
169
153
|
}
|
|
170
154
|
});
|
|
171
155
|
});
|
|
172
|
-
|
|
173
156
|
Some(Paginator {
|
|
174
157
|
is_end: ArcSwap::new(Arc::new(false)),
|
|
175
158
|
last_err: ArcSwap::new(Arc::new(None)),
|
|
@@ -187,7 +170,7 @@ impl ListStream {
|
|
|
187
170
|
None => Ok(None),
|
|
188
171
|
Some(pg) => {
|
|
189
172
|
match pg.has_next() {
|
|
190
|
-
Err(ex) => return Err(
|
|
173
|
+
Err(ex) => return Err(map_tos_error(ex)),
|
|
191
174
|
Ok(has_next) => {
|
|
192
175
|
if !has_next {
|
|
193
176
|
return Ok(None);
|
|
@@ -199,7 +182,7 @@ impl ListStream {
|
|
|
199
182
|
self.runtime.block_on(async {
|
|
200
183
|
match pg.next_page().await {
|
|
201
184
|
Ok(output) => Ok(Some(ListObjectsResult::new(output))),
|
|
202
|
-
Err(ex) => Err(
|
|
185
|
+
Err(ex) => Err(map_tos_error(ex)),
|
|
203
186
|
}
|
|
204
187
|
})
|
|
205
188
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
use crate::tos_client::{InnerTosClient, SharedPrefetchContext};
|
|
2
|
-
use crate::tos_error::
|
|
2
|
+
use crate::tos_error::map_tos_error;
|
|
3
3
|
use crate::tos_model::TosObject;
|
|
4
4
|
use async_channel::{Receiver, Sender};
|
|
5
5
|
use bytes::Bytes;
|
|
@@ -52,7 +52,7 @@ impl ReadStream {
|
|
|
52
52
|
.py()
|
|
53
53
|
.allow_threads(|| runtime.block_on(async move { fetcher.read(offset, length).await }))
|
|
54
54
|
{
|
|
55
|
-
Err(ex) => Err(
|
|
55
|
+
Err(ex) => Err(map_tos_error(ex)),
|
|
56
56
|
Ok(result) => match result {
|
|
57
57
|
None => Ok(None),
|
|
58
58
|
Some(data) => Ok(Some(PyBytes::new(slf.py(), data.as_ref()))),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
use crate::list_stream::ListStream;
|
|
2
2
|
use crate::read_stream::ReadStream;
|
|
3
|
-
use crate::tos_error::
|
|
3
|
+
use crate::tos_error::map_tos_error;
|
|
4
4
|
use crate::tos_model::TosObject;
|
|
5
5
|
use crate::write_stream::WriteStream;
|
|
6
6
|
use async_trait::async_trait;
|
|
@@ -10,8 +10,7 @@ use std::future::Future;
|
|
|
10
10
|
use std::sync::atomic::{AtomicIsize, Ordering};
|
|
11
11
|
use std::sync::Arc;
|
|
12
12
|
use std::time::Duration;
|
|
13
|
-
use tokio::runtime;
|
|
14
|
-
use tokio::runtime::{Handle, Runtime};
|
|
13
|
+
use tokio::runtime::{Builder, Handle, Runtime};
|
|
15
14
|
use tracing_appender::non_blocking::WorkerGuard;
|
|
16
15
|
use ve_tos_rust_sdk::asynchronous::object::ObjectAPI;
|
|
17
16
|
use ve_tos_rust_sdk::asynchronous::tos;
|
|
@@ -101,7 +100,12 @@ impl TosClient {
|
|
|
101
100
|
_guard = Some(init_tracing_log(directives, directory, file_name_prefix));
|
|
102
101
|
}
|
|
103
102
|
|
|
104
|
-
let
|
|
103
|
+
let logical_cores = num_cpus::get();
|
|
104
|
+
let mut builder = Builder::new_multi_thread();
|
|
105
|
+
if logical_cores > 0 {
|
|
106
|
+
builder.worker_threads(logical_cores);
|
|
107
|
+
}
|
|
108
|
+
let runtime = Arc::new(builder.enable_all().build()?);
|
|
105
109
|
let mut clients = Vec::with_capacity(2);
|
|
106
110
|
for _ in 0..2 {
|
|
107
111
|
match tos::builder()
|
|
@@ -118,7 +122,7 @@ impl TosClient {
|
|
|
118
122
|
})
|
|
119
123
|
.build()
|
|
120
124
|
{
|
|
121
|
-
Err(ex) => return Err(
|
|
125
|
+
Err(ex) => return Err(map_tos_error(ex)),
|
|
122
126
|
Ok(client) => {
|
|
123
127
|
clients.push(client);
|
|
124
128
|
}
|
|
@@ -165,7 +169,7 @@ impl TosClient {
|
|
|
165
169
|
slf.py().allow_threads(|| {
|
|
166
170
|
runtime.block_on(async move {
|
|
167
171
|
match client.head_object(&input).await {
|
|
168
|
-
Err(ex) => Err(
|
|
172
|
+
Err(ex) => Err(map_tos_error(ex)),
|
|
169
173
|
Ok(output) => Ok(TosObject::new(input.bucket(), input.key(), output)),
|
|
170
174
|
}
|
|
171
175
|
})
|
|
@@ -188,22 +192,23 @@ impl TosClient {
|
|
|
188
192
|
|
|
189
193
|
#[pyo3(signature = (bucket, key, storage_class=None))]
|
|
190
194
|
pub fn put_object(
|
|
191
|
-
|
|
195
|
+
slf: PyRef<'_, Self>,
|
|
192
196
|
bucket: String,
|
|
193
197
|
key: String,
|
|
194
198
|
storage_class: Option<String>,
|
|
195
199
|
) -> PyResult<WriteStream> {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
200
|
+
let client = slf.wclient.clone();
|
|
201
|
+
let runtime = slf.runtime.clone();
|
|
202
|
+
let part_size = slf.part_size;
|
|
203
|
+
slf.py().allow_threads(|| {
|
|
204
|
+
runtime.clone().block_on(async move {
|
|
205
|
+
match WriteStream::new(client, runtime, bucket, key, storage_class, part_size).await
|
|
206
|
+
{
|
|
207
|
+
Err(ex) => Err(map_tos_error(ex)),
|
|
208
|
+
Ok(ws) => Ok(ws),
|
|
209
|
+
}
|
|
210
|
+
})
|
|
211
|
+
})
|
|
207
212
|
}
|
|
208
213
|
}
|
|
209
214
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
use pyo3::exceptions::PyException;
|
|
2
2
|
use pyo3::{create_exception, pyclass, pymethods, PyErr};
|
|
3
|
+
use std::error::Error;
|
|
3
4
|
|
|
4
5
|
#[pyclass]
|
|
5
6
|
#[derive(Clone)]
|
|
@@ -55,7 +56,11 @@ pub(crate) fn map_error_from_string(message: impl Into<String>) -> PyErr {
|
|
|
55
56
|
))
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
pub(crate) fn map_error(err:
|
|
59
|
+
pub(crate) fn map_error(err: impl Error) -> PyErr {
|
|
60
|
+
PyErr::new::<TosException, _>(TosError::message(err.to_string()))
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
pub(crate) fn map_tos_error(err: ve_tos_rust_sdk::error::TosError) -> PyErr {
|
|
59
64
|
match err {
|
|
60
65
|
ve_tos_rust_sdk::error::TosError::TosClientError { message, .. } => {
|
|
61
66
|
PyErr::new::<TosException, _>(TosError::message(message))
|
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
use crate::tos_client::{InnerTosClient, TokioRuntime};
|
|
2
|
+
use crate::tos_error::{map_error, map_tos_error};
|
|
3
|
+
use bytes::Buf;
|
|
4
|
+
use futures_util::StreamExt;
|
|
5
|
+
use pyo3::{pyclass, pymethods, PyRef, PyRefMut, PyResult};
|
|
6
|
+
use std::collections::HashMap;
|
|
7
|
+
use std::sync::Arc;
|
|
8
|
+
use tokio::runtime;
|
|
9
|
+
use tokio::runtime::Runtime;
|
|
10
|
+
use tokio::sync::Mutex;
|
|
11
|
+
use ve_tos_rust_sdk::asynchronous::object::{ObjectAPI, ObjectContent};
|
|
12
|
+
use ve_tos_rust_sdk::asynchronous::tos;
|
|
13
|
+
|
|
14
|
+
#[pyclass(name = "TosRawClient")]
|
|
15
|
+
pub struct TosRawClient {
|
|
16
|
+
client: Arc<InnerTosClient>,
|
|
17
|
+
runtime: Arc<Runtime>,
|
|
18
|
+
#[pyo3(get)]
|
|
19
|
+
region: String,
|
|
20
|
+
#[pyo3(get)]
|
|
21
|
+
endpoint: String,
|
|
22
|
+
#[pyo3(get)]
|
|
23
|
+
ak: String,
|
|
24
|
+
#[pyo3(get)]
|
|
25
|
+
sk: String,
|
|
26
|
+
#[pyo3(get)]
|
|
27
|
+
connection_timeout: isize,
|
|
28
|
+
#[pyo3(get)]
|
|
29
|
+
request_timeout: isize,
|
|
30
|
+
#[pyo3(get)]
|
|
31
|
+
max_connections: isize,
|
|
32
|
+
#[pyo3(get)]
|
|
33
|
+
max_retry_count: isize,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
#[pymethods]
|
|
37
|
+
impl TosRawClient {
|
|
38
|
+
#[new]
|
|
39
|
+
#[pyo3(signature = (region, endpoint, ak="", sk="", connection_timeout=10000, request_timeout=120000, max_connections=1024, max_retry_count=3)
|
|
40
|
+
)]
|
|
41
|
+
pub fn new(
|
|
42
|
+
region: &str,
|
|
43
|
+
endpoint: &str,
|
|
44
|
+
ak: &str,
|
|
45
|
+
sk: &str,
|
|
46
|
+
connection_timeout: isize,
|
|
47
|
+
request_timeout: isize,
|
|
48
|
+
max_connections: isize,
|
|
49
|
+
max_retry_count: isize,
|
|
50
|
+
) -> PyResult<Self> {
|
|
51
|
+
let runtime = Arc::new(runtime::Builder::new_multi_thread().enable_all().build()?);
|
|
52
|
+
match tos::builder()
|
|
53
|
+
.connection_timeout(connection_timeout)
|
|
54
|
+
.request_timeout(request_timeout)
|
|
55
|
+
.max_connections(max_connections)
|
|
56
|
+
.max_retry_count(max_retry_count)
|
|
57
|
+
.ak(ak)
|
|
58
|
+
.sk(sk)
|
|
59
|
+
.region(region)
|
|
60
|
+
.endpoint(endpoint)
|
|
61
|
+
.async_sleeper(TokioRuntime {
|
|
62
|
+
runtime: Some(runtime.clone()),
|
|
63
|
+
})
|
|
64
|
+
.build()
|
|
65
|
+
{
|
|
66
|
+
Err(ex) => Err(map_tos_error(ex)),
|
|
67
|
+
Ok(client) => Ok(Self {
|
|
68
|
+
client: Arc::new(client),
|
|
69
|
+
runtime,
|
|
70
|
+
region: region.to_string(),
|
|
71
|
+
endpoint: endpoint.to_string(),
|
|
72
|
+
ak: ak.to_string(),
|
|
73
|
+
sk: sk.to_string(),
|
|
74
|
+
connection_timeout,
|
|
75
|
+
request_timeout,
|
|
76
|
+
max_connections,
|
|
77
|
+
max_retry_count,
|
|
78
|
+
}),
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
pub fn head_object<'py>(
|
|
82
|
+
slf: PyRef<'_, Self>,
|
|
83
|
+
input: &HeadObjectInput,
|
|
84
|
+
) -> PyResult<HeadObjectOutput> {
|
|
85
|
+
let input = ve_tos_rust_sdk::object::HeadObjectInput::new_with_version_id(
|
|
86
|
+
&input.bucket,
|
|
87
|
+
&input.key,
|
|
88
|
+
&input.version_id,
|
|
89
|
+
);
|
|
90
|
+
let client = slf.client.clone();
|
|
91
|
+
let runtime = slf.runtime.clone();
|
|
92
|
+
slf.py().allow_threads(|| {
|
|
93
|
+
runtime.block_on(async move {
|
|
94
|
+
match client.head_object(&input).await {
|
|
95
|
+
Err(ex) => Err(map_tos_error(ex)),
|
|
96
|
+
Ok(output) => Ok(HeadObjectOutput {
|
|
97
|
+
request_id: output.request_id().to_string(),
|
|
98
|
+
status_code: output.status_code(),
|
|
99
|
+
header: output.header().clone(),
|
|
100
|
+
content_length: output.content_length(),
|
|
101
|
+
etag: output.etag().to_string(),
|
|
102
|
+
version_id: output.version_id().to_string(),
|
|
103
|
+
hash_crc64ecma: output.hash_crc64ecma(),
|
|
104
|
+
}),
|
|
105
|
+
}
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
pub fn delete_object(
|
|
111
|
+
slf: PyRef<'_, Self>,
|
|
112
|
+
input: &DeleteObjectInput,
|
|
113
|
+
) -> PyResult<DeleteObjectOutput> {
|
|
114
|
+
let input = ve_tos_rust_sdk::object::DeleteObjectInput::new_with_version_id(
|
|
115
|
+
&input.bucket,
|
|
116
|
+
&input.key,
|
|
117
|
+
&input.version_id,
|
|
118
|
+
);
|
|
119
|
+
let client = slf.client.clone();
|
|
120
|
+
let runtime = slf.runtime.clone();
|
|
121
|
+
slf.py().allow_threads(|| {
|
|
122
|
+
runtime.block_on(async move {
|
|
123
|
+
match client.delete_object(&input).await {
|
|
124
|
+
Err(ex) => Err(map_tos_error(ex)),
|
|
125
|
+
Ok(output) => Ok(DeleteObjectOutput {
|
|
126
|
+
request_id: output.request_id().to_string(),
|
|
127
|
+
status_code: output.status_code(),
|
|
128
|
+
header: output.header().clone(),
|
|
129
|
+
delete_marker: output.delete_marker(),
|
|
130
|
+
version_id: output.version_id().to_string(),
|
|
131
|
+
}),
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
pub fn get_object(slf: PyRef<'_, Self>, input: &GetObjectInput) -> PyResult<GetObjectOutput> {
|
|
138
|
+
let mut rinput = ve_tos_rust_sdk::object::GetObjectInput::new_with_version_id(
|
|
139
|
+
&input.bucket,
|
|
140
|
+
&input.key,
|
|
141
|
+
&input.version_id,
|
|
142
|
+
);
|
|
143
|
+
rinput.set_range(&input.range);
|
|
144
|
+
|
|
145
|
+
let client = slf.client.clone();
|
|
146
|
+
let runtime = slf.runtime.clone();
|
|
147
|
+
slf.py().allow_threads(|| {
|
|
148
|
+
runtime.clone().block_on(async move {
|
|
149
|
+
match client.get_object(&rinput).await {
|
|
150
|
+
Err(ex) => Err(map_tos_error(ex)),
|
|
151
|
+
Ok(output) => Ok(GetObjectOutput {
|
|
152
|
+
request_id: output.request_id().to_string(),
|
|
153
|
+
status_code: output.status_code(),
|
|
154
|
+
header: output.header().clone(),
|
|
155
|
+
content_length: output.content_length(),
|
|
156
|
+
etag: output.etag().to_string(),
|
|
157
|
+
version_id: output.version_id().to_string(),
|
|
158
|
+
content_range: output.content_range().to_string(),
|
|
159
|
+
hash_crc64ecma: output.hash_crc64ecma(),
|
|
160
|
+
output: Arc::new(Mutex::new(output)),
|
|
161
|
+
runtime: runtime.clone(),
|
|
162
|
+
}),
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
})
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
pub fn put_object_from_buffer(
|
|
169
|
+
slf: PyRef<'_, Self>,
|
|
170
|
+
input: &PutObjectFromBufferInput,
|
|
171
|
+
) -> PyResult<PutObjectOutput> {
|
|
172
|
+
let mut rinput =
|
|
173
|
+
ve_tos_rust_sdk::object::PutObjectFromBufferInput::new(&input.bucket, &input.key);
|
|
174
|
+
if input.content.len() > 0 {
|
|
175
|
+
rinput.set_content(input.content.as_slice());
|
|
176
|
+
}
|
|
177
|
+
let client = slf.client.clone();
|
|
178
|
+
let runtime = slf.runtime.clone();
|
|
179
|
+
slf.py().allow_threads(|| {
|
|
180
|
+
runtime.clone().block_on(async move {
|
|
181
|
+
match client.put_object_from_buffer(&rinput).await {
|
|
182
|
+
Err(ex) => Err(map_tos_error(ex)),
|
|
183
|
+
Ok(output) => Ok(PutObjectOutput {
|
|
184
|
+
request_id: output.request_id().to_string(),
|
|
185
|
+
status_code: output.status_code(),
|
|
186
|
+
header: output.header().clone(),
|
|
187
|
+
etag: output.etag().to_string(),
|
|
188
|
+
version_id: output.version_id().to_string(),
|
|
189
|
+
hash_crc64ecma: output.hash_crc64ecma(),
|
|
190
|
+
}),
|
|
191
|
+
}
|
|
192
|
+
})
|
|
193
|
+
})
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
pub fn put_object_from_file(
|
|
197
|
+
slf: PyRef<'_, Self>,
|
|
198
|
+
input: &PutObjectFromFileInput,
|
|
199
|
+
) -> PyResult<PutObjectOutput> {
|
|
200
|
+
let mut rinput =
|
|
201
|
+
ve_tos_rust_sdk::object::PutObjectFromFileInput::new(&input.bucket, &input.key);
|
|
202
|
+
rinput.set_file_path(&input.file_path);
|
|
203
|
+
let client = slf.client.clone();
|
|
204
|
+
let runtime = slf.runtime.clone();
|
|
205
|
+
slf.py().allow_threads(|| {
|
|
206
|
+
runtime.clone().block_on(async move {
|
|
207
|
+
match client.put_object_from_file(&rinput).await {
|
|
208
|
+
Err(ex) => Err(map_tos_error(ex)),
|
|
209
|
+
Ok(output) => Ok(PutObjectOutput {
|
|
210
|
+
request_id: output.request_id().to_string(),
|
|
211
|
+
status_code: output.status_code(),
|
|
212
|
+
header: output.header().clone(),
|
|
213
|
+
etag: output.etag().to_string(),
|
|
214
|
+
version_id: output.version_id().to_string(),
|
|
215
|
+
hash_crc64ecma: output.hash_crc64ecma(),
|
|
216
|
+
}),
|
|
217
|
+
}
|
|
218
|
+
})
|
|
219
|
+
})
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
#[pyclass(name = "HeadObjectInput")]
|
|
224
|
+
pub struct HeadObjectInput {
|
|
225
|
+
#[pyo3(get, set)]
|
|
226
|
+
pub(crate) bucket: String,
|
|
227
|
+
#[pyo3(get, set)]
|
|
228
|
+
pub(crate) key: String,
|
|
229
|
+
#[pyo3(get, set)]
|
|
230
|
+
pub(crate) version_id: String,
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
#[pymethods]
|
|
234
|
+
impl HeadObjectInput {
|
|
235
|
+
#[new]
|
|
236
|
+
#[pyo3(signature = (bucket, key, version_id = ""))]
|
|
237
|
+
pub fn new(bucket: &str, key: &str, version_id: &str) -> PyResult<Self> {
|
|
238
|
+
Ok(Self {
|
|
239
|
+
bucket: bucket.to_string(),
|
|
240
|
+
key: key.to_string(),
|
|
241
|
+
version_id: version_id.to_string(),
|
|
242
|
+
})
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
#[pyclass(name = "HeadObjectOutput")]
|
|
247
|
+
pub struct HeadObjectOutput {
|
|
248
|
+
#[pyo3(get)]
|
|
249
|
+
pub(crate) request_id: String,
|
|
250
|
+
#[pyo3(get)]
|
|
251
|
+
pub(crate) status_code: isize,
|
|
252
|
+
#[pyo3(get)]
|
|
253
|
+
pub(crate) header: HashMap<String, String>,
|
|
254
|
+
#[pyo3(get)]
|
|
255
|
+
pub(crate) content_length: i64,
|
|
256
|
+
#[pyo3(get)]
|
|
257
|
+
pub(crate) etag: String,
|
|
258
|
+
#[pyo3(get)]
|
|
259
|
+
pub(crate) version_id: String,
|
|
260
|
+
#[pyo3(get)]
|
|
261
|
+
pub(crate) hash_crc64ecma: u64,
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
#[pyclass(name = "DeleteObjectInput")]
|
|
265
|
+
pub struct DeleteObjectInput {
|
|
266
|
+
#[pyo3(get, set)]
|
|
267
|
+
pub(crate) bucket: String,
|
|
268
|
+
#[pyo3(get, set)]
|
|
269
|
+
pub(crate) key: String,
|
|
270
|
+
#[pyo3(get, set)]
|
|
271
|
+
pub(crate) version_id: String,
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
#[pymethods]
|
|
275
|
+
impl DeleteObjectInput {
|
|
276
|
+
#[new]
|
|
277
|
+
#[pyo3(signature = (bucket, key, version_id = ""))]
|
|
278
|
+
pub fn new(bucket: &str, key: &str, version_id: &str) -> PyResult<Self> {
|
|
279
|
+
Ok(Self {
|
|
280
|
+
bucket: bucket.to_string(),
|
|
281
|
+
key: key.to_string(),
|
|
282
|
+
version_id: version_id.to_string(),
|
|
283
|
+
})
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
#[pyclass(name = "DeleteObjectOutput")]
|
|
288
|
+
pub struct DeleteObjectOutput {
|
|
289
|
+
#[pyo3(get)]
|
|
290
|
+
pub(crate) request_id: String,
|
|
291
|
+
#[pyo3(get)]
|
|
292
|
+
pub(crate) status_code: isize,
|
|
293
|
+
#[pyo3(get)]
|
|
294
|
+
pub(crate) header: HashMap<String, String>,
|
|
295
|
+
#[pyo3(get)]
|
|
296
|
+
pub(crate) delete_marker: bool,
|
|
297
|
+
#[pyo3(get)]
|
|
298
|
+
pub(crate) version_id: String,
|
|
299
|
+
}
|
|
300
|
+
#[pyclass(name = "GetObjectInput")]
|
|
301
|
+
pub struct GetObjectInput {
|
|
302
|
+
#[pyo3(get, set)]
|
|
303
|
+
pub(crate) bucket: String,
|
|
304
|
+
#[pyo3(get, set)]
|
|
305
|
+
pub(crate) key: String,
|
|
306
|
+
#[pyo3(get, set)]
|
|
307
|
+
pub(crate) version_id: String,
|
|
308
|
+
#[pyo3(get, set)]
|
|
309
|
+
pub(crate) range: String,
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
#[pymethods]
|
|
313
|
+
impl GetObjectInput {
|
|
314
|
+
#[new]
|
|
315
|
+
#[pyo3(signature = (bucket, key, version_id = "", range = ""))]
|
|
316
|
+
pub fn new(bucket: &str, key: &str, version_id: &str, range: &str) -> PyResult<Self> {
|
|
317
|
+
Ok(Self {
|
|
318
|
+
bucket: bucket.to_string(),
|
|
319
|
+
key: key.to_string(),
|
|
320
|
+
version_id: version_id.to_string(),
|
|
321
|
+
range: range.to_string(),
|
|
322
|
+
})
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
#[pyclass(name = "GetObjectOutput")]
|
|
327
|
+
pub struct GetObjectOutput {
|
|
328
|
+
#[pyo3(get)]
|
|
329
|
+
pub(crate) request_id: String,
|
|
330
|
+
#[pyo3(get)]
|
|
331
|
+
pub(crate) status_code: isize,
|
|
332
|
+
#[pyo3(get)]
|
|
333
|
+
pub(crate) header: HashMap<String, String>,
|
|
334
|
+
#[pyo3(get)]
|
|
335
|
+
pub(crate) content_length: i64,
|
|
336
|
+
#[pyo3(get)]
|
|
337
|
+
pub(crate) etag: String,
|
|
338
|
+
#[pyo3(get)]
|
|
339
|
+
pub(crate) version_id: String,
|
|
340
|
+
#[pyo3(get)]
|
|
341
|
+
pub(crate) content_range: String,
|
|
342
|
+
#[pyo3(get)]
|
|
343
|
+
pub(crate) hash_crc64ecma: u64,
|
|
344
|
+
output: Arc<Mutex<ve_tos_rust_sdk::object::GetObjectOutput>>,
|
|
345
|
+
runtime: Arc<Runtime>,
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
#[pymethods]
|
|
349
|
+
impl GetObjectOutput {
|
|
350
|
+
pub fn read_all(slf: PyRefMut<'_, Self>) -> PyResult<Option<Vec<u8>>> {
|
|
351
|
+
let runtime = slf.runtime.clone();
|
|
352
|
+
let output = slf.output.clone();
|
|
353
|
+
runtime.block_on(async move {
|
|
354
|
+
match output.lock().await.read_all().await {
|
|
355
|
+
Err(ex) => Err(map_tos_error(ex)),
|
|
356
|
+
Ok(buf) => Ok(Some(buf)),
|
|
357
|
+
}
|
|
358
|
+
})
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
pub fn read(slf: PyRefMut<'_, Self>) -> PyResult<Option<Vec<u8>>> {
|
|
362
|
+
let runtime = slf.runtime.clone();
|
|
363
|
+
let output = slf.output.clone();
|
|
364
|
+
runtime.block_on(async move {
|
|
365
|
+
match output.lock().await.next().await {
|
|
366
|
+
None => Ok(None),
|
|
367
|
+
Some(result) => match result {
|
|
368
|
+
Err(ex) => Err(map_error(ex)),
|
|
369
|
+
Ok(buf) => Ok(Some(buf.chunk().to_vec())),
|
|
370
|
+
},
|
|
371
|
+
}
|
|
372
|
+
})
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
#[pyclass(name = "PutObjectFromBufferInput")]
|
|
377
|
+
pub struct PutObjectFromBufferInput {
|
|
378
|
+
#[pyo3(get, set)]
|
|
379
|
+
pub(crate) bucket: String,
|
|
380
|
+
#[pyo3(get, set)]
|
|
381
|
+
pub(crate) key: String,
|
|
382
|
+
#[pyo3(get, set)]
|
|
383
|
+
pub(crate) content: Vec<u8>,
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
#[pymethods]
|
|
387
|
+
impl PutObjectFromBufferInput {
|
|
388
|
+
#[new]
|
|
389
|
+
#[pyo3(signature = (bucket, key, content))]
|
|
390
|
+
pub fn new(bucket: &str, key: &str, content: &[u8]) -> PyResult<Self> {
|
|
391
|
+
Ok(Self {
|
|
392
|
+
bucket: bucket.to_string(),
|
|
393
|
+
key: key.to_string(),
|
|
394
|
+
content: content.to_vec(),
|
|
395
|
+
})
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
#[pyclass(name = "PutObjectFromFileInput")]
|
|
400
|
+
pub struct PutObjectFromFileInput {
|
|
401
|
+
#[pyo3(get, set)]
|
|
402
|
+
pub(crate) bucket: String,
|
|
403
|
+
#[pyo3(get, set)]
|
|
404
|
+
pub(crate) key: String,
|
|
405
|
+
#[pyo3(get, set)]
|
|
406
|
+
pub(crate) file_path: String,
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
#[pymethods]
|
|
410
|
+
impl PutObjectFromFileInput {
|
|
411
|
+
#[new]
|
|
412
|
+
#[pyo3(signature = (bucket, key, file_path))]
|
|
413
|
+
pub fn new(bucket: &str, key: &str, file_path: &str) -> PyResult<Self> {
|
|
414
|
+
Ok(Self {
|
|
415
|
+
bucket: bucket.to_string(),
|
|
416
|
+
key: key.to_string(),
|
|
417
|
+
file_path: file_path.to_string(),
|
|
418
|
+
})
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
#[pyclass(name = "PutObjectOutput")]
|
|
423
|
+
pub struct PutObjectOutput {
|
|
424
|
+
#[pyo3(get)]
|
|
425
|
+
pub(crate) request_id: String,
|
|
426
|
+
#[pyo3(get)]
|
|
427
|
+
pub(crate) status_code: isize,
|
|
428
|
+
#[pyo3(get)]
|
|
429
|
+
pub(crate) header: HashMap<String, String>,
|
|
430
|
+
#[pyo3(get)]
|
|
431
|
+
pub(crate) etag: String,
|
|
432
|
+
#[pyo3(get)]
|
|
433
|
+
pub(crate) version_id: String,
|
|
434
|
+
#[pyo3(get)]
|
|
435
|
+
pub(crate) hash_crc64ecma: u64,
|
|
436
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
use crate::tos_client::InnerTosClient;
|
|
2
|
-
use crate::tos_error::
|
|
2
|
+
use crate::tos_error::map_tos_error;
|
|
3
3
|
use async_channel::{Receiver, Sender};
|
|
4
4
|
use futures_util::future::join_all;
|
|
5
5
|
use pyo3::{pyclass, pymethods, PyRefMut, PyResult};
|
|
@@ -52,7 +52,7 @@ impl WriteStream {
|
|
|
52
52
|
.py()
|
|
53
53
|
.allow_threads(|| runtime.block_on(async move { writer.write(data, offset).await }))
|
|
54
54
|
{
|
|
55
|
-
Err(ex) => Err(
|
|
55
|
+
Err(ex) => Err(map_tos_error(ex)),
|
|
56
56
|
Ok(written) => {
|
|
57
57
|
slf.offset += written;
|
|
58
58
|
Ok(written)
|
|
@@ -67,14 +67,14 @@ impl WriteStream {
|
|
|
67
67
|
.py()
|
|
68
68
|
.allow_threads(|| runtime.block_on(async move { writer.release().await }))
|
|
69
69
|
{
|
|
70
|
-
Err(ex) => Err(
|
|
70
|
+
Err(ex) => Err(map_tos_error(ex)),
|
|
71
71
|
Ok(_) => Ok(()),
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
impl WriteStream {
|
|
77
|
-
pub(crate) fn new(
|
|
77
|
+
pub(crate) async fn new(
|
|
78
78
|
client: Arc<InnerTosClient>,
|
|
79
79
|
runtime: Arc<Runtime>,
|
|
80
80
|
bucket: String,
|
|
@@ -93,10 +93,8 @@ impl WriteStream {
|
|
|
93
93
|
let _key = key.clone();
|
|
94
94
|
let _storage_class = storage_class.clone();
|
|
95
95
|
|
|
96
|
-
let object_writer =
|
|
97
|
-
ObjectWriter::new(client, _bucket, _key, _storage_class, part_size).await
|
|
98
|
-
})?;
|
|
99
|
-
|
|
96
|
+
let object_writer =
|
|
97
|
+
ObjectWriter::new(client, _bucket, _key, _storage_class, part_size).await?;
|
|
100
98
|
Ok(Self {
|
|
101
99
|
object_writer: Arc::new(object_writer),
|
|
102
100
|
runtime,
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
from typing import List
|
|
2
|
-
|
|
3
|
-
from typing import Optional
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class TosClient(object):
|
|
7
|
-
region: str
|
|
8
|
-
endpoint: str
|
|
9
|
-
ak: str
|
|
10
|
-
sk: str
|
|
11
|
-
part_size: int
|
|
12
|
-
max_retry_count: int
|
|
13
|
-
max_prefetch_tasks: int
|
|
14
|
-
|
|
15
|
-
def __init__(self, region: str, endpoint: str, ak: str = '', sk: str = '', part_size: int = 8388608,
|
|
16
|
-
max_retry_count: int = 3, max_prefetch_tasks: int = 3, directives: str = '', directory: str = '',
|
|
17
|
-
file_name_prefix: str = '', shared_prefetch_tasks: int = 20):
|
|
18
|
-
...
|
|
19
|
-
|
|
20
|
-
def list_objects(self, bucket: str, prefix: str = '', max_keys: int = 1000, delimiter: str = '') -> ListStream:
|
|
21
|
-
...
|
|
22
|
-
|
|
23
|
-
def head_object(self, bucket: str, key: str) -> TosObject:
|
|
24
|
-
...
|
|
25
|
-
|
|
26
|
-
def get_object(self, bucket: str, key: str, etag: str, size: int) -> ReadStream:
|
|
27
|
-
...
|
|
28
|
-
|
|
29
|
-
def put_object(self, bucket: str, key: str, storage_class: str = '') -> WriteStream:
|
|
30
|
-
...
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class ListStream(object):
|
|
34
|
-
bucket: str
|
|
35
|
-
prefix: str
|
|
36
|
-
delimiter: str
|
|
37
|
-
max_keys: int
|
|
38
|
-
|
|
39
|
-
def __iter__(self) -> ListStream: ...
|
|
40
|
-
|
|
41
|
-
def __next__(self) -> ListObjectsResult: ...
|
|
42
|
-
|
|
43
|
-
def close(self) -> None: ...
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
class ListObjectsResult(object):
|
|
47
|
-
contents: List[TosObject]
|
|
48
|
-
common_prefixes: List[str]
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
class TosObject(object):
|
|
52
|
-
bucket: str
|
|
53
|
-
key: str
|
|
54
|
-
size: int
|
|
55
|
-
etag: str
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class ReadStream(object):
|
|
59
|
-
bucket: str
|
|
60
|
-
key: str
|
|
61
|
-
size: int
|
|
62
|
-
etag: str
|
|
63
|
-
|
|
64
|
-
def read(self, offset: int, length: int) -> bytes:
|
|
65
|
-
...
|
|
66
|
-
|
|
67
|
-
def close(self) -> None:
|
|
68
|
-
...
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
class WriteStream(object):
|
|
72
|
-
bucket: str
|
|
73
|
-
key: str
|
|
74
|
-
storage_class: Optional[str]
|
|
75
|
-
|
|
76
|
-
def write(self, data: bytes) -> int:
|
|
77
|
-
...
|
|
78
|
-
|
|
79
|
-
def close(self) -> None:
|
|
80
|
-
...
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
class TosError(object):
|
|
84
|
-
message: str
|
|
85
|
-
status_code: Optional[int]
|
|
86
|
-
ec: str
|
|
87
|
-
request_id: str
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
class TosException(Exception):
|
|
91
|
-
args: List[TosError]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|