Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion vortex-error/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ all-features = true

[features]
flatbuffers = ["dep:flatbuffers"]
python = ["dep:pyo3"]
serde = ["dep:serde_json"]

[dependencies]
Expand Down
3 changes: 0 additions & 3 deletions vortex-error/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
//! This crate defines error & result types for Vortex.
//! It also contains a variety of useful macros for error handling.

#[cfg(feature = "python")]
pub mod python;

use std::backtrace::Backtrace;
use std::borrow::Cow;
use std::convert::Infallible;
Expand Down
24 changes: 0 additions & 24 deletions vortex-error/src/python.rs

This file was deleted.

2 changes: 1 addition & 1 deletion vortex-python/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ tokio = { workspace = true, features = ["fs", "rt-multi-thread"] }
# This feature makes the underlying tracing logs to be emitted as `log` events
tracing = { workspace = true, features = ["std", "log"] }
url = { workspace = true }
vortex = { workspace = true, features = ["object_store", "python", "tokio"] }
vortex = { workspace = true, features = ["object_store", "tokio"] }

[dev-dependencies]
vortex-array = { workspace = true, features = ["_test-harness"] }
3 changes: 2 additions & 1 deletion vortex-python/src/arrays/builtins/struct_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::arrays::PyArrayRef;
use crate::arrays::native::AsArrayRef;
use crate::arrays::native::EncodingSubclass;
use crate::arrays::native::PyNativeArray;
use crate::error::PyVortexError;

