feat: implement StringLiteral macro
This commit is contained in:
@@ -26,6 +26,7 @@ pyo3 = { workspace = true }
|
||||
pyo3-async-runtimes = { workspace = true, features = ["tokio-runtime"] }
|
||||
python-utils = { path = "../python-utils", features = ["macros"] }
|
||||
snafu = { workspace = true }
|
||||
string-literal = { path = "../string-literal", features = ["macros"] }
|
||||
strum = { workspace = true, features = ["derive"] }
|
||||
tokio = { workspace = true }
|
||||
tracing = { optional = true, workspace = true }
|
||||
|
||||
@@ -4,39 +4,14 @@ use std::str::FromStr;
|
||||
use pyo3::FromPyObject;
|
||||
use python_utils::{FromPyFromStr, ToStrToPy};
|
||||
use snafu::Snafu;
|
||||
use string_literal::StringLiteral;
|
||||
|
||||
use crate::{entity_id::EntityId, state_object::StateObject};
|
||||
|
||||
// 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)]
|
||||
#[derive(Debug, Clone, StringLiteral, FromPyFromStr, ToStrToPy)]
|
||||
#[string_literal(value = "state_changed")]
|
||||
pub struct Type;
|
||||
|
||||
/// expected a string of value "state_changed", but got {actual}
|
||||
#[derive(Debug, Snafu)]
|
||||
pub struct ParseTypeError {
|
||||
actual: 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(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Type {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "state_changed")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, FromPyObject)]
|
||||
#[pyo3(from_item_all)]
|
||||
pub struct Data<
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
use std::{future::Future, sync::Arc};
|
||||
|
||||
use emitter_and_signal::{Signal, SignalExt};
|
||||
use pyo3::{
|
||||
exceptions::{PyException, PyValueError},
|
||||
prelude::*,
|
||||
};
|
||||
use python_utils::FromPyObjectViaParse;
|
||||
use snafu::{ensure, ResultExt, Snafu};
|
||||
use pyo3::{FromPyObject, Py, PyAny, PyErr, Python};
|
||||
use python_utils::{FromPyFromStr, FromPyObjectViaParse, ToStrToPy};
|
||||
use snafu::{ResultExt, Snafu};
|
||||
use string_literal::StringLiteral;
|
||||
|
||||
use super::super::state_classes::measurement::Measurement;
|
||||
use crate::{
|
||||
@@ -18,45 +16,10 @@ use crate::{
|
||||
unit_of_measurement::power::UnitOfMeasurement,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone, Copy, StringLiteral, FromPyFromStr, ToStrToPy)]
|
||||
#[string_literal(value = "power")]
|
||||
struct Power;
|
||||
|
||||
#[derive(Debug, Snafu)]
|
||||
pub enum ExtractPowerError {
|
||||
/// couldn't extract the object as a string
|
||||
ExtractStringError { source: PyErr },
|
||||
|
||||
/// the string {actual:?} is not "power" like it's supposed to be
|
||||
NotPower { actual: String },
|
||||
}
|
||||
|
||||
impl From<ExtractPowerError> for PyErr {
|
||||
fn from(error: ExtractPowerError) -> Self {
|
||||
match &error {
|
||||
ExtractPowerError::ExtractStringError { .. } => PyException::new_err(error.to_string()),
|
||||
ExtractPowerError::NotPower { .. } => PyValueError::new_err(error.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 Power {
|
||||
type Error = ExtractPowerError;
|
||||
|
||||
fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {
|
||||
let string: &str = obj.extract().context(ExtractStringSnafu)?;
|
||||
|
||||
ensure!(
|
||||
string == "power",
|
||||
NotPowerSnafu {
|
||||
actual: string.to_owned()
|
||||
}
|
||||
);
|
||||
|
||||
Ok(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, FromPyObject)]
|
||||
#[pyo3(from_item_all)]
|
||||
pub struct PowerSensorAttributes {
|
||||
|
||||
@@ -1,48 +1,6 @@
|
||||
use pyo3::{
|
||||
exceptions::{PyException, PyValueError},
|
||||
prelude::*,
|
||||
};
|
||||
use snafu::{ensure, ResultExt, Snafu};
|
||||
use python_utils::{FromPyFromStr, ToStrToPy};
|
||||
use string_literal::StringLiteral;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone, Copy, StringLiteral, FromPyFromStr, ToStrToPy)]
|
||||
#[string_literal(value = "measurement")]
|
||||
pub struct Measurement;
|
||||
|
||||
#[derive(Debug, Snafu)]
|
||||
pub enum ExtractMeasurementError {
|
||||
/// couldn't extract the object as a string
|
||||
ExtractStringError { source: PyErr },
|
||||
|
||||
/// the string {actual:?} is not "measurement" like it's supposed to be
|
||||
NotMeasurement { actual: String },
|
||||
}
|
||||
|
||||
impl From<ExtractMeasurementError> for PyErr {
|
||||
fn from(error: ExtractMeasurementError) -> Self {
|
||||
match &error {
|
||||
ExtractMeasurementError::ExtractStringError { .. } => {
|
||||
PyException::new_err(error.to_string())
|
||||
}
|
||||
ExtractMeasurementError::NotMeasurement { .. } => {
|
||||
PyValueError::new_err(error.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 Measurement {
|
||||
type Error = ExtractMeasurementError;
|
||||
|
||||
fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {
|
||||
let string: &str = obj.extract().context(ExtractStringSnafu)?;
|
||||
|
||||
ensure!(
|
||||
string == "measurement",
|
||||
NotMeasurementSnafu {
|
||||
actual: string.to_owned()
|
||||
}
|
||||
);
|
||||
|
||||
Ok(Self)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user