use std::{convert::Infallible, sync::Arc}; use pyo3::{ types::PyAnyMethods as _, Borrowed, Bound, FromPyObject, IntoPyObject, Py, PyAny, PyErr, Python, }; use python_utils::{detach, validate_type_by_name, TypeByNameValidationError}; use snafu::{ResultExt, Snafu}; use super::{service_registry::ServiceRegistry, state_machine::StateMachine}; #[derive(Debug)] pub struct HomeAssistant(Py); impl<'a, 'py> FromPyObject<'a, 'py> for HomeAssistant { type Error = TypeByNameValidationError; fn extract(ob: Borrowed<'a, 'py, PyAny>) -> Result { // region: Validation validate_type_by_name(&ob, "HomeAssistant")?; // endregion: Validation Ok(Self(detach(ob))) } } impl<'py> IntoPyObject<'py> for &HomeAssistant { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(self.0.bind(py).to_owned()) } } #[derive(Debug, Clone, Snafu)] pub enum GetStatesError { /// couldn't get the `states` attribute on the Home Assistant object GetStatesAttributeError { source: Arc }, /// couldn't extract the `states` as a [`StateMachine`] ExtractStateMachineError { source: Arc, }, } #[derive(Debug, Clone, Snafu)] pub enum GetServicesError { /// couldn't get the `services` attribute on the Home Assistant object GetServicesAttributeError { source: Arc }, /// couldn't extract the `states` as a [`ServiceRegistry`] ExtractServiceRegistryError { source: Arc, }, } impl HomeAssistant { /// Return the representation pub fn repr(&self, py: Python<'_>) -> Result { let bound = self.0.bind(py); let repr = bound.repr()?; repr.extract() } /// Return if Home Assistant is running. pub fn is_running(&self, py: Python<'_>) -> Result { let is_running = self.0.getattr(py, "is_running")?; is_running.extract(py) } /// Return if Home Assistant is stopping. pub fn is_stopping(&self, py: Python<'_>) -> Result { let is_stopping = self.0.getattr(py, "is_stopping")?; is_stopping.extract(py) } pub fn states(&self, py: Python<'_>) -> Result { let states = self .0 .getattr(py, "states") .map_err(Arc::new) .context(GetStatesAttributeSnafu)?; states .extract(py) .map_err(Arc::new) .context(ExtractStateMachineSnafu) } pub fn services(&self, py: Python<'_>) -> Result { let services = self .0 .getattr(py, "services") .map_err(Arc::new) .context(GetServicesAttributeSnafu)?; services .extract(py) .map_err(Arc::new) .context(ExtractServiceRegistrySnafu) } }