tosnativeclient 1.0.1__tar.gz → 1.0.4__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.

@@ -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.1"
1524
+ version = "1.0.4"
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",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "tosnativeclient"
3
- version = "1.0.1"
3
+ version = "1.0.4"
4
4
  edition = "2021"
5
5
  publish = false
6
6
  authors = ["xiangshijian"]
@@ -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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tosnativeclient
3
- Version: 1.0.1
3
+ Version: 1.0.4
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -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
+ ]
@@ -3,31 +3,27 @@ from typing import List, Dict
3
3
  from typing import Optional
4
4
 
5
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
6
+ class TosError(object):
7
+ message: str
8
+ status_code: Optional[int]
9
+ ec: str
10
+ request_id: str
14
11
 
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
12
 
20
- def list_objects(self, bucket: str, prefix: str = '', max_keys: int = 1000, delimiter: str = '') -> ListStream:
21
- ...
13
+ class TosException(Exception):
14
+ args: List[TosError]
22
15
 
23
- def head_object(self, bucket: str, key: str) -> TosObject:
24
- ...
25
16
 
26
- def get_object(self, bucket: str, key: str, etag: str, size: int) -> ReadStream:
27
- ...
17
+ class TosObject(object):
18
+ bucket: str
19
+ key: str
20
+ size: int
21
+ etag: str
28
22
 
29
- def put_object(self, bucket: str, key: str, storage_class: str = '') -> WriteStream:
30
- ...
23
+
24
+ class ListObjectsResult(object):
25
+ contents: List[TosObject]
26
+ common_prefixes: List[str]
31
27
 
32
28
 
33
29
  class ListStream(object):
@@ -43,25 +39,13 @@ class ListStream(object):
43
39
  def close(self) -> None: ...
44
40
 
45
41
 
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
42
  class ReadStream(object):
59
43
  bucket: str
60
44
  key: str
61
45
  size: int
62
46
  etag: str
63
47
 
64
- def read(self, offset: int, length: int) -> bytes:
48
+ def read(self, offset: int, length: int) -> Optional[bytes]:
65
49
  ...
66
50
 
67
51
  def close(self) -> None:
@@ -80,44 +64,34 @@ class WriteStream(object):
80
64
  ...
81
65
 
82
66
 
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]
92
-
93
-
94
- class TosRawClient(object):
67
+ class TosClient(object):
95
68
  region: str
96
69
  endpoint: str
97
70
  ak: str
98
71
  sk: str
99
- connection_timeout: int
100
- request_timeout: int
101
- max_connections: int
72
+ part_size: int
102
73
  max_retry_count: int
74
+ max_prefetch_tasks: int
75
+ directives: str
76
+ directory: str
77
+ file_name_prefix: str
78
+ shared_prefetch_tasks: int
103
79
 
104
- def __init__(self, region: str, endpoint: str, ak: str = '', sk: str = '', connection_timeout: int = 10000,
105
- request_timeout: int = 120000, max_connections: int = 1024, max_retry_count: int = 3):
106
- ...
107
-
108
- def head_object(self, input: HeadObjectInput) -> HeadObjectOutput:
80
+ def __init__(self, region: str, endpoint: str, ak: str = '', sk: str = '', part_size: int = 8388608,
81
+ max_retry_count: int = 3, max_prefetch_tasks: int = 3, directives: str = '', directory: str = '',
82
+ file_name_prefix: str = '', shared_prefetch_tasks: int = 20):
109
83
  ...
110
84
 
111
- def delete_object(self, input: DeleteObjectInput) -> DeleteObjectOutput:
85
+ def list_objects(self, bucket: str, prefix: str = '', max_keys: int = 1000, delimiter: str = '') -> ListStream:
112
86
  ...
113
87
 
114
- def get_object(self, input: GetObjectInput) -> GetObjectOutput:
88
+ def head_object(self, bucket: str, key: str) -> TosObject:
115
89
  ...
116
90
 
117
- def put_object_from_buffer(self, input: PutObjectFromBufferInput) -> PutObjectOutput:
91
+ def get_object(self, bucket: str, key: str, etag: str, size: int) -> ReadStream:
118
92
  ...
119
93
 
120
- def put_object_from_file(self, input: PutObjectFromFileInput) -> PutObjectOutput:
94
+ def put_object(self, bucket: str, key: str, storage_class: Optional[str] = '') -> WriteStream:
121
95
  ...
122
96
 
123
97
 
@@ -177,10 +151,10 @@ class GetObjectOutput(object):
177
151
  content_range: str
