From 01d4ad3c0160b97be1786ad2dbaa9ee8945e7f8f Mon Sep 17 00:00:00 2001 From: Mike Schmidt Date: Tue, 6 Feb 2024 09:02:18 -0700 Subject: [PATCH] feat(python): Improved errors from type conversions. --- CHANGELOG.md | 1 + pylace/src/utils.rs | 17 ++++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3cdca13..665e2885 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Added parallelism to `Slice` row reassignment kernel. Run time is ~6x faster. +- (Python) Improved errors in type conversions. ### Fixed - Initializing an engine with a codebook that has a different number of rows than the data will result in an error instead of printing a bunch on nonsense. diff --git a/pylace/src/utils.rs b/pylace/src/utils.rs index 32fd63d3..0e45a1f0 100644 --- a/pylace/src/utils.rs +++ b/pylace/src/utils.rs @@ -532,7 +532,11 @@ pub(crate) fn value_to_datum(val: &PyAny, ftype: FType) -> PyResult { match ftype { FType::Continuous => { - let x: f64 = val.extract().unwrap(); + let x: f64 = val.extract().map_err(|err| { + PyTypeError::new_err(format!( + "Expected real number, got `{val}` ({err})" + )) + })?; if x.is_nan() { Ok(Datum::Missing) } else { @@ -543,10 +547,9 @@ pub(crate) fn value_to_datum(val: &PyAny, ftype: FType) -> PyResult { let x = pyany_to_category(val)?; Ok(Datum::Categorical(x)) } - FType::Count => Ok(Datum::Count(val.extract().unwrap())), - ftype => Err(PyErr::new::(format!( - "Unsupported ftype: {:?}", - ftype + FType::Count => Ok(Datum::Count(val.extract()?)), + ftype => Err(PyTypeError::new_err(format!( + "Unsupported ftype: `{ftype:?}`" ))), } } @@ -556,7 +559,7 @@ pub(crate) fn value_to_name( indexer: &Indexer, ) -> PyResult { val.extract::().or_else(|_| { - let ix: usize = val.extract().unwrap(); + let ix: usize = val.extract()?; if let Some(name) = indexer.to_name.get(&ix) { Ok(name.to_owned()) } else { @@ -570,7 +573,7 @@ pub(crate) fn value_to_index( indexer: &Indexer, ) -> PyResult { val.extract::().or_else(|_| { - let s: &str = val.extract().unwrap(); + let s: &str = val.extract()?; if let Some(ix) = indexer.to_ix.get(s) { Ok(*ix) } else {