diff --git a/pyproject.toml b/pyproject.toml index 1a6bb11..e970754 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ dependencies = [ ] [project.optional-dependencies] -test = ["pytest"] +test = ["pytest", "tiffwrite"] [project.scripts] ndbioimage = "ndbioimage:ndbioimage_rs.main" @@ -38,7 +38,6 @@ python-source = "py" features = ["python", "bioformats_java", "tiffwrite"] module-name = "ndbioimage.ndbioimage_rs" include = ["py/ndbioimage/jassets/j4rs*", "py/ndbioimage/deps/libj4rs*"] -strip = true [tool.isort] line_length = 119 diff --git a/src/error.rs b/src/error.rs index 35bc3d9..cb346aa 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,6 +1,7 @@ +use strum::IntoStaticStr; use thiserror::Error; -#[derive(Debug, Error)] +#[derive(Debug, Error, IntoStaticStr)] pub enum Error { #[error(transparent)] IO(#[from] std::io::Error), @@ -113,3 +114,9 @@ pub enum Error { #[error("cannot remove axes {0}, size {1} != 1")] SizeMismatch(String, usize), } + +impl Error { + pub fn variant_name(&self) -> &'static str { + self.into() + } +} diff --git a/src/py.rs b/src/py.rs index 11ecee5..384fcb2 100644 --- a/src/py.rs +++ b/src/py.rs @@ -14,7 +14,9 @@ use numpy::{ use ome_metadata::Ome; use postcard::{from_bytes, to_stdvec}; use pyo3::IntoPyObjectExt; -use pyo3::exceptions::{PyIndexError, PyNotImplementedError, PyTypeError, PyValueError}; +use pyo3::exceptions::{ + PyIndexError, PyNotImplementedError, PyRuntimeError, PyTypeError, PyValueError, +}; use pyo3::prelude::*; use pyo3::types::{ PyBytes, PyEllipsis, PyInt, PyList, PyNone, PySlice, PySliceMethods, PyString, PyTuple, @@ -24,11 +26,25 @@ use pyo3_stub_gen::inventory::submit; use pyo3_stub_gen::{StubGenConfig, StubInfo}; use serde::{Deserialize, Serialize}; use std::collections::HashSet; +use std::error::Error as StdError; use std::path::PathBuf; +fn format_error_chain(err: &crate::error::Error) -> String { + let mut msg = format!("[{}] {err}", err.variant_name()); + let mut source = err.source(); + while let Some(s) = source { + msg.push_str(&format!("\n |-> {s}")); + source = s.source(); + } + msg +} + impl From for PyErr { + #[track_caller] fn from(err: crate::error::Error) -> PyErr { - color_eyre::eyre::Report::from(err).into() + let location = std::panic::Location::caller(); + let msg = format!("{}: {}", location, format_error_chain(&err)); + PyRuntimeError::new_err(msg) } } @@ -200,7 +216,7 @@ impl PyView { let dtype_str = name.extract::()?; dtype_str.parse()? } else { - PixelType::U16 + *view.pixel_type() }; let ome = view.metadata()?; Ok(Self { diff --git a/tests/test_open.py b/tests/test_open.py index 4d76d8e..3b16349 100644 --- a/tests/test_open.py +++ b/tests/test_open.py @@ -13,7 +13,7 @@ from ndbioimage import Imread for path in (Path(__file__).parent / "files").iterdir() if path.is_dir() and path.name != "czi_xml" for file in path.iterdir() - if not file.suffix == ".pzl" + if file.suffix.lower() not in [".pzl", ".xml", "", ".txt"] ], ) def test_open(file): diff --git a/tests/test_slicing.py b/tests/test_slicing.py index dc77594..3fa9a57 100644 --- a/tests/test_slicing.py +++ b/tests/test_slicing.py @@ -18,7 +18,7 @@ def array(): @pytest.fixture() def image(array): with tempfile.TemporaryDirectory() as folder: - file = Path(folder) / "tiff" / "test.tif" + file = Path(folder) / "test.tif" tiffwrite(file, array, "yxczt") with Imread(file, axes="yxczt") as im: yield im