- better python errors
This commit is contained in:
+1
-2
@@ -27,7 +27,7 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
test = ["pytest"]
|
test = ["pytest", "tiffwrite"]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
ndbioimage = "ndbioimage:ndbioimage_rs.main"
|
ndbioimage = "ndbioimage:ndbioimage_rs.main"
|
||||||
@@ -38,7 +38,6 @@ python-source = "py"
|
|||||||
features = ["python", "bioformats_java", "tiffwrite"]
|
features = ["python", "bioformats_java", "tiffwrite"]
|
||||||
module-name = "ndbioimage.ndbioimage_rs"
|
module-name = "ndbioimage.ndbioimage_rs"
|
||||||
include = ["py/ndbioimage/jassets/j4rs*", "py/ndbioimage/deps/libj4rs*"]
|
include = ["py/ndbioimage/jassets/j4rs*", "py/ndbioimage/deps/libj4rs*"]
|
||||||
strip = true
|
|
||||||
|
|
||||||
[tool.isort]
|
[tool.isort]
|
||||||
line_length = 119
|
line_length = 119
|
||||||
|
|||||||
+8
-1
@@ -1,6 +1,7 @@
|
|||||||
|
use strum::IntoStaticStr;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error, IntoStaticStr)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
IO(#[from] std::io::Error),
|
IO(#[from] std::io::Error),
|
||||||
@@ -113,3 +114,9 @@ pub enum Error {
|
|||||||
#[error("cannot remove axes {0}, size {1} != 1")]
|
#[error("cannot remove axes {0}, size {1} != 1")]
|
||||||
SizeMismatch(String, usize),
|
SizeMismatch(String, usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Error {
|
||||||
|
pub fn variant_name(&self) -> &'static str {
|
||||||
|
self.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ use numpy::{
|
|||||||
use ome_metadata::Ome;
|
use ome_metadata::Ome;
|
||||||
use postcard::{from_bytes, to_stdvec};
|
use postcard::{from_bytes, to_stdvec};
|
||||||
use pyo3::IntoPyObjectExt;
|
use pyo3::IntoPyObjectExt;
|
||||||
use pyo3::exceptions::{PyIndexError, PyNotImplementedError, PyTypeError, PyValueError};
|
use pyo3::exceptions::{
|
||||||
|
PyIndexError, PyNotImplementedError, PyRuntimeError, PyTypeError, PyValueError,
|
||||||
|
};
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::types::{
|
use pyo3::types::{
|
||||||
PyBytes, PyEllipsis, PyInt, PyList, PyNone, PySlice, PySliceMethods, PyString, PyTuple,
|
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 pyo3_stub_gen::{StubGenConfig, StubInfo};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use std::error::Error as StdError;
|
||||||
use std::path::PathBuf;
|
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<crate::error::Error> for PyErr {
|
impl From<crate::error::Error> for PyErr {
|
||||||
|
#[track_caller]
|
||||||
fn from(err: crate::error::Error) -> PyErr {
|
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::<String>()?;
|
let dtype_str = name.extract::<String>()?;
|
||||||
dtype_str.parse()?
|
dtype_str.parse()?
|
||||||
} else {
|
} else {
|
||||||
PixelType::U16
|
*view.pixel_type()
|
||||||
};
|
};
|
||||||
let ome = view.metadata()?;
|
let ome = view.metadata()?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ from ndbioimage import Imread
|
|||||||
for path in (Path(__file__).parent / "files").iterdir()
|
for path in (Path(__file__).parent / "files").iterdir()
|
||||||
if path.is_dir() and path.name != "czi_xml"
|
if path.is_dir() and path.name != "czi_xml"
|
||||||
for file in path.iterdir()
|
for file in path.iterdir()
|
||||||
if not file.suffix == ".pzl"
|
if file.suffix.lower() not in [".pzl", ".xml", "", ".txt"]
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_open(file):
|
def test_open(file):
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ def array():
|
|||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def image(array):
|
def image(array):
|
||||||
with tempfile.TemporaryDirectory() as folder:
|
with tempfile.TemporaryDirectory() as folder:
|
||||||
file = Path(folder) / "tiff" / "test.tif"
|
file = Path(folder) / "test.tif"
|
||||||
tiffwrite(file, array, "yxczt")
|
tiffwrite(file, array, "yxczt")
|
||||||
with Imread(file, axes="yxczt") as im:
|
with Imread(file, axes="yxczt") as im:
|
||||||
yield im
|
yield im
|
||||||
|
|||||||
Reference in New Issue
Block a user