Skip to content
Merged
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::PyVortexResult;

/// 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) -> PyVortexResult<PyArrayRef> {
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::PyVortexResult;

/// 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) -> PyVortexResult<PyArrayRef> {
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::PyVortexResult;

/// 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>) -> PyVortexResult<PyArrayRef> {
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| -> PyVortexResult<_> {
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
64 changes: 39 additions & 25 deletions vortex-python/src/arrays/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ mod range_to_sequence;
use arrow_array::Array as ArrowArray;
use arrow_array::ArrayRef as ArrowArrayRef;
use pyo3::IntoPyObjectExt;
use pyo3::exceptions::PyIndexError;
use pyo3::exceptions::PyTypeError;
use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;
Expand All @@ -33,7 +34,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 +43,8 @@ use crate::arrays::py::PyPythonArray;
use crate::arrays::py::PythonArray;
use crate::arrow::ToPyArrow;
use crate::dtype::PyDType;
use crate::error::PyVortexError;
use crate::error::PyVortexResult;
use crate::install_module;
use crate::python_repr::PythonRepr;
use crate::scalar::PyScalar;
Expand Down Expand Up @@ -112,7 +114,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 +216,7 @@ impl PyArray {
/// -------
/// :class:`~vortex.Array`
#[staticmethod]
fn from_arrow(obj: Bound<'_, PyAny>) -> PyResult<PyArrayRef> {
fn from_arrow(obj: Bound<'_, PyAny>) -> PyVortexResult<PyArrayRef> {
from_arrow::from_arrow(&obj.as_borrowed())
}

Expand Down Expand Up @@ -257,7 +259,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>>,
) -> PyVortexResult<PyArrayRef> {
let range = range.cast::<PyRange>()?;
let start = range.start()?;
let stop = range.stop()?;
Expand All @@ -268,7 +273,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 +319,7 @@ 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>) -> PyVortexResult<Bound<'py, PyAny>> {
// 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,8 @@ impl PyArray {
let chunks = chunked_array
.chunks()
.iter()
.map(|chunk| PyResult::Ok(chunk.clone().into_arrow(&arrow_dtype)?))
.collect::<PyResult<Vec<ArrowArrayRef>>>()?;
.map(|chunk| -> PyVortexResult<_> { 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 +345,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 +423,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) -> PyVortexResult<PyArrayRef> {
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) -> PyVortexResult<PyArrayRef> {
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) -> PyVortexResult<PyArrayRef> {
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) -> PyVortexResult<PyArrayRef> {
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) -> PyVortexResult<PyArrayRef> {
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) -> PyVortexResult<PyArrayRef> {
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 +492,7 @@ impl PyArray {
/// 5
/// ]
/// ```
fn filter(slf: Bound<Self>, mask: PyArrayRef) -> PyResult<PyArrayRef> {
fn filter(slf: Bound<Self>, mask: PyArrayRef) -> PyVortexResult<PyArrayRef> {
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 @@ -551,7 +557,7 @@ impl PyArray {
/// >>> vx.array([10, 42, 999, 1992]).scalar_at(10)
/// Traceback (most recent call last):
/// ...
/// ValueError: index 10 out of bounds from 0 to 4
/// IndexError: Index 10 out of bounds from 0 to 4
/// ```
///
/// Unlike Python, negative indices are not supported:
Expand All @@ -563,10 +569,17 @@ impl PyArray {
/// OverflowError: can't convert negative int to unsigned
/// ```
// TODO(ngates): return a vortex.Scalar
fn scalar_at(slf: Bound<Self>, index: usize) -> PyResult<Bound<PyScalar>> {
fn scalar_at(slf: Bound<Self>, index: usize) -> PyVortexResult<Bound<PyScalar>> {
let py = slf.py();
let slf = PyArrayRef::extract(slf.as_any().as_borrowed())?.into_inner();
PyScalar::init(py, slf.scalar_at(index)?)
if index >= slf.len() {
return Err(PyIndexError::new_err(format!(
"Index {index} out of bounds from 0 to {}",
slf.len()
))
.into());
}
Ok(PyScalar::init(py, slf.scalar_at(index)?)?)
}

/// Filter, permute, and/or repeat elements by their index.
Expand Down Expand Up @@ -611,14 +624,15 @@ impl PyArray {
/// "a"
/// ]
/// ```
fn take(slf: Bound<Self>, indices: PyArrayRef) -> PyResult<PyArrayRef> {
fn take(slf: Bound<Self>, indices: PyArrayRef) -> PyVortexResult<PyArrayRef> {
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 @@ -668,7 +682,7 @@ impl PyArray {
.to_string())
}

fn serialize(slf: &Bound<Self>, ctx: &PyArrayContext) -> PyResult<Vec<Vec<u8>>> {
fn serialize(slf: &Bound<Self>, ctx: &PyArrayContext) -> PyVortexResult<Vec<Vec<u8>>> {
// FIXME(ngates): do not copy to vec, use buffer protocol
let array = PyArrayRef::extract(slf.as_any().as_borrowed())?;
Ok(array
Expand All @@ -684,7 +698,7 @@ impl PyArray {
/// the data needed for pickle to reconstruct the array.
fn __reduce__<'py>(
slf: &'py Bound<'py, Self>,
) -> PyResult<(Bound<'py, PyAny>, Bound<'py, PyAny>)> {
) -> PyVortexResult<(Bound<'py, PyAny>, Bound<'py, PyAny>)> {
let py = slf.py();
let array = PyArrayRef::extract(slf.as_any().as_borrowed())?.into_inner();

Expand All @@ -711,7 +725,7 @@ impl PyArray {
fn __reduce_ex__<'py>(
slf: &'py Bound<'py, Self>,
protocol: i32,
) -> PyResult<(Bound<'py, PyAny>, Bound<'py, PyAny>)> {
) -> PyVortexResult<(Bound<'py, PyAny>, Bound<'py, PyAny>)> {
let py = slf.py();

if protocol < 5 {
Expand Down
Loading
Loading