tosnativeclient 1.0.2__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.

@@ -1521,7 +1521,7 @@ dependencies = [
1521
1521
 
1522
1522
  [[package]]
1523
1523
  name = "tosnativeclient"
1524
- version = "1.0.2"
1524
+ version = "1.0.4"
1525
1525
  dependencies = [
1526
1526
  "arc-swap",
1527
1527
  "async-channel",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "tosnativeclient"
3
- version = "1.0.2"
3
+ version = "1.0.4"
4
4
  edition = "2021"
5
5
  publish = false
6
6
  authors = ["xiangshijian"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tosnativeclient
3
- Version: 1.0.2
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
@@ -45,7 +45,7 @@ class ReadStream(object):
45
45
  size: int
46
46
  etag: str
47
47
 
48
- def read(self, offset: int, length: int) -> bytes:
48
+ def read(self, offset: int, length: int) -> Optional[bytes]:
49
49
  ...
50
50
 
51
51
  def close(self) -> None:
@@ -72,6 +72,10 @@ class TosClient(object):
72
72
  part_size: int
73
73
  max_retry_count: int
74
74
  max_prefetch_tasks: int
75
+ directives: str
76
+ directory: str
77
+ file_name_prefix: str
78
+ shared_prefetch_tasks: int
75
79
 
76
80
  def __init__(self, region: str, endpoint: str, ak: str = '', sk: str = '', part_size: int = 8388608,
77
81
  max_retry_count: int = 3, max_prefetch_tasks: int = 3, directives: str = '', directory: str = '',
@@ -147,10 +151,10 @@ class GetObjectOutput(object):
147
151
  content_range: str
148
152
  hash_crc64ecma: int
149
153
 
150
- def read_all(self) -> bytes:
154
+ def read_all(self) -> Optional[bytes]:
151
155
  ...
152
156
 
153
- def read(self) -> bytes:
157
+ def read(self) -> Optional[bytes]:
154
158
  ...
155
159
 
156
160
 
@@ -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>,
@@ -63,6 +64,17 @@ impl ListStream {
63
64
  }
64
65
  }
65
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
+ }
66
78
  }
67
79
 
68
80
  impl ListStream {
@@ -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,7 +5,9 @@ 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;
@@ -53,7 +55,7 @@ impl AsyncRuntime for TokioRuntime {
53
55
  pub(crate) type InnerTosClient =
54
56
  TosClientImpl<CommonCredentialsProvider<CommonCredentials>, CommonCredentials, TokioRuntime>;
55
57
 
56
- #[pyclass(name = "TosClient")]
58
+ #[pyclass(name = "TosClient", module = "tosnativeclient")]
57
59
  pub struct TosClient {
58
60
  rclient: Arc<InnerTosClient>,
59
61
  wclient: Arc<InnerTosClient>,
@@ -75,6 +77,14 @@ pub struct TosClient {
75
77
  max_retry_count: isize,
76
78
  #[pyo3(get)]
77
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,
78
88
  }
79
89
 
80
90
  #[pymethods]
@@ -97,7 +107,11 @@ impl TosClient {
97
107
  ) -> PyResult<Self> {
98
108
  let mut _guard = None;
99
109
  if directives != "" {
100
- _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
+ ));
101
115
  }
102
116
 
103
117
  let logical_cores = num_cpus::get();
@@ -142,6 +156,10 @@ impl TosClient {
142
156
  part_size,
143
157
  max_retry_count,
144
158
  max_prefetch_tasks,
159
+ directives,
160
+ directory,
161
+ file_name_prefix,
162
+ shared_prefetch_tasks,
145
163
  })
146
164
  }
147
165
 
@@ -210,6 +228,24 @@ impl TosClient {
210
228
  })
211
229
  })
212
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)
248
+ }
213
249
  }
214
250
 
215
251
  pub(crate) struct SharedPrefetchContext {
@@ -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,6 +72,16 @@ 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 {