Skip to content

Commit f1970d9

Browse files
authored
chore: Bump pyo3 to 0.27 (#584)
* chore: Bump pyo3 to 0.27 * Bump to pyo3 0.27 and arrow 57 * compile fixes from bumping to 0.27 * newline * cleaner code
1 parent 956add1 commit f1970d9

26 files changed

Lines changed: 366 additions & 314 deletions

Cargo.lock

Lines changed: 67 additions & 101 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ futures = "0.3.31"
2727
http = "1.2"
2828
indexmap = "2"
2929
object_store = "0.12.4"
30-
pyo3 = { version = "0.26", features = ["macros", "indexmap"] }
31-
pyo3-async-runtimes = { version = "0.26", features = ["tokio-runtime"] }
32-
pyo3-file = { git = "https://github.com/alex/pyo3-file", rev = "82b96dc188a48b88421f41b24cb13da114fd2fe8" }
30+
pyo3 = { version = "0.27.1", features = ["macros", "indexmap"] }
31+
pyo3-async-runtimes = { version = "0.27", features = ["tokio-runtime"] }
32+
pyo3-file = { git = "https://github.com/kylebarron/pyo3-file", rev = "aacc18816591f9987247bac8b7011b452b4eeb3e" }
3333
thiserror = "1"
3434
tokio = "1.40"
3535
url = "2"

obstore/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@ name = "_obstore"
1818
crate-type = ["cdylib"]
1919

2020
[dependencies]
21-
arrow = "56"
21+
arrow = "57"
2222
bytes = { workspace = true }
2323
chrono = { workspace = true }
2424
futures = { workspace = true }
2525
http = { workspace = true }
2626
indexmap = { workspace = true }
2727
object_store = { workspace = true }
2828
pyo3 = { workspace = true, features = ["chrono"] }
29-
pyo3-arrow = "0.12"
29+
pyo3-arrow = "0.15"
3030
pyo3-async-runtimes = { workspace = true, features = ["tokio-runtime"] }
31-
pyo3-bytes = "0.4"
31+
pyo3-bytes = "0.5"
3232
pyo3-file = { workspace = true }
3333
pyo3-object_store = { path = "../pyo3-object_store" }
3434
tokio = { workspace = true, features = [

obstore/src/attributes.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ use pyo3::types::PyDict;
1010
#[derive(Debug, PartialEq, Eq, Hash)]
1111
pub(crate) struct PyAttribute(Attribute);
1212

13-
impl<'py> FromPyObject<'py> for PyAttribute {
14-
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
15-
let s = ob.extract::<PyBackedStr>()?;
13+
impl<'py> FromPyObject<'_, 'py> for PyAttribute {
14+
type Error = PyErr;
15+
16+
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
17+
let s = obj.extract::<PyBackedStr>()?;
1618
match s.to_ascii_lowercase().as_str() {
1719
"content-disposition" | "contentdisposition" => Ok(Self(Attribute::ContentDisposition)),
1820
"content-encoding" | "contentencoding" => Ok(Self(Attribute::ContentEncoding)),
@@ -39,9 +41,11 @@ fn attribute_to_string(attribute: &Attribute) -> Cow<'static, str> {
3941
#[derive(Debug, PartialEq, Eq, Hash)]
4042
pub(crate) struct PyAttributeValue(AttributeValue);
4143

42-
impl<'py> FromPyObject<'py> for PyAttributeValue {
43-
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
44-
Ok(Self(ob.extract::<String>()?.into()))
44+
impl<'py> FromPyObject<'_, 'py> for PyAttributeValue {
45+
type Error = PyErr;
46+
47+
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
48+
Ok(Self(obj.extract::<String>()?.into()))
4549
}
4650
}
4751

@@ -58,9 +62,11 @@ impl PyAttributes {
5862
}
5963
}
6064

61-
impl<'py> FromPyObject<'py> for PyAttributes {
62-
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
63-
let d = ob.extract::<HashMap<PyAttribute, PyAttributeValue>>()?;
65+
impl<'py> FromPyObject<'_, 'py> for PyAttributes {
66+
type Error = PyErr;
67+
68+
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
69+
let d = obj.extract::<HashMap<PyAttribute, PyAttributeValue>>()?;
6470
let mut attributes = Attributes::with_capacity(d.len());
6571
for (k, v) in d.into_iter() {
6672
attributes.insert(k.0, v.0);

obstore/src/get.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ pub(crate) struct PyGetOptions {
3030
head: bool,
3131
}
3232

33-
impl<'py> FromPyObject<'py> for PyGetOptions {
34-
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
33+
impl<'py> FromPyObject<'_, 'py> for PyGetOptions {
34+
type Error = PyErr;
35+
36+
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
3537
// Update to use derive(FromPyObject) when default is implemented:
3638
// https://github.com/PyO3/pyo3/issues/4643
37-
let dict = ob.extract::<HashMap<String, Bound<PyAny>>>()?;
39+
let dict = obj.extract::<HashMap<String, Bound<PyAny>>>()?;
3840
Ok(Self {
3941
if_match: dict.get("if_match").map(|x| x.extract()).transpose()?,
4042
if_none_match: dict.get("if_none_match").map(|x| x.extract()).transpose()?,
@@ -102,13 +104,15 @@ pub(crate) struct PyGetRange(GetRange);
102104
// - [usize, usize] to refer to a bounded range from start to end (exclusive)
103105
// - {"offset": usize} to request all bytes starting from a given byte offset
104106
// - {"suffix": usize} to request the last `n` bytes
105-
impl<'py> FromPyObject<'py> for PyGetRange {
106-
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
107-
if let Ok(bounded) = ob.extract::<[u64; 2]>() {
107+
impl<'py> FromPyObject<'_, 'py> for PyGetRange {
108+
type Error = PyErr;
109+
110+
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
111+
if let Ok(bounded) = obj.extract::<[u64; 2]>() {
108112
Ok(Self(GetRange::Bounded(bounded[0]..bounded[1])))
109-
} else if let Ok(offset_range) = ob.extract::<PyOffsetRange>() {
113+
} else if let Ok(offset_range) = obj.extract::<PyOffsetRange>() {
110114
Ok(Self(offset_range.into()))
111-
} else if let Ok(suffix_range) = ob.extract::<PySuffixRange>() {
115+
} else if let Ok(suffix_range) = obj.extract::<PySuffixRange>() {
112116
Ok(Self(suffix_range.into()))
113117
} else {
114118
Err(PyValueError::new_err("Unexpected input for byte range.\nExpected two-integer tuple or list, or dict with 'offset' or 'suffix' key." ))

obstore/src/path.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ pub(crate) enum PyPaths {
99
Many(Vec<Path>),
1010
}
1111

12-
impl<'py> FromPyObject<'py> for PyPaths {
13-
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
14-
if let Ok(path) = ob.extract::<PyPath>() {
12+
impl<'py> FromPyObject<'_, 'py> for PyPaths {
13+
type Error = PyErr;
14+
15+
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
16+
if let Ok(path) = obj.extract::<PyPath>() {
1517
Ok(Self::One(path.into_inner()))
16-
} else if let Ok(paths) = ob.extract::<Vec<PyPath>>() {
18+
} else if let Ok(paths) = obj.extract::<Vec<PyPath>>() {
1719
Ok(Self::Many(
1820
paths.into_iter().map(|path| path.into_inner()).collect(),
1921
))

obstore/src/put.rs

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ use crate::tags::PyTagSet;
2626

2727
pub(crate) struct PyPutMode(PutMode);
2828

29-
impl<'py> FromPyObject<'py> for PyPutMode {
30-
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
31-
if let Ok(s) = ob.extract::<PyBackedStr>() {
29+
impl<'py> FromPyObject<'_, 'py> for PyPutMode {
30+
type Error = PyErr;
31+
32+
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
33+
if let Ok(s) = obj.extract::<PyBackedStr>() {
3234
let s = s.to_ascii_lowercase();
3335
match s.as_str() {
3436
"create" => Ok(Self(PutMode::Create)),
@@ -38,19 +40,21 @@ impl<'py> FromPyObject<'py> for PyPutMode {
3840
))),
3941
}
4042
} else {
41-
let update_version = ob.extract::<PyUpdateVersion>()?;
43+
let update_version = obj.extract::<PyUpdateVersion>()?;
4244
Ok(Self(PutMode::Update(update_version.0)))
4345
}
4446
}
4547
}
4648

4749
pub(crate) struct PyUpdateVersion(UpdateVersion);
4850

49-
impl<'py> FromPyObject<'py> for PyUpdateVersion {
50-
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
51+
impl<'py> FromPyObject<'_, 'py> for PyUpdateVersion {
52+
type Error = PyErr;
53+
54+
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
5155
// Update to use derive(FromPyObject) when default is implemented:
5256
// https://github.com/PyO3/pyo3/issues/4643
53-
let dict = ob.extract::<HashMap<String, Bound<PyAny>>>()?;
57+
let dict = obj.extract::<HashMap<String, Bound<PyAny>>>()?;
5458
Ok(Self(UpdateVersion {
5559
e_tag: dict.get("e_tag").map(|x| x.extract()).transpose()?,
5660
version: dict.get("version").map(|x| x.extract()).transpose()?,
@@ -233,40 +237,48 @@ impl PutInput {
233237
}
234238
}
235239

236-
impl<'py> FromPyObject<'py> for PutInput {
237-
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
238-
let py = ob.py();
239-
if let Ok(path) = ob.extract::<PathBuf>() {
240+
impl<'py> FromPyObject<'_, 'py> for PutInput {
241+
type Error = PyErr;
242+
243+
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
244+
let py = obj.py();
245+
if let Ok(path) = obj.extract::<PathBuf>() {
240246
Ok(Self::Pull(PullSource::File(BufReader::new(File::open(
241247
path,
242248
)?))))
243-
} else if let Ok(buffer) = ob.extract::<PyBytes>() {
249+
} else if let Ok(buffer) = obj.extract::<PyBytes>() {
244250
Ok(Self::Pull(PullSource::Buffer(Cursor::new(
245251
buffer.into_inner(),
246252
))))
247253
}
248254
// Check for file-like object
249-
else if ob.hasattr(intern!(py, "read"))? && ob.hasattr(intern!(py, "seek"))? {
255+
else if obj.hasattr(intern!(py, "read"))? && obj.hasattr(intern!(py, "seek"))? {
250256
Ok(Self::Pull(PullSource::FileLike(
251-
PyFileLikeObject::py_with_requirements(ob.clone(), true, false, true, false)?,
257+
PyFileLikeObject::py_with_requirements(
258+
obj.as_any().clone(),
259+
true,
260+
false,
261+
true,
262+
false,
263+
)?,
252264
)))
253265
}
254266
// Ensure we check _first_ for an async generator before a sync one
255-
else if ob.hasattr(intern!(py, "__aiter__"))? {
267+
else if obj.hasattr(intern!(py, "__aiter__"))? {
256268
Ok(Self::AsyncPush(AsyncPushSource::AsyncIterator(
257-
ob.call_method0(intern!(py, "__aiter__"))?.unbind(),
269+
obj.call_method0(intern!(py, "__aiter__"))?.unbind(),
258270
)))
259-
} else if ob.hasattr(intern!(py, "__anext__"))? {
271+
} else if obj.hasattr(intern!(py, "__anext__"))? {
260272
Ok(Self::AsyncPush(AsyncPushSource::AsyncIterator(
261-
ob.clone().unbind(),
273+
obj.as_unbound().clone_ref(py),
262274
)))
263-
} else if ob.hasattr(intern!(py, "__iter__"))? {
275+
} else if obj.hasattr(intern!(py, "__iter__"))? {
264276
Ok(Self::SyncPush(SyncPushSource::Iterator(
265-
ob.call_method0(intern!(py, "__iter__"))?.unbind(),
277+
obj.call_method0(intern!(py, "__iter__"))?.unbind(),
266278
)))
267-
} else if ob.hasattr(intern!(py, "__next__"))? {
279+
} else if obj.hasattr(intern!(py, "__next__"))? {
268280
Ok(Self::SyncPush(SyncPushSource::Iterator(
269-
ob.clone().unbind(),
281+
obj.as_unbound().clone_ref(py),
270282
)))
271283
} else {
272284
Err(PyValueError::new_err("Unexpected input for PutInput"))

obstore/src/signer.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,20 @@ pub(crate) enum SignCapableStore {
2929
Azure(Arc<MaybePrefixedStore<MicrosoftAzure>>),
3030
}
3131

32-
impl<'py> FromPyObject<'py> for SignCapableStore {
33-
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
34-
if let Ok(store) = ob.downcast::<PyS3Store>() {
32+
impl<'py> FromPyObject<'_, 'py> for SignCapableStore {
33+
type Error = PyErr;
34+
35+
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
36+
if let Ok(store) = obj.cast::<PyS3Store>() {
3537
Ok(Self::S3(store.get().as_ref().clone()))
36-
} else if let Ok(store) = ob.downcast::<PyGCSStore>() {
38+
} else if let Ok(store) = obj.cast::<PyGCSStore>() {
3739
Ok(Self::Gcs(store.get().as_ref().clone()))
38-
} else if let Ok(store) = ob.downcast::<PyAzureStore>() {
40+
} else if let Ok(store) = obj.cast::<PyAzureStore>() {
3941
Ok(Self::Azure(store.get().as_ref().clone()))
4042
} else {
41-
let py = ob.py();
43+
let py = obj.py();
4244
// Check for object-store instance from other library
43-
let cls_name = ob
45+
let cls_name = obj
4446
.getattr(intern!(py, "__class__"))?
4547
.getattr(intern!(py, "__name__"))?
4648
.extract::<PyBackedStr>()?;
@@ -59,7 +61,7 @@ impl<'py> FromPyObject<'py> for SignCapableStore {
5961

6062
Err(PyValueError::new_err(format!(
6163
"Expected an S3Store, GCSStore, or AzureStore instance, got {}",
62-
ob.repr()?
64+
obj.repr()?
6365
)))
6466
}
6567
}
@@ -114,9 +116,11 @@ impl Signer for SignCapableStore {
114116

115117
pub(crate) struct PyMethod(Method);
116118

117-
impl<'py> FromPyObject<'py> for PyMethod {
118-
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
119-
let s = ob.extract::<PyBackedStr>()?;
119+
impl<'py> FromPyObject<'_, 'py> for PyMethod {
120+
type Error = PyErr;
121+
122+
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
123+
let s = obj.extract::<PyBackedStr>()?;
120124
let method = match s.as_ref() {
121125
"GET" => Method::GET,
122126
"PUT" => Method::PUT,

obstore/src/tags.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ impl PyTagSet {
1212
}
1313
}
1414

15-
impl<'py> FromPyObject<'py> for PyTagSet {
16-
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
17-
let input = ob.extract::<HashMap<PyBackedStr, PyBackedStr>>()?;
15+
impl<'py> FromPyObject<'_, 'py> for PyTagSet {
16+
type Error = PyErr;
17+
18+
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
19+
let input = obj.extract::<HashMap<PyBackedStr, PyBackedStr>>()?;
1820
let mut tag_set = TagSet::default();
1921
for (key, value) in input.into_iter() {
2022
tag_set.push(&key, &value);

pyo3-object_store/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ object_store = { version = "0.12.4", features = [
3636
] }
3737
# This is already an object_store dependency
3838
percent-encoding = "2.1"
39-
pyo3 = { version = "0.26", features = ["chrono", "indexmap"] }
40-
pyo3-async-runtimes = { version = "0.26", features = ["tokio-runtime"] }
39+
pyo3 = { version = "0.27", features = ["chrono", "indexmap"] }
40+
pyo3-async-runtimes = { version = "0.27", features = ["tokio-runtime"] }
4141
serde = "1"
4242
thiserror = "1"
4343
tokio = { version = "1.40", features = ["rt-multi-thread"] }

0 commit comments

Comments
 (0)