Skip to content

Commit 42bbf80

Browse files
authored
chore(pyo3-arrow): Bump to pyo3 0.27 (#421)
* chore(pyo3-arrow): Bump to pyo3 0.27 * use git rev * Improved dev docs for updating arro3 * Use released numpy
1 parent e2de4da commit 42bbf80

File tree

22 files changed

+198
-152
lines changed

22 files changed

+198
-152
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ numpy = "0.26"
3636
object_store = "0.12.4"
3737
parquet = "56.2"
3838
pyo3 = { version = "0.26", features = ["macros", "indexmap"] }
39-
pyo3-arrow = { path = "./pyo3-arrow" }
39+
pyo3-arrow = { git = "https://github.com/kylebarron/arro3", rev = "e2de4da2f732667dd796335ea7def8b111f79838" }
4040
pyo3-async-runtimes = { version = "0.26", features = ["tokio-runtime"] }
4141
pyo3-file = { git = "https://github.com/alex/pyo3-file", rev = "82b96dc188a48b88421f41b24cb13da114fd2fe8" }
4242
pyo3-object_store = "0.6"

DEVELOP.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,23 @@ RUSTUP_TOOLCHAIN=nightly \
5454
--target wasm32-unknown-emscripten \
5555
-i python3.11
5656
```
57+
58+
## Updating pyo3 version
59+
60+
It takes a few steps to update for a new pyo3 version. We have to do these steps in a specific order because of intertangled dependencies.
61+
62+
arro3 depends on pyo3-arrow and pyo3-object_store. pyo3-object_store itself depends on pyo3-arrow, so we have to wait for a pyo3-arrow release before we can update pyo3-object_store, and then we need a `pyo3-object_store` release before we can update arro3 itself.
63+
64+
1. For simplicity, arro3 often uses the workspace dependency version of `pyo3-arrow`, with `pyo3-arrow = { path = "./pyo3-arrow" }` in `Cargo.toml`. Instead, we need to unlink this so that we can update arro3.
65+
66+
Change this to use the git dependency instead, pointing to the latest commit hash of `pyo3-arrow` that uses the existing pyo3 version. I.e. something like this
67+
68+
```toml
69+
pyo3-arrow = { git = "https://github.com/kylebarron/arro3", rev = "e2de4da2f732667dd796335ea7def8b111f79838" }
70+
```
71+
Where this `rev` is the current `main`.
72+
73+
2. Update pyo3 version in `pyo3-arrow/Cargo.toml`. Open a PR and release a new version of `pyo3-arrow`. Note that `pyo3-arrow` also depends on `numpy`, so we need to wait for a new release there, but that should be pretty fast.
74+
3. Ensure `pyo3-async-runtimes` and `pyo3-file` have releases for latest `pyo3`.
75+
4. Update `pyo3-object-store` to depend on the new `pyo3-arrow` version. Open a PR and release a new version of `pyo3-object-store`.
76+
5. Finally, update `arro3/Cargo.toml` to depend on the new `pyo3-arrow` and `pyo3-object-store` versions, and update pyo3 version. Open a PR and release a new version of `arro3`.

pyo3-arrow/Cargo.lock

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

pyo3-arrow/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ arrow-schema = "56"
2727
arrow-select = "56"
2828
chrono = "0.4"
2929
chrono-tz = "0.10"
30-
pyo3 = { version = "0.26", features = ["chrono", "chrono-tz", "indexmap"] }
30+
pyo3 = { version = "0.27", features = ["chrono", "chrono-tz", "indexmap"] }
3131
half = "2"
3232
indexmap = "2"
33-
numpy = { version = "0.26", features = ["half"] }
33+
numpy = { version = "0.27", features = ["half"] }
3434
thiserror = "1"
3535

3636
[lib]

pyo3-arrow/src/array.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ impl PyArray {
410410
return buf.try_into();
411411
}
412412

413-
let numpy_array: Bound<PyUntypedArray> = FromPyObject::extract_bound(&numpy_array)?;
413+
let numpy_array: Bound<PyUntypedArray> = numpy_array.extract()?;
414414
let arrow_array = from_numpy(py, &numpy_array)?;
415415
Ok(Self::from_array_ref(arrow_array))
416416
}

pyo3-arrow/src/buffer.rs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,11 @@ impl PyArrowBuffer {
109109
unsafe fn __releasebuffer__(&self, _view: *mut ffi::Py_buffer) {}
110110
}
111111

112-
impl<'py> FromPyObject<'py> for PyArrowBuffer {
113-
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
114-
let buffer = ob.extract::<AnyBufferProtocol>()?;
112+
impl<'py> FromPyObject<'_, 'py> for PyArrowBuffer {
113+
type Error = PyErr;
114+
115+
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
116+
let buffer = obj.extract::<AnyBufferProtocol>()?;
115117
if !matches!(buffer, AnyBufferProtocol::UInt8(_)) {
116118
return Err(PyValueError::new_err("Expected u8 buffer protocol object"));
117119
}
@@ -136,27 +138,29 @@ pub enum AnyBufferProtocol {
136138
Float64(PyBuffer<f64>),
137139
}
138140

139-
impl<'py> FromPyObject<'py> for AnyBufferProtocol {
140-
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
141-
if let Ok(buf) = ob.extract() {
141+
impl<'py> FromPyObject<'_, 'py> for AnyBufferProtocol {
142+
type Error = PyErr;
143+
144+
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
145+
if let Ok(buf) = obj.extract() {
142146
Ok(Self::UInt8(buf))
143-
} else if let Ok(buf) = ob.extract() {
147+
} else if let Ok(buf) = obj.extract() {
144148
Ok(Self::UInt16(buf))
145-
} else if let Ok(buf) = ob.extract() {
149+
} else if let Ok(buf) = obj.extract() {
146150
Ok(Self::UInt32(buf))
147-
} else if let Ok(buf) = ob.extract() {
151+
} else if let Ok(buf) = obj.extract() {
148152
Ok(Self::UInt64(buf))
149-
} else if let Ok(buf) = ob.extract() {
153+
} else if let Ok(buf) = obj.extract() {
150154
Ok(Self::Int8(buf))
151-
} else if let Ok(buf) = ob.extract() {
155+
} else if let Ok(buf) = obj.extract() {
152156
Ok(Self::Int16(buf))
153-
} else if let Ok(buf) = ob.extract() {
157+
} else if let Ok(buf) = obj.extract() {
154158
Ok(Self::Int32(buf))
155-
} else if let Ok(buf) = ob.extract() {
159+
} else if let Ok(buf) = obj.extract() {
156160
Ok(Self::Int64(buf))
157-
} else if let Ok(buf) = ob.extract() {
161+
} else if let Ok(buf) = obj.extract() {
158162
Ok(Self::Float32(buf))
159-
} else if let Ok(buf) = ob.extract() {
163+
} else if let Ok(buf) = obj.extract() {
160164
Ok(Self::Float64(buf))
161165
} else {
162166
Err(PyValueError::new_err("Not a buffer protocol object"))

pyo3-arrow/src/datatypes.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ use crate::PyField;
1717

1818
struct PyTimeUnit(arrow_schema::TimeUnit);
1919

20-
impl<'a> FromPyObject<'a> for PyTimeUnit {
21-
fn extract_bound(ob: &Bound<'a, PyAny>) -> PyResult<Self> {
22-
let s: String = ob.extract()?;
20+
impl<'a> FromPyObject<'_, 'a> for PyTimeUnit {
21+
type Error = PyErr;
22+
23+
fn extract(obj: Borrowed<'_, 'a, PyAny>) -> Result<Self, Self::Error> {
24+
let s: String = obj.extract()?;
2325
match s.to_lowercase().as_str() {
2426
"s" => Ok(Self(TimeUnit::Second)),
2527
"ms" => Ok(Self(TimeUnit::Millisecond)),

pyo3-arrow/src/error.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use numpy::BorrowError;
44
use pyo3::exceptions::{PyException, PyValueError};
55
use pyo3::prelude::*;
6-
use pyo3::DowncastError;
6+
use pyo3::CastError;
77
use thiserror::Error;
88

99
/// The Error variants returned by this crate.
@@ -33,8 +33,8 @@ impl From<PyArrowError> for PyErr {
3333
}
3434
}
3535

36-
impl<'a, 'py> From<DowncastError<'a, 'py>> for PyArrowError {
37-
fn from(other: DowncastError<'a, 'py>) -> Self {
36+
impl<'a, 'py> From<CastError<'a, 'py>> for PyArrowError {
37+
fn from(other: CastError<'a, 'py>) -> Self {
3838
Self::PyErr(PyValueError::new_err(format!(
3939
"Could not downcast: {}",
4040
other

pyo3-arrow/src/ffi/from_python/array.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@ use crate::buffer::AnyBufferProtocol;
44
use crate::ffi::from_python::utils::call_arrow_c_array;
55
use pyo3::exceptions::PyValueError;
66
use pyo3::prelude::*;
7-
use pyo3::{intern, PyAny, PyResult};
7+
use pyo3::{intern, PyAny};
88

9-
impl<'a> FromPyObject<'a> for PyArray {
10-
fn extract_bound(ob: &Bound<'a, PyAny>) -> PyResult<Self> {
11-
if ob.hasattr(intern!(ob.py(), "__arrow_c_array__"))? {
12-
let (schema_capsule, array_capsule) = call_arrow_c_array(ob)?;
9+
impl<'py> FromPyObject<'_, 'py> for PyArray {
10+
type Error = PyErr;
11+
12+
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
13+
if obj.hasattr(intern!(obj.py(), "__arrow_c_array__"))? {
14+
let (schema_capsule, array_capsule) = call_arrow_c_array(&obj)?;
1315
Self::from_arrow_pycapsule(&schema_capsule, &array_capsule)
1416
} else {
1517
#[cfg(feature = "buffer_protocol")]
16-
if let Ok(buf) = ob.extract::<AnyBufferProtocol>() {
18+
if let Ok(buf) = obj.extract::<AnyBufferProtocol>() {
1719
return Ok(buf.try_into()?);
1820
}
1921

0 commit comments

Comments
 (0)