/// Concrete class for arrays with `vortex.struct` encoding.
#[pyclass(name = "StructArray", module = "vortex", extends=PyNativeArray, frozen)]
Expand All @@ -24,7 +25,7 @@ impl EncodingSubclass for PyStructArray {
#[pymethods]
impl PyStructArray {
/// Returns the given field of the struct array.
pub fn field(self_: PyRef<'_, Self>, name: &str) -> PyResult<PyArrayRef> {
pub fn field(self_: PyRef<'_, Self>, name: &str) -> Result<PyArrayRef, PyVortexError> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you type alias a PyVortexResult

let field = self_.as_array_ref().field_by_name(name)?.clone();
Ok(PyArrayRef::from(field))
}
Expand Down
3 changes: 2 additions & 1 deletion vortex-python/src/arrays/compressed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::PyVortex;
use crate::arrays::PyArrayRef;
use crate::arrays::native::EncodingSubclass;
use crate::arrays::native::PyNativeArray;
use crate::error::PyVortexError;

/// Concrete class for arrays with `vortex.alp` encoding.
#[pyclass(name = "AlpArray", module = "vortex", extends=PyNativeArray, frozen)]
Expand Down Expand Up @@ -87,7 +88,7 @@ impl EncodingSubclass for PyZigZagArray {
#[pymethods]
impl PyZigZagArray {
#[staticmethod]
pub fn encode(array: PyArrayRef) -> PyResult<PyArrayRef> {
pub fn encode(array: PyArrayRef) -> Result<PyArrayRef, PyVortexError> {
Ok(PyVortex(
zigzag_encode(array.inner().clone().to_primitive())?.into_array(),
))
Expand Down
16 changes: 7 additions & 9 deletions vortex-python/src/arrays/from_arrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use arrow_array::make_array;
use arrow_data::ArrayData as ArrowArrayData;
use arrow_schema::DataType;
use arrow_schema::Field;
use itertools::Itertools;
use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;
use vortex::array::ArrayRef;
Expand All @@ -17,13 +16,13 @@ use vortex::array::arrow::FromArrowArray;
use vortex::dtype::DType;
use vortex::dtype::arrow::FromArrowType;
use vortex::error::VortexError;
use vortex::error::VortexResult;

use crate::arrays::PyArrayRef;
use crate::arrow::FromPyArrow;
use crate::error::PyVortexError;

/// Convert an Arrow object to a Vortex array.
pub(super) fn from_arrow(obj: &Borrowed<'_, '_, PyAny>) -> PyResult<PyArrayRef> {
pub(super) fn from_arrow(obj: &Borrowed<'_, '_, PyAny>) -> Result<PyArrayRef, PyVortexError> {
let pa = obj.py().import("pyarrow")?;
let pa_array = pa.getattr("Array")?;
let chunked_array = pa.getattr("ChunkedArray")?;
Expand Down Expand Up @@ -56,15 +55,14 @@ pub(super) fn from_arrow(obj: &Borrowed<'_, '_, PyAny>) -> PyResult<PyArrayRef>
let dtype = DType::from_arrow(array_stream.schema());
let chunks = array_stream
.into_iter()
.map(|b| b.map_err(VortexError::from))
.map_ok(|b| ArrayRef::from_arrow(b, false))
.collect::<VortexResult<Vec<_>>>()?;
.map(|b| -> Result<_, PyVortexError> {
Ok(ArrayRef::from_arrow(b.map_err(VortexError::from)?, false))
})
.collect::<Result<Vec<_>, _>>()?;
Ok(PyArrayRef::from(
ChunkedArray::try_new(chunks, dtype)?.into_array(),
))
} else {
Err(PyValueError::new_err(
"Cannot convert object to Vortex array",
))
Err(PyValueError::new_err("Cannot convert object to Vortex array").into())
}
}
11 changes: 9 additions & 2 deletions vortex-python/src/arrays/into_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use pyo3::Borrowed;
use pyo3::FromPyObject;
use pyo3::PyAny;
use pyo3::PyErr;
use pyo3::exceptions::PyRuntimeError;
use pyo3::exceptions::PyTypeError;
use pyo3::types::PyAnyMethods;
use vortex::array::ArrayRef;
Expand All @@ -17,6 +18,7 @@ use vortex::array::iter::ArrayIteratorAdapter;
use vortex::array::iter::ArrayIteratorExt;
use vortex::dtype::DType;
use vortex::dtype::arrow::FromArrowType as _;
use vortex::error::VortexError;
use vortex::error::VortexResult;

use crate::PyVortex;
Expand Down Expand Up @@ -64,9 +66,14 @@ impl<'py> FromPyObject<'_, 'py> for PyIntoArray {
let vortex_iter = arrow_stream
.into_iter()
.map(|batch_result| -> VortexResult<_> {
Ok(ArrayRef::from_arrow(batch_result?, false))
Ok(ArrayRef::from_arrow(
batch_result.map_err(VortexError::from)?,
false,
))
});
let array = ArrayIteratorAdapter::new(dtype, vortex_iter).read_all()?;
let array = ArrayIteratorAdapter::new(dtype, vortex_iter)
.read_all()
.map_err(|e| PyRuntimeError::new_err(e.to_string()))?;
return Ok(PyIntoArray(PyVortex(array)));
}

Expand Down
49 changes: 29 additions & 20 deletions vortex-python/src/arrays/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ use vortex::dtype::DType;
use vortex::dtype::Nullability;
use vortex::dtype::PType;
use vortex::dtype::match_each_integer_ptype;
use vortex::error::VortexError;
use vortex::ipc::messages::EncoderMessage;
use vortex::ipc::messages::MessageEncoder;

Expand All @@ -43,6 +42,7 @@ use crate::arrays::py::PyPythonArray;
use crate::arrays::py::PythonArray;
use crate::arrow::ToPyArrow;
use crate::dtype::PyDType;
use crate::error::PyVortexError;
use crate::install_module;
use crate::python_repr::PythonRepr;
use crate::scalar::PyScalar;
Expand Down Expand Up @@ -112,7 +112,7 @@ impl<'py> FromPyObject<'_, 'py> for PyArrayRef {
impl<'py> IntoPyObject<'py> for PyArrayRef {
type Target = PyAny;
type Output = Bound<'py, PyAny>;
type Error = VortexError;
type Error = PyVortexError;

fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
// If the ArrayRef is a PyArrayInstance, extract the Python object.
Expand Down Expand Up @@ -214,7 +214,7 @@ impl PyArray {
/// -------
/// :class:`~vortex.Array`
#[staticmethod]
fn from_arrow(obj: Bound<'_, PyAny>) -> PyResult<PyArrayRef> {
fn from_arrow(obj: Bound<'_, PyAny>) -> Result<PyArrayRef, PyVortexError> {
from_arrow::from_arrow(&obj.as_borrowed())
}

Expand Down Expand Up @@ -257,7 +257,10 @@ impl PyArray {
/// ```
#[staticmethod]
#[pyo3(signature = (range, *, dtype = None))]
fn from_range(range: Bound<PyAny>, dtype: Option<Bound<PyDType>>) -> PyResult<PyArrayRef> {
fn from_range(
range: Bound<PyAny>,
dtype: Option<Bound<PyDType>>,
) -> Result<PyArrayRef, PyVortexError> {
let range = range.cast::<PyRange>()?;
let start = range.start()?;
let stop = range.stop()?;
Expand All @@ -268,7 +271,8 @@ impl PyArray {
let DType::Primitive(ptype, ..) = &dtype else {
return Err(PyValueError::new_err(
"Cannot construct non-numeric array from a range.",
));
)
.into());
};
(*ptype, dtype)
} else {
Expand Down Expand Up @@ -313,7 +317,9 @@ impl PyArray {
/// ]
/// ```
///
fn to_arrow_array<'py>(self_: &'py Bound<'py, Self>) -> PyResult<Bound<'py, PyAny>> {
fn to_arrow_array<'py>(
self_: &'py Bound<'py, Self>,
) -> Result<Bound<'py, PyAny>, PyVortexError> {
// NOTE(ngates): for struct arrays, we could also return a RecordBatchStreamReader.
let array = PyArrayRef::extract(self_.as_any().as_borrowed())?.into_inner();
let py = self_.py();
Expand All @@ -326,8 +332,10 @@ impl PyArray {
let chunks = chunked_array
.chunks()
.iter()
.map(|chunk| PyResult::Ok(chunk.clone().into_arrow(&arrow_dtype)?))
.collect::<PyResult<Vec<ArrowArrayRef>>>()?;
.map(|chunk| -> Result<_, PyVortexError> {
Ok(chunk.clone().into_arrow(&arrow_dtype)?)
})
.collect::<Result<Vec<ArrowArrayRef>, _>>()?;

let pa_data_type = arrow_dtype.clone().to_pyarrow(py)?;
let chunks = chunks
Expand All @@ -339,11 +347,11 @@ impl PyArray {
PyDict::from_sequence(&PyList::new(py, vec![("type", pa_data_type)])?.into_any())?;

// Combine into a chunked array
PyModule::import(py, "pyarrow")?.call_method(
Ok(PyModule::import(py, "pyarrow")?.call_method(
"chunked_array",
(PyList::new(py, chunks)?,),
Some(&kwargs),
)
)?)
} else {
Ok(array
.clone()
Expand Down Expand Up @@ -417,42 +425,42 @@ impl PyArray {
}

///Rust docs are *not* copied into Python for __lt__: https://github.com/PyO3/pyo3/issues/4326
fn __lt__(slf: Bound<Self>, other: PyArrayRef) -> PyResult<PyArrayRef> {
fn __lt__(slf: Bound<Self>, other: PyArrayRef) -> Result<PyArrayRef, PyVortexError> {
let slf = PyArrayRef::extract(slf.as_any().as_borrowed())?.into_inner();
let inner = compare(&slf, &*other, Operator::Lt)?;
Ok(PyArrayRef::from(inner))
}

///Rust docs are *not* copied into Python for __le__: https://github.com/PyO3/pyo3/issues/4326
fn __le__(slf: Bound<Self>, other: PyArrayRef) -> PyResult<PyArrayRef> {
fn __le__(slf: Bound<Self>, other: PyArrayRef) -> Result<PyArrayRef, PyVortexError> {
let slf = PyArrayRef::extract(slf.as_any().as_borrowed())?.into_inner();
let inner = compare(&*slf, &*other, Operator::Lte)?;
Ok(PyArrayRef::from(inner))
}

///Rust docs are *not* copied into Python for __eq__: https://github.com/PyO3/pyo3/issues/4326
fn __eq__(slf: Bound<Self>, other: PyArrayRef) -> PyResult<PyArrayRef> {
fn __eq__(slf: Bound<Self>, other: PyArrayRef) -> Result<PyArrayRef, PyVortexError> {
let slf = PyArrayRef::extract(slf.as_any().as_borrowed())?.into_inner();
let inner = compare(&*slf, &*other, Operator::Eq)?;
Ok(PyArrayRef::from(inner))
}

///Rust docs are *not* copied into Python for __ne__: https://github.com/PyO3/pyo3/issues/4326
fn __ne__(slf: Bound<Self>, other: PyArrayRef) -> PyResult<PyArrayRef> {
fn __ne__(slf: Bound<Self>, other: PyArrayRef) -> Result<PyArrayRef, PyVortexError> {
let slf = PyArrayRef::extract(slf.as_any().as_borrowed())?.into_inner();
let inner = compare(&*slf, &*other, Operator::NotEq)?;
Ok(PyArrayRef::from(inner))
}

///Rust docs are *not* copied into Python for __ge__: https://github.com/PyO3/pyo3/issues/4326
fn __ge__(slf: Bound<Self>, other: PyArrayRef) -> PyResult<PyArrayRef> {
fn __ge__(slf: Bound<Self>, other: PyArrayRef) -> Result<PyArrayRef, PyVortexError> {
let slf = PyArrayRef::extract(slf.as_any().as_borrowed())?.into_inner();
let inner = compare(&*slf, &*other, Operator::Gte)?;
Ok(PyArrayRef::from(inner))
}

///Rust docs are *not* copied into Python for __gt__: https://github.com/PyO3/pyo3/issues/4326
fn __gt__(slf: Bound<Self>, other: PyArrayRef) -> PyResult<PyArrayRef> {
fn __gt__(slf: Bound<Self>, other: PyArrayRef) -> Result<PyArrayRef, PyVortexError> {
let slf = PyArrayRef::extract(slf.as_any().as_borrowed())?.into_inner();
let inner = compare(&*slf, &*other, Operator::Gt)?;
Ok(PyArrayRef::from(inner))
Expand Down Expand Up @@ -486,7 +494,7 @@ impl PyArray {
/// 5
/// ]
/// ```
fn filter(slf: Bound<Self>, mask: PyArrayRef) -> PyResult<PyArrayRef> {
fn filter(slf: Bound<Self>, mask: PyArrayRef) -> Result<PyArrayRef, PyVortexError> {
let slf = PyArrayRef::extract(slf.as_any().as_borrowed())?.into_inner();
let mask = (&*mask as &dyn Array).to_bool().to_mask_fill_null_false();
let inner = vortex::compute::filter(&*slf, &mask)?;
Expand Down Expand Up @@ -612,14 +620,15 @@ impl PyArray {
/// "a"
/// ]
/// ```
fn take(slf: Bound<Self>, indices: PyArrayRef) -> PyResult<PyArrayRef> {
fn take(slf: Bound<Self>, indices: PyArrayRef) -> Result<PyArrayRef, PyVortexError> {
let slf = PyArrayRef::extract(slf.as_any().as_borrowed())?.into_inner();

if !indices.dtype().is_int() {
return Err(PyValueError::new_err(format!(
"indices: expected int or uint array, but found: {}",
indices.dtype().python_repr()
)));
))
.into());
}

let inner = take(&slf, &*indices)?;
Expand Down Expand Up @@ -669,7 +678,7 @@ impl PyArray {
.to_string())
}

fn serialize(slf: &Bound<Self>, ctx: &PyArrayContext) -> PyResult<Vec<Vec<u8>>> {
fn serialize(slf: &Bound<Self>, ctx: &PyArrayContext) -> Result<Vec<Vec<u8>>, PyVortexError> {
// FIXME(ngates): do not copy to vec, use buffer protocol
let array = PyArrayRef::extract(slf.as_any().as_borrowed())?;
Ok(array
Expand Down
4 changes: 2 additions & 2 deletions vortex-python/src/arrays/py/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use pyo3::prelude::*;
use vortex::array::stats::ArrayStats;
use vortex::array::vtable::ArrayId;
use vortex::dtype::DType;
use vortex::error::VortexError;

use crate::arrays::py::PyPythonArray;
use crate::error::PyVortexError;

/// Wrapper struct encapsulating a Vortex array implemented using a Python object.
///
Expand Down Expand Up @@ -48,7 +48,7 @@ impl<'py> FromPyObject<'_, 'py> for PythonArray {
impl<'py> IntoPyObject<'py> for PythonArray {
type Target = PyAny;
type Output = Bound<'py, PyAny>;
type Error = VortexError;
type Error = PyVortexError;

fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
Ok(self.object.bind(py).to_owned())
Expand Down
5 changes: 3 additions & 2 deletions vortex-python/src/arrays/py/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ use pyo3::exceptions::PyValueError;
use pyo3::prelude::PyAnyMethods;
pub(crate) use python::*;
use vortex::array::vtable::ArrayId;
use vortex::error::VortexResult;
pub(crate) use vtable::*;

use crate::error::PyVortexError;

/// Extract the array id from a Python class `id` attribute.
pub fn id_from_obj(cls: &Bound<PyAny>) -> VortexResult<ArrayId> {
pub fn id_from_obj(cls: &Bound<PyAny>) -> Result<ArrayId, PyVortexError> {
Ok(ArrayId::new_arc(
cls.getattr("id")
.map_err(|_| {
Expand Down
3 changes: 2 additions & 1 deletion vortex-python/src/arrays/py/python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use vortex::dtype::DType;
use crate::arrays::PyArray;
use crate::arrays::py::id_from_obj;
use crate::dtype::PyDType;
use crate::error::PyVortexError;

/// Base class for implementing a Vortex encoding in Python.
///
Expand All @@ -31,7 +32,7 @@ impl PyPythonArray {
cls: &Bound<'_, PyType>,
len: usize,
dtype: PyDType,
) -> PyResult<PyClassInitializer<Self>> {
) -> Result<PyClassInitializer<Self>, PyVortexError> {
let id = id_from_obj(cls)?;
Ok(PyClassInitializer::from(PyArray).add_subclass(Self {
id,
Expand Down
Loading
Loading