Compare commits

..

No commits in common. "1bdef8c4932e6891949a994785f5adf990c93cce" and "f8f88e79c301fc0182704116f8066c6913de8d57" have entirely different histories.

56 changed files with 503 additions and 977 deletions

View file

@ -1,30 +1,9 @@
[workspace] [package]
resolver = "2" name = "libpt"
members = [ version = "0.1.6"
".",
"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 = "MIT" license = "GPL-3.0-or-later"
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"
@ -32,47 +11,39 @@ 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"]
[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]
name = "libpt"
crate-type = [
"dylib", # .dll, .so, .dynlib
"staticlib" # .lib, .a
]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "pt"
crate-type = ["cdylib", "rlib"]
[[bin]]
name = "pt"
path = "src/bin/main/mod.rs"
[[bin]]
name = "ccc"
path = "src/bin/ccc/mod.rs"
[dependencies] [dependencies]
pt-bintols = { version = "0.1.0", path = "members/pt-bintols" } clap = { version = "4.3.11", features = ["derive"] }
pt-core = { version = "0.1.0", path = "members/pt-core" } clap-num = "1.0.2"
pt-hedu = { version = "0.1.0", path = "members/pt-hedu" } clap-verbosity-flag = "2.0.1"
pt-log = { version = "0.1.0", path = "members/pt-log" } env_logger = "0.10.0"
pt-math = { version = "0.1.0", path = "members/pt-math" } humantime = "2.1.0"
pt-net = { version = "0.1.0", path = "members/pt-net" } num = "0.4.0"
pt-ccc = { version = "0.1.0", path = "members/pt-ccc" } num-traits = "0.2.16"
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,6 +9,10 @@ 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`

View file

@ -1,30 +0,0 @@
[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

@ -1,20 +0,0 @@
[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

@ -1,41 +0,0 @@
//* # 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

@ -1,67 +0,0 @@
//* # 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

@ -1,27 +0,0 @@
//* # 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

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

View file

@ -1,63 +0,0 @@
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"));
}

View file

@ -1,22 +0,0 @@
[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

@ -1,15 +0,0 @@
[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,17 +0,0 @@
[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

@ -1,6 +0,0 @@
//! # 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.

View file

@ -1,22 +0,0 @@
[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,17 +0,0 @@
[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,24 +0,0 @@
[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,120 +0,0 @@
# 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 *

View file

@ -1,72 +0,0 @@
/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

View file

@ -1,22 +0,0 @@
[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 = "../../" }

View file

@ -1,21 +0,0 @@
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.

View file

@ -1,76 +0,0 @@
# 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

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

View file

@ -1,101 +0,0 @@
// 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

@ -15,10 +15,11 @@
#![warn(clippy::pedantic)] #![warn(clippy::pedantic)]
//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// //// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
use libpt::ccc::*; use pt::math::calculator::{*, self};
use libpt::log::*; use pt::logger::*;
use clap::Parser; use clap::{Parser, Subcommand};
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;
@ -41,7 +42,6 @@ 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: Level = match cli.verbose.log_level().unwrap().as_str() { let ll: tracing::Level = match cli.verbose.log_level().unwrap().as_str() {
"TRACE" => Level::TRACE, "TRACE" => tracing::Level::TRACE,
"DEBUG" => Level::DEBUG, "DEBUG" => tracing::Level::DEBUG,
"INFO" => Level::INFO, "INFO" => tracing::Level::INFO,
"WARN" => Level::WARN, "WARN" => tracing::Level::WARN,
"ERROR" => Level::ERROR, "ERROR" => tracing::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,7 +15,11 @@
//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// //// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
use libpt::{log::*, net::monitoring::uptime}; use pt::{logger, networking::monitoring::uptime, common::*};
// we want the log macros in any case
#[allow(unused_imports)]
use tracing::{debug, error, info, trace, warn};
use clap::Parser; use clap::Parser;
@ -41,19 +45,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: Level = match cli.verbose.log_level().unwrap().as_str() { let ll: tracing::Level = match cli.verbose.log_level().unwrap().as_str() {
"TRACE" => Level::TRACE, "TRACE" => tracing::Level::TRACE,
"DEBUG" => Level::DEBUG, "DEBUG" => tracing::Level::DEBUG,
"INFO" => Level::INFO, "INFO" => tracing::Level::INFO,
"WARN" => Level::WARN, "WARN" => tracing::Level::WARN,
"ERROR" => Level::ERROR, "ERROR" => tracing::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(EXIT_FAILURE_USAGE);
} }
}; };
if cli.log_meta { if cli.log_meta {
Logger::init_customized( logger::Logger::init_customized(
false, false,
PathBuf::from("/dev/null"), PathBuf::from("/dev/null"),
true, true,
@ -68,7 +72,7 @@ pub fn main() {
.expect("could not initialize Logger"); .expect("could not initialize Logger");
} else { } else {
// less verbose version // less verbose version
Logger::init_customized( logger::Logger::init_customized(
false, false,
PathBuf::from("/dev/null"), PathBuf::from("/dev/null"),
true, true,

View file

@ -1,10 +1,7 @@
//! # common functionalities //! # common functionalities
//! //!
//! This crate is part of [`pt`](../libpt/index.html), but can also be used as a standalone //! This module implements common functionality useful for many use cases, such as macros,
//! module. //! Formatting functions and more.
//!
//! 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
@ -26,6 +23,8 @@ 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,6 +14,8 @@
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 /////////////////////////////////////////////////////////////////////////////////////
@ -45,5 +47,17 @@ 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

@ -1,22 +1,129 @@
//! # A library for common needs //! # `libpt`
//! //!
//! `pt` aims to implement a number of functionalities that might me useful to develop //! [`libpt`](crate) contains my personal code. It is compiled as all of the following:
//! programs in Rust. It aims to be a collection of generally, possibly useful things.
//! //!
//! `pt` is a project consisting of multiple smaller crates, all bundled together in this //! - dynamic library (`cdylib`, `.so` file on Linux)
//! "main crate". Most crates will only show up if you activate their feature. //! - rust library crate (`rlib`, usable as )
//! - 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).
#[cfg(feature = "core")] //// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
pub use pt_core as core; // we want docs
#[cfg(feature = "bintols")] #![warn(missing_docs)]
pub use pt_bintols as bintols; #![warn(rustdoc::missing_crate_level_docs)]
#[cfg(feature = "hedu")] // we want Debug everywhere. This is a library and there will be many bugs.
pub use pt_hedu as hedu; #![warn(missing_debug_implementations)]
#[cfg(feature = "log")] // enable clippy's extra lints, the pedantic version
pub use pt_log as log; #![warn(clippy::pedantic)]
#[cfg(feature = "math")]
pub use pt_math as math; //// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "net")] /// contains useful code, such as macros, for general use
pub use pt_net as net; pub mod common;
#[cfg(feature = "ccc")] /// logger used by libpt
pub use pt_ccc as ccc; pub mod logger;
/// networking tools
pub mod networking;
/// math tools
pub mod math;
use crate::logger::Logger;
use pyo3::prelude::*;
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
/// ## Check if [`libpt`](crate) has been loaded
///
/// Always returns `true` if you can execute it.
#[pyfunction]
pub fn is_loaded() -> bool {
true
}
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
/// ## Python module: logger
#[pymodule]
fn py_logger(py: Python, parent: &PyModule) -> PyResult<()> {
let module = PyModule::new(py, "logger")?;
module.add_class::<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,6 +1,12 @@
//! # Error module for [`pt-log`](crate) //! # very short description
//! //!
//! This module handles errors in logging contexts. //! Short description
//!
//! Details
//!
//! ## Section 1
//!
//! ## Section 2
//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// //// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
// we want docs // we want docs
@ -16,7 +22,7 @@ use pyo3::{exceptions::PyException, PyErr};
use tracing::subscriber::SetGlobalDefaultError; use tracing::subscriber::SetGlobalDefaultError;
//// TYPES ///////////////////////////////////////////////////////////////////////////////////////// //// TYPES /////////////////////////////////////////////////////////////////////////////////////////
/// a quick alias for a result with a [`Error`] /// a quick alias for a result with a [`LoggerError`]
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////// //// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
@ -26,7 +32,7 @@ pub type Result<T> = std::result::Result<T, Error>;
//// MACROS //////////////////////////////////////////////////////////////////////////////////////// //// MACROS ////////////////////////////////////////////////////////////////////////////////////////
//// ENUMS ///////////////////////////////////////////////////////////////////////////////////////// //// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
/// ## Errors for the [Logger](super::Logger) /// ## Errors for the [logger](crate::logger)
pub enum Error { pub enum Error {
/// Bad IO operation /// Bad IO operation
IO(std::io::Error), IO(std::io::Error),
@ -90,4 +96,3 @@ impl std::fmt::Display for Error {
//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// //// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// //// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////

View file

@ -1,18 +1,14 @@
//! # A specialized Logger for [`pt`](../libpt/index.html) //! # A specialized Logger for [`pt`](crate)
//! //!
//! This crate is part of [`pt`](../libpt/index.html), but can also be used as a standalone //! For the library version, only the basic [`log`] is used, so that it is possible for
//! module. //! the end user to use the [`log`] frontend they desire.
//!
//! 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`](../libpt/index.html), but is still just as usable in other contexts. //! with the python module of [`pt`](crate), but is still just as usable in other contexts.
//! //!
//! ## Technologies used for logging: //! ## Technologies used for logging:
//! - [`tracing`]: base logging crate //! - [`log`]: base logging crate
//! - [`tracing_appender`]: Used to log to files //! - [`env_logger`]: used for the executable
//! - [`tracing_subscriber`]: Used to do actual logging, formatting, to stdout
//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// //// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
@ -43,10 +39,21 @@ 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`](../libpt/index.html) /// ## Logger for [`pt`](crate)
/// ///
/// 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 {}
@ -64,7 +71,7 @@ impl Logger {
/// ///
/// Will enable the logger to be used. /// Will enable the logger to be used.
/// ///
/// Assumes some defaults, use [`init_customized`](Self::init_customized) for more control /// Assumes some defaults, use [`init_customized`](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(),
@ -100,7 +107,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
@ -147,35 +154,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,
@ -241,7 +248,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,
@ -254,4 +261,3 @@ impl fmt::Debug for Logger {
//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// //// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// //// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////

View file

@ -15,13 +15,7 @@
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 /////////////////////////////////////////////////////////////////////////////////////
@ -75,54 +69,38 @@ 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,8 +1,5 @@
//! # 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
@ -25,9 +22,7 @@ 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 pt_log::*; use crate::logger::{trace, debug, info, warn, error};
#[allow(unused_imports)] // import more complex math stuff from there
use pt_math;
//// TYPES ///////////////////////////////////////////////////////////////////////////////////////// //// TYPES /////////////////////////////////////////////////////////////////////////////////////////

View file

@ -21,10 +21,7 @@ use std::collections::VecDeque;
//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// //// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
pub use super::{Error, Result, Value, base::{self, *}}; pub use super::{Error, Result, Value, base::{self, *}};
#[allow(unused_imports)] // we possibly want to use all log levels use crate::logger::*;
use pt_log::*;
#[allow(unused_imports)] // import more complex math stuff from there
use pt_math;
//// TYPES ///////////////////////////////////////////////////////////////////////////////////////// //// TYPES /////////////////////////////////////////////////////////////////////////////////////////
@ -44,14 +41,11 @@ use pt_math;
#[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 ///////////////////////////////////////////////////////////////////////////////////////
@ -71,7 +65,6 @@ 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>
} }
@ -99,9 +92,9 @@ impl Term {
self.text = Self::filter(&self.original)?; self.text = Self::filter(&self.original)?;
// Storage for unfinished tokens // Storage for unfinished tokens
let _unfinished_chars: Vec<char> = Vec::new(); let mut 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
@ -128,8 +121,7 @@ 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.
#[allow(unused)] // tmp fn to_tok(s: Vec<char>) -> Result<Token> {
fn to_tok(_s: Vec<char>) -> Result<Token> {
Ok(19.into()) Ok(19.into())
} }

View file

@ -1,9 +1,12 @@
//! # General Mathmatics functionalities //! # very short description
//! //!
//! This crate is part of [`pt`](../libpt/index.html), but can also be used as a standalone //! Short description
//! module.
//! //!
//! This module is currently empty, but will contain many math functionalities in a future version. //! Details
//!
//! ## Section 1
//!
//! ## Section 2
//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// //// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
// we want docs // we want docs
@ -15,6 +18,7 @@
#![warn(clippy::pedantic)] #![warn(clippy::pedantic)]
//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// //// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
pub mod calculator;
//// TYPES ///////////////////////////////////////////////////////////////////////////////////////// //// TYPES /////////////////////////////////////////////////////////////////////////////////////////

View file

@ -1,8 +1,5 @@
//! # 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,17 +19,19 @@
use std::{fmt, time::Duration}; use std::{fmt, time::Duration};
//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// //// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
use pt_log::*; use crate::logger::*;
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 pt_core::divider; use crate::divider;
//// TYPES ///////////////////////////////////////////////////////////////////////////////////////// //// TYPES /////////////////////////////////////////////////////////////////////////////////////////
@ -48,20 +50,27 @@ 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,
} }
@ -137,6 +146,38 @@ 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 {
@ -220,6 +261,30 @@ 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(

40
src/template.rs Normal file
View file

@ -0,0 +1,40 @@
//! # 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 ///////////////////////////////////////////////////////////////////////////////////////
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
//// MACROS ////////////////////////////////////////////////////////////////////////////////////////
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

0
tests/bin.rs Normal file
View file

12
tests/lib.rs Normal file
View file

@ -0,0 +1,12 @@
/// # 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())
}

0
tests/python/__init__.py Normal file
View file

15
tests/python/lib.py Normal file
View file

@ -0,0 +1,15 @@
"""
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

@ -0,0 +1,21 @@
"""
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

@ -0,0 +1,88 @@
//! # 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");
}