Compare commits

...

18 commits

Author SHA1 Message Date
1bdef8c493 make things hopefully ready for v0.1.7 2023-09-29 17:50:47 +02:00
2fb3fc298c python shenanigans 2023-09-29 13:42:37 +02:00
8cd7dcd77d fix warnings 2023-09-29 12:32:06 +02:00
0e9da09102 link docu files 2023-09-29 12:31:26 +02:00
9d1a242060 docu things i guess 2023-09-20 20:35:07 +02:00
cbd0717cc6 fix log and math docu 2023-09-20 20:14:10 +02:00
Christoph J. Scherr
341a64a0f5 renaming things back to libpt, its kinda responsible 2023-09-20 18:37:06 +02:00
Christoph J. Scherr
3334920d18 bintols work with generic hmnsize 2023-09-20 18:16:21 +02:00
Christoph J. Scherr
12ac4ebb38 structure stuff 2023-09-20 18:15:53 +02:00
Christoph J. Scherr
ebac3201cd bintols 2023-09-20 15:37:50 +02:00
Christoph J. Scherr
3c8a2d9661 everything compiles 2023-09-20 14:52:22 +02:00
Christoph J. Scherr
fa6eb387ce Merge branch 'devel' of https://git.cscherr.de/PlexSheep/pt into devel 2023-09-20 14:32:36 +02:00
f2bab05909 intermediate 2023-09-20 14:32:25 +02:00
Christoph J. Scherr
482e246bc8 add bintols 2023-09-20 14:28:40 +02:00
9fb726b5df compile pt-core 2023-09-15 20:14:50 +02:00
Christoph J. Scherr
999c753d3e move more stuff 2023-09-15 17:28:57 +02:00
Christoph J. Scherr
8113e5ac65 make pt-log compile 2023-09-15 17:15:09 +02:00
Christoph J. Scherr
7803195c24 restructure to workspace oriented design 2023-09-15 17:00:22 +02:00
56 changed files with 975 additions and 501 deletions

View file

@ -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"

View file

@ -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
View 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"] }

View file

@ -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);

View file

@ -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,

View 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" }

View 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)
);
}
}
};
}

View 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!()
}
}
}

View 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;

View file

@ -0,0 +1,7 @@
use pt_bintols::*;
#[test]
fn mkdmp() {
let v = vec![true, true, false];
investigate_memory_layout!(bool, v);
}

View 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
View 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" }

View file

@ -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 ////////////////////////////////////////////////////////////////////////////////

View file

@ -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 /////////////////////////////////////////////////////////////////////////////////////////

View file

@ -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())
} }

View 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]

View file

@ -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 ///////////////////////////////////////////////////////////////////////////////////////

View file

@ -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 /////////////////////////////////////////////////////////////////////////////

View 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]

View 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
View 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"

View file

@ -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 /////////////////////////////////////////////////////////////////////////////

View file

@ -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 /////////////////////////////////////////////////////////////////////////////

View 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]

View file

@ -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
View 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"

View file

@ -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.

View file

@ -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
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,76 @@
# pt / libpt
![pt-logo](data/media/pt-logo.svg)
`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**

View file

@ -0,0 +1 @@
python -m unittest discover -fs tests/python

101
members/pt-py/src/lib.rs Normal file
View 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(())
}

View file

@ -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(())
}

View file

@ -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 /////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

View file

View file

@ -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())
}

View file

@ -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()

View file

@ -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()

View file

@ -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");
}