generated from PlexSheep/baserepo
Compare commits
18 commits
f8f88e79c3
...
1bdef8c493
Author | SHA1 | Date | |
---|---|---|---|
1bdef8c493 | |||
2fb3fc298c | |||
8cd7dcd77d | |||
0e9da09102 | |||
9d1a242060 | |||
cbd0717cc6 | |||
|
341a64a0f5 | ||
|
3334920d18 | ||
|
12ac4ebb38 | ||
|
ebac3201cd | ||
|
3c8a2d9661 | ||
|
fa6eb387ce | ||
f2bab05909 | |||
|
482e246bc8 | ||
9fb726b5df | |||
|
999c753d3e | ||
|
8113e5ac65 | ||
|
7803195c24 |
56 changed files with 975 additions and 501 deletions
99
Cargo.toml
99
Cargo.toml
|
@ -1,9 +1,30 @@
|
||||||
[package]
|
[workspace]
|
||||||
name = "libpt"
|
resolver = "2"
|
||||||
version = "0.1.6"
|
members = [
|
||||||
|
".",
|
||||||
|
"members/pt-core",
|
||||||
|
"members/pt-bintols",
|
||||||
|
"members/pt-math",
|
||||||
|
"members/pt-bin",
|
||||||
|
"members/pt-log",
|
||||||
|
"members/pt-net",
|
||||||
|
"members/pt-py",
|
||||||
|
"members/pt-hedu",
|
||||||
|
]
|
||||||
|
default-members = [
|
||||||
|
".",
|
||||||
|
"members/pt-bin",
|
||||||
|
"members/pt-core",
|
||||||
|
"members/pt-py",
|
||||||
|
"members/pt-log",
|
||||||
|
"members/pt-math",
|
||||||
|
]
|
||||||
|
[workspace.package]
|
||||||
|
publish = false
|
||||||
|
version = "0.1.7"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Christoph J. Scherr <software@cscherr.de>"]
|
authors = ["Christoph J. Scherr <software@cscherr.de>"]
|
||||||
license = "GPL-3.0-or-later"
|
license = "MIT"
|
||||||
description = "Personal multitool"
|
description = "Personal multitool"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
homepage = "https://git.cscherr.de/PlexSheep/pt"
|
homepage = "https://git.cscherr.de/PlexSheep/pt"
|
||||||
|
@ -11,39 +32,47 @@ repository = "https://git.cscherr.de/PlexSheep/pt"
|
||||||
keywords = ["cli", "python", "scriptable", "pyo3", "library"]
|
keywords = ["cli", "python", "scriptable", "pyo3", "library"]
|
||||||
categories = ["command-line-utilities", "development-tools", "development-tools::ffi"]
|
categories = ["command-line-utilities", "development-tools", "development-tools::ffi"]
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
[workspace.dependencies]
|
||||||
|
pyo3 = "0.19"
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "libpt"
|
||||||
|
publish = true
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
description.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
keywords.workspace = true
|
||||||
|
categories.workspace = true
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["core", "log"]
|
||||||
|
core = []
|
||||||
|
math = []
|
||||||
|
log = []
|
||||||
|
bintols = []
|
||||||
|
net = []
|
||||||
|
ccc = ["math"]
|
||||||
|
hedu = ["bintols"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "pt"
|
name = "libpt"
|
||||||
crate-type = ["cdylib", "rlib"]
|
crate-type = [
|
||||||
|
"dylib", # .dll, .so, .dynlib
|
||||||
|
"staticlib" # .lib, .a
|
||||||
|
]
|
||||||
|
|
||||||
[[bin]]
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
name = "pt"
|
|
||||||
path = "src/bin/main/mod.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "ccc"
|
|
||||||
path = "src/bin/ccc/mod.rs"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4.3.11", features = ["derive"] }
|
pt-bintols = { version = "0.1.0", path = "members/pt-bintols" }
|
||||||
clap-num = "1.0.2"
|
pt-core = { version = "0.1.0", path = "members/pt-core" }
|
||||||
clap-verbosity-flag = "2.0.1"
|
pt-hedu = { version = "0.1.0", path = "members/pt-hedu" }
|
||||||
env_logger = "0.10.0"
|
pt-log = { version = "0.1.0", path = "members/pt-log" }
|
||||||
humantime = "2.1.0"
|
pt-math = { version = "0.1.0", path = "members/pt-math" }
|
||||||
num = "0.4.0"
|
pt-net = { version = "0.1.0", path = "members/pt-net" }
|
||||||
num-traits = "0.2.16"
|
pt-ccc = { version = "0.1.0", path = "members/pt-ccc" }
|
||||||
openssl = "0.10.55"
|
|
||||||
openssl-sys = "0.9.90"
|
|
||||||
pyo3 = "0.18.1"
|
|
||||||
regex = "1.9.1"
|
|
||||||
reqwest = { version = "0.11.18", features = ["blocking"] }
|
|
||||||
serde = { version = "1.0.171", features = ["derive"] }
|
|
||||||
serde_json = "1.0.102"
|
|
||||||
signal-hook = "0.3.15"
|
|
||||||
tracing = "0.1.37"
|
|
||||||
tracing-appender = "0.2.2"
|
|
||||||
tracing-subscriber = "0.3.17"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
gag = "1.0.0"
|
|
||||||
|
|
|
@ -9,10 +9,6 @@ crate, python module or executable.
|
||||||
|
|
||||||
Let's see if I make it a bloated mess or stop committing after 30 hello worlds.
|
Let's see if I make it a bloated mess or stop committing after 30 hello worlds.
|
||||||
|
|
||||||
#### But the name `pt` / `libpt` already exists!
|
|
||||||
|
|
||||||
So what? I don't care. Besides, there is not enough names to name everything unique.
|
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
- See `cargo.toml`
|
- See `cargo.toml`
|
||||||
|
|
30
members/pt-bin/Cargo.toml
Normal file
30
members/pt-bin/Cargo.toml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
[package]
|
||||||
|
autobins = true
|
||||||
|
name = "pt-bin"
|
||||||
|
publish.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
description.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
keywords.workspace = true
|
||||||
|
categories.workspace = true
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "ccc"
|
||||||
|
path = "src/ccc/mod.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "pt"
|
||||||
|
path = "src/main/mod.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
clap = { version = "4.4.4", features = ["derive"] }
|
||||||
|
clap-num = "1.0.2"
|
||||||
|
clap-verbosity-flag = "2.0.1"
|
||||||
|
libpt = { version = "0.1.7", path = "../..", features = ["ccc", "math", "hedu", "net"] }
|
|
@ -15,11 +15,10 @@
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
use pt::math::calculator::{*, self};
|
use libpt::ccc::*;
|
||||||
use pt::logger::*;
|
use libpt::log::*;
|
||||||
|
|
||||||
use clap::{Parser, Subcommand};
|
use clap::Parser;
|
||||||
use clap_num::number_range;
|
|
||||||
use clap_verbosity_flag::{Verbosity, InfoLevel};
|
use clap_verbosity_flag::{Verbosity, InfoLevel};
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -42,6 +41,7 @@ static LONG_ABOUT_ROOT: &'static str = r##"
|
||||||
"##;
|
"##;
|
||||||
|
|
||||||
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// defines CLI interface
|
||||||
#[derive(Debug, Clone, Parser)]
|
#[derive(Debug, Clone, Parser)]
|
||||||
#[command(
|
#[command(
|
||||||
author,
|
author,
|
||||||
|
@ -81,12 +81,12 @@ pub struct Cli {
|
||||||
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
||||||
fn main() {
|
fn main() {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
let ll: tracing::Level = match cli.verbose.log_level().unwrap().as_str() {
|
let ll: Level = match cli.verbose.log_level().unwrap().as_str() {
|
||||||
"TRACE" => tracing::Level::TRACE,
|
"TRACE" => Level::TRACE,
|
||||||
"DEBUG" => tracing::Level::DEBUG,
|
"DEBUG" => Level::DEBUG,
|
||||||
"INFO" => tracing::Level::INFO,
|
"INFO" => Level::INFO,
|
||||||
"WARN" => tracing::Level::WARN,
|
"WARN" => Level::WARN,
|
||||||
"ERROR" => tracing::Level::ERROR,
|
"ERROR" => Level::ERROR,
|
||||||
_ => {
|
_ => {
|
||||||
eprintln!("'{}' is not a valid loglevel", cli.verbose.to_string());
|
eprintln!("'{}' is not a valid loglevel", cli.verbose.to_string());
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
|
@ -15,11 +15,7 @@
|
||||||
|
|
||||||
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
use pt::{logger, networking::monitoring::uptime, common::*};
|
use libpt::{log::*, net::monitoring::uptime};
|
||||||
|
|
||||||
// we want the log macros in any case
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
use tracing::{debug, error, info, trace, warn};
|
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
|
@ -45,19 +41,19 @@ use std::path::PathBuf;
|
||||||
/// ## Main function of the [`pt`](crate) binary
|
/// ## Main function of the [`pt`](crate) binary
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
let ll: tracing::Level = match cli.verbose.log_level().unwrap().as_str() {
|
let ll: Level = match cli.verbose.log_level().unwrap().as_str() {
|
||||||
"TRACE" => tracing::Level::TRACE,
|
"TRACE" => Level::TRACE,
|
||||||
"DEBUG" => tracing::Level::DEBUG,
|
"DEBUG" => Level::DEBUG,
|
||||||
"INFO" => tracing::Level::INFO,
|
"INFO" => Level::INFO,
|
||||||
"WARN" => tracing::Level::WARN,
|
"WARN" => Level::WARN,
|
||||||
"ERROR" => tracing::Level::ERROR,
|
"ERROR" => Level::ERROR,
|
||||||
_ => {
|
_ => {
|
||||||
eprintln!("'{}' is not a valid loglevel", cli.verbose.to_string());
|
eprintln!("'{}' is not a valid loglevel", cli.verbose.to_string());
|
||||||
std::process::exit(EXIT_FAILURE_USAGE);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if cli.log_meta {
|
if cli.log_meta {
|
||||||
logger::Logger::init_customized(
|
Logger::init_customized(
|
||||||
false,
|
false,
|
||||||
PathBuf::from("/dev/null"),
|
PathBuf::from("/dev/null"),
|
||||||
true,
|
true,
|
||||||
|
@ -72,7 +68,7 @@ pub fn main() {
|
||||||
.expect("could not initialize Logger");
|
.expect("could not initialize Logger");
|
||||||
} else {
|
} else {
|
||||||
// less verbose version
|
// less verbose version
|
||||||
logger::Logger::init_customized(
|
Logger::init_customized(
|
||||||
false,
|
false,
|
||||||
PathBuf::from("/dev/null"),
|
PathBuf::from("/dev/null"),
|
||||||
true,
|
true,
|
20
members/pt-bintols/Cargo.toml
Normal file
20
members/pt-bintols/Cargo.toml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
[package]
|
||||||
|
name = "pt-bintols"
|
||||||
|
publish.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
description.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
keywords.workspace = true
|
||||||
|
categories.workspace = true
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
num-traits = "0.2.16"
|
||||||
|
pt-core = { version = "0.1.0", path = "../pt-core" }
|
||||||
|
pt-log = { version = "0.1.0", path = "../pt-log" }
|
41
members/pt-bintols/src/datalayout.rs
Normal file
41
members/pt-bintols/src/datalayout.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
//* # See what's behind the datatypes of Rust
|
||||||
|
//*
|
||||||
|
//* This Crate shows off how datatypes of rust are stored in memory.
|
||||||
|
|
||||||
|
// reexport macros
|
||||||
|
pub use crate::investigate_memory_layout;
|
||||||
|
|
||||||
|
/// ## Investigate the internal representation of variables
|
||||||
|
///
|
||||||
|
/// Takes 1. the Type and 2. a [`Vec`] of items (of that datatype).
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! investigate_memory_layout {
|
||||||
|
($t:ty, $v:tt) => {
|
||||||
|
println!("Type:\t{}", std::any::type_name::<$t>());
|
||||||
|
println!("\talign:\t{:?} B", std::mem::align_of::<$t>());
|
||||||
|
println!("\tID:\t{:?}\n", std::any::TypeId::of::<$t>());
|
||||||
|
println!("\tItems:");
|
||||||
|
unsafe {
|
||||||
|
for (index, item) in $v.iter().enumerate() {
|
||||||
|
let pointer = item as *const $t;
|
||||||
|
let mut memory: [u8; std::mem::size_of::<$t>()] = std::mem::transmute(item.clone());
|
||||||
|
memory.reverse();
|
||||||
|
println!("\
|
||||||
|
\t{index:02x}\titem:\t\t{item:?}\n\
|
||||||
|
\t\tpointer: \t{:X?}\n\
|
||||||
|
\t\talign: \t{}\n\
|
||||||
|
\t\tsize: \t{}\n\
|
||||||
|
\t\tmemory: \t{:X?}\n\
|
||||||
|
\t\tbin mem: \t{}\n\
|
||||||
|
\t\tnote: \tmemory order reversed\n\
|
||||||
|
",
|
||||||
|
pointer,
|
||||||
|
display::byte_bit_display(std::mem::align_of_val(item)),
|
||||||
|
display::byte_bit_display(memory.len()),
|
||||||
|
memory,
|
||||||
|
display::bytes_to_bin(&memory)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
67
members/pt-bintols/src/display.rs
Normal file
67
members/pt-bintols/src/display.rs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
//* # Tools that help display binary values, data sizes, etc
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
pub use num_traits::{PrimInt, ToPrimitive};
|
||||||
|
|
||||||
|
/// ## Get the binary representation for a Byte array [`&[u8]`]
|
||||||
|
///
|
||||||
|
/// ### Arguments
|
||||||
|
/// * `data` - The data you are trying to dump
|
||||||
|
pub fn bytes_to_bin(data: &[u8]) -> String {
|
||||||
|
let mut s = format!("0b{:08b}", data.first().unwrap());
|
||||||
|
for i in 1..data.len() {
|
||||||
|
s.push_str(&format!("_{:08b}", data[i]));
|
||||||
|
if i % 8 == 0 {
|
||||||
|
s.push_str("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Quickly format a number of Bytes [`usize`] with the corresponding
|
||||||
|
/// number of bits
|
||||||
|
pub fn byte_bit_display(data: usize) -> String {
|
||||||
|
format!("{} B = {} bit", data.clone(), data * 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ## Format total byte sizes to human readable sizes
|
||||||
|
pub fn humanbytes<T>(total: T) -> String
|
||||||
|
where
|
||||||
|
T: PrimInt,
|
||||||
|
T: ToPrimitive,
|
||||||
|
T: Ord,
|
||||||
|
T: std::fmt::Display,
|
||||||
|
T: std::fmt::Debug,
|
||||||
|
{
|
||||||
|
if total < T::from(KIBI).unwrap() {
|
||||||
|
return format!("{total} B");
|
||||||
|
} else if T::from(KIBI).unwrap() <= total && total < T::from(MEBI).unwrap() {
|
||||||
|
return format!("{:.2} K", total.to_f64().unwrap() / KIBI as f64);
|
||||||
|
} else if T::from(MEBI).unwrap() <= total && total < T::from(GIBI).unwrap() {
|
||||||
|
return format!("{:.2} M", total.to_f64().unwrap() / MEBI as f64);
|
||||||
|
} else if T::from(GIBI).unwrap() <= total && total < T::from(TEBI).unwrap() {
|
||||||
|
return format!("{:.2} G", total.to_f64().unwrap() / GIBI as f64);
|
||||||
|
} else if T::from(TEBI).unwrap() <= total && total < T::from(PEBI).unwrap() {
|
||||||
|
return format!("{:.2} T", total.to_f64().unwrap() / TEBI as f64);
|
||||||
|
} else if T::from(PEBI).unwrap() <= total && total < T::from(EXBI).unwrap() {
|
||||||
|
return format!("{:.2} P", total.to_f64().unwrap() / PEBI as f64);
|
||||||
|
}
|
||||||
|
// now we are starting to reach the sizes that are pretty unrealistic
|
||||||
|
// (as of 2023 that is, hello future)
|
||||||
|
//
|
||||||
|
// the later ones overflow `usize` on 64 Bit computers, so we have
|
||||||
|
// to work with a fixed, larger sized datatype
|
||||||
|
else {
|
||||||
|
let total: u128 = total.to_u128().unwrap();
|
||||||
|
if EXBI <= total && total < ZEBI {
|
||||||
|
return format!("{:.2} E", total.to_f64().unwrap() / EXBI as f64);
|
||||||
|
} else if ZEBI <= total && total < YOBI {
|
||||||
|
return format!("{:.2} Z", total.to_f64().unwrap() / ZEBI as f64);
|
||||||
|
} else if YOBI <= total {
|
||||||
|
return format!("{:.2} Y", total.to_f64().unwrap() / YOBI as f64);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
members/pt-bintols/src/lib.rs
Normal file
27
members/pt-bintols/src/lib.rs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
//* # Tools to work with binary values, memory, storage
|
||||||
|
//!
|
||||||
|
//! This crate is part of [`pt`](../libpt/index.html), but can also be used as a standalone
|
||||||
|
//! module.
|
||||||
|
|
||||||
|
// official binary prefixes, see [https://en.wikipedia.org/wiki/Binary_prefix]
|
||||||
|
/// 2^10
|
||||||
|
pub const KIBI: usize = 2usize.pow(10);
|
||||||
|
/// 2^20
|
||||||
|
pub const MEBI: usize = 2usize.pow(20);
|
||||||
|
/// 2^30
|
||||||
|
pub const GIBI: usize = 2usize.pow(30);
|
||||||
|
/// 2^40
|
||||||
|
pub const TEBI: usize = 2usize.pow(40);
|
||||||
|
/// 2^50
|
||||||
|
pub const PEBI: usize = 2usize.pow(50);
|
||||||
|
/// 2^60
|
||||||
|
pub const EXBI: u128 = 2u128.pow(60);
|
||||||
|
// at this point, `usize` would overflow, so we have to switch to a bigger datatype.
|
||||||
|
/// 2^70
|
||||||
|
pub const ZEBI: u128 = 2u128.pow(70);
|
||||||
|
/// 2^80
|
||||||
|
pub const YOBI: u128 = 2u128.pow(80);
|
||||||
|
|
||||||
|
// use pt_core;
|
||||||
|
pub mod datalayout;
|
||||||
|
pub mod display;
|
7
members/pt-bintols/tests/datalayout.rs
Normal file
7
members/pt-bintols/tests/datalayout.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
use pt_bintols::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mkdmp() {
|
||||||
|
let v = vec![true, true, false];
|
||||||
|
investigate_memory_layout!(bool, v);
|
||||||
|
}
|
63
members/pt-bintols/tests/display.rs
Normal file
63
members/pt-bintols/tests/display.rs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
use pt_bintols::*;
|
||||||
|
use pt_bintols::display::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn btobin() {
|
||||||
|
let data = [19, 19];
|
||||||
|
let r = bytes_to_bin(&data);
|
||||||
|
assert_eq!(r, format!("0b00010011_00010011"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn big_btobin() {
|
||||||
|
let data = [12,31,82,32,123,32,92,23,12,32,12,1,1,1];
|
||||||
|
let r = bytes_to_bin(&data);
|
||||||
|
assert_eq!(r, format!("0b00001100_00011111_01010010_\
|
||||||
|
00100000_01111011_00100000_01011100_00010111_00001100\n\
|
||||||
|
_00100000_00001100_00000001_00000001_00000001"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bybit() {
|
||||||
|
assert_eq!(byte_bit_display(120), format!("120 B = 960 bit"));
|
||||||
|
assert_eq!(byte_bit_display(12), format!("12 B = 96 bit"));
|
||||||
|
assert_eq!(byte_bit_display(8), format!("8 B = 64 bit"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hmnbytes() {
|
||||||
|
assert_eq!(humanbytes(0), format!("0 B"));
|
||||||
|
assert_eq!(humanbytes(1), format!("1 B"));
|
||||||
|
|
||||||
|
assert_eq!(humanbytes(KIBI-1), format!("1023 B"));
|
||||||
|
assert_eq!(humanbytes(KIBI), format!("1.00 K"));
|
||||||
|
assert_eq!(humanbytes(KIBI+1), format!("1.00 K"));
|
||||||
|
|
||||||
|
assert_eq!(humanbytes(MEBI-1), format!("1024.00 K"));
|
||||||
|
assert_eq!(humanbytes(MEBI), format!("1.00 M"));
|
||||||
|
assert_eq!(humanbytes(MEBI+1), format!("1.00 M"));
|
||||||
|
|
||||||
|
assert_eq!(humanbytes(GIBI-1), format!("1024.00 M"));
|
||||||
|
assert_eq!(humanbytes(GIBI), format!("1.00 G"));
|
||||||
|
assert_eq!(humanbytes(GIBI+1), format!("1.00 G"));
|
||||||
|
|
||||||
|
assert_eq!(humanbytes(TEBI-1), format!("1024.00 G"));
|
||||||
|
assert_eq!(humanbytes(TEBI), format!("1.00 T"));
|
||||||
|
assert_eq!(humanbytes(TEBI+1), format!("1.00 T"));
|
||||||
|
|
||||||
|
assert_eq!(humanbytes(PEBI-1), format!("1024.00 T"));
|
||||||
|
assert_eq!(humanbytes(PEBI), format!("1.00 P"));
|
||||||
|
assert_eq!(humanbytes(PEBI+1), format!("1.00 P"));
|
||||||
|
|
||||||
|
assert_eq!(humanbytes(EXBI-1), format!("1024.00 P"));
|
||||||
|
assert_eq!(humanbytes(EXBI), format!("1.00 E"));
|
||||||
|
assert_eq!(humanbytes(EXBI+1), format!("1.00 E"));
|
||||||
|
|
||||||
|
assert_eq!(humanbytes(ZEBI-1), format!("1024.00 E"));
|
||||||
|
assert_eq!(humanbytes(ZEBI), format!("1.00 Z"));
|
||||||
|
assert_eq!(humanbytes(ZEBI+1), format!("1.00 Z"));
|
||||||
|
|
||||||
|
assert_eq!(humanbytes(YOBI-1), format!("1024.00 Z"));
|
||||||
|
assert_eq!(humanbytes(YOBI), format!("1.00 Y"));
|
||||||
|
assert_eq!(humanbytes(YOBI+1), format!("1.00 Y"));
|
||||||
|
}
|
22
members/pt-ccc/Cargo.toml
Normal file
22
members/pt-ccc/Cargo.toml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
[package]
|
||||||
|
name = "pt-ccc"
|
||||||
|
publish.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
description.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
keywords.workspace = true
|
||||||
|
categories.workspace = true
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
num = "0.4.1"
|
||||||
|
num-traits = "0.2.16"
|
||||||
|
pt-core = { version = "0.1.7", path = "../pt-core" }
|
||||||
|
pt-log = { version = "0.1.7", path = "../pt-log" }
|
||||||
|
pt-math = { version = "0.1.7", path = "../pt-math" }
|
|
@ -15,7 +15,13 @@
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
pub use num_traits::PrimInt;
|
pub use num_traits::PrimInt;
|
||||||
|
|
||||||
|
#[allow(unused_imports)] // we possibly want to use all log levels
|
||||||
|
use pt_log::*;
|
||||||
|
#[allow(unused_imports)] // import more complex math stuff from there
|
||||||
|
use pt_math;
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Quick Result with a ccc error
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -69,38 +75,54 @@ pub enum Function {
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Top Level Error Type
|
||||||
|
///
|
||||||
|
/// Contains many variants of other errors, that can occur when using the crate.
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
/// The term has bad syntax
|
||||||
SyntaxError(String)
|
SyntaxError(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Represents some kind of computed value
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
|
/// Variable value
|
||||||
Variable(VarVal),
|
Variable(VarVal),
|
||||||
|
/// Numerical value
|
||||||
Numerical(NumVal),
|
Numerical(NumVal),
|
||||||
|
/// Complex number value
|
||||||
Complex(ComplVal),
|
Complex(ComplVal),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents some kind of numeric value
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum NumVal {
|
pub enum NumVal {
|
||||||
|
/// Value > 0
|
||||||
Signed(i128),
|
Signed(i128),
|
||||||
|
/// Value can be negative
|
||||||
Unsigned(u128),
|
Unsigned(u128),
|
||||||
|
/// Value is not an integer
|
||||||
Float(f64)
|
Float(f64)
|
||||||
}
|
}
|
||||||
|
|
||||||
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Represents a Value with at least one variable,
|
||||||
|
///
|
||||||
|
/// currently not implemented
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct VarVal {
|
pub struct VarVal {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Represents a Value with a complex number,
|
||||||
|
///
|
||||||
|
/// currently not implemented
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ComplVal {
|
pub struct ComplVal {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
|
@ -1,5 +1,8 @@
|
||||||
//! # Calculate expressions
|
//! # Calculate expressions
|
||||||
//!
|
//!
|
||||||
|
//! This crate is part of [`pt`](../libpt/index.html), but can also be used as a standalone
|
||||||
|
//! module.
|
||||||
|
//!
|
||||||
//! Calculate Calculations with your Calculator (`ccc`)
|
//! Calculate Calculations with your Calculator (`ccc`)
|
||||||
//!
|
//!
|
||||||
//! This modules aim is to take a term of any kind ([String]) and calculate it's value, be it
|
//! This modules aim is to take a term of any kind ([String]) and calculate it's value, be it
|
||||||
|
@ -22,7 +25,9 @@ pub mod term;
|
||||||
pub use term::*;
|
pub use term::*;
|
||||||
|
|
||||||
#[allow(unused_imports)] // we possibly want to use all log levels
|
#[allow(unused_imports)] // we possibly want to use all log levels
|
||||||
use crate::logger::{trace, debug, info, warn, error};
|
use pt_log::*;
|
||||||
|
#[allow(unused_imports)] // import more complex math stuff from there
|
||||||
|
use pt_math;
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -21,7 +21,10 @@ use std::collections::VecDeque;
|
||||||
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
pub use super::{Error, Result, Value, base::{self, *}};
|
pub use super::{Error, Result, Value, base::{self, *}};
|
||||||
use crate::logger::*;
|
#[allow(unused_imports)] // we possibly want to use all log levels
|
||||||
|
use pt_log::*;
|
||||||
|
#[allow(unused_imports)] // import more complex math stuff from there
|
||||||
|
use pt_math;
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -41,11 +44,14 @@ use crate::logger::*;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Token {
|
enum Token {
|
||||||
/// Some kind of operator
|
/// Some kind of operator
|
||||||
|
#[allow(unused)] // tmp
|
||||||
Operator(Operator),
|
Operator(Operator),
|
||||||
/// A concrete value that we can calculate something with. May be a constant, integer, float,
|
/// A concrete value that we can calculate something with. May be a constant, integer, float,
|
||||||
/// etc.
|
/// etc.
|
||||||
|
/// The Token has a value that can be used in calculation
|
||||||
Value(super::base::Value),
|
Value(super::base::Value),
|
||||||
/// A variable of some kind that will be present in the result
|
/// A variable of some kind that will be present in the result
|
||||||
|
#[allow(unused)] // tmp
|
||||||
Variable(char),
|
Variable(char),
|
||||||
}
|
}
|
||||||
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -65,6 +71,7 @@ pub struct Term {
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
///// internal values following /////
|
///// internal values following /////
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
|
#[allow(unused)] // tmp
|
||||||
operator_stack: Vec<Operator>,
|
operator_stack: Vec<Operator>,
|
||||||
output_queue: VecDeque<Token>
|
output_queue: VecDeque<Token>
|
||||||
}
|
}
|
||||||
|
@ -92,9 +99,9 @@ impl Term {
|
||||||
self.text = Self::filter(&self.original)?;
|
self.text = Self::filter(&self.original)?;
|
||||||
|
|
||||||
// Storage for unfinished tokens
|
// Storage for unfinished tokens
|
||||||
let mut unfinished_chars: Vec<char> = Vec::new();
|
let _unfinished_chars: Vec<char> = Vec::new();
|
||||||
|
|
||||||
for (index, c) in self.original.chars().enumerate() {
|
for (_index, c) in self.original.chars().enumerate() {
|
||||||
// this will be a mess, but it has to be before i can sort the mess.
|
// this will be a mess, but it has to be before i can sort the mess.
|
||||||
match c {
|
match c {
|
||||||
// TODO: make function to check if character is an operator, use it
|
// TODO: make function to check if character is an operator, use it
|
||||||
|
@ -121,7 +128,8 @@ impl Term {
|
||||||
///
|
///
|
||||||
/// Returns: A tuple with a [`Token`] and a [`bool`]. If the bool is false, the [`Token`] is
|
/// Returns: A tuple with a [`Token`] and a [`bool`]. If the bool is false, the [`Token`] is
|
||||||
/// marked as "incomplete", meaning that the character cannot be used yet.
|
/// marked as "incomplete", meaning that the character cannot be used yet.
|
||||||
fn to_tok(s: Vec<char>) -> Result<Token> {
|
#[allow(unused)] // tmp
|
||||||
|
fn to_tok(_s: Vec<char>) -> Result<Token> {
|
||||||
Ok(19.into())
|
Ok(19.into())
|
||||||
}
|
}
|
||||||
|
|
15
members/pt-core/Cargo.toml
Normal file
15
members/pt-core/Cargo.toml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[package]
|
||||||
|
name = "pt-core"
|
||||||
|
publish.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
description.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
keywords.workspace = true
|
||||||
|
categories.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
|
@ -1,7 +1,10 @@
|
||||||
//! # common functionalities
|
//! # common functionalities
|
||||||
//!
|
//!
|
||||||
//! This module implements common functionality useful for many use cases, such as macros,
|
//! This crate is part of [`pt`](../libpt/index.html), but can also be used as a standalone
|
||||||
//! Formatting functions and more.
|
//! module.
|
||||||
|
//!
|
||||||
|
//! This crate implements core functionality useful for many use cases, such as macros,
|
||||||
|
//! formatting functions and more.
|
||||||
|
|
||||||
//// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
|
//// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
|
||||||
// we want docs
|
// we want docs
|
||||||
|
@ -23,8 +26,6 @@ pub mod macros;
|
||||||
pub mod printing;
|
pub mod printing;
|
||||||
|
|
||||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
pub const EXIT_SUCCESS: i32 = 0;
|
|
||||||
pub const EXIT_FAILURE_USAGE: i32 = 1;
|
|
||||||
|
|
||||||
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -14,8 +14,6 @@
|
||||||
pub use crate::divider;
|
pub use crate::divider;
|
||||||
pub use crate::print_divider;
|
pub use crate::print_divider;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -47,17 +45,5 @@ macro_rules! print_divider {
|
||||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||||
/// python interface for [`divider!`], can also be used with rust
|
|
||||||
#[pyfunction]
|
|
||||||
pub fn divider() -> String {
|
|
||||||
divider!()
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// python interface for [`print_divider!`], can also be used with rust
|
|
||||||
#[pyfunction]
|
|
||||||
pub fn print_divider() {
|
|
||||||
print_divider!()
|
|
||||||
}
|
|
||||||
|
|
||||||
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
17
members/pt-hedu/Cargo.toml
Normal file
17
members/pt-hedu/Cargo.toml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
[package]
|
||||||
|
name = "pt-hedu"
|
||||||
|
publish.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
description.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
keywords.workspace = true
|
||||||
|
categories.workspace = true
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
6
members/pt-hedu/src/lib.rs
Normal file
6
members/pt-hedu/src/lib.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
//! # Dump data
|
||||||
|
//!
|
||||||
|
//! This crate is part of [`pt`](../libpt/index.html), but can also be used as a standalone
|
||||||
|
//! module.
|
||||||
|
//!
|
||||||
|
//! This crate is currently empty.
|
22
members/pt-log/Cargo.toml
Normal file
22
members/pt-log/Cargo.toml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
[package]
|
||||||
|
name = "pt-log"
|
||||||
|
publish.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
description.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
keywords.workspace = true
|
||||||
|
categories.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tracing = "0.1.37"
|
||||||
|
tracing-appender = "0.2.2"
|
||||||
|
tracing-subscriber = "0.3.17"
|
||||||
|
pyo3 = {workspace = true}
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
gag = "1.0.0"
|
|
@ -1,12 +1,6 @@
|
||||||
//! # very short description
|
//! # Error module for [`pt-log`](crate)
|
||||||
//!
|
//!
|
||||||
//! Short description
|
//! This module handles errors in logging contexts.
|
||||||
//!
|
|
||||||
//! Details
|
|
||||||
//!
|
|
||||||
//! ## Section 1
|
|
||||||
//!
|
|
||||||
//! ## Section 2
|
|
||||||
|
|
||||||
//// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
|
//// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
|
||||||
// we want docs
|
// we want docs
|
||||||
|
@ -22,7 +16,7 @@ use pyo3::{exceptions::PyException, PyErr};
|
||||||
use tracing::subscriber::SetGlobalDefaultError;
|
use tracing::subscriber::SetGlobalDefaultError;
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// a quick alias for a result with a [`LoggerError`]
|
/// a quick alias for a result with a [`Error`]
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -32,7 +26,7 @@ pub type Result<T> = std::result::Result<T, Error>;
|
||||||
//// MACROS ////////////////////////////////////////////////////////////////////////////////////////
|
//// MACROS ////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// ## Errors for the [logger](crate::logger)
|
/// ## Errors for the [Logger](super::Logger)
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Bad IO operation
|
/// Bad IO operation
|
||||||
IO(std::io::Error),
|
IO(std::io::Error),
|
||||||
|
@ -96,3 +90,4 @@ impl std::fmt::Display for Error {
|
||||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
//! # A specialized Logger for [`pt`](crate)
|
//! # A specialized Logger for [`pt`](../libpt/index.html)
|
||||||
//!
|
//!
|
||||||
//! For the library version, only the basic [`log`] is used, so that it is possible for
|
//! This crate is part of [`pt`](../libpt/index.html), but can also be used as a standalone
|
||||||
//! the end user to use the [`log`] frontend they desire.
|
//! module.
|
||||||
|
//!
|
||||||
|
//! For the library version, only the basic [`tracing`] is used, so that it is possible for
|
||||||
|
//! the end user to use the [`tracing`] frontend they desire.
|
||||||
//!
|
//!
|
||||||
//! I did however decide to create a [`Logger`] struct. This struct is mainly intended to be used
|
//! I did however decide to create a [`Logger`] struct. This struct is mainly intended to be used
|
||||||
//! with the python module of [`pt`](crate), but is still just as usable in other contexts.
|
//! with the python module of [`pt`](../libpt/index.html), but is still just as usable in other contexts.
|
||||||
//!
|
//!
|
||||||
//! ## Technologies used for logging:
|
//! ## Technologies used for logging:
|
||||||
//! - [`log`]: base logging crate
|
//! - [`tracing`]: base logging crate
|
||||||
//! - [`env_logger`]: used for the executable
|
//! - [`tracing_appender`]: Used to log to files
|
||||||
|
//! - [`tracing_subscriber`]: Used to do actual logging, formatting, to stdout
|
||||||
|
|
||||||
//// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
|
//// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -39,21 +43,10 @@ pub const DEFAULT_LOG_DIR: &'static str = "/dev/null";
|
||||||
static INITIALIZED: AtomicBool = AtomicBool::new(false);
|
static INITIALIZED: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// ## Logger for [`pt`](crate)
|
/// ## Logger for [`pt`](../libpt/index.html)
|
||||||
///
|
///
|
||||||
/// This struct exists mainly for the python module, so that we can use the same logger with both
|
/// This struct exists mainly for the python module, so that we can use the same logger with both
|
||||||
/// python and rust.
|
/// python and rust.
|
||||||
///
|
|
||||||
/// ### Setting a [`Level`](log::Level)
|
|
||||||
///
|
|
||||||
/// To set a [`Level`](log::Level), you need to set the environment variable `LIBPT_LOGLEVEL`
|
|
||||||
/// to either of:
|
|
||||||
///
|
|
||||||
/// - `Trace`
|
|
||||||
/// - `Debug`
|
|
||||||
/// - `Info`
|
|
||||||
/// - `Warn`
|
|
||||||
/// - `Error`
|
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
pub struct Logger {}
|
pub struct Logger {}
|
||||||
|
|
||||||
|
@ -71,7 +64,7 @@ impl Logger {
|
||||||
///
|
///
|
||||||
/// Will enable the logger to be used.
|
/// Will enable the logger to be used.
|
||||||
///
|
///
|
||||||
/// Assumes some defaults, use [`init_customized`](init_customized) for more control
|
/// Assumes some defaults, use [`init_customized`](Self::init_customized) for more control
|
||||||
pub fn init(log_dir: Option<PathBuf>, max_level: Option<Level>) -> Result<()> {
|
pub fn init(log_dir: Option<PathBuf>, max_level: Option<Level>) -> Result<()> {
|
||||||
Self::init_customized(
|
Self::init_customized(
|
||||||
log_dir.is_some(),
|
log_dir.is_some(),
|
||||||
|
@ -107,7 +100,7 @@ impl Logger {
|
||||||
warn!("trying to reinitialize the logger, ignoring");
|
warn!("trying to reinitialize the logger, ignoring");
|
||||||
return Err(Error::Usage(format!("logging is already initialized")));
|
return Err(Error::Usage(format!("logging is already initialized")));
|
||||||
} else {
|
} else {
|
||||||
let filter = tracing_subscriber::filter::FilterFn::new(|metadata| {
|
let filter = tracing_subscriber::filter::FilterFn::new(|_metadata| {
|
||||||
// let mut filter = false;
|
// let mut filter = false;
|
||||||
//
|
//
|
||||||
// // if it's this lib, continue
|
// // if it's this lib, continue
|
||||||
|
@ -154,35 +147,35 @@ impl Logger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ## logging at [`Level::Error`]
|
/// ## logging at [`Level::ERROR`]
|
||||||
pub fn error<T>(&self, printable: T)
|
pub fn error<T>(&self, printable: T)
|
||||||
where
|
where
|
||||||
T: fmt::Display,
|
T: fmt::Display,
|
||||||
{
|
{
|
||||||
error!("{}", printable)
|
error!("{}", printable)
|
||||||
}
|
}
|
||||||
/// ## logging at [`Level::Warn`]
|
/// ## logging at [`Level::WARN`]
|
||||||
pub fn warn<T>(&self, printable: T)
|
pub fn warn<T>(&self, printable: T)
|
||||||
where
|
where
|
||||||
T: fmt::Display,
|
T: fmt::Display,
|
||||||
{
|
{
|
||||||
warn!("{}", printable)
|
warn!("{}", printable)
|
||||||
}
|
}
|
||||||
/// ## logging at [`Level::Info`]
|
/// ## logging at [`Level::INFO`]
|
||||||
pub fn info<T>(&self, printable: T)
|
pub fn info<T>(&self, printable: T)
|
||||||
where
|
where
|
||||||
T: fmt::Display,
|
T: fmt::Display,
|
||||||
{
|
{
|
||||||
info!("{}", printable)
|
info!("{}", printable)
|
||||||
}
|
}
|
||||||
/// ## logging at [`Level::Debug`]
|
/// ## logging at [`Level::DEBUG`]
|
||||||
pub fn debug<T>(&self, printable: T)
|
pub fn debug<T>(&self, printable: T)
|
||||||
where
|
where
|
||||||
T: fmt::Display,
|
T: fmt::Display,
|
||||||
{
|
{
|
||||||
debug!("{}", printable)
|
debug!("{}", printable)
|
||||||
}
|
}
|
||||||
/// ## logging at [`Level::Trace`]
|
/// ## logging at [`Level::TRACE`]
|
||||||
pub fn trace<T>(&self, printable: T)
|
pub fn trace<T>(&self, printable: T)
|
||||||
where
|
where
|
||||||
T: fmt::Display,
|
T: fmt::Display,
|
||||||
|
@ -248,7 +241,7 @@ impl Logger {
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
impl fmt::Debug for Logger {
|
impl fmt::Debug for Logger {
|
||||||
/// ## Debug representation for [`Logger`]
|
/// ## DEBUG representation for [`Logger`]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
|
@ -261,3 +254,4 @@ impl fmt::Debug for Logger {
|
||||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
17
members/pt-math/Cargo.toml
Normal file
17
members/pt-math/Cargo.toml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
[package]
|
||||||
|
name = "pt-math"
|
||||||
|
publish.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
description.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
keywords.workspace = true
|
||||||
|
categories.workspace = true
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
|
@ -1,12 +1,9 @@
|
||||||
//! # very short description
|
//! # General Mathmatics functionalities
|
||||||
//!
|
//!
|
||||||
//! Short description
|
//! This crate is part of [`pt`](../libpt/index.html), but can also be used as a standalone
|
||||||
|
//! module.
|
||||||
//!
|
//!
|
||||||
//! Details
|
//! This module is currently empty, but will contain many math functionalities in a future version.
|
||||||
//!
|
|
||||||
//! ## Section 1
|
|
||||||
//!
|
|
||||||
//! ## Section 2
|
|
||||||
|
|
||||||
//// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
|
//// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
|
||||||
// we want docs
|
// we want docs
|
24
members/pt-net/Cargo.toml
Normal file
24
members/pt-net/Cargo.toml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
[package]
|
||||||
|
name = "pt-net"
|
||||||
|
publish.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
description.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
keywords.workspace = true
|
||||||
|
categories.workspace = true
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
humantime = "2.1.0"
|
||||||
|
pt-core = { version = "0.1.0", path = "../pt-core" }
|
||||||
|
pt-log = { version = "0.1.0", path = "../pt-log" }
|
||||||
|
pt-math = { version = "0.1.0", path = "../pt-math" }
|
||||||
|
reqwest = { version = "0.11.20", features = ["blocking"] }
|
||||||
|
serde = { version = "1.0.188", features = ["serde_derive"] }
|
||||||
|
serde_json = "1.0.107"
|
|
@ -1,5 +1,8 @@
|
||||||
//! # various networking tools
|
//! # various networking tools
|
||||||
//!
|
//!
|
||||||
|
//! This crate is part of [`pt`](../libpt/index.html), but can also be used as a standalone
|
||||||
|
//! module.
|
||||||
|
//!
|
||||||
//! The networking module contains various tools related to connections. For example, it contains a
|
//! The networking module contains various tools related to connections. For example, it contains a
|
||||||
//! tool that has the purpose to check if your connection is consistently available.
|
//! tool that has the purpose to check if your connection is consistently available.
|
||||||
|
|
|
@ -19,19 +19,17 @@
|
||||||
use std::{fmt, time::Duration};
|
use std::{fmt, time::Duration};
|
||||||
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
use crate::logger::*;
|
use pt_log::*;
|
||||||
|
|
||||||
use reqwest;
|
use reqwest;
|
||||||
|
|
||||||
use humantime::{format_duration, format_rfc3339};
|
use humantime::{format_duration, format_rfc3339};
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
use crate::divider;
|
use pt_core::divider;
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -50,27 +48,20 @@ pub const DEFAULT_CHECK_URLS: &'static [&'static str] =
|
||||||
/// ## Describes an uptime status
|
/// ## Describes an uptime status
|
||||||
///
|
///
|
||||||
/// [`UptimeStatus`] describes the result of an uptime check.
|
/// [`UptimeStatus`] describes the result of an uptime check.
|
||||||
#[pyclass]
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct UptimeStatus {
|
pub struct UptimeStatus {
|
||||||
/// true if the [`UptimeStatus`] is considered successful
|
/// true if the [`UptimeStatus`] is considered successful
|
||||||
#[pyo3(get, set)]
|
|
||||||
pub success: bool,
|
pub success: bool,
|
||||||
/// the percentage of reachable urls out of the total urls
|
/// the percentage of reachable urls out of the total urls
|
||||||
#[pyo3(get, set)]
|
|
||||||
pub success_ratio: u8,
|
pub success_ratio: u8,
|
||||||
/// the percentage of reachable urls out of the total urls that need to be reachable in order
|
/// the percentage of reachable urls out of the total urls that need to be reachable in order
|
||||||
/// for this [`UptimeStatus`] to be considered a success.
|
/// for this [`UptimeStatus`] to be considered a success.
|
||||||
#[pyo3(get, set)]
|
|
||||||
pub success_ratio_target: u8,
|
pub success_ratio_target: u8,
|
||||||
/// the number of reachable [`urls`](UptimeStatus::urls)
|
/// the number of reachable [`urls`](UptimeStatus::urls)
|
||||||
#[pyo3(get, set)]
|
|
||||||
pub reachable: usize,
|
pub reachable: usize,
|
||||||
/// which urls to check in [`check()`](UptimeStatus::check)
|
/// which urls to check in [`check()`](UptimeStatus::check)
|
||||||
#[pyo3(get, set)]
|
|
||||||
pub urls: Vec<String>,
|
pub urls: Vec<String>,
|
||||||
/// timeout length for requests (in ms)
|
/// timeout length for requests (in ms)
|
||||||
#[pyo3(get, set)]
|
|
||||||
pub timeout: u64,
|
pub timeout: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,38 +137,6 @@ impl UptimeStatus {
|
||||||
trace!("calculated success as: {}", self.success)
|
trace!("calculated success as: {}", self.success)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Implementation of the Python interface
|
|
||||||
#[pymethods]
|
|
||||||
impl UptimeStatus {
|
|
||||||
/// calls [`new()`](UptimeStatus::new) with python compatible arguments
|
|
||||||
#[new]
|
|
||||||
pub fn py_new(success_ratio_target: u8, urls: Vec<String>, timeout: u64) -> Self {
|
|
||||||
Self::new(success_ratio_target, urls, timeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Same as [`check()`](UptimeStatus::check)
|
|
||||||
#[pyo3(name = "check")]
|
|
||||||
pub fn py_check(&mut self) {
|
|
||||||
self.check();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Same as [`calc_success()`](UptimeStatus::calc_success)
|
|
||||||
#[pyo3(name = "calc_success")]
|
|
||||||
pub fn py_calc_success(&mut self) {
|
|
||||||
self.calc_success();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// we want to display the [`UptimeStatus`] in python too, so we need `__str__`
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
format!("{}", self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// we want to debug display the [`UptimeStatus`] in python too, so we need `__str__`
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
format!("{:?}", self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
impl fmt::Debug for UptimeStatus {
|
impl fmt::Debug for UptimeStatus {
|
||||||
|
@ -261,30 +220,6 @@ pub fn continuous_uptime_monitor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Python interface for [`continuous_uptime_monitor`]
|
|
||||||
///
|
|
||||||
/// Runs the function in a different thread and checks from time to time for things like Pythons
|
|
||||||
/// `KeyboardInterrupt` exception.
|
|
||||||
#[pyfunction]
|
|
||||||
#[pyo3(name = "continuous_uptime_monitor")]
|
|
||||||
pub fn py_continuous_uptime_monitor(
|
|
||||||
py: Python,
|
|
||||||
success_ratio_target: u8,
|
|
||||||
urls: Vec<String>,
|
|
||||||
interval: u64,
|
|
||||||
timeout: u64,
|
|
||||||
) -> PyResult<()> {
|
|
||||||
// execute the function in a different thread
|
|
||||||
let _th = std::thread::spawn(move || {
|
|
||||||
continuous_uptime_monitor(success_ratio_target, urls, interval, timeout);
|
|
||||||
});
|
|
||||||
loop {
|
|
||||||
Python::check_signals(py)?;
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(100))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
||||||
/// Displays the current status for the [continuous uptime monitor](continuous_uptime_monitor)
|
/// Displays the current status for the [continuous uptime monitor](continuous_uptime_monitor)
|
||||||
fn display_uptime_status(
|
fn display_uptime_status(
|
120
members/pt-py/.github/workflows/CI.yml
vendored
Normal file
120
members/pt-py/.github/workflows/CI.yml
vendored
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
# This file is autogenerated by maturin v1.1.0
|
||||||
|
# To update, run
|
||||||
|
#
|
||||||
|
# maturin generate-ci github
|
||||||
|
#
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- master
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
target: [x86_64, x86, aarch64, armv7, s390x, ppc64le]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.10'
|
||||||
|
- name: Build wheels
|
||||||
|
uses: PyO3/maturin-action@v1
|
||||||
|
with:
|
||||||
|
target: ${{ matrix.target }}
|
||||||
|
args: --release --out dist --find-interpreter
|
||||||
|
sccache: 'true'
|
||||||
|
manylinux: auto
|
||||||
|
- name: Upload wheels
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: wheels
|
||||||
|
path: dist
|
||||||
|
|
||||||
|
windows:
|
||||||
|
runs-on: windows-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
target: [x64, x86]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.10'
|
||||||
|
architecture: ${{ matrix.target }}
|
||||||
|
- name: Build wheels
|
||||||
|
uses: PyO3/maturin-action@v1
|
||||||
|
with:
|
||||||
|
target: ${{ matrix.target }}
|
||||||
|
args: --release --out dist --find-interpreter
|
||||||
|
sccache: 'true'
|
||||||
|
- name: Upload wheels
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: wheels
|
||||||
|
path: dist
|
||||||
|
|
||||||
|
macos:
|
||||||
|
runs-on: macos-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
target: [x86_64, aarch64]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.10'
|
||||||
|
- name: Build wheels
|
||||||
|
uses: PyO3/maturin-action@v1
|
||||||
|
with:
|
||||||
|
target: ${{ matrix.target }}
|
||||||
|
args: --release --out dist --find-interpreter
|
||||||
|
sccache: 'true'
|
||||||
|
- name: Upload wheels
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: wheels
|
||||||
|
path: dist
|
||||||
|
|
||||||
|
sdist:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Build sdist
|
||||||
|
uses: PyO3/maturin-action@v1
|
||||||
|
with:
|
||||||
|
command: sdist
|
||||||
|
args: --out dist
|
||||||
|
- name: Upload sdist
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: wheels
|
||||||
|
path: dist
|
||||||
|
|
||||||
|
release:
|
||||||
|
name: Release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: "startsWith(github.ref, 'refs/tags/')"
|
||||||
|
needs: [linux, windows, macos, sdist]
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: wheels
|
||||||
|
- name: Publish to PyPI
|
||||||
|
uses: PyO3/maturin-action@v1
|
||||||
|
env:
|
||||||
|
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
|
||||||
|
with:
|
||||||
|
command: upload
|
||||||
|
args: --skip-existing *
|
72
members/pt-py/.gitignore
vendored
Normal file
72
members/pt-py/.gitignore
vendored
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/target
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
.pytest_cache/
|
||||||
|
*.py[cod]
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
.venv/
|
||||||
|
env/
|
||||||
|
bin/
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
include/
|
||||||
|
man/
|
||||||
|
venv/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
pip-selfcheck.json
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.coverage
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
|
||||||
|
# Mr Developer
|
||||||
|
.mr.developer.cfg
|
||||||
|
.project
|
||||||
|
.pydevproject
|
||||||
|
|
||||||
|
# Rope
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# VSCode
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
# Pyenv
|
||||||
|
.python-version
|
22
members/pt-py/Cargo.toml
Normal file
22
members/pt-py/Cargo.toml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
[package]
|
||||||
|
name = "pt-py"
|
||||||
|
publish.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
description.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
keywords.workspace = true
|
||||||
|
categories.workspace = true
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
[lib]
|
||||||
|
name = "pt_py"
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
pyo3 = { workspace = true }
|
||||||
|
libpt = { version = "0.1.7", path = "../../" }
|
21
members/pt-py/LICENSE
Normal file
21
members/pt-py/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 Christoph Johannes Scherr
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
76
members/pt-py/README.md
Normal file
76
members/pt-py/README.md
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
# pt / libpt
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
`pt` stands for either one of "personal tool", "plex tool", "pete" or something among those lines.
|
||||||
|
It is a collection of tools that i might or might not use. The intended purpose of this repo is that
|
||||||
|
I program whatever i feel is worth having in a personal thing into it, then use it as either a lib,
|
||||||
|
crate, python module or executable.
|
||||||
|
|
||||||
|
Let's see if I make it a bloated mess or stop committing after 30 hello worlds.
|
||||||
|
|
||||||
|
#### But the name `pt` / `libpt` already exists!
|
||||||
|
|
||||||
|
So what? I don't care. Besides, there is not enough names to name everything unique.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- See `cargo.toml`
|
||||||
|
- [openssl bindings for rust](https://docs.rs/openssl/latest/openssl/)
|
||||||
|
- [Python](https://www.python.org/)
|
||||||
|
- [`maturin`](https://maturin.rs) - `pip install maturin`
|
||||||
|
|
||||||
|
## Compiling & Installing from source
|
||||||
|
|
||||||
|
If you only want the rust library, you can simply build it with `cargo build`. Add it to your
|
||||||
|
project like any other local dependency.
|
||||||
|
|
||||||
|
If you want to use the python variant too, you need to compile with maturing.
|
||||||
|
|
||||||
|
- Install in `venv`: `maturin develop --release`
|
||||||
|
- Install in system: `maturin build --release && pip install target/wheels/libpt-x.x.x-*`
|
||||||
|
|
||||||
|
## Installing from [pypi](https://pypi.org)
|
||||||
|
|
||||||
|
`libpt` has been packaged for [pypi.org](https://pypi.org/project/libpt/).
|
||||||
|
|
||||||
|
You can install it with `pip install libpt`
|
||||||
|
|
||||||
|
## Installing from [crates.io](https://crates.io)
|
||||||
|
|
||||||
|
`libpt` has been packaged for [crates.io](https://crates.io/crates/libpt).
|
||||||
|
|
||||||
|
You can add the library to your project with `cargo add libpt`.
|
||||||
|
|
||||||
|
## Installing from my personal package registry
|
||||||
|
|
||||||
|
`libpt` has been packaged for [git.cscherr.de](https://git.cscherr.de).
|
||||||
|
|
||||||
|
You can add the registry to your `config.toml` and then `cargo add libpt`
|
||||||
|
|
||||||
|
[Package](https://git.cscherr.de/PlexSheep/-/packages/cargo/libpt/)
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Testing needs to be done separately for the rust and python parts:
|
||||||
|
|
||||||
|
- Rust testing with `cargo test`
|
||||||
|
- Python testing with `./scripts/pytests.sh` or `python -m unittest discover -fs tests/python`
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
The documentation can be automatically generated with `cargo doc --open`.
|
||||||
|
|
||||||
|
An up to date version of the Documentation can be found [here](https://docs.rs/libpt/)
|
||||||
|
|
||||||
|
## Mirrored
|
||||||
|
|
||||||
|
The origin of this repository is [git.cscherr.de](https://git.cscherr.de/PlexSheep/pt)
|
||||||
|
|
||||||
|
It is mirrored to:
|
||||||
|
- [Codeberg](https://codeberg.org/PlexSheep/pt)
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
**Pt is MIT Licensed**
|
1
members/pt-py/scripts/pytests.sh
Executable file
1
members/pt-py/scripts/pytests.sh
Executable file
|
@ -0,0 +1 @@
|
||||||
|
python -m unittest discover -fs tests/python
|
101
members/pt-py/src/lib.rs
Normal file
101
members/pt-py/src/lib.rs
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
// FIXME: Using a local dependency does not work with maturin as it seems?
|
||||||
|
use libpt::{
|
||||||
|
log::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
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::<Logger>()?;
|
||||||
|
|
||||||
|
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::<networking::monitoring::uptime::UptimeStatus>()?;
|
||||||
|
// 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(())
|
||||||
|
}
|
145
src/lib.rs
145
src/lib.rs
|
@ -1,129 +1,22 @@
|
||||||
//! # `libpt`
|
//! # A library for common needs
|
||||||
//!
|
//!
|
||||||
//! [`libpt`](crate) contains my personal code. It is compiled as all of the following:
|
//! `pt` aims to implement a number of functionalities that might me useful to develop
|
||||||
|
//! programs in Rust. It aims to be a collection of generally, possibly useful things.
|
||||||
//!
|
//!
|
||||||
//! - dynamic library (`cdylib`, `.so` file on Linux)
|
//! `pt` is a project consisting of multiple smaller crates, all bundled together in this
|
||||||
//! - rust library crate (`rlib`, usable as )
|
//! "main crate". Most crates will only show up if you activate their feature.
|
||||||
//! - python module (with [`PyO3`](pyo3))
|
|
||||||
//! - executable (as `pt`)
|
|
||||||
//!
|
|
||||||
//! For more info on the linkage types, please refer to the
|
|
||||||
//! [rust reference](https://doc.rust-lang.org/reference/linkage.html).
|
|
||||||
|
|
||||||
//// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
|
#[cfg(feature = "core")]
|
||||||
// we want docs
|
pub use pt_core as core;
|
||||||
#![warn(missing_docs)]
|
#[cfg(feature = "bintols")]
|
||||||
#![warn(rustdoc::missing_crate_level_docs)]
|
pub use pt_bintols as bintols;
|
||||||
// we want Debug everywhere. This is a library and there will be many bugs.
|
#[cfg(feature = "hedu")]
|
||||||
#![warn(missing_debug_implementations)]
|
pub use pt_hedu as hedu;
|
||||||
// enable clippy's extra lints, the pedantic version
|
#[cfg(feature = "log")]
|
||||||
#![warn(clippy::pedantic)]
|
pub use pt_log as log;
|
||||||
|
#[cfg(feature = "math")]
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
pub use pt_math as math;
|
||||||
/// contains useful code, such as macros, for general use
|
#[cfg(feature = "net")]
|
||||||
pub mod common;
|
pub use pt_net as net;
|
||||||
/// logger used by libpt
|
#[cfg(feature = "ccc")]
|
||||||
pub mod logger;
|
pub use pt_ccc as ccc;
|
||||||
/// 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::<Logger>()?;
|
|
||||||
|
|
||||||
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::<networking::monitoring::uptime::UptimeStatus>()?;
|
|
||||||
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(())
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
//! # very short description
|
|
||||||
//!
|
|
||||||
//! Short description
|
|
||||||
//!
|
|
||||||
//! Details
|
|
||||||
//!
|
|
||||||
//! ## Section 1
|
|
||||||
//!
|
|
||||||
//! ## Section 2
|
|
||||||
|
|
||||||
//// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// we want docs
|
|
||||||
#![warn(missing_docs)]
|
|
||||||
#![warn(rustdoc::missing_crate_level_docs)]
|
|
||||||
// we want Debug everywhere.
|
|
||||||
#![warn(missing_debug_implementations)]
|
|
||||||
// enable clippy's extra lints, the pedantic version
|
|
||||||
#![warn(clippy::pedantic)]
|
|
||||||
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
pub mod calculator;
|
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// MACROS ////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
12
tests/lib.rs
12
tests/lib.rs
|
@ -1,12 +0,0 @@
|
||||||
/// # tests for the general behaviour of the libraries availability
|
|
||||||
///
|
|
||||||
/// These tests will not go very in depth
|
|
||||||
|
|
||||||
// IMPORTS /////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
use pt;
|
|
||||||
|
|
||||||
/// ## check if pt is loaded
|
|
||||||
#[test]
|
|
||||||
fn test_pt_is_loaded() {
|
|
||||||
assert!(pt::is_loaded())
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
"""
|
|
||||||
tests for the general behaviour of the libraries availability
|
|
||||||
"""
|
|
||||||
import unittest
|
|
||||||
import libpt
|
|
||||||
|
|
||||||
class TestLibptGeneral(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_loaded(self):
|
|
||||||
assert libpt.is_loaded()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
||||||
|
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
"""
|
|
||||||
test the logger
|
|
||||||
"""
|
|
||||||
import unittest
|
|
||||||
from libpt import logger
|
|
||||||
|
|
||||||
class TestLogger(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_basic_logging(self):
|
|
||||||
logger.Logger.init()
|
|
||||||
l = logger.Logger()
|
|
||||||
l.trace("MSG")
|
|
||||||
l.debug("MSG")
|
|
||||||
l.info("MSG")
|
|
||||||
l.warn("MSG")
|
|
||||||
l.error("MSG")
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
||||||
|
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
//! # Tests for pt::logger::Logger
|
|
||||||
//!
|
|
||||||
//! Note: the module uses a global variable to store if the thread has
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
use pt::common::macros::get_stdout_for;
|
|
||||||
/// ## Tests for basic logging functionality
|
|
||||||
use pt::logger::*;
|
|
||||||
|
|
||||||
use regex::Regex;
|
|
||||||
|
|
||||||
use std::sync::Once;
|
|
||||||
|
|
||||||
//// HELPERS ///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
static SETUP: Once = Once::new();
|
|
||||||
// only initialize once
|
|
||||||
/// ## setup that's needed before testing the logger struct
|
|
||||||
fn setup() {
|
|
||||||
SETUP.call_once(|| {
|
|
||||||
// we don't want to log messages during our tests!
|
|
||||||
Logger::init_customized(
|
|
||||||
false,
|
|
||||||
std::path::PathBuf::from("/dev/null"),
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
tracing::Level::TRACE,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.expect("could not initialize Logger");
|
|
||||||
println!()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/// ## Tests for basic logging
|
|
||||||
///
|
|
||||||
/// This test tests if the loggers basic logging functionality works, that is it's methods:
|
|
||||||
///
|
|
||||||
/// - [`Logger::trace`]
|
|
||||||
/// - [`Logger::debug`]
|
|
||||||
/// - [`Logger::info`]
|
|
||||||
/// - [`Logger::warn`]
|
|
||||||
/// - [`Logger::error`]
|
|
||||||
///
|
|
||||||
/// After those methods have Successfully been executed, their outputs gets stored in a single
|
|
||||||
/// [`String`] and a [`Regex`] checks if we have five correctly formatted messages.
|
|
||||||
#[test]
|
|
||||||
fn test_log_basic() {
|
|
||||||
setup();
|
|
||||||
let l = Logger::new();
|
|
||||||
let trace_out = get_stdout_for!(l.trace("MSG"));
|
|
||||||
let debug_out = get_stdout_for!(l.debug("MSG"));
|
|
||||||
let info_out = get_stdout_for!(l.info("MSG"));
|
|
||||||
let warn_out = get_stdout_for!(l.warn("MSG"));
|
|
||||||
let error_out = get_stdout_for!(l.error("MSG"));
|
|
||||||
let combined = format!(
|
|
||||||
"{}{}{}{}{}",
|
|
||||||
trace_out, debug_out, info_out, warn_out, error_out
|
|
||||||
);
|
|
||||||
print!("{}", combined);
|
|
||||||
|
|
||||||
// too long, so i split into two lines.
|
|
||||||
// this matches the format of the env_logger perfectly, but make sure that color is off,
|
|
||||||
// else the ANSI escape sequences break this test
|
|
||||||
let regex = Regex::new(concat!(
|
|
||||||
r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}Z\s+(TRACE|DEBUG|INFO|WARN|ERROR)\sMSG"
|
|
||||||
))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// we have 5 log levels, therefore we should have 5 captures
|
|
||||||
assert_eq!(regex.captures_iter(&combined).count(), 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_multi_initialize() {
|
|
||||||
setup();
|
|
||||||
let l = Logger::new();
|
|
||||||
// these should be ignored due to the global flag
|
|
||||||
Logger::init(None, None).unwrap_err();
|
|
||||||
Logger::init(None, None).unwrap_err();
|
|
||||||
Logger::init(None, None).unwrap_err();
|
|
||||||
Logger::init(None, None).unwrap_err();
|
|
||||||
l.info("Successfully ignored extra init");
|
|
||||||
}
|
|
Reference in a new issue