feat: FromPyFromStr and ToStrToPy macros YAY

This commit is contained in:
J / Jacob Babich
2026-07-09 01:35:49 -04:00
parent c637ad2d76
commit 9a9cefee37
25 changed files with 343 additions and 394 deletions

View File

@@ -1,7 +1,6 @@
use std::{convert::Infallible, str::FromStr};
use pyo3::{exceptions::PyException, prelude::*};
use snafu::{ResultExt, Snafu};
use python_utils::{FromPyFromStr, ToStrToPy};
pub mod error_state;
pub mod unexpected_state;
@@ -9,13 +8,30 @@ pub mod unexpected_state;
pub use error_state::ErrorState;
pub use unexpected_state::UnexpectedState;
#[derive(Debug, Clone, derive_more::Display)]
#[derive(Debug, Clone, derive_more::Display, FromPyFromStr, ToStrToPy)]
pub enum HomeAssistantState<State> {
Ok(State),
Err(ErrorState),
UnexpectedErr(UnexpectedState),
}
impl<State> From<String> for HomeAssistantState<State>
where
State: FromStr,
{
fn from(s: String) -> Self {
if let Ok(ok) = State::from_str(&s) {
return HomeAssistantState::Ok(ok);
}
if let Ok(error) = ErrorState::from_str(&s) {
return HomeAssistantState::Err(error);
}
HomeAssistantState::UnexpectedErr(UnexpectedState(s.into()))
}
}
impl<State: FromStr> FromStr for HomeAssistantState<State> {
type Err = Infallible;
@@ -31,34 +47,3 @@ impl<State: FromStr> FromStr for HomeAssistantState<State> {
Ok(HomeAssistantState::UnexpectedErr(UnexpectedState(s.into())))
}
}
#[derive(Debug, Snafu)]
pub enum ExtractHomeAssistantStateError {
/// couldn't extract the object as a string
ExtractStringError { source: PyErr },
}
impl From<ExtractHomeAssistantStateError> for PyErr {
fn from(error: ExtractHomeAssistantStateError) -> Self {
match &error {
ExtractHomeAssistantStateError::ExtractStringError { .. } => {
PyException::new_err(error.to_string())
}
}
}
}
// TODO: replace with a derive(PyFromStr) (analogous to serde_with::DeserializeFromStr) once I make one
impl<'a, 'py, State: FromStr + FromPyObject<'a, 'py>> FromPyObject<'a, 'py>
for HomeAssistantState<State>
{
type Error = ExtractHomeAssistantStateError;
fn extract(ob: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {
let s = ob.extract::<&str>().context(ExtractStringSnafu)?;
let Ok(state) = s.parse();
Ok(state)
}
}