use crate::diag::Verbosity as RustVerbosity;
use pyo3::Borrowed;
use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;
use pyo3::types::PyAnyMethods;
pub(super) fn register(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<PyVerbosity>()?;
Ok(())
}
#[pyclass(
name = "Verbosity",
module = "copp_py._native",
eq,
eq_int,
rename_all = "SCREAMING_SNAKE_CASE",
from_py_object
)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum PyVerbosity {
Silent,
Summary,
Debug,
Trace,
}
impl PyVerbosity {
pub(super) fn to_rust(self) -> RustVerbosity {
match self {
Self::Silent => RustVerbosity::Silent,
Self::Summary => RustVerbosity::Summary,
Self::Debug => RustVerbosity::Debug,
Self::Trace => RustVerbosity::Trace,
}
}
pub(super) fn from_rust(value: RustVerbosity) -> Self {
match value {
RustVerbosity::Silent => Self::Silent,
RustVerbosity::Summary => Self::Summary,
RustVerbosity::Debug => Self::Debug,
RustVerbosity::Trace => Self::Trace,
}
}
}
#[derive(Clone, Copy)]
pub(super) struct VerbosityArg(
pub(super) PyVerbosity,
);
impl FromPyObject<'_, '_> for VerbosityArg {
type Error = PyErr;
fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {
if obj.is_none() {
return Ok(Self(PyVerbosity::from_rust(RustVerbosity::default())));
}
if let Ok(verbosity) = obj.extract::<PyVerbosity>() {
return Ok(Self(verbosity));
}
if let Ok(text) = obj.extract::<&str>() {
return match normalize_token(text).as_str() {
"silent" => Ok(Self(PyVerbosity::Silent)),
"summary" => Ok(Self(PyVerbosity::Summary)),
"debug" => Ok(Self(PyVerbosity::Debug)),
"trace" => Ok(Self(PyVerbosity::Trace)),
_ => Err(PyValueError::new_err(
"`verbosity` must be Verbosity.SILENT, Verbosity.SUMMARY, Verbosity.DEBUG, Verbosity.TRACE, or one of \"silent\", \"summary\", \"debug\", \"trace\"",
)),
};
}
Err(PyValueError::new_err(
"`verbosity` must be a Verbosity value or a string",
))
}
}
pub(super) fn parse_verbosity(value: &Bound<'_, PyAny>) -> PyResult<PyVerbosity> {
VerbosityArg::extract(value.as_borrowed()).map(|verbosity| verbosity.0)
}
pub(super) fn normalize_token(text: &str) -> String {
text.trim().to_ascii_lowercase().replace('-', "_")
}