Compare commits
3 Commits
338a8c571c
...
17fabbf178
| Author | SHA1 | Date | |
|---|---|---|---|
| 17fabbf178 | |||
| 6abe278aa3 | |||
| 120ad97c53 |
@@ -4,8 +4,8 @@ use ijson::{IArray, INumber, IObject, IString, IValue};
|
|||||||
#[cfg(feature = "pyo3")]
|
#[cfg(feature = "pyo3")]
|
||||||
use pyo3::{
|
use pyo3::{
|
||||||
exceptions::{PyException, PyTypeError, PyValueError},
|
exceptions::{PyException, PyTypeError, PyValueError},
|
||||||
prelude::*,
|
types::{PyAnyMethods as _, PyList, PyNone, PyTypeMethods as _},
|
||||||
types::{PyList, PyNone},
|
Borrowed, Bound, FromPyObject, IntoPyObject, PyAny, PyErr, Python,
|
||||||
};
|
};
|
||||||
use snafu::{ResultExt, Snafu};
|
use snafu::{ResultExt, Snafu};
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ use itertools::Itertools;
|
|||||||
#[cfg(feature = "pyo3")]
|
#[cfg(feature = "pyo3")]
|
||||||
use pyo3::{
|
use pyo3::{
|
||||||
exceptions::PyTypeError,
|
exceptions::PyTypeError,
|
||||||
prelude::*,
|
types::{PyAnyMethods as _, PyNone, PyTuple, PyTypeMethods as _},
|
||||||
types::{PyNone, PyTuple},
|
Borrowed, Bound, FromPyObject, IntoPyObject, PyAny, PyErr, Python,
|
||||||
};
|
};
|
||||||
use snafu::{ResultExt, Snafu};
|
use snafu::{ResultExt, Snafu};
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,11 @@ use driver_kasa::connection::LB130USHandle;
|
|||||||
use futures::stream::{FuturesUnordered, StreamExt};
|
use futures::stream::{FuturesUnordered, StreamExt};
|
||||||
use home_assistant::{home_assistant::HomeAssistant, object_id::ObjectId};
|
use home_assistant::{home_assistant::HomeAssistant, object_id::ObjectId};
|
||||||
use protocol::light::{Kelvin, TurnToTemperature};
|
use protocol::light::{Kelvin, TurnToTemperature};
|
||||||
use pyo3::prelude::*;
|
use pyo3::{
|
||||||
|
pyfunction, pymodule,
|
||||||
|
types::{PyModule, PyModuleMethods as _},
|
||||||
|
wrap_pyfunction, Bound, PyAny, PyResult, Python,
|
||||||
|
};
|
||||||
use shadow_rs::shadow;
|
use shadow_rs::shadow;
|
||||||
use tokio::time::{interval, MissedTickBehavior};
|
use tokio::time::{interval, MissedTickBehavior};
|
||||||
use tracing::{level_filters::LevelFilter, Level};
|
use tracing::{level_filters::LevelFilter, Level};
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
use super::id::Id;
|
use super::id::Id;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use pyo3::{prelude::*, types::PyType};
|
use pyo3::{
|
||||||
|
types::{PyAnyMethods, PyModule, PyType},
|
||||||
|
Bound, FromPyObject, IntoPyObject, Py, PyAny, PyErr, Python,
|
||||||
|
};
|
||||||
|
|
||||||
/// The context that triggered something.
|
/// The context that triggered something.
|
||||||
#[derive(Debug, FromPyObject)]
|
#[derive(Debug, FromPyObject)]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use pyo3::prelude::*;
|
use pyo3::FromPyObject;
|
||||||
|
|
||||||
use super::event_origin::EventOrigin;
|
use super::event_origin::EventOrigin;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ use std::str::FromStr;
|
|||||||
|
|
||||||
use pyo3::{
|
use pyo3::{
|
||||||
exceptions::{PyException, PyTypeError, PyValueError},
|
exceptions::{PyException, PyTypeError, PyValueError},
|
||||||
prelude::*,
|
types::PyAnyMethods,
|
||||||
|
Borrowed, FromPyObject, PyAny, PyErr,
|
||||||
};
|
};
|
||||||
use snafu::{ResultExt, Snafu};
|
use snafu::{ResultExt, Snafu};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::{
|
||||||
|
types::PyAnyMethods as _, Borrowed, Bound, FromPyObject, IntoPyObject, Py, PyAny, PyErr, Python,
|
||||||
|
};
|
||||||
use python_utils::{detach, validate_type_by_name, TypeByNameValidationError};
|
use python_utils::{detach, validate_type_by_name, TypeByNameValidationError};
|
||||||
use snafu::{ResultExt, Snafu};
|
use snafu::{ResultExt, Snafu};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use pyo3::prelude::*;
|
use pyo3::FromPyObject;
|
||||||
|
|
||||||
#[derive(Debug, FromPyObject)]
|
#[derive(Debug, FromPyObject)]
|
||||||
#[pyo3(from_item_all)]
|
#[pyo3(from_item_all)]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use attributes::LightAttributes;
|
use attributes::LightAttributes;
|
||||||
use pyo3::prelude::*;
|
use pyo3::{FromPyObject, Py, PyAny, Python};
|
||||||
use snafu::{ResultExt, Snafu};
|
use snafu::{ResultExt, Snafu};
|
||||||
use state::LightState;
|
use state::LightState;
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crate::{
|
|||||||
state::{ErrorState, HomeAssistantState, UnexpectedState},
|
state::{ErrorState, HomeAssistantState, UnexpectedState},
|
||||||
};
|
};
|
||||||
use protocol::light::{GetState, SetState};
|
use protocol::light::{GetState, SetState};
|
||||||
use pyo3::prelude::*;
|
use pyo3::Python;
|
||||||
use python_utils::IsNone;
|
use python_utils::IsNone;
|
||||||
use snafu::{ResultExt, Snafu};
|
use snafu::{ResultExt, Snafu};
|
||||||
|
|
||||||
|
|||||||
@@ -1,54 +1,13 @@
|
|||||||
use std::str::FromStr;
|
use python_utils::{FromPyFromStr, ToStrToPy};
|
||||||
|
|
||||||
use pyo3::{
|
|
||||||
exceptions::{PyException, PyValueError},
|
|
||||||
prelude::*,
|
|
||||||
};
|
|
||||||
use snafu::{ResultExt, Snafu};
|
|
||||||
use strum::EnumString;
|
use strum::EnumString;
|
||||||
|
|
||||||
#[derive(Debug, Clone, EnumString, strum::Display)]
|
#[derive(Debug, Clone, EnumString, strum::Display, FromPyFromStr, ToStrToPy)]
|
||||||
#[strum(serialize_all = "snake_case")]
|
#[strum(serialize_all = "snake_case")]
|
||||||
pub enum LightState {
|
pub enum LightState {
|
||||||
On,
|
On,
|
||||||
Off,
|
Off,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
|
||||||
pub enum ExtractLightStateError {
|
|
||||||
/// couldn't extract the object as a string
|
|
||||||
ExtractStringError { source: PyErr },
|
|
||||||
|
|
||||||
/// couldn't parse the string as a [`LightState`]
|
|
||||||
ParseError {
|
|
||||||
source: <LightState as FromStr>::Err,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ExtractLightStateError> for PyErr {
|
|
||||||
fn from(error: ExtractLightStateError) -> Self {
|
|
||||||
match &error {
|
|
||||||
ExtractLightStateError::ExtractStringError { .. } => {
|
|
||||||
PyException::new_err(error.to_string())
|
|
||||||
}
|
|
||||||
ExtractLightStateError::ParseError { .. } => PyValueError::new_err(error.to_string()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: replace with a derive(PyFromStr) (analogous to serde_with::DeserializeFromStr) once I make one
|
|
||||||
impl<'a, 'py> FromPyObject<'a, 'py> for LightState {
|
|
||||||
type Error = ExtractLightStateError;
|
|
||||||
|
|
||||||
fn extract(ob: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {
|
|
||||||
let s = ob.extract::<&str>().context(ExtractStringSnafu)?;
|
|
||||||
|
|
||||||
let state = LightState::from_str(&s).context(ParseSnafu)?;
|
|
||||||
|
|
||||||
Ok(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<LightState> for protocol::light::State {
|
impl From<LightState> for protocol::light::State {
|
||||||
fn from(light_state: LightState) -> Self {
|
fn from(light_state: LightState) -> Self {
|
||||||
match light_state {
|
match light_state {
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
use arbitrary_value::{arbitrary::Arbitrary, map::Map};
|
use arbitrary_value::{arbitrary::Arbitrary, map::Map};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use pyo3::{prelude::*, types::PyTuple};
|
use pyo3::{
|
||||||
|
types::{PyAnyMethods as _, PyModule, PyTuple},
|
||||||
|
Borrowed, FromPyObject, IntoPyObject, Py, PyAny, PyErr, Python,
|
||||||
|
};
|
||||||
use python_utils::{detach, validate_type_by_name, TypeByNameValidationError};
|
use python_utils::{detach, validate_type_by_name, TypeByNameValidationError};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -54,7 +57,7 @@ pub struct LogData<ExcInfo> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl HassLogger {
|
impl HassLogger {
|
||||||
pub fn new(py: Python<'_>, name: &str) -> PyResult<Self> {
|
pub fn new(py: Python<'_>, name: &str) -> Result<Self, PyErr> {
|
||||||
static LOGGING_MODULE: OnceCell<Py<PyModule>> = OnceCell::new();
|
static LOGGING_MODULE: OnceCell<Py<PyModule>> = OnceCell::new();
|
||||||
|
|
||||||
let logging_module = LOGGING_MODULE
|
let logging_module = LOGGING_MODULE
|
||||||
@@ -71,7 +74,7 @@ impl HassLogger {
|
|||||||
msg: &str,
|
msg: &str,
|
||||||
args: Vec<Arbitrary>,
|
args: Vec<Arbitrary>,
|
||||||
log_data: Option<LogData<ExcInfo>>,
|
log_data: Option<LogData<ExcInfo>>,
|
||||||
) -> PyResult<()> {
|
) -> Result<(), PyErr> {
|
||||||
let mut all_args = vec![msg.into_pyobject(py)?.into_any()];
|
let mut all_args = vec![msg.into_pyobject(py)?.into_any()];
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let arg = arg.into_pyobject(py)?;
|
let arg = arg.into_pyobject(py)?;
|
||||||
@@ -94,7 +97,7 @@ impl HassLogger {
|
|||||||
msg: &str,
|
msg: &str,
|
||||||
args: Vec<Arbitrary>,
|
args: Vec<Arbitrary>,
|
||||||
log_data: Option<LogData<ExcInfo>>,
|
log_data: Option<LogData<ExcInfo>>,
|
||||||
) -> PyResult<()> {
|
) -> Result<(), PyErr> {
|
||||||
let mut all_args = vec![msg.into_pyobject(py)?.into_any()];
|
let mut all_args = vec![msg.into_pyobject(py)?.into_any()];
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let arg = arg.into_pyobject(py)?;
|
let arg = arg.into_pyobject(py)?;
|
||||||
@@ -117,7 +120,7 @@ impl HassLogger {
|
|||||||
msg: &str,
|
msg: &str,
|
||||||
args: Vec<Arbitrary>,
|
args: Vec<Arbitrary>,
|
||||||
log_data: Option<LogData<ExcInfo>>,
|
log_data: Option<LogData<ExcInfo>>,
|
||||||
) -> PyResult<()> {
|
) -> Result<(), PyErr> {
|
||||||
let mut all_args = vec![msg.into_pyobject(py)?.into_any()];
|
let mut all_args = vec![msg.into_pyobject(py)?.into_any()];
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let arg = arg.into_pyobject(py)?;
|
let arg = arg.into_pyobject(py)?;
|
||||||
@@ -141,7 +144,7 @@ impl HassLogger {
|
|||||||
msg: &str,
|
msg: &str,
|
||||||
args: Vec<Arbitrary>,
|
args: Vec<Arbitrary>,
|
||||||
log_data: Option<LogData<ExcInfo>>,
|
log_data: Option<LogData<ExcInfo>>,
|
||||||
) -> PyResult<()> {
|
) -> Result<(), PyErr> {
|
||||||
let mut all_args = vec![msg.into_pyobject(py)?.into_any()];
|
let mut all_args = vec![msg.into_pyobject(py)?.into_any()];
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let arg = arg.into_pyobject(py)?;
|
let arg = arg.into_pyobject(py)?;
|
||||||
@@ -164,7 +167,7 @@ impl HassLogger {
|
|||||||
msg: &str,
|
msg: &str,
|
||||||
args: Vec<Arbitrary>,
|
args: Vec<Arbitrary>,
|
||||||
log_data: Option<LogData<ExcInfo>>,
|
log_data: Option<LogData<ExcInfo>>,
|
||||||
) -> PyResult<()> {
|
) -> Result<(), PyErr> {
|
||||||
let mut all_args = vec![msg.into_pyobject(py)?.into_any()];
|
let mut all_args = vec![msg.into_pyobject(py)?.into_any()];
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let arg = arg.into_pyobject(py)?;
|
let arg = arg.into_pyobject(py)?;
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
use super::{event::context::context::Context, service::IntoServiceCall};
|
use super::{event::context::context::Context, service::IntoServiceCall};
|
||||||
use pyo3::{
|
use pyo3::{
|
||||||
|
conversion::FromPyObjectOwned,
|
||||||
exceptions::{PyException, PyTypeError},
|
exceptions::{PyException, PyTypeError},
|
||||||
prelude::*,
|
types::PyAnyMethods as _,
|
||||||
|
Borrowed, FromPyObject, IntoPyObject, Py, PyAny, PyErr, Python,
|
||||||
};
|
};
|
||||||
use python_utils::{detach, validate_type_by_name, TypeByNameValidationError};
|
use python_utils::{detach, validate_type_by_name, TypeByNameValidationError};
|
||||||
use snafu::{ResultExt, Snafu};
|
use snafu::{ResultExt, Snafu};
|
||||||
@@ -73,7 +75,7 @@ impl ServiceRegistry {
|
|||||||
return_response,
|
return_response,
|
||||||
);
|
);
|
||||||
|
|
||||||
let future = Python::attach::<_, PyResult<_>>(|py| {
|
let future = Python::attach::<_, Result<_, PyErr>>(|py| {
|
||||||
let service_registry = self.0.bind(py);
|
let service_registry = self.0.bind(py);
|
||||||
let awaitable = service_registry.call_method("async_call", args, None)?;
|
let awaitable = service_registry.call_method("async_call", args, None)?;
|
||||||
pyo3_async_runtimes::tokio::into_future(awaitable)
|
pyo3_async_runtimes::tokio::into_future(awaitable)
|
||||||
|
|||||||
@@ -1,35 +1,14 @@
|
|||||||
use std::sync::Arc;
|
use std::{convert::Infallible, str::FromStr, sync::Arc};
|
||||||
|
|
||||||
use pyo3::{exceptions::PyException, prelude::*};
|
use python_utils::{FromPyFromStr, ToStrToPy};
|
||||||
use snafu::{ResultExt, Snafu};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, derive_more::Display)]
|
#[derive(Debug, Clone, derive_more::Display, FromPyFromStr, ToStrToPy)]
|
||||||
pub struct UnexpectedState(pub Arc<str>);
|
pub struct UnexpectedState(pub Arc<str>);
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
impl FromStr for UnexpectedState {
|
||||||
pub enum ExtractUnexpectedStateError {
|
type Err = Infallible;
|
||||||
/// couldn't extract the object as a string
|
|
||||||
ExtractStringError { source: PyErr },
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ExtractUnexpectedStateError> for PyErr {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
fn from(error: ExtractUnexpectedStateError) -> Self {
|
Ok(Self(s.into()))
|
||||||
match &error {
|
|
||||||
ExtractUnexpectedStateError::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> FromPyObject<'a, 'py> for UnexpectedState {
|
|
||||||
type Error = ExtractUnexpectedStateError;
|
|
||||||
|
|
||||||
fn extract(ob: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {
|
|
||||||
let s = ob.extract::<String>().context(ExtractStringSnafu)?;
|
|
||||||
let s = s.into();
|
|
||||||
|
|
||||||
Ok(UnexpectedState(s))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use super::entity_id::EntityId;
|
use super::entity_id::EntityId;
|
||||||
use super::state_object::StateObject;
|
use super::state_object::StateObject;
|
||||||
use pyo3::prelude::*;
|
use pyo3::{conversion::FromPyObjectOwned, Borrowed, FromPyObject, Py, PyAny, PyErr, Python};
|
||||||
use python_utils::{detach, validate_type_by_name, TypeByNameValidationError};
|
use python_utils::{detach, validate_type_by_name, TypeByNameValidationError};
|
||||||
use snafu::{ResultExt, Snafu};
|
use snafu::{ResultExt, Snafu};
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ use chrono::{DateTime, Utc};
|
|||||||
use emitter_and_signal::signal::Signal;
|
use emitter_and_signal::signal::Signal;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use pyo3::{
|
use pyo3::{
|
||||||
prelude::*,
|
types::{PyAnyMethods as _, PyCFunction, PyDict, PyModule, PyTuple},
|
||||||
types::{PyCFunction, PyDict, PyTuple},
|
Bound, FromPyObject, IntoPyObject as _, Py, PyAny, PyErr, Python,
|
||||||
};
|
};
|
||||||
use snafu::{ResultExt, Snafu};
|
use snafu::{ResultExt, Snafu};
|
||||||
use std::{future::Future, sync::Arc};
|
use std::{future::Future, sync::Arc};
|
||||||
@@ -86,7 +86,7 @@ impl<
|
|||||||
while let Some(publisher) = publisher_stream.wait().await {
|
while let Some(publisher) = publisher_stream.wait().await {
|
||||||
let (new_state_sender, mut new_state_receiver) = mpsc::channel(8);
|
let (new_state_sender, mut new_state_receiver) = mpsc::channel(8);
|
||||||
|
|
||||||
let untrack = Python::attach::<_, PyResult<_>>(|py| {
|
let untrack = Python::attach::<_, Result<_, PyErr>>(|py| {
|
||||||
static EVENT_MODULE: OnceCell<Py<PyModule>> = OnceCell::new();
|
static EVENT_MODULE: OnceCell<Py<PyModule>> = OnceCell::new();
|
||||||
|
|
||||||
let event_module = EVENT_MODULE
|
let event_module = EVENT_MODULE
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use pyo3::{
|
use pyo3::{
|
||||||
exceptions::{PyException, PyTypeError},
|
exceptions::{PyException, PyTypeError},
|
||||||
prelude::*,
|
types::{PyAnyMethods as _, PyStringMethods, PyTypeMethods as _},
|
||||||
|
Borrowed, Bound, Py, PyAny, PyErr,
|
||||||
};
|
};
|
||||||
use snafu::{ResultExt, Snafu};
|
use snafu::{ResultExt, Snafu};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user