feat: FromPyFromStr and ToStrToPy macros YAY
This commit is contained in:
@@ -1,15 +1,18 @@
|
||||
use std::{convert::Infallible, fmt::Display, str::FromStr, sync::Arc};
|
||||
|
||||
use pyo3::{
|
||||
exceptions::{PyException, PyTypeError, PyValueError},
|
||||
exceptions::{PyException, PyTypeError},
|
||||
prelude::*,
|
||||
types::PyString,
|
||||
};
|
||||
use snafu::{ResultExt, Snafu};
|
||||
|
||||
pub use python_utils_macros::PyFromStr;
|
||||
#[cfg(feature = "macros")]
|
||||
pub use python_utils_macros::{FromPyFromStr, ToStrToPy};
|
||||
|
||||
pub mod from_pyobject_via_parse;
|
||||
pub mod into_pyobject_via_display;
|
||||
pub mod none;
|
||||
|
||||
pub use from_pyobject_via_parse::{ExtractPyObjectViaParseError, FromPyObjectViaParse};
|
||||
pub use into_pyobject_via_display::IntoPyObjectViaDisplay;
|
||||
pub use none::IsNone;
|
||||
|
||||
/// Create a GIL-independent reference
|
||||
@@ -83,70 +86,3 @@ pub fn validate_type_by_name(
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, derive_more::Display)]
|
||||
pub struct IntoPyObjectViaDisplay<T>(pub T);
|
||||
|
||||
impl<'py, T> IntoPyObject<'py> for IntoPyObjectViaDisplay<T>
|
||||
where
|
||||
T: Display,
|
||||
{
|
||||
type Target = PyString;
|
||||
type Output = Bound<'py, Self::Target>;
|
||||
type Error = Infallible;
|
||||
|
||||
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
|
||||
let s = self.to_string();
|
||||
s.into_pyobject(py)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, derive_more::FromStr)]
|
||||
pub struct FromPyObjectViaParse<T>(pub T);
|
||||
|
||||
#[derive(Debug, Clone, Snafu)]
|
||||
pub enum ExtractPyObjectViaParseError<ParseError>
|
||||
where
|
||||
ParseError: 'static + snafu::Error,
|
||||
{
|
||||
/// couldn't extract the object as a string
|
||||
ExtractStringError { source: Arc<PyErr> },
|
||||
|
||||
/// couldn't parse the string as an instance of this Rust type
|
||||
ParseError { source: ParseError },
|
||||
}
|
||||
|
||||
impl<E> From<ExtractPyObjectViaParseError<E>> for PyErr
|
||||
where
|
||||
E: 'static + snafu::Error,
|
||||
{
|
||||
fn from(error: ExtractPyObjectViaParseError<E>) -> Self {
|
||||
match &error {
|
||||
ExtractPyObjectViaParseError::ExtractStringError { .. } => {
|
||||
PyException::new_err(error.to_string())
|
||||
}
|
||||
ExtractPyObjectViaParseError::ParseError { .. } => {
|
||||
PyValueError::new_err(error.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'py, T> FromPyObject<'a, 'py> for FromPyObjectViaParse<T>
|
||||
where
|
||||
T: FromStr,
|
||||
<T as FromStr>::Err: 'static + snafu::Error,
|
||||
PyErr: From<ExtractPyObjectViaParseError<<T as FromStr>::Err>>,
|
||||
{
|
||||
type Error = ExtractPyObjectViaParseError<<T as FromStr>::Err>;
|
||||
|
||||
fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {
|
||||
let s = obj
|
||||
.extract::<&str>()
|
||||
.map_err(Arc::new)
|
||||
.context(ExtractStringSnafu)?;
|
||||
let t = T::from_str(s).context(ParseSnafu)?;
|
||||
|
||||
Ok(FromPyObjectViaParse(t))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user