use pyo3::exceptions::{PyRuntimeError, PyValueError};
use pyo3::prelude::*;
mod interactive;
mod session;
use interactive::PyInteractiveShell;
use session::{PyOutputStream, PyPortForwarder, PySession, PySessionManager};
#[allow(missing_docs)]
mod exceptions {
pyo3::create_exception!(_internal, SsmError, pyo3::exceptions::PyException);
pyo3::create_exception!(_internal, SsmAwsError, SsmError);
pyo3::create_exception!(_internal, SsmProtocolError, SsmError);
pyo3::create_exception!(_internal, SsmTransportError, SsmError);
pyo3::create_exception!(_internal, SsmClosedError, SsmError);
pyo3::create_exception!(_internal, SsmCryptoError, SsmError);
pyo3::create_exception!(_internal, SsmTimeoutError, SsmError);
}
use exceptions::*;
pub(crate) fn to_py_err(error: crate::Error) -> PyErr {
use crate::Error;
match error {
Error::Aws { message, .. } => SsmAwsError::new_err(message),
Error::Protocol(message) => SsmProtocolError::new_err(message),
Error::Transport(message) => SsmTransportError::new_err(message),
Error::SessionClosed(message) => SsmClosedError::new_err(message),
Error::Crypto(message) => SsmCryptoError::new_err(message),
Error::Timeout(duration) => {
SsmTimeoutError::new_err(format!("operation timed out after {duration:?}"))
}
Error::Config(message) => PyValueError::new_err(message),
Error::Unsupported(message) => PyRuntimeError::new_err(message),
other => SsmError::new_err(other.to_string()),
}
}
#[pyfunction]
#[pyo3(signature = (level = "warn"))]
fn configure_logging(level: &str) -> PyResult<()> {
use tracing::level_filters::LevelFilter;
let filter = match level.to_ascii_lowercase().as_str() {
"off" => LevelFilter::OFF,
"error" => LevelFilter::ERROR,
"warn" => LevelFilter::WARN,
"info" => LevelFilter::INFO,
"debug" => LevelFilter::DEBUG,
"trace" => LevelFilter::TRACE,
other => {
return Err(PyValueError::new_err(format!(
"unknown log level {other:?}; use off, error, warn, info, debug or trace"
)))
}
};
let _ = tracing_subscriber::fmt()
.with_writer(std::io::stderr)
.with_env_filter(
tracing_subscriber::EnvFilter::builder()
.with_default_directive(filter.into())
.from_env_lossy(),
)
.try_init();
Ok(())
}
#[pymodule]
fn _internal(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<PySessionManager>()?;
m.add_class::<PySession>()?;
m.add_class::<PyOutputStream>()?;
m.add_class::<PyPortForwarder>()?;
m.add_class::<PyInteractiveShell>()?;
m.add_function(wrap_pyfunction!(configure_logging, m)?)?;
m.add("SsmError", m.py().get_type::<SsmError>())?;
m.add("SsmAwsError", m.py().get_type::<SsmAwsError>())?;
m.add("SsmProtocolError", m.py().get_type::<SsmProtocolError>())?;
m.add("SsmTransportError", m.py().get_type::<SsmTransportError>())?;
m.add("SsmClosedError", m.py().get_type::<SsmClosedError>())?;
m.add("SsmCryptoError", m.py().get_type::<SsmCryptoError>())?;
m.add("SsmTimeoutError", m.py().get_type::<SsmTimeoutError>())?;
m.add("__version__", env!("CARGO_PKG_VERSION"))?;
Ok(())
}