178
152
  hash_crc64ecma: int
179
153
 
180
- def read_all(self) -> bytes:
154
+ def read_all(self) -> Optional[bytes]:
181
155
  ...
182
156
 
183
- def read(self) -> bytes:
157
+ def read(self) -> Optional[bytes]:
184
158
  ...
185
159
 
186
160
 
@@ -209,3 +183,33 @@ class PutObjectOutput(object):
209
183
  etag: str
210
184
  version_id: str
211
185
  hash_crc64ecma: int
186
+
187
+
188
+ class TosRawClient(object):
189
+ region: str
190
+ endpoint: str
191
+ ak: str
192
+ sk: str
193
+ connection_timeout: int
194
+ request_timeout: int
195
+ max_connections: int
196
+ max_retry_count: int
197
+
198
+ def __init__(self, region: str, endpoint: str, ak: str = '', sk: str = '', connection_timeout: int = 10000,
199
+ request_timeout: int = 120000, max_connections: int = 1024, max_retry_count: int = 3):
200
+ ...
201
+
202
+ def head_object(self, input: HeadObjectInput) -> HeadObjectOutput:
203
+ ...
204
+
205
+ def delete_object(self, input: DeleteObjectInput) -> DeleteObjectOutput:
206
+ ...
207
+
208
+ def get_object(self, input: GetObjectInput) -> GetObjectOutput:
209
+ ...
210
+
211
+ def put_object_from_buffer(self, input: PutObjectFromBufferInput) -> PutObjectOutput:
212
+ ...
213
+
214
+ def put_object_from_file(self, input: PutObjectFromFileInput) -> PutObjectOutput:
215
+ ...
@@ -3,7 +3,8 @@ 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;
6
- use pyo3::{pyclass, pymethods, PyRef, PyRefMut, PyResult, Python};
6
+ use pyo3::types::PyTuple;
7
+ use pyo3::{pyclass, pymethods, Bound, IntoPyObject, PyRef, PyRefMut, PyResult, Python};
7
8
  use std::sync::atomic::{AtomicI8, Ordering};
8
9
  use std::sync::{Arc, RwLock};
9
10
  use tokio::runtime::Runtime;
@@ -12,7 +13,7 @@ use ve_tos_rust_sdk::error::TosError;
12
13
  use ve_tos_rust_sdk::object::{ListObjectsType2Input, ListObjectsType2Output};
13
14
 
14
15
  const DEFAULT_TASK_COUNT: usize = 5;
15
- #[pyclass(name = "ListStream")]
16
+ #[pyclass(name = "ListStream", module = "tosnativeclient")]
16
17
  pub struct ListStream {
17
18
  client: Arc<InnerTosClient>,
18
19
  runtime: Arc<Runtime>,
@@ -46,14 +47,11 @@ impl ListStream {
46
47
  return Err(map_error_from_string("ListStream is closed"));
47
48
  }
48
49
 
49
- {
50
- let mut pg = slf.paginator.write().unwrap();
51
- if pg.is_none() {
52
- *pg = slf.list_background(slf.py());
53
- }
50
+ let mut pg = slf.paginator.write().unwrap();
51
+ if pg.is_none() {
52
+ *pg = slf.list_background(slf.py());
54
53
  }
55
-
56
- slf.next_page(slf.paginator.read().unwrap().as_ref(), slf.py())
54
+ slf.next_page(pg.as_ref(), slf.py())
57
55
  }
58
56
 
59
57
  pub fn close(&self) {
@@ -66,6 +64,17 @@ impl ListStream {
66
64
  }
67
65
  }
68
66
  }
67
+
68
+ pub fn __getnewargs__(slf: PyRef<'_, Self>) -> PyResult<Bound<'_, PyTuple>> {
69
+ let py = slf.py();
70
+ let state = [
71
+ slf.bucket.clone().into_pyobject(py)?.into_any(),
72
+ slf.prefix.clone().into_pyobject(py)?.into_any(),
73
+ slf.delimiter.clone().into_pyobject(py)?.into_any(),
74
+ slf.max_keys.clone().into_pyobject(py)?.into_any(),
75
+ ];
76
+ PyTuple::new(py, state)
77
+ }
69
78
  }
70
79
 
