feat: HassLogger
This commit is contained in:
180
src/home_assistant/logger.rs
Normal file
180
src/home_assistant/logger.rs
Normal file
@@ -0,0 +1,180 @@
|
||||
use pyo3::{prelude::*, types::PyTuple};
|
||||
|
||||
use crate::{
|
||||
arbitrary::{arbitrary::Arbitrary, map::Map},
|
||||
python_utils::{detach, validate_type_by_name},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct HassLogger(Py<PyAny>);
|
||||
|
||||
impl<'source> FromPyObject<'source> for HassLogger {
|
||||
fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult<Self> {
|
||||
// region: Validation
|
||||
validate_type_by_name(ob, "HassLogger")?;
|
||||
// endregion: Validation
|
||||
|
||||
Ok(Self(detach(ob)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, IntoPyObject)]
|
||||
pub struct LogData<ExcInfo> {
|
||||
/// If exc_info does not evaluate as false, it causes exception information to be added to the logging message.
|
||||
/// If an exception tuple (in the format returned by sys.exc_info()) or an exception instance is provided, it is used;
|
||||
/// otherwise, sys.exc_info() is called to get the exception information.
|
||||
exc_info: Option<ExcInfo>,
|
||||
|
||||
/// If true, stack information is added to the logging message, including the actual logging call.
|
||||
/// Note that this is not the same stack information as that displayed through specifying exc_info:
|
||||
/// The former is stack frames from the bottom of the stack up to the logging call in the current thread,
|
||||
/// whereas the latter is information about stack frames which have been unwound,
|
||||
/// following an exception, while searching for exception handlers.
|
||||
///
|
||||
/// You can specify stack_info independently of exc_info,
|
||||
/// e.g. to just show how you got to a certain point in your code, even when no exceptions were raised.
|
||||
/// The stack frames are printed following a header line which says:
|
||||
///
|
||||
/// Stack (most recent call last):
|
||||
///
|
||||
/// This mimics the `Traceback (most recent call last):` which is used when displaying exception frames.
|
||||
stack_info: bool,
|
||||
|
||||
/// If greater than 1, the corresponding number of stack frames are skipped
|
||||
/// when computing the line number and function name set in the LogRecord created for the logging event.
|
||||
/// This can be used in logging helpers so that the function name, filename and line number recorded
|
||||
/// are not the information for the helper function/method, but rather its caller.
|
||||
stacklevel: u16,
|
||||
|
||||
/// This can be used to pass a dictionary which is used to populate the __dict__ of the LogRecord
|
||||
/// created for the logging event with user-defined attributes.
|
||||
/// These custom attributes can then be used as you like.
|
||||
/// For example, they could be incorporated into logged messages.
|
||||
extra: Map,
|
||||
}
|
||||
|
||||
impl HassLogger {
|
||||
pub fn new(py: Python<'_>, name: &str) -> PyResult<Self> {
|
||||
let logging = py.import("logging")?;
|
||||
let logger = logging.call_method1("getLogger", (name,))?;
|
||||
|
||||
Ok(logger.extract()?)
|
||||
}
|
||||
|
||||
pub fn debug<'py, ExcInfo: IntoPyObject<'py>>(
|
||||
&self,
|
||||
py: Python<'py>,
|
||||
msg: &str,
|
||||
args: Vec<Arbitrary>,
|
||||
log_data: Option<LogData<ExcInfo>>,
|
||||
) -> PyResult<()> {
|
||||
let mut all_args = vec![msg.into_pyobject(py)?.into_any()];
|
||||
for arg in args {
|
||||
let arg = arg.into_pyobject(py)?;
|
||||
all_args.push(arg);
|
||||
}
|
||||
let all_args = PyTuple::new(py, all_args)?;
|
||||
|
||||
let kwargs = log_data
|
||||
.map(|log_data| log_data.into_pyobject(py))
|
||||
.transpose()?;
|
||||
|
||||
self.0.call_method(py, "debug", all_args, kwargs.as_ref())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn info<'py, ExcInfo: IntoPyObject<'py>>(
|
||||
&self,
|
||||
py: Python<'py>,
|
||||
msg: &str,
|
||||
args: Vec<Arbitrary>,
|
||||
log_data: Option<LogData<ExcInfo>>,
|
||||
) -> PyResult<()> {
|
||||
let mut all_args = vec![msg.into_pyobject(py)?.into_any()];
|
||||
for arg in args {
|
||||
let arg = arg.into_pyobject(py)?;
|
||||
all_args.push(arg);
|
||||
}
|
||||
let all_args = PyTuple::new(py, all_args)?;
|
||||
|
||||
let kwargs = log_data
|
||||
.map(|log_data| log_data.into_pyobject(py))
|
||||
.transpose()?;
|
||||
|
||||
self.0.call_method(py, "info", all_args, kwargs.as_ref())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn warning<'py, ExcInfo: IntoPyObject<'py>>(
|
||||
&self,
|
||||
py: Python<'py>,
|
||||
msg: &str,
|
||||
args: Vec<Arbitrary>,
|
||||
log_data: Option<LogData<ExcInfo>>,
|
||||
) -> PyResult<()> {
|
||||
let mut all_args = vec![msg.into_pyobject(py)?.into_any()];
|
||||
for arg in args {
|
||||
let arg = arg.into_pyobject(py)?;
|
||||
all_args.push(arg);
|
||||
}
|
||||
let all_args = PyTuple::new(py, all_args)?;
|
||||
|
||||
let kwargs = log_data
|
||||
.map(|log_data| log_data.into_pyobject(py))
|
||||
.transpose()?;
|
||||
|
||||
self.0
|
||||
.call_method(py, "warning", all_args, kwargs.as_ref())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn error<'py, ExcInfo: IntoPyObject<'py>>(
|
||||
&self,
|
||||
py: Python<'py>,
|
||||
msg: &str,
|
||||
args: Vec<Arbitrary>,
|
||||
log_data: Option<LogData<ExcInfo>>,
|
||||
) -> PyResult<()> {
|
||||
let mut all_args = vec![msg.into_pyobject(py)?.into_any()];
|
||||
for arg in args {
|
||||
let arg = arg.into_pyobject(py)?;
|
||||
all_args.push(arg);
|
||||
}
|
||||
let all_args = PyTuple::new(py, all_args)?;
|
||||
|
||||
let kwargs = log_data
|
||||
.map(|log_data| log_data.into_pyobject(py))
|
||||
.transpose()?;
|
||||
|
||||
self.0.call_method(py, "error", all_args, kwargs.as_ref())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn critical<'py, ExcInfo: IntoPyObject<'py>>(
|
||||
&self,
|
||||
py: Python<'py>,
|
||||
msg: &str,
|
||||
args: Vec<Arbitrary>,
|
||||
log_data: Option<LogData<ExcInfo>>,
|
||||
) -> PyResult<()> {
|
||||
let mut all_args = vec![msg.into_pyobject(py)?.into_any()];
|
||||
for arg in args {
|
||||
let arg = arg.into_pyobject(py)?;
|
||||
all_args.push(arg);
|
||||
}
|
||||
let all_args = PyTuple::new(py, all_args)?;
|
||||
|
||||
let kwargs = log_data
|
||||
.map(|log_data| log_data.into_pyobject(py))
|
||||
.transpose()?;
|
||||
|
||||
self.0
|
||||
.call_method(py, "critical", all_args, kwargs.as_ref())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@@ -2,6 +2,7 @@ pub mod domain;
|
||||
pub mod entity_id;
|
||||
pub mod event;
|
||||
pub mod home_assistant;
|
||||
pub mod logger;
|
||||
pub mod object_id;
|
||||
pub mod state;
|
||||
pub mod state_machine;
|
||||
|
Reference in New Issue
Block a user