diff --git a/Cargo.toml b/Cargo.toml index 6c76ecf..5ec6758 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,9 +12,26 @@ members = [ ] default-members = [ "members/pt", + "members/pt-bin", "members/pt-core", "members/pt-py", "members/pt-log", "members/pt-math", ] +[workspace.package] +publish = false +default-run = "pt" +name = "libpt" +version = "0.1.7" +edition = "2021" +authors = ["Christoph J. Scherr "] +license = "MIT" +description = "Personal multitool" +readme = "README.md" +homepage = "https://git.cscherr.de/PlexSheep/pt" +repository = "https://git.cscherr.de/PlexSheep/pt" +keywords = ["cli", "python", "scriptable", "pyo3", "library"] +categories = ["command-line-utilities", "development-tools", "development-tools::ffi"] +[workspace.dependencies] +pyo3 = "0.19" diff --git a/members/pt-bin/Cargo.toml b/members/pt-bin/Cargo.toml index f7f64a7..5c00af2 100644 --- a/members/pt-bin/Cargo.toml +++ b/members/pt-bin/Cargo.toml @@ -1,4 +1,5 @@ [package] +autobins = true name = "pt-bin" version = "0.1.0" edition = "2021" diff --git a/members/pt-ccc/src/main.rs b/members/pt-ccc/src/lib.rs similarity index 100% rename from members/pt-ccc/src/main.rs rename to members/pt-ccc/src/lib.rs diff --git a/members/pt-hedu/src/main.rs b/members/pt-hedu/src/lib.rs similarity index 100% rename from members/pt-hedu/src/main.rs rename to members/pt-hedu/src/lib.rs diff --git a/members/pt-log/Cargo.toml b/members/pt-log/Cargo.toml index 9753159..af166c0 100644 --- a/members/pt-log/Cargo.toml +++ b/members/pt-log/Cargo.toml @@ -10,6 +10,7 @@ tracing = "0.1.37" tracing-appender = "0.2.2" tracing-subscriber = "0.3.17" env_logger = "0.10.0" +pyo3 = {workspace = true} [dev-dependencies] gag = "1.0.0" diff --git a/members/pt-log/src/error.rs b/members/pt-log/src/error.rs index 9fb721b..435ee9f 100644 --- a/members/pt-log/src/error.rs +++ b/members/pt-log/src/error.rs @@ -18,6 +18,7 @@ #![warn(clippy::pedantic)] //// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// +use pyo3::{exceptions::PyException, PyErr}; use tracing::subscriber::SetGlobalDefaultError; //// TYPES ///////////////////////////////////////////////////////////////////////////////////////// @@ -57,6 +58,19 @@ impl From for Error { } } +//////////////////////////////////////////////////////////////////////////////////////////////////// +impl Into for Error { + fn into(self) -> PyErr { + match self { + Error::IO(err) => PyException::new_err(format!("LoggerError: IO {err:?}")), + Error::Usage(err) => PyException::new_err(format!("LoggerError: Usage {err}")), + Error::SetGlobalDefaultFail(err) => { + PyException::new_err(format!("LoggerError: SetGlobalDefaultFail {err}")) + } + } + } +} + //////////////////////////////////////////////////////////////////////////////////////////////////// impl std::fmt::Debug for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -82,3 +96,4 @@ impl std::fmt::Display for Error { //// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// //// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// + diff --git a/members/pt-log/src/lib.rs b/members/pt-log/src/lib.rs index 6fe76cf..7cbf81b 100644 --- a/members/pt-log/src/lib.rs +++ b/members/pt-log/src/lib.rs @@ -25,6 +25,8 @@ use error::*; pub use tracing::{debug, error, info, trace, warn, Level}; use tracing_appender; use tracing_subscriber::{prelude::*, fmt::format::FmtSpan}; + +use pyo3::prelude::*; //// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////// /// The log level used when none is specified pub const DEFAULT_LOG_LEVEL: Level = Level::INFO; @@ -52,6 +54,7 @@ static INITIALIZED: AtomicBool = AtomicBool::new(false); /// - `Info` /// - `Warn` /// - `Error` +#[pyclass] pub struct Logger {} //// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// @@ -188,6 +191,61 @@ impl Logger { } } +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// ## Implementation of the python interface +#[pymethods] +impl Logger { + /// ## Python version of [`new()`](Logger::new) + #[new] + pub fn py_new() -> PyResult { + Ok(Logger::new()) + } + /// ## Python version of [`init()`](Logger::init) + #[pyo3(name = "init")] + #[staticmethod] + pub fn py_init(log_dir: Option, max_level: Option) -> Result<()> { + Self::init( + log_dir, + match max_level { + Some(s) => match s.to_uppercase().as_str() { + "TRACE" => Some(tracing::Level::TRACE), + "DEBUG" => Some(tracing::Level::DEBUG), + "INFO" => Some(tracing::Level::INFO), + "WARN" => Some(tracing::Level::WARN), + "ERROR" => Some(tracing::Level::ERROR), + _ => return Err(Error::Usage(format!("'{s}' is not a valid log level"))), + }, + None => None, + }, + ) + } + /// ## Python version of [`error()`](Logger::error) + #[pyo3(name = "error")] + pub fn py_error(&self, printable: String) { + self.error(printable) + } + /// ## Python version of [`warn()`](Logger::warn) + #[pyo3(name = "warn")] + pub fn py_warn(&self, printable: String) { + self.warn(printable) + } + /// ## Python version of [`info()`](Logger::info) + #[pyo3(name = "info")] + pub fn py_info(&self, printable: String) { + self.info(printable) + } + /// ## Python version of [`debug()`](Logger::debug) + #[pyo3(name = "debug")] + pub fn py_debug(&self, printable: String) { + self.debug(printable) + } + /// ## Python version of [`trace()`](Logger::trace) + #[pyo3(name = "trace")] + pub fn py_trace(&self, printable: String) { + self.trace(printable) + } +} + //////////////////////////////////////////////////////////////////////////////////////////////////// impl fmt::Debug for Logger { /// ## Debug representation for [`Logger`] @@ -203,3 +261,4 @@ impl fmt::Debug for Logger { //// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// //// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// + diff --git a/members/pt-py/Cargo.toml b/members/pt-py/Cargo.toml index 4da490f..f0d14ed 100644 --- a/members/pt-py/Cargo.toml +++ b/members/pt-py/Cargo.toml @@ -6,3 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +pt = { version = "0.1.0", path = "../pt" } +pyo3 = { workspace = true } diff --git a/members/pt-py/src/lib.rs b/members/pt-py/src/lib.rs index fa8f42a..bc2f15b 100644 --- a/members/pt-py/src/lib.rs +++ b/members/pt-py/src/lib.rs @@ -1,14 +1,98 @@ +use pt::*; + use pyo3::prelude::*; -/// Formats the sum of two numbers as string. +//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// +/// ## Check if [`libpt`](crate) has been loaded +/// +/// Always returns `true` if you can execute it. #[pyfunction] -fn sum_as_string(a: usize, b: usize) -> PyResult { - Ok((a + b).to_string()) +pub fn is_loaded() -> bool { + true } -/// A Python module implemented in Rust. +//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// +/// ## Python module: logger #[pymodule] -fn pt_py(_py: Python, m: &PyModule) -> PyResult<()> { - m.add_function(wrap_pyfunction!(sum_as_string, m)?)?; +fn py_logger(py: Python, parent: &PyModule) -> PyResult<()> { + let module = PyModule::new(py, "logger")?; + module.add_class::()?; + + parent.add_submodule(module)?; Ok(()) -} \ No newline at end of file +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// ## Python module: common +#[pymodule] +fn py_common(py: Python, parent: &PyModule) -> PyResult<()> { + let module = PyModule::new(py, "common")?; + py_common_printing(py, module)?; + + parent.add_submodule(module)?; + Ok(()) +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// ## Python module: common.printing +#[pymodule] +fn py_common_printing(py: Python, parent: &PyModule) -> PyResult<()> { + let module = PyModule::new(py, "printing")?; + module.add_function(wrap_pyfunction!(common::printing::divider, module)?)?; + module.add_function(wrap_pyfunction!(common::printing::print_divider, module)?)?; + + parent.add_submodule(module)?; + Ok(()) +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// ## Python module: networking +#[pymodule] +fn py_networking(py: Python, parent: &PyModule) -> PyResult<()> { + let module = PyModule::new(py, "networking")?; + py_networking_monitoring(py, module)?; + + parent.add_submodule(module)?; + Ok(()) +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// ## Python module: networking.monitoring +#[pymodule] +fn py_networking_monitoring(py: Python, parent: &PyModule) -> PyResult<()> { + let module = PyModule::new(py, "monitoring")?; + py_networking_monitoring_uptime(py, module)?; + + parent.add_submodule(module)?; + Ok(()) +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// ## Python module: networking.monitoring.uptime +#[pymodule] +fn py_networking_monitoring_uptime(py: Python, parent: &PyModule) -> PyResult<()> { + let module = PyModule::new(py, "uptime")?; + module.add_class::()?; + module.add_function(wrap_pyfunction!( + networking::monitoring::uptime::py_continuous_uptime_monitor, + module + )?)?; + + parent.add_submodule(module)?; + Ok(()) +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// ## Python module: root +/// +/// This function is the entry point of [`PyO3`](pyo3). This is where the main module is built. +#[pymodule] +fn _libpt(py: Python, m: &PyModule) -> PyResult<()> { + m.add_function(wrap_pyfunction!(is_loaded, m)?)?; + + // load sub modules + py_common(py, m)?; + py_logger(py, m)?; + py_networking(py, m)?; + Ok(()) +} diff --git a/members/pt/Cargo.toml b/members/pt/Cargo.toml index e746e81..4add354 100644 --- a/members/pt/Cargo.toml +++ b/members/pt/Cargo.toml @@ -1,18 +1,7 @@ [package] -publish = true -autobins = true default-run = "pt" -name = "libpt" -version = "0.1.6" -edition = "2021" -authors = ["Christoph J. Scherr "] -license = "GPL-3.0-or-later" -description = "Personal multitool" -readme = "README.md" -homepage = "https://git.cscherr.de/PlexSheep/pt" -repository = "https://git.cscherr.de/PlexSheep/pt" -keywords = ["cli", "python", "scriptable", "pyo3", "library"] -categories = ["command-line-utilities", "development-tools", "development-tools::ffi"] +name = "pt" +version = "0.1.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -39,7 +28,12 @@ num = "0.4.0" num-traits = "0.2.16" openssl = "0.10.55" openssl-sys = "0.9.90" -pyo3 = "0.18.1" +pt-bin = { version = "0.1.0", path = "../pt-bin" } +pt-core = { version = "0.1.0", path = "../pt-core" } +pt-hedu = { version = "0.1.0", path = "../pt-hedu" } +pt-log = { version = "0.1.0", path = "../pt-log" } +pt-math = { version = "0.1.0", path = "../pt-math" } +pt-net = { version = "0.1.0", path = "../pt-net" } regex = "1.9.1" reqwest = { version = "0.11.18", features = ["blocking"] } serde = { version = "1.0.171", features = ["derive"] } diff --git a/members/pt/src/lib.rs b/members/pt/src/lib.rs index dd093e3..fc9bbff 100644 --- a/members/pt/src/lib.rs +++ b/members/pt/src/lib.rs @@ -21,109 +21,7 @@ //// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// /// contains useful code, such as macros, for general use -pub mod common; -/// logger used by libpt -pub mod logger; -/// networking tools -pub mod networking; -/// math tools -pub mod math; - -use crate::logger::Logger; - -use pyo3::prelude::*; - -//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// -/// ## Check if [`libpt`](crate) has been loaded -/// -/// Always returns `true` if you can execute it. -#[pyfunction] -pub fn is_loaded() -> bool { - true -} - -//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// -/// ## Python module: logger -#[pymodule] -fn py_logger(py: Python, parent: &PyModule) -> PyResult<()> { - let module = PyModule::new(py, "logger")?; - module.add_class::()?; - - parent.add_submodule(module)?; - Ok(()) -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// ## Python module: common -#[pymodule] -fn py_common(py: Python, parent: &PyModule) -> PyResult<()> { - let module = PyModule::new(py, "common")?; - py_common_printing(py, module)?; - - parent.add_submodule(module)?; - Ok(()) -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// ## Python module: common.printing -#[pymodule] -fn py_common_printing(py: Python, parent: &PyModule) -> PyResult<()> { - let module = PyModule::new(py, "printing")?; - module.add_function(wrap_pyfunction!(common::printing::divider, module)?)?; - module.add_function(wrap_pyfunction!(common::printing::print_divider, module)?)?; - - parent.add_submodule(module)?; - Ok(()) -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// ## Python module: networking -#[pymodule] -fn py_networking(py: Python, parent: &PyModule) -> PyResult<()> { - let module = PyModule::new(py, "networking")?; - py_networking_monitoring(py, module)?; - - parent.add_submodule(module)?; - Ok(()) -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// ## Python module: networking.monitoring -#[pymodule] -fn py_networking_monitoring(py: Python, parent: &PyModule) -> PyResult<()> { - let module = PyModule::new(py, "monitoring")?; - py_networking_monitoring_uptime(py, module)?; - - parent.add_submodule(module)?; - Ok(()) -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// ## Python module: networking.monitoring.uptime -#[pymodule] -fn py_networking_monitoring_uptime(py: Python, parent: &PyModule) -> PyResult<()> { - let module = PyModule::new(py, "uptime")?; - module.add_class::()?; - module.add_function(wrap_pyfunction!( - networking::monitoring::uptime::py_continuous_uptime_monitor, - module - )?)?; - - parent.add_submodule(module)?; - Ok(()) -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// ## Python module: root -/// -/// This function is the entry point of [`PyO3`](pyo3). This is where the main module is built. -#[pymodule] -fn _libpt(py: Python, m: &PyModule) -> PyResult<()> { - m.add_function(wrap_pyfunction!(is_loaded, m)?)?; - - // load sub modules - py_common(py, m)?; - py_logger(py, m)?; - py_networking(py, m)?; - Ok(()) -} +pub use pt_core; +pub use pt_log; +pub use pt_net; +pub use pt_hedu;