71
80
  impl ListStream {
@@ -100,67 +109,54 @@ impl ListStream {
100
109
  py.allow_threads(|| {
101
110
  self.runtime.spawn(async move {
102
111
  let mut need_break = false;
103
- if input.delimiter() == "/" {
104
- let mut prefixes = Vec::with_capacity(16);
105
- let mut last_page_end = false;
112
+ if input.delimiter() == "" {
106
113
  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
114
  let result = client.list_objects_type2(&input).await;
128
115
  if let Ok(ref o) = result {
129
116
  if o.is_truncated() {
130
117
  input.set_continuation_token(o.next_continuation_token());
131
118
  } else {
132
- last_page_end = true;
133
- }
134
-
135
- for cp in o.common_prefixes() {
136
- prefixes.push(cp.prefix().to_string());
119
+ need_break = true;
137
120
  }
138
- need_break = last_page_end && prefixes.is_empty();
139
121
  } else {
140
122
  need_break = true;
141
123
  }
142
-
143
124
  if let Err(_) = sender.send((need_break, result)).await {
144
- need_break = true;
125
+ need_break = true
145
126
  }
146
127
  if need_break {
147
128
  break;
148
129
  }
149
130
  }
150
131
  } else {
132
+ let mut prefixes = Vec::with_capacity(16);
133
+ let mut last_page_end = false;
151
134
  loop {
135
+ if last_page_end {
136
+ let prefix = prefixes.remove(0);
137
+ input.set_prefix(prefix);
138
+ input.set_start_after("");
139
+ input.set_continuation_token("");
140
+ last_page_end = false;
141
+ }
152
142
  let result = client.list_objects_type2(&input).await;
153
143
  if let Ok(ref o) = result {
154
144
  if o.is_truncated() {
155
145
  input.set_continuation_token(o.next_continuation_token());
156
146
  } else {
157
- need_break = true;
147
+ last_page_end = true;
148
+ }
149
+
150
+ for cp in o.common_prefixes() {
151
+ prefixes.push(cp.prefix().to_string());
158
152
  }
153
+ need_break = last_page_end && prefixes.is_empty();
159
154
  } else {
160
155
  need_break = true;
161
156
  }
157
+
162
158
  if let Err(_) = sender.send((need_break, result)).await {
163
- need_break = true
159
+ need_break = true;
164
160
  }
165
161
  if need_break {
166
162
  break;
@@ -169,7 +165,6 @@ impl ListStream {
169
165
  }
170
166
  });
171
167
  });
172
-
173
168
  Some(Paginator {
174
169
  is_end: ArcSwap::new(Arc::new(false)),
175
170
  last_err: ArcSwap::new(Arc::new(None)),
@@ -4,8 +4,8 @@ use crate::tos_model::TosObject;
4
4
  use async_channel::{Receiver, Sender};
5
5
  use bytes::Bytes;
6
6
  use futures_util::StreamExt;
7
- use pyo3::types::PyBytes;
8
- use pyo3::{pyclass, pymethods, Bound, PyRef, PyResult};
7
+ use pyo3::types::{PyBytes, PyTuple};
8
+ use pyo3::{pyclass, pymethods, Bound, IntoPyObject, PyRef, PyResult};
9
9
  use std::collections::LinkedList;
10
10
  use std::sync::atomic::{AtomicI8, AtomicIsize, Ordering};
11
11
  use std::sync::Arc;
@@ -24,7 +24,7 @@ const DEFAULT_PART_SIZE: isize = 8 * 1024 * 1024;
24
24
  const DEFAULT_FETCH_RETRY_COUNT: isize = 3;
25
25
  const DEFAULT_SHARED_PREFETCH_TASK_LIMIT: isize = 100;
26
26
 
27
- #[pyclass(name = "ReadStream")]
27
+ #[pyclass(name = "ReadStream", module = "tosnativeclient")]
28
28
  pub struct ReadStream {
29
29
  object_fetcher: Arc<ObjectFetcher>,
30
30
  runtime: Arc<Runtime>,
@@ -66,6 +66,17 @@ impl ReadStream {
66
66
  slf.py()
67
67
  .allow_threads(|| runtime.block_on(async move { fetcher.close().await }))
68
68
  }
69
+
70
+ pub fn __getnewargs__(slf: PyRef<'_, Self>) -> PyResult<Bound<'_, PyTuple>> {
71
+ let py = slf.py();
72
+ let state = [
73
+ slf.bucket.clone().into_pyobject(py)?.into_any(),
74
+ slf.key.clone().into_pyobject(py)?.into_any(),
75
+ slf.etag.clone().into_pyobject(py)?.into_any(),
76
+ slf.size.clone().into_pyobject(py)?.into_any(),
77
+ ];
78
+ PyTuple::new(py, state)
79
+ }
69
80
  }
70
81
 
71
82
  impl ReadStream {
@@ -5,13 +5,14 @@ use crate::tos_model::TosObject;
5
5
  use crate::write_stream::WriteStream;
6
6
  use async_trait::async_trait;
7
7
  use futures_util::future::BoxFuture;
8
- use pyo3::{pyclass, pymethods, PyRef, PyResult};
8
+ use pyo3::prelude::PyDictMethods;
9
+ use pyo3::types::{PyDict, PyTuple};
10
+ use pyo3::{pyclass, pymethods, Bound, IntoPyObject, PyAny, PyObject, PyRef, PyRefMut, PyResult};
9
11
  use std::future::Future;
10
12
  use std::sync::atomic::{AtomicIsize, Ordering};
11
13
  use std::sync::Arc;
12
14
  use std::time::Duration;
13
- use tokio::runtime;
14
- use tokio::runtime::{Handle, Runtime};
15
+ use tokio::runtime::{Builder, Handle, Runtime};
15
16
  use tracing_appender::non_blocking::WorkerGuard;
16
17
  use ve_tos_rust_sdk::asynchronous::object::ObjectAPI;
17
18
  use ve_tos_rust_sdk::asynchronous::tos;
@@ -54,7 +55,7 @@ impl AsyncRuntime for TokioRuntime {
54
55
  pub(crate) type InnerTosClient =
55
56
  TosClientImpl<CommonCredentialsProvider<CommonCredentials>, CommonCredentials, TokioRuntime>;
56
57
 
57
- #[pyclass(name = "TosClient")]
58
+ #[pyclass(name = "TosClient", module = "tosnativeclient")]
58
59
  pub struct TosClient {
59
60
  rclient: Arc<InnerTosClient>,
60
61
  wclient: Arc<InnerTosClient>,
@@ -76,6 +77,14 @@ pub struct TosClient {
76
77
  max_retry_count: isize,
77
78
  #[pyo3(get)]
78
79
  max_prefetch_tasks: isize,
80
+ #[pyo3(get)]
81
+ directives: String,
82
+ #[pyo3(get)]
83
+ directory: String,
84
+ #[pyo3(get)]
85
+ file_name_prefix: String,
86
+ #[pyo3(get)]
87
+ shared_prefetch_tasks: isize,
79
88
  }
80
89
 
81
90
  #[pymethods]
@@ -98,10 +107,19 @@ impl TosClient {
98
107
  ) -> PyResult<Self> {
99
108
  let mut _guard = None;
100
109
  if directives != "" {
101
- _guard = Some(init_tracing_log(directives, directory, file_name_prefix));
110
+ _guard = Some(init_tracing_log(
111
+ directives.clone(),
112
+ directory.clone(),
113
+ file_name_prefix.clone(),
114
+ ));
102
115
  }
103
116
 
104
- let runtime = Arc::new(runtime::Builder::new_multi_thread().enable_all().build()?);
117
+ let logical_cores = num_cpus::get();
118
+ let mut builder = Builder::new_multi_thread();
119
+ if logical_cores > 0 {
120
+ builder.worker_threads(logical_cores);
121
+ }
122
+ let runtime = Arc::new(builder.enable_all().build()?);
105
123
  let mut clients = Vec::with_capacity(2);
106
124
  for _ in 0..2 {
107
125
  match tos::builder()
@@ -138,6 +156,10 @@ impl TosClient {
138
156
  part_size,
139
157
  max_retry_count,
140
158
  max_prefetch_tasks,
159
+ directives,
160
+ directory,
161
+ file_name_prefix,
162
+ shared_prefetch_tasks,
141
163
  })
142
164
  }
143
165
 
@@ -188,22 +210,41 @@ impl TosClient {
188
210
 
189
211
  #[pyo3(signature = (bucket, key, storage_class=None))]
190
212
  pub fn put_object(
191
- &self,
213
+ slf: PyRef<'_, Self>,
192
214
  bucket: String,
193
215
  key: String,
194
216
  storage_class: Option<String>,
195
217
  ) -> PyResult<WriteStream> {
196
- match WriteStream::new(
197
- self.wclient.clone(),
198
- self.runtime.clone(),
199
- bucket,
200
- key,
201
- storage_class,
202
- self.part_size,
203
- ) {
204
- Err(ex) => Err(map_tos_error(ex)),
205
- Ok(ws) => Ok(ws),
206
- }
218
+ let client = slf.wclient.clone();
219
+ let runtime = slf.runtime.clone();
220
+ let part_size = slf.part_size;
221
+ slf.py().allow_threads(|| {
222
+ runtime.clone().block_on(async move {
223
+ match WriteStream::new(client, runtime, bucket, key, storage_class, part_size).await
224
+ {
225
+ Err(ex) => Err(map_tos_error(ex)),
226
+ Ok(ws) => Ok(ws),
227
+ }
228
+ })
229
+ })
230
+ }
231
+
232
+ pub fn __getnewargs__(slf: PyRef<'_, Self>) -> PyResult<Bound<'_, PyTuple>> {
233
+ let py = slf.py();
234
+ let state = [
235
+ slf.region.clone().into_pyobject(py)?.into_any(),
236
+ slf.endpoint.clone().into_pyobject(py)?.into_any(),
237
+ slf.ak.clone().into_pyobject(py)?.into_any(),
238
+ slf.sk.clone().into_pyobject(py)?.into_any(),
239
+ slf.part_size.into_pyobject(py)?.into_any(),
240
+ slf.max_retry_count.into_pyobject(py)?.into_any(),
241
+ slf.max_prefetch_tasks.into_pyobject(py)?.into_any(),
242
+ "".into_pyobject(py)?.into_any(),
243
+ "".into_pyobject(py)?.into_any(),
244
+ "".into_pyobject(py)?.into_any(),
245
+ slf.shared_prefetch_tasks.into_pyobject(py)?.into_any(),
246
+ ];
247
+ PyTuple::new(py, state)
207
248
  }
208
249
  }
209
250
 
@@ -1,9 +1,10 @@
1
1
  use pyo3::exceptions::PyException;
2
- use pyo3::{create_exception, pyclass, pymethods, PyErr};
2
+ use pyo3::types::PyTuple;
3
+ use pyo3::{create_exception, pyclass, pymethods, Bound, IntoPyObject, PyErr, PyRef, PyResult};
3
4
  use std::error::Error;
4
5
 
5
- #[pyclass]
6
6
  #[derive(Clone)]
7
+ #[pyclass(name = "TosError", module = "tosnativeclient")]
7
8
  pub struct TosError {
8
9
  #[pyo3(get)]
9
10
  message: String,
@@ -43,6 +44,17 @@ impl TosError {
43
44
  request_id,
44
45
  }
45
46
  }
47
+
48
+ pub fn __getnewargs__(slf: PyRef<'_, Self>) -> PyResult<Bound<'_, PyTuple>> {
49
+ let py = slf.py();
50
+ let state = [
51
+ slf.message.clone().into_pyobject(py)?.into_any(),
52
+ slf.status_code.clone().into_pyobject(py)?.into_any(),
53
+ slf.ec.clone().into_pyobject(py)?.into_any(),
54
+ slf.request_id.clone().into_pyobject(py)?.into_any(),
55
+ ];
56
+ PyTuple::new(py, state)
57
+ }
46
58
  }
47
59
 
48
60
  create_exception!(tosnativeclient, TosException, PyException);
@@ -1,7 +1,7 @@
1
1
  use pyo3::pyclass;
2
2
  use ve_tos_rust_sdk::object::{HeadObjectOutput, ListObjectsType2Output};
3
3
 
4
- #[pyclass(name = "ListObjectsResult")]
4
+ #[pyclass(name = "ListObjectsResult", module = "tosnativeclient")]
5
5
  pub struct ListObjectsResult {
6
6
  #[pyo3(get)]
7
7
  contents: Vec<TosObject>,
@@ -33,7 +33,7 @@ impl ListObjectsResult {
33
33
  }
34
34
 
35
35
  #[derive(Clone)]
36
- #[pyclass(name = "TosObject")]
36
+ #[pyclass(name = "TosObject", module = "tosnativeclient")]
37
37
  pub struct TosObject {
38
38
  #[pyo3(get)]
39
39
  pub(crate) bucket: String,
@@ -2,8 +2,10 @@ use crate::tos_client::{InnerTosClient, TokioRuntime};
2
2
  use crate::tos_error::{map_error, map_tos_error};
3
3
  use bytes::Buf;
4
4
  use futures_util::StreamExt;
5
- use pyo3::{pyclass, pymethods, PyRef, PyRefMut, PyResult};
5
+ use pyo3::types::PyTuple;
6
+ use pyo3::{pyclass, pymethods, Bound, IntoPyObject, PyRef, PyRefMut, PyResult};
6
7
  use std::collections::HashMap;
8
+ use std::sync::atomic::{AtomicI8, Ordering};
7
9
  use std::sync::Arc;
8
10
  use tokio::runtime;
9
11
  use tokio::runtime::Runtime;
@@ -11,7 +13,7 @@ use tokio::sync::Mutex;
11
13
  use ve_tos_rust_sdk::asynchronous::object::{ObjectAPI, ObjectContent};
12
14
  use ve_tos_rust_sdk::asynchronous::tos;
13
15
 
14
- #[pyclass(name = "TosRawClient")]
16
+ #[pyclass(name = "TosRawClient", module = "tosnativeclient")]
15
17
  pub struct TosRawClient {
16
18
  client: Arc<InnerTosClient>,
17
19
  runtime: Arc<Runtime>,
@@ -158,7 +160,7 @@ impl TosRawClient {
158
160
  content_range: output.content_range().to_string(),
159
161
  hash_crc64ecma: output.hash_crc64ecma(),
160
162
  output: Arc::new(Mutex::new(output)),
161
- runtime: runtime.clone(),
163
+ runtime,
162
164
  }),
163
165
  }
164
166
  })
@@ -218,9 +220,24 @@ impl TosRawClient {
218
220
  })
219
221
  })
220
222
  }
223
+
224
+ pub fn __getnewargs__(slf: PyRef<'_, Self>) -> PyResult<Bound<'_, PyTuple>> {
225
+ let py = slf.py();
226
+ let state = [
227
+ slf.region.clone().into_pyobject(py)?.into_any(),
228
+ slf.endpoint.clone().into_pyobject(py)?.into_any(),
229
+ slf.ak.clone().into_pyobject(py)?.into_any(),
230
+ slf.sk.clone().into_pyobject(py)?.into_any(),
231
+ slf.connection_timeout.clone().into_pyobject(py)?.into_any(),
232
+ slf.request_timeout.clone().into_pyobject(py)?.into_any(),
233
+ slf.max_connections.clone().into_pyobject(py)?.into_any(),
234
+ slf.max_retry_count.clone().into_pyobject(py)?.into_any(),
235
+ ];
236
+ PyTuple::new(py, state)
237
+ }
221
238
  }
222
239
 
223
- #[pyclass(name = "HeadObjectInput")]
240
+ #[pyclass(name = "HeadObjectInput", module = "tosnativeclient")]
224
241
  pub struct HeadObjectInput {
225
242
  #[pyo3(get, set)]
226
243
  pub(crate) bucket: String,
@@ -241,9 +258,18 @@ impl HeadObjectInput {
241
258
  version_id: version_id.to_string(),
242
259
  })
243
260
  }
261
+ pub fn __getnewargs__(slf: PyRef<'_, Self>) -> PyResult<Bound<'_, PyTuple>> {
262
+ let py = slf.py();
263
+ let state = [
264
+ slf.bucket.clone().into_pyobject(py)?.into_any(),
265
+ slf.key.clone().into_pyobject(py)?.into_any(),
266
+ slf.version_id.clone().into_pyobject(py)?.into_any(),
267
+ ];
268
+ PyTuple::new(py, state)
269
+ }
244
270
  }
245
271
 
246
- #[pyclass(name = "HeadObjectOutput")]
272
+ #[pyclass(name = "HeadObjectOutput", module = "tosnativeclient")]
247
273
  pub struct HeadObjectOutput {
248
274
  #[pyo3(get)]
249
275
  pub(crate) request_id: String,
@@ -261,7 +287,7 @@ pub struct HeadObjectOutput {
261
287
  pub(crate) hash_crc64ecma: u64,
262
288
  }
263
289
 
264
- #[pyclass(name = "DeleteObjectInput")]
290
+ #[pyclass(name = "DeleteObjectInput", module = "tosnativeclient")]
265
291
  pub struct DeleteObjectInput {
266
292
  #[pyo3(get, set)]
267
293
  pub(crate) bucket: String,
@@ -282,9 +308,18 @@ impl DeleteObjectInput {
282
308
  version_id: version_id.to_string(),
283
309
  })
284
310
  }
311
+ pub fn __getnewargs__(slf: PyRef<'_, Self>) -> PyResult<Bound<'_, PyTuple>> {
312
+ let py = slf.py();
313
+ let state = [
314
+ slf.bucket.clone().into_pyobject(py)?.into_any(),
315
+ slf.key.clone().into_pyobject(py)?.into_any(),
316
+ slf.version_id.clone().into_pyobject(py)?.into_any(),
317
+ ];
318
+ PyTuple::new(py, state)
319
+ }
285
320
  }
286
321
 
287
- #[pyclass(name = "DeleteObjectOutput")]
322
+ #[pyclass(name = "DeleteObjectOutput", module = "tosnativeclient")]
288
323
  pub struct DeleteObjectOutput {
289
324
  #[pyo3(get)]
290
325
  pub(crate) request_id: String,
@@ -297,7 +332,7 @@ pub struct DeleteObjectOutput {
297
332
  #[pyo3(get)]
298
333
  pub(crate) version_id: String,
299
334
  }
300
- #[pyclass(name = "GetObjectInput")]
335
+ #[pyclass(name = "GetObjectInput", module = "tosnativeclient")]
301
336
  pub struct GetObjectInput {
302
337
  #[pyo3(get, set)]
303
338
  pub(crate) bucket: String,
@@ -321,9 +356,19 @@ impl GetObjectInput {
321
356
  range: range.to_string(),
322
357
  })
323
358
  }
359
+ pub fn __getnewargs__(slf: PyRef<'_, Self>) -> PyResult<Bound<'_, PyTuple>> {
360
+ let py = slf.py();
361
+ let state = [
362
+ slf.bucket.clone().into_pyobject(py)?.into_any(),
363
+ slf.key.clone().into_pyobject(py)?.into_any(),
364
+ slf.version_id.clone().into_pyobject(py)?.into_any(),
365
+ slf.range.clone().into_pyobject(py)?.into_any(),
366
+ ];
367
+ PyTuple::new(py, state)
368
+ }
324
369
  }
325
370
 
326
- #[pyclass(name = "GetObjectOutput")]
371
+ #[pyclass(name = "GetObjectOutput", module = "tosnativeclient")]
327
372
  pub struct GetObjectOutput {
328
373
  #[pyo3(get)]
329
374
  pub(crate) request_id: String,
@@ -350,30 +395,34 @@ impl GetObjectOutput {
350
395
  pub fn read_all(slf: PyRefMut<'_, Self>) -> PyResult<Option<Vec<u8>>> {
351
396
  let runtime = slf.runtime.clone();
352
397
  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
- }
398
+ slf.py().allow_threads(|| {
399
+ runtime.block_on(async move {
400
+ match output.lock().await.read_all().await {
401
+ Err(ex) => Err(map_tos_error(ex)),
402
+ Ok(buf) => Ok(Some(buf)),
403
+ }
404
+ })
358
405
  })
359
406
  }
360
407
 
361
408
  pub fn read(slf: PyRefMut<'_, Self>) -> PyResult<Option<Vec<u8>>> {
362
409
  let runtime = slf.runtime.clone();
363
410
  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
- }
411
+ slf.py().allow_threads(|| {
412
+ runtime.block_on(async move {
413
+ match output.lock().await.next().await {
414
+ None => Ok(None),
415
+ Some(result) => match result {
416
+ Err(ex) => Err(map_error(ex)),
417
+ Ok(buf) => Ok(Some(buf.chunk().to_vec())),
418
+ },
419
+ }
420
+ })
372
421
  })
373
422
  }
374
423
  }
375
424
 
376
- #[pyclass(name = "PutObjectFromBufferInput")]
425
+ #[pyclass(name = "PutObjectFromBufferInput", module = "tosnativeclient")]
377
426
  pub struct PutObjectFromBufferInput {
378
427
  #[pyo3(get, set)]
379
428
  pub(crate) bucket: String,
@@ -394,9 +443,18 @@ impl PutObjectFromBufferInput {
394
443
  content: content.to_vec(),
395
444
  })
396
445
  }
446
+ pub fn __getnewargs__(slf: PyRef<'_, Self>) -> PyResult<Bound<'_, PyTuple>> {
447
+ let py = slf.py();
448
+ let state = [
449
+ slf.bucket.clone().into_pyobject(py)?.into_any(),
450
+ slf.key.clone().into_pyobject(py)?.into_any(),
451
+ slf.content.clone().into_pyobject(py)?.into_any(),
452
+ ];
453
+ PyTuple::new(py, state)
454
+ }
397
455
  }
398
456
 
399
- #[pyclass(name = "PutObjectFromFileInput")]
457
+ #[pyclass(name = "PutObjectFromFileInput", module = "tosnativeclient")]
400
458
  pub struct PutObjectFromFileInput {
401
459
  #[pyo3(get, set)]
402
460
  pub(crate) bucket: String,
@@ -417,9 +475,18 @@ impl PutObjectFromFileInput {
417
475
  file_path: file_path.to_string(),
418
476
  })
419
477
  }
478
+ pub fn __getnewargs__(slf: PyRef<'_, Self>) -> PyResult<Bound<'_, PyTuple>> {
479
+ let py = slf.py();
480
+ let state = [
481
+ slf.bucket.clone().into_pyobject(py)?.into_any(),
482
+ slf.key.clone().into_pyobject(py)?.into_any(),
483
+ slf.file_path.clone().into_pyobject(py)?.into_any(),
484
+ ];
485
+ PyTuple::new(py, state)
486
+ }
420
487
  }
421
488
 
422
- #[pyclass(name = "PutObjectOutput")]
489
+ #[pyclass(name = "PutObjectOutput", module = "tosnativeclient")]
423
490
  pub struct PutObjectOutput {
424
491
  #[pyo3(get)]
425
492
  pub(crate) request_id: String,
@@ -2,7 +2,8 @@ use crate::tos_client::InnerTosClient;
2
2
  use crate::tos_error::map_tos_error;
3
3
  use async_channel::{Receiver, Sender};
4
4
  use futures_util::future::join_all;
5
- use pyo3::{pyclass, pymethods, PyRefMut, PyResult};
5
+ use pyo3::types::PyTuple;
6
+ use pyo3::{pyclass, pymethods, Bound, IntoPyObject, PyRef, PyRefMut, PyResult};
6
7
  use std::collections::HashMap;
7
8
  use std::sync::atomic::{AtomicI8, AtomicIsize, Ordering};
8
9
  use std::sync::Arc;
@@ -29,7 +30,7 @@ const MAX_PART_NUMBER: isize = 10000;
29
30
  const OTHER_MU_KICK_OFF: i8 = 1;
30
31
  const RELEASE_MU_KICK_OFF: i8 = 2;
31
32
 
32
- #[pyclass(name = "WriteStream")]
33
+ #[pyclass(name = "WriteStream", module = "tosnativeclient")]
33
34
  pub struct WriteStream {
34
35
  object_writer: Arc<ObjectWriter>,
35
36
  runtime: Arc<Runtime>,
@@ -71,10 +72,20 @@ impl WriteStream {
71
72
  Ok(_) => Ok(()),
72
73
  }
73
74
  }
75
+
76
+ pub fn __getnewargs__(slf: PyRef<'_, Self>) -> PyResult<Bound<'_, PyTuple>> {
77
+ let py = slf.py();
78
+ let state = [
79
+ slf.bucket.clone().into_pyobject(py)?.into_any(),
80
+ slf.key.clone().into_pyobject(py)?.into_any(),
81
+ slf.storage_class.clone().into_pyobject(py)?.into_any(),
82
+ ];
83
+ PyTuple::new(py, state)
84
+ }
74
85
  }
75
86
 
76
87
  impl WriteStream {
77
- pub(crate) fn new(
88
+ pub(crate) async fn new(
78
89
  client: Arc<InnerTosClient>,
79
90
  runtime: Arc<Runtime>,
80
91
  bucket: String,
@@ -93,10 +104,8 @@ impl WriteStream {
93
104
  let _key = key.clone();
94
105
  let _storage_class = storage_class.clone();
95
106
 
96
- let object_writer = runtime.block_on(async move {
97
- ObjectWriter::new(client, _bucket, _key, _storage_class, part_size).await
98
- })?;
99
-
107
+ let object_writer =
108
+ ObjectWriter::new(client, _bucket, _key, _storage_class, part_size).await?;
100
109
  Ok(Self {
101
110
  object_writer: Arc::new(object_writer),
102
111
  runtime,
@@ -1,21 +0,0 @@
1
- from .tosnativeclient import TosClient, ListStream, ListObjectsResult, TosObject, TosError, TosException, TosRawClient, \
2
- HeadObjectInput, HeadObjectOutput, GetObjectOutput, DeleteObjectInput, DeleteObjectOutput, GetObjectInput, \
3
- PutObjectFromBufferInput, PutObjectFromFileInput, PutObjectOutput
4
-
5
- __all__ = ['TosClient',
6
- 'ListStream',
7
- 'ListObjectsResult',
8
- 'TosObject',
9
- 'TosError',
10
- 'TosException',
11
- 'TosRawClient',
12
- 'HeadObjectInput',
13
- 'HeadObjectOutput',
14
- 'DeleteObjectInput',
15
- 'DeleteObjectOutput',
16
- 'GetObjectInput',
17
- 'GetObjectOutput',
18
- 'PutObjectFromBufferInput',
19
- 'PutObjectFromFileInput',
20
- 'PutObjectOutput'
21
- ]