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,42 +1,39 @@
use pyo3::exceptions::{PyTypeError, PyValueError};
use pyo3::prelude::*;
use snafu::{ResultExt, Snafu};
use std::fmt::Display;
use std::str::FromStr;
use pyo3::FromPyObject;
use python_utils::{FromPyFromStr, ToStrToPy};
use snafu::Snafu;
use crate::{entity_id::EntityId, state_object::StateObject};
#[derive(Debug, Clone)]
// TODO: replace with a derive(PyFromStrLiteral) / #[literal = "state_changed"] once I learn how to make something like that and see about serde or strum integration or inspiration
#[derive(Debug, Clone, FromPyFromStr, ToStrToPy)]
pub struct Type;
/// expected a string of value "state_changed", but got {actual}
#[derive(Debug, Snafu)]
pub enum ExtractTypeError {
/// couldn't extract this object as a string
ExtractStringError { source: PyErr },
/// expected a string of value "state_changed", but got {actual}
UnexpectedValue { actual: String },
pub struct ParseTypeError {
actual: String,
}
impl From<ExtractTypeError> for PyErr {
fn from(error: ExtractTypeError) -> Self {
match &error {
ExtractTypeError::ExtractStringError { .. } => PyTypeError::new_err(error.to_string()),
ExtractTypeError::UnexpectedValue { .. } => PyValueError::new_err(error.to_string()),
impl FromStr for Type {
type Err = ParseTypeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s == "state_changed" {
Ok(Self)
} else {
Err(ParseTypeError {
actual: s.to_owned(),
})
}
}
}
// TODO: replace with a derive(PyFromStrLiteral) / #[literal = "state_changed"] once I learn how to make something like that and see about serde or strum integration or inspiration
impl<'a, 'py> FromPyObject<'a, 'py> for Type {
type Error = ExtractTypeError;
fn extract(ob: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {
let s = ob.extract::<&str>().context(ExtractStringSnafu)?;
if s == "state_changed" {
Ok(Type)
} else {
Err(ExtractTypeError::UnexpectedValue { actual: s.into() })
}
impl Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "state_changed")
}
}