generated from PlexSheep/baserepo
Compare commits
No commits in common. "edcec991dc1b31ac4d269acf217d3451b10e741c" and "a63262825e241003798eaca7b57ec8bcd18ac597" have entirely different histories.
edcec991dc
...
a63262825e
50 changed files with 1576 additions and 645 deletions
|
@ -1,22 +0,0 @@
|
||||||
name: Cargo Check, Format, Fix, Test and publish
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
format:
|
|
||||||
name: cargo CI
|
|
||||||
permissions:
|
|
||||||
# Give the default GITHUB_TOKEN write permission to commit and push the
|
|
||||||
# added or changed files to the repository.
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
- run: cargo check --all-features --all-targets
|
|
||||||
- run: rustup component add rustfmt
|
|
||||||
- run: cargo fix --all-features --all-targets
|
|
||||||
- run: cargo fmt --all
|
|
||||||
- run: cargo test --all-features --all-targets
|
|
||||||
- run: cargo publish --index "https://git.cscherr.de/PlexSheep/_cargo-index.git --dry-run
|
|
|
@ -1,27 +0,0 @@
|
||||||
name: Cargo Check, Format, Fix and Test
|
|
||||||
on: [push, pull_request]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
format:
|
|
||||||
name: cargo CI
|
|
||||||
permissions:
|
|
||||||
# Give the default GITHUB_TOKEN write permission to commit and push the
|
|
||||||
# added or changed files to the repository.
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
- run: cargo check --all-features --all-targets
|
|
||||||
- run: rustup component add rustfmt
|
|
||||||
- run: cargo fix --all-features --all-targets
|
|
||||||
- run: cargo fmt --all
|
|
||||||
- run: cargo test --all-features --all-targets
|
|
||||||
- uses: stefanzweifel/git-auto-commit-action@v5
|
|
||||||
with:
|
|
||||||
# Optional. Commit message for the created commit.
|
|
||||||
# Defaults to "Apply automatic changes"
|
|
||||||
commit_message: automatic cargo CI changes
|
|
||||||
commit_user_name: Gitea CI
|
|
||||||
commit_user_email: noreply@cscherr.de
|
|
||||||
commit_author: Gitea CI <noreply@cscherr.de>
|
|
||||||
|
|
120
.github/workflows/CI.yml
vendored
Normal file
120
.github/workflows/CI.yml
vendored
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
# This file is autogenerated by maturin v0.14.17
|
||||||
|
# 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 *
|
56
Cargo.toml
56
Cargo.toml
|
@ -8,12 +8,20 @@ members = [
|
||||||
"members/libpt-bin",
|
"members/libpt-bin",
|
||||||
"members/libpt-log",
|
"members/libpt-log",
|
||||||
"members/libpt-net",
|
"members/libpt-net",
|
||||||
|
"members/libpt-py",
|
||||||
"members/libpt-hedu",
|
"members/libpt-hedu",
|
||||||
]
|
]
|
||||||
default-members = [".", "members/libpt-bin", "members/libpt-core"]
|
default-members = [
|
||||||
|
".",
|
||||||
|
"members/libpt-bin",
|
||||||
|
"members/libpt-core",
|
||||||
|
"members/libpt-py",
|
||||||
|
"members/libpt-log",
|
||||||
|
"members/libpt-math",
|
||||||
|
]
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
publish = true
|
publish = false
|
||||||
version = "0.2.4"
|
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 = "MIT"
|
||||||
|
@ -21,20 +29,15 @@ description = "Personal multitool"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
homepage = "https://git.cscherr.de/PlexSheep/libpt"
|
homepage = "https://git.cscherr.de/PlexSheep/libpt"
|
||||||
repository = "https://git.cscherr.de/PlexSheep/libpt"
|
repository = "https://git.cscherr.de/PlexSheep/libpt"
|
||||||
keywords = ["cli", "library"]
|
keywords = ["cli", "python", "scriptable", "pyo3", "library"]
|
||||||
categories = [
|
categories = ["command-line-utilities", "development-tools", "development-tools::ffi"]
|
||||||
"command-line-utilities",
|
|
||||||
"development-tools",
|
|
||||||
"development-tools::ffi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
anyhow = "1.0.79"
|
pyo3 = "0.19"
|
||||||
thiserror = "1.0.56"
|
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "libpt"
|
name = "libpt"
|
||||||
publish.workspace = true
|
publish = true
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
|
@ -47,9 +50,16 @@ keywords.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["log", "core"]
|
default = ["log"]
|
||||||
all = ["default", "math", "log", "bintols", "net", "ccc", "hedu", "core"]
|
all = [
|
||||||
core = []
|
"default",
|
||||||
|
"math",
|
||||||
|
"log",
|
||||||
|
"bintols",
|
||||||
|
"net",
|
||||||
|
"ccc",
|
||||||
|
"hedu"
|
||||||
|
]
|
||||||
fw = []
|
fw = []
|
||||||
math = []
|
math = []
|
||||||
log = []
|
log = []
|
||||||
|
@ -63,16 +73,16 @@ name = "libpt"
|
||||||
crate-type = [
|
crate-type = [
|
||||||
"dylib", # .dll, .so, .dynlib
|
"dylib", # .dll, .so, .dynlib
|
||||||
"staticlib", # .lib, .a
|
"staticlib", # .lib, .a
|
||||||
"rlib",
|
"rlib"
|
||||||
]
|
]
|
||||||
|
|
||||||
# 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
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libpt-bintols = { path = "members/libpt-bintols" }
|
libpt-bintols = { version = "0.1.7", path = "members/libpt-bintols" }
|
||||||
libpt-core = { path = "members/libpt-core" }
|
libpt-core = { version = "0.1.7", path = "members/libpt-core" }
|
||||||
libpt-hedu = { path = "members/libpt-hedu" }
|
libpt-hedu = { version = "0.1.7", path = "members/libpt-hedu" }
|
||||||
libpt-log = { path = "members/libpt-log" }
|
libpt-log = { version = "0.1.7", path = "members/libpt-log" }
|
||||||
libpt-math = { path = "members/libpt-math" }
|
libpt-math = { version = "0.1.7", path = "members/libpt-math" }
|
||||||
libpt-ccc = { path = "members/libpt-ccc" }
|
libpt-net = { version = "0.1.7", path = "members/libpt-net" }
|
||||||
libpt-net = { path = "members/libpt-net" }
|
libpt-ccc = { version = "0.1.7", path = "members/libpt-ccc" }
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -19,10 +19,6 @@ categories.workspace = true
|
||||||
name = "ccc"
|
name = "ccc"
|
||||||
path = "src/ccc/mod.rs"
|
path = "src/ccc/mod.rs"
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "hedu"
|
|
||||||
path = "src/hedu/mod.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "libpt"
|
name = "libpt"
|
||||||
path = "src/main/mod.rs"
|
path = "src/main/mod.rs"
|
||||||
|
@ -31,4 +27,4 @@ path = "src/main/mod.rs"
|
||||||
clap = { version = "4.4.4", features = ["derive"] }
|
clap = { version = "4.4.4", features = ["derive"] }
|
||||||
clap-num = "1.0.2"
|
clap-num = "1.0.2"
|
||||||
clap-verbosity-flag = "2.0.1"
|
clap-verbosity-flag = "2.0.1"
|
||||||
libpt = {path = "../..", features = ["default", "ccc", "math", "hedu", "net", "log"] }
|
libpt = { version = "0.1.7", path = "../..", features = ["ccc", "math", "hedu", "net"] }
|
||||||
|
|
|
@ -15,11 +15,13 @@
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
use libpt::ccc::*;
|
||||||
use libpt::log::*;
|
use libpt::log::*;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use clap_verbosity_flag::{InfoLevel, Verbosity};
|
use clap_verbosity_flag::{Verbosity, InfoLevel};
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -91,14 +93,49 @@ fn main() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if cli.log_meta {
|
if cli.log_meta {
|
||||||
Logger::init(None, Some(ll)).expect("could not initialize Logger");
|
Logger::init_customized(
|
||||||
|
false,
|
||||||
|
PathBuf::from("/dev/null"),
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
ll,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.expect("could not initialize Logger");
|
||||||
} else {
|
} else {
|
||||||
// less verbose version
|
// less verbose version
|
||||||
Logger::init_mini(Some(ll)).expect("could not initialize Logger");
|
Logger::init_customized(
|
||||||
|
false,
|
||||||
|
PathBuf::from("/dev/null"),
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
ll,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.expect("could not initialize Logger");
|
||||||
}
|
}
|
||||||
let mut expr: String = String::new();
|
let mut expr: String = String::new();
|
||||||
for part in cli.expression {
|
for part in cli.expression {
|
||||||
expr += ∂
|
expr += ∂
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug!("exporssion: {}", expr);
|
||||||
|
let r = Calculator::oneshot(expr);
|
||||||
|
match r {
|
||||||
|
Ok(r) => {
|
||||||
|
println!("{r}");
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
error!("Could not compute: {err}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -1,151 +0,0 @@
|
||||||
//! # Executable for the hedu submodule
|
|
||||||
//!
|
|
||||||
//! Dump data to a fancy format.
|
|
||||||
|
|
||||||
//// 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 ///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
use libpt::{hedu::*, log::*};
|
|
||||||
|
|
||||||
use clap::Parser;
|
|
||||||
use clap_verbosity_flag::{InfoLevel, Verbosity};
|
|
||||||
|
|
||||||
use std::{fs::File, io::IsTerminal};
|
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// short about section displayed in help
|
|
||||||
const ABOUT_ROOT: &'static str = r##"
|
|
||||||
Dumps data in fancy formats.
|
|
||||||
"##;
|
|
||||||
/// longer about section displayed in help, is combined with [the short help](ABOUT_ROOT)
|
|
||||||
static LONG_ABOUT_ROOT: &'static str = r##"
|
|
||||||
|
|
||||||
libpt is a personal general purpose library, offering this executable, a python module and a
|
|
||||||
dynamic library.
|
|
||||||
"##;
|
|
||||||
|
|
||||||
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// MACROS ////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// defines CLI interface
|
|
||||||
#[derive(Debug, Clone, Parser)]
|
|
||||||
#[command(
|
|
||||||
author,
|
|
||||||
version,
|
|
||||||
about = ABOUT_ROOT,
|
|
||||||
long_about = format!("{}{}", ABOUT_ROOT ,LONG_ABOUT_ROOT),
|
|
||||||
help_template =
|
|
||||||
r#"{about-section}
|
|
||||||
{usage-heading} {usage}
|
|
||||||
{all-args}{tab}
|
|
||||||
|
|
||||||
libpt: {version}
|
|
||||||
Author: {author-with-newline}
|
|
||||||
"#
|
|
||||||
)]
|
|
||||||
pub struct Cli {
|
|
||||||
// clap_verbosity_flag seems to make this a global option implicitly
|
|
||||||
/// set a verbosity, multiple allowed (f.e. -vvv)
|
|
||||||
#[command(flatten)]
|
|
||||||
pub verbose: Verbosity<InfoLevel>,
|
|
||||||
|
|
||||||
/// show additional logging meta data
|
|
||||||
#[arg(long)]
|
|
||||||
pub meta: bool,
|
|
||||||
|
|
||||||
/// show character representation
|
|
||||||
#[arg(short, long)]
|
|
||||||
pub chars: bool,
|
|
||||||
|
|
||||||
/// skip first N bytes
|
|
||||||
#[arg(short, long, default_value_t = 0)]
|
|
||||||
pub skip: usize,
|
|
||||||
|
|
||||||
/// only interpret N bytes (end after N)
|
|
||||||
#[arg(short, long, default_value_t = 0)]
|
|
||||||
pub limit: usize,
|
|
||||||
|
|
||||||
/// show identical lines
|
|
||||||
#[arg(short = 'i', long)]
|
|
||||||
pub show_identical: bool,
|
|
||||||
|
|
||||||
/// a data source, probably a file.
|
|
||||||
///
|
|
||||||
/// If left empty or set as "-", the program will read from stdin.
|
|
||||||
pub data_source: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
|
||||||
fn main() {
|
|
||||||
let cli = cli_parse();
|
|
||||||
let mut source: Box<dyn DataSource>;
|
|
||||||
if cli.data_source.is_some() && cli.data_source.clone().is_some_and(|val| val != "-") {
|
|
||||||
let data_source = cli.data_source.unwrap();
|
|
||||||
trace!("Trying to open '{}'", data_source);
|
|
||||||
source = match File::open(&data_source) {
|
|
||||||
Ok(file) => Box::new(file),
|
|
||||||
Err(err) => {
|
|
||||||
error!("Could not open file '{}': {err}", data_source);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
trace!("Trying to open stdout");
|
|
||||||
let stdin = std::io::stdin();
|
|
||||||
if stdin.is_terminal() {
|
|
||||||
warn!("Refusing to dump from interactive terminal");
|
|
||||||
std::process::exit(2)
|
|
||||||
}
|
|
||||||
source = Box::new(stdin);
|
|
||||||
}
|
|
||||||
|
|
||||||
match dump(
|
|
||||||
&mut *source,
|
|
||||||
HeduConfig::new(cli.chars, cli.skip, cli.show_identical, cli.limit),
|
|
||||||
) {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(err) => {
|
|
||||||
error!("Could not dump data of file: {err}");
|
|
||||||
std::process::exit(3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
fn cli_parse() -> Cli {
|
|
||||||
let cli = Cli::parse();
|
|
||||||
let ll: Level = match cli.verbose.log_level().unwrap().as_str() {
|
|
||||||
"TRACE" => Level::TRACE,
|
|
||||||
"DEBUG" => Level::DEBUG,
|
|
||||||
"INFO" => Level::INFO,
|
|
||||||
"WARN" => Level::WARN,
|
|
||||||
"ERROR" => Level::ERROR,
|
|
||||||
_ => {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if cli.meta {
|
|
||||||
Logger::init(None, Some(ll)).expect("could not initialize Logger");
|
|
||||||
} else {
|
|
||||||
// less verbose version
|
|
||||||
Logger::init_mini(Some(ll)).expect("could not initialize Logger");
|
|
||||||
}
|
|
||||||
return cli;
|
|
||||||
}
|
|
|
@ -19,7 +19,7 @@ use clap::{Parser, Subcommand};
|
||||||
|
|
||||||
use clap_num::number_range;
|
use clap_num::number_range;
|
||||||
|
|
||||||
use clap_verbosity_flag::{InfoLevel, Verbosity};
|
use clap_verbosity_flag::{Verbosity, InfoLevel};
|
||||||
|
|
||||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// short about section displayed in help
|
/// short about section displayed in help
|
||||||
|
@ -103,10 +103,13 @@ pub enum NetCommands {
|
||||||
|
|
||||||
/// set a timeout (in ms)
|
/// set a timeout (in ms)
|
||||||
#[clap(short, long, default_value_t = 100)]
|
#[clap(short, long, default_value_t = 100)]
|
||||||
timeout: u64,
|
timeout: u64
|
||||||
|
|
||||||
},
|
},
|
||||||
/// discover hosts in your network
|
/// discover hosts in your network
|
||||||
Discover {},
|
Discover {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// enable clippy's extra lints, the pedantic version
|
// enable clippy's extra lints, the pedantic version
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
||||||
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
use libpt::{log::*, net::monitoring::uptime};
|
use libpt::{log::*, net::monitoring::uptime};
|
||||||
|
|
||||||
|
@ -21,8 +22,11 @@ use clap::Parser;
|
||||||
pub mod args;
|
pub mod args;
|
||||||
use args::*;
|
use args::*;
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
||||||
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//// MACROS ////////////////////////////////////////////////////////////////////////////////////////
|
//// MACROS ////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -49,10 +53,34 @@ pub fn main() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if cli.log_meta {
|
if cli.log_meta {
|
||||||
Logger::init(None, Some(ll)).expect("could not initialize Logger");
|
Logger::init_customized(
|
||||||
|
false,
|
||||||
|
PathBuf::from("/dev/null"),
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
ll,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.expect("could not initialize Logger");
|
||||||
} else {
|
} else {
|
||||||
// less verbose version
|
// less verbose version
|
||||||
Logger::init_mini(Some(ll)).expect("could not initialize Logger");
|
Logger::init_customized(
|
||||||
|
false,
|
||||||
|
PathBuf::from("/dev/null"),
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
ll,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.expect("could not initialize Logger");
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!("started the main function");
|
trace!("started the main function");
|
||||||
|
|
|
@ -16,5 +16,5 @@ categories.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
num-traits = "0.2.16"
|
num-traits = "0.2.16"
|
||||||
libpt-core = { path = "../libpt-core" }
|
libpt-core = { version = "0.1.0", path = "../libpt-core" }
|
||||||
libpt-log = { path = "../libpt-log" }
|
libpt-log = { version = "0.1.0", path = "../libpt-log" }
|
||||||
|
|
|
@ -20,8 +20,7 @@ macro_rules! investigate_memory_layout {
|
||||||
let pointer = item as *const $t;
|
let pointer = item as *const $t;
|
||||||
let mut memory: [u8; std::mem::size_of::<$t>()] = std::mem::transmute(item.clone());
|
let mut memory: [u8; std::mem::size_of::<$t>()] = std::mem::transmute(item.clone());
|
||||||
memory.reverse();
|
memory.reverse();
|
||||||
println!(
|
println!("\
|
||||||
"\
|
|
||||||
\t{index:02x}\titem:\t\t{item:?}\n\
|
\t{index:02x}\titem:\t\t{item:?}\n\
|
||||||
\t\tpointer: \t{:X?}\n\
|
\t\tpointer: \t{:X?}\n\
|
||||||
\t\talign: \t{}\n\
|
\t\talign: \t{}\n\
|
||||||
|
|
|
@ -59,7 +59,8 @@ where
|
||||||
return format!("{:.2} Z", total.to_f64().unwrap() / ZEBI as f64);
|
return format!("{:.2} Z", total.to_f64().unwrap() / ZEBI as f64);
|
||||||
} else if YOBI <= total {
|
} else if YOBI <= total {
|
||||||
return format!("{:.2} Y", total.to_f64().unwrap() / YOBI as f64);
|
return format!("{:.2} Y", total.to_f64().unwrap() / YOBI as f64);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use libpt_bintols::display::*;
|
|
||||||
use libpt_bintols::*;
|
use libpt_bintols::*;
|
||||||
|
use libpt_bintols::display::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn btobin() {
|
fn btobin() {
|
||||||
|
@ -12,14 +12,9 @@ fn btobin() {
|
||||||
fn big_btobin() {
|
fn big_btobin() {
|
||||||
let data = [12,31,82,32,123,32,92,23,12,32,12,1,1,1];
|
let data = [12,31,82,32,123,32,92,23,12,32,12,1,1,1];
|
||||||
let r = bytes_to_bin(&data);
|
let r = bytes_to_bin(&data);
|
||||||
assert_eq!(
|
assert_eq!(r, format!("0b00001100_00011111_01010010_\
|
||||||
r,
|
|
||||||
format!(
|
|
||||||
"0b00001100_00011111_01010010_\
|
|
||||||
00100000_01111011_00100000_01011100_00010111_00001100\n\
|
00100000_01111011_00100000_01011100_00010111_00001100\n\
|
||||||
_00100000_00001100_00000001_00000001_00000001"
|
_00100000_00001100_00000001_00000001_00000001"));
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -17,6 +17,6 @@ categories.workspace = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
num = "0.4.1"
|
num = "0.4.1"
|
||||||
num-traits = "0.2.16"
|
num-traits = "0.2.16"
|
||||||
libpt-core = { path = "../libpt-core" }
|
libpt-core = { version = "0.1.7", path = "../libpt-core" }
|
||||||
libpt-log = { path = "../libpt-log" }
|
libpt-log = { version = "0.1.7", path = "../libpt-log" }
|
||||||
libpt-math = { path = "../libpt-math" }
|
libpt-math = { version = "0.1.7", path = "../libpt-math" }
|
||||||
|
|
225
members/libpt-ccc/src/base.rs
Normal file
225
members/libpt-ccc/src/base.rs
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
//! # Results and Errors for the calculate module
|
||||||
|
//!
|
||||||
|
//! This module defines the errors and results that can be processed from any given term.
|
||||||
|
|
||||||
|
//// 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 ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
use std::fmt::Display;
|
||||||
|
pub use num_traits::PrimInt;
|
||||||
|
|
||||||
|
#[allow(unused_imports)] // we possibly want to use all log levels
|
||||||
|
use libpt_log::*;
|
||||||
|
#[allow(unused_imports)] // import more complex math stuff from there
|
||||||
|
use libpt_math;
|
||||||
|
|
||||||
|
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Quick Result with a ccc error
|
||||||
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
|
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//// MACROS ////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// ## Supported Operations
|
||||||
|
///
|
||||||
|
/// This `enum` contains all operations supported in this module.
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Operator {
|
||||||
|
/// Mathmatical addition
|
||||||
|
Addition,
|
||||||
|
/// Mathmatical subtraction
|
||||||
|
Subtraction,
|
||||||
|
/// Mathmatical multiplication
|
||||||
|
Multiplication,
|
||||||
|
/// Mathmatical division
|
||||||
|
Division,
|
||||||
|
/// Mathmatical modulo, finite field arithmetic
|
||||||
|
Modulo,
|
||||||
|
/// Any function, seel [`Function`]
|
||||||
|
Function(Function)
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// ## Supported Functions
|
||||||
|
///
|
||||||
|
/// This `enum` contains all functions supported in this module.
|
||||||
|
///
|
||||||
|
/// A function has a name followed by braces directly afterwards.
|
||||||
|
/// A function may have 0 to 31 Arguments.
|
||||||
|
///
|
||||||
|
/// Example: `sqrt(19)`, `floor(19.9)`
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Function {
|
||||||
|
/// Draw the mathmatical root, attribute n is the nth root
|
||||||
|
Root(u16),
|
||||||
|
/// round up
|
||||||
|
Floor,
|
||||||
|
/// round down
|
||||||
|
Ceil,
|
||||||
|
/// round to nearest integer
|
||||||
|
/// (commercial rounding)
|
||||||
|
Round,
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Top Level Error Type
|
||||||
|
///
|
||||||
|
/// Contains many variants of other errors, that can occur when using the crate.
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
/// The term has bad syntax
|
||||||
|
SyntaxError(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Represents some kind of computed value
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Value {
|
||||||
|
/// Variable value
|
||||||
|
Variable(VarVal),
|
||||||
|
/// Numerical value
|
||||||
|
Numerical(NumVal),
|
||||||
|
/// Complex number value
|
||||||
|
Complex(ComplVal),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents some kind of numeric value
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum NumVal {
|
||||||
|
/// Value > 0
|
||||||
|
Signed(i128),
|
||||||
|
/// Value can be negative
|
||||||
|
Unsigned(u128),
|
||||||
|
/// Value is not an integer
|
||||||
|
Float(f64)
|
||||||
|
}
|
||||||
|
|
||||||
|
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Represents a Value with at least one variable,
|
||||||
|
///
|
||||||
|
/// currently not implemented
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct VarVal {
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Represents a Value with a complex number,
|
||||||
|
///
|
||||||
|
/// currently not implemented
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ComplVal {
|
||||||
|
}
|
||||||
|
|
||||||
|
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
||||||
|
impl<T: num_traits::PrimInt> From<T> for NumVal where
|
||||||
|
u128: TryFrom<T>,
|
||||||
|
u128: TryFrom<T> {
|
||||||
|
fn from(value: T) -> Self {
|
||||||
|
if T::min_value().is_zero() {
|
||||||
|
// unsigned data types
|
||||||
|
// `u128` is the largest unsigned datatype, any other type will fit.
|
||||||
|
NumVal::Unsigned(value.to_u128().unwrap())
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// signed data types
|
||||||
|
// `i128` is the largest unsigned datatype, any other type will fit.
|
||||||
|
NumVal::Signed(value.to_i128().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Display Errors with a nice little reason
|
||||||
|
impl Display for Error {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::SyntaxError(reason) => {
|
||||||
|
write!(f, "Syntax Error: {}", reason)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
impl<T: PrimInt> From<T> for Value where
|
||||||
|
u128: TryFrom<T>,
|
||||||
|
u128: TryFrom<T> {
|
||||||
|
fn from(value: T) -> Self {
|
||||||
|
NumVal::from(value).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
impl From<NumVal> for Value {
|
||||||
|
fn from(value: NumVal) -> Self {
|
||||||
|
Value::Numerical(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
impl Display for Value {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Value::Numerical(val) => {
|
||||||
|
write!(f, "{}", val)
|
||||||
|
}
|
||||||
|
Value::Complex(val) => {
|
||||||
|
write!(f, "{}", val)
|
||||||
|
}
|
||||||
|
Value::Variable(val) => {
|
||||||
|
write!(f, "{}", val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
impl Display for NumVal {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
NumVal::Float(val) => {
|
||||||
|
write!(f, "{val}")
|
||||||
|
}
|
||||||
|
NumVal::Signed(val) => {
|
||||||
|
write!(f, "{val}")
|
||||||
|
}
|
||||||
|
NumVal::Unsigned(val) => {
|
||||||
|
write!(f, "{val}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
impl Display for ComplVal {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
impl Display for VarVal {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
@ -19,7 +19,14 @@
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
use libpt_log;
|
pub mod base;
|
||||||
|
pub use base::{Error, Result, Value};
|
||||||
|
pub mod term;
|
||||||
|
pub use term::*;
|
||||||
|
|
||||||
|
#[allow(unused_imports)] // we possibly want to use all log levels
|
||||||
|
use libpt_log::*;
|
||||||
|
#[allow(unused_imports)] // import more complex math stuff from there
|
||||||
use libpt_math;
|
use libpt_math;
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -33,8 +40,44 @@ use libpt_math;
|
||||||
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// ## A Calculator struct
|
||||||
|
///
|
||||||
|
/// This struct does not do anything at the moment, but aims to be the target for high level
|
||||||
|
/// control. Instead of using the [`Calculator`], you could just use the [`Term`] struct for
|
||||||
|
/// lower level control.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Calculator;
|
||||||
|
|
||||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
||||||
|
impl Calculator {
|
||||||
|
/// Do a single calculation without doing anything else
|
||||||
|
pub fn oneshot(t: String) -> Result<Value> {
|
||||||
|
trace!(orig=t, "parsing original string to Term");
|
||||||
|
let t = Term::new(t)?;
|
||||||
|
trace!("term has been parsed, starting Calculation");
|
||||||
|
debug!("parsed term: {t:#?}");
|
||||||
|
Self::calc(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ## Calculate a [`Term`]
|
||||||
|
///
|
||||||
|
/// This method makes use of the
|
||||||
|
/// [shunting yard algorithm](https://en.wikipedia.org/wiki/Shunting_yard_algorithm) to
|
||||||
|
/// Calculate the final value of any term.
|
||||||
|
///
|
||||||
|
/// This method only processes a single term at a time, without caching.
|
||||||
|
pub fn calc(mut t: Term) -> Result<Value> {
|
||||||
|
trace!("Calculating term {t:?}");
|
||||||
|
t.prepare()?;
|
||||||
|
t.process()?;
|
||||||
|
if t.result.is_none() {
|
||||||
|
let reason = format!("Term was processed but no result was assigned.");
|
||||||
|
// FIXME: unfitting error type
|
||||||
|
return Err(Error::SyntaxError(reason))
|
||||||
|
}
|
||||||
|
return t.result.unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
223
members/libpt-ccc/src/term.rs
Normal file
223
members/libpt-ccc/src/term.rs
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
//! # A term that can be the input for calculation
|
||||||
|
//!
|
||||||
|
//! 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)]
|
||||||
|
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
pub use super::{Error, Result, Value, base::{self, *}};
|
||||||
|
#[allow(unused_imports)] // we possibly want to use all log levels
|
||||||
|
use libpt_log::*;
|
||||||
|
#[allow(unused_imports)] // import more complex math stuff from there
|
||||||
|
use libpt_math;
|
||||||
|
|
||||||
|
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//// MACROS ////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// ## Parsed value to be calculated
|
||||||
|
///
|
||||||
|
/// This enum represents anything that goes to the output queue of [`Term::prepare()`] and will
|
||||||
|
/// then be used to actually calculate something in [`Term::process()`].
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Token {
|
||||||
|
/// Some kind of operator
|
||||||
|
#[allow(unused)] // tmp
|
||||||
|
Operator(Operator),
|
||||||
|
/// A concrete value that we can calculate something with. May be a constant, integer, float,
|
||||||
|
/// etc.
|
||||||
|
/// The Token has a value that can be used in calculation
|
||||||
|
Value(super::base::Value),
|
||||||
|
/// A variable of some kind that will be present in the result
|
||||||
|
#[allow(unused)] // tmp
|
||||||
|
Variable(char),
|
||||||
|
}
|
||||||
|
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// ## Term that can be calculated
|
||||||
|
///
|
||||||
|
/// Represents a signular term, that can be calculated. Terms will be evaluated by the [`Term::prepare`]
|
||||||
|
/// function, afterwards calculated (as much as possible) in the [`Term::process`] function.
|
||||||
|
///
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Term {
|
||||||
|
/// the original expression to calculate
|
||||||
|
pub original: String,
|
||||||
|
/// the filtered text of the expression, only with relevant information
|
||||||
|
pub text: String,
|
||||||
|
/// the calculated result, may be of diffrent types, see [`crate::math::calculator::result`].
|
||||||
|
pub result: Option<Result<Value>>,
|
||||||
|
/////////////////////////////////////
|
||||||
|
///// internal values following /////
|
||||||
|
/////////////////////////////////////
|
||||||
|
#[allow(unused)] // tmp
|
||||||
|
operator_stack: Vec<Operator>,
|
||||||
|
output_queue: VecDeque<Token>
|
||||||
|
}
|
||||||
|
|
||||||
|
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
||||||
|
impl Term {
|
||||||
|
/// Build a new term from an expression
|
||||||
|
///
|
||||||
|
/// Invalid terms will result in an [`Err`].
|
||||||
|
pub fn new(orig: String) -> Result<Term> {
|
||||||
|
return Ok(
|
||||||
|
Term {
|
||||||
|
original: orig,
|
||||||
|
text: String::new(), // will be initialized in `prepare()`
|
||||||
|
result: None,
|
||||||
|
operator_stack: Vec::new(),
|
||||||
|
output_queue: VecDeque::new()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Prepare the term for the processing.
|
||||||
|
pub fn prepare(&mut self) -> Result<()> {
|
||||||
|
trace!("preparing term: {:#?}", self);
|
||||||
|
self.text = Self::filter(&self.original)?;
|
||||||
|
|
||||||
|
// Storage for unfinished tokens
|
||||||
|
let _unfinished_chars: Vec<char> = Vec::new();
|
||||||
|
|
||||||
|
for (_index, c) in self.original.chars().enumerate() {
|
||||||
|
// this will be a mess, but it has to be before i can sort the mess.
|
||||||
|
match c {
|
||||||
|
// TODO: make function to check if character is an operator, use it
|
||||||
|
_ => {
|
||||||
|
let reason = format!("The meaning of '{c}' could not be identified.");
|
||||||
|
warn!(reason);
|
||||||
|
return Err(Error::SyntaxError(reason));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Process a prepared term, calculating it's result
|
||||||
|
pub fn process(&mut self) -> Result<()> {
|
||||||
|
debug!("processing term: {:#?}", self);
|
||||||
|
debug!("queue: {:#?}", self.output_queue);
|
||||||
|
// TODO: process RPN and set result
|
||||||
|
self.result = Some(Ok(19.into()));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a character into a token
|
||||||
|
///
|
||||||
|
/// 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.
|
||||||
|
#[allow(unused)] // tmp
|
||||||
|
fn to_tok(_s: Vec<char>) -> Result<Token> {
|
||||||
|
Ok(19.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// only leave relevant chars for calculation
|
||||||
|
// TODO: make function to check if character is an operator, use it
|
||||||
|
fn filter(s: &str) -> Result<String> {
|
||||||
|
// pre checks
|
||||||
|
// NOTE: Apperently, "alphanumeric" in Rust is a pretty broad term.
|
||||||
|
// Even CJK characters or Japanese Kana are allowed:
|
||||||
|
// - 'さ' alphanumeric
|
||||||
|
// - '数' alphanumeric
|
||||||
|
// - '学' alphanumeric
|
||||||
|
// - '+' not alphanumeric
|
||||||
|
for c in s.chars() {
|
||||||
|
#[cfg(debug_assertions)] {
|
||||||
|
debug!("filter checks for '{c}':
|
||||||
|
alphanumeric: {}
|
||||||
|
allowed special: {}
|
||||||
|
EXCEPT IF
|
||||||
|
ascii control: {}
|
||||||
|
",
|
||||||
|
!c.is_alphanumeric(),
|
||||||
|
!Self::is_allowed_special_c(&c),
|
||||||
|
c.is_ascii_control(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if
|
||||||
|
(
|
||||||
|
!c.is_alphanumeric() ||
|
||||||
|
!Self::is_allowed_special_c(&c)
|
||||||
|
)
|
||||||
|
&&
|
||||||
|
(
|
||||||
|
c.is_ascii_control()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// TODO: allow any unicode char to be a variable
|
||||||
|
let reason = format!("'{c}' is not a valid character, only alphanumeric, punctuation, operators are allowed.");
|
||||||
|
warn!(reason);
|
||||||
|
return Err(Error::SyntaxError(reason));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter out single chars
|
||||||
|
let mut filtered = String::new();
|
||||||
|
for c in s.chars() {
|
||||||
|
if !Self::is_ignore(&c) {
|
||||||
|
filtered.push(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(filtered)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// check if we should ignore this character
|
||||||
|
fn is_ignore(c: &char) -> bool {
|
||||||
|
match *c {
|
||||||
|
' ' => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// allowed special chars
|
||||||
|
fn is_allowed_special_c(c: &char) -> bool {
|
||||||
|
match *c {
|
||||||
|
'+' | '-' | '*' | '/' | '%' => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Helper methods for Tokens
|
||||||
|
impl Token { }
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
impl<T> From<T> for Token where
|
||||||
|
T: Into<Value>,
|
||||||
|
T: PrimInt,
|
||||||
|
u128: TryFrom<T>
|
||||||
|
{
|
||||||
|
fn from(value: T) -> Self {
|
||||||
|
Token::Value(base::Value::from(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
@ -13,6 +13,3 @@ keywords.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.79"
|
|
||||||
cucumber = "0.20.2"
|
|
||||||
libpt-log = {path = "../libpt-log" }
|
|
||||||
|
|
|
@ -10,9 +10,11 @@
|
||||||
// we want docs
|
// we want docs
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
#![warn(rustdoc::missing_crate_level_docs)]
|
#![warn(rustdoc::missing_crate_level_docs)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// we want Debug everywhere.
|
// we want Debug everywhere.
|
||||||
#![warn(missing_debug_implementations)]
|
#![warn(missing_debug_implementations)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// enable clippy's extra lints, the pedantic version
|
// enable clippy's extra lints, the pedantic version
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
|
@ -6,9 +6,11 @@
|
||||||
// we want docs
|
// we want docs
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
#![warn(rustdoc::missing_crate_level_docs)]
|
#![warn(rustdoc::missing_crate_level_docs)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// we want Debug everywhere.
|
// we want Debug everywhere.
|
||||||
#![warn(missing_debug_implementations)]
|
#![warn(missing_debug_implementations)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// enable clippy's extra lints, the pedantic version
|
// enable clippy's extra lints, the pedantic version
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
|
@ -15,7 +15,3 @@ categories.workspace = true
|
||||||
# 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
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = { workspace = true }
|
|
||||||
thiserror = { workspace = true }
|
|
||||||
libpt-log = {path = "../libpt-log" }
|
|
||||||
libpt-bintols = {path = "../libpt-bintols" }
|
|
||||||
|
|
|
@ -4,175 +4,3 @@
|
||||||
//! module.
|
//! module.
|
||||||
//!
|
//!
|
||||||
//! This crate is currently empty.
|
//! This crate is currently empty.
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
|
||||||
use libpt_bintols::display::{bytes_to_bin, humanbytes};
|
|
||||||
use libpt_log::{debug, error, info, trace, warn};
|
|
||||||
use std::io::{prelude::*, BufReader, Read, SeekFrom};
|
|
||||||
|
|
||||||
const BYTES_PER_LINE: usize = 16;
|
|
||||||
const LINE_SEP_HORIZ: char = '─';
|
|
||||||
const LINE_SEP_VERT: char = '│';
|
|
||||||
|
|
||||||
pub struct HeduConfig {
|
|
||||||
pub chars: bool,
|
|
||||||
pub skip: usize,
|
|
||||||
pub show_identical: bool,
|
|
||||||
pub limit: usize,
|
|
||||||
stop: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HeduConfig {
|
|
||||||
pub fn new(chars: bool, skip: usize, show_identical: bool, limit: usize) -> Self {
|
|
||||||
HeduConfig {
|
|
||||||
chars,
|
|
||||||
skip,
|
|
||||||
show_identical,
|
|
||||||
limit: limit,
|
|
||||||
stop: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait DataSource: Read {
|
|
||||||
fn skip(&mut self, length: usize) -> std::io::Result<()>;
|
|
||||||
}
|
|
||||||
impl DataSource for std::io::Stdin {
|
|
||||||
fn skip(&mut self, _length: usize) -> std::io::Result<()> {
|
|
||||||
warn!("can't skip bytes for the stdin!");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl DataSource for std::fs::File {
|
|
||||||
fn skip(&mut self, length: usize) -> std::io::Result<()> {
|
|
||||||
self.seek(SeekFrom::Current(length as i64))?;
|
|
||||||
// returns the new position from the start, we don't need it here.
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dump(data: &mut dyn DataSource, mut config: HeduConfig) -> Result<()> {
|
|
||||||
// prepare some variables
|
|
||||||
let mut buf: [[u8; BYTES_PER_LINE]; 2] = [[0; BYTES_PER_LINE]; 2];
|
|
||||||
let mut alt_buf = 0usize;
|
|
||||||
let mut byte_counter: usize = 0;
|
|
||||||
let mut len: usize;
|
|
||||||
|
|
||||||
// skip a given number of bytes
|
|
||||||
if config.skip > 0 {
|
|
||||||
data.skip(config.skip)?;
|
|
||||||
byte_counter += config.skip;
|
|
||||||
debug!("Skipped {}", humanbytes(config.skip));
|
|
||||||
}
|
|
||||||
|
|
||||||
// print the head
|
|
||||||
print!("DATA IDX {LINE_SEP_VERT} DATA AS HEX");
|
|
||||||
if config.chars {
|
|
||||||
print!("{:width$} {LINE_SEP_VERT} FOO", "", width = 37);
|
|
||||||
}
|
|
||||||
println!();
|
|
||||||
if config.chars {
|
|
||||||
println!("{}", format!("{LINE_SEP_HORIZ}").repeat(80));
|
|
||||||
} else {
|
|
||||||
println!("{}", format!("{LINE_SEP_HORIZ}").repeat(59));
|
|
||||||
}
|
|
||||||
|
|
||||||
// data dump loop
|
|
||||||
len = rd_data(data, &mut buf, &mut alt_buf, &mut byte_counter, &mut config).unwrap();
|
|
||||||
while len > 0 {
|
|
||||||
print!("{:08X} {LINE_SEP_VERT} ", byte_counter);
|
|
||||||
for i in 0..len {
|
|
||||||
if i as usize % BYTES_PER_LINE == BYTES_PER_LINE / 2 {
|
|
||||||
print!(" ");
|
|
||||||
}
|
|
||||||
print!("{:02X} ", buf[alt_buf][i]);
|
|
||||||
}
|
|
||||||
if len == BYTES_PER_LINE / 2 {
|
|
||||||
print!(" ")
|
|
||||||
}
|
|
||||||
for i in 0..(BYTES_PER_LINE - len) {
|
|
||||||
if i as usize % BYTES_PER_LINE == BYTES_PER_LINE / 2 {
|
|
||||||
print!(" ");
|
|
||||||
}
|
|
||||||
print!(" ");
|
|
||||||
}
|
|
||||||
if config.chars {
|
|
||||||
print!("{LINE_SEP_VERT} |");
|
|
||||||
for i in 0..len {
|
|
||||||
print!("{}", mask_chars(buf[alt_buf][i] as char));
|
|
||||||
}
|
|
||||||
print!("|");
|
|
||||||
}
|
|
||||||
println!();
|
|
||||||
|
|
||||||
// loop breaker logic
|
|
||||||
if config.stop {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// after line logic
|
|
||||||
len = rd_data(data, &mut buf, &mut alt_buf, &mut byte_counter, &mut config).unwrap();
|
|
||||||
alt_buf ^= 1; // toggle the alt buf
|
|
||||||
if buf[0] == buf[1] && len == BYTES_PER_LINE && !config.show_identical {
|
|
||||||
trace!(buf = format!("{:?}", buf), "found a duplicating line");
|
|
||||||
let start_line = byte_counter;
|
|
||||||
while buf[0] == buf[1] && len == BYTES_PER_LINE {
|
|
||||||
len =
|
|
||||||
rd_data(data, &mut buf, &mut alt_buf, &mut byte_counter, &mut config).unwrap();
|
|
||||||
byte_counter += BYTES_PER_LINE;
|
|
||||||
}
|
|
||||||
println!(
|
|
||||||
"^^^^^^^^ {LINE_SEP_VERT} (repeats {} lines)",
|
|
||||||
byte_counter - start_line
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// switch to the second half of the buf, the original half is stored the old buffer
|
|
||||||
// We detect duplicate lines with this
|
|
||||||
alt_buf ^= 1; // toggle the alt buf
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mask_chars(c: char) -> char {
|
|
||||||
if c.is_ascii_graphic() {
|
|
||||||
return c;
|
|
||||||
} else if c == '\n' {
|
|
||||||
return '↩';
|
|
||||||
} else if c == ' ' {
|
|
||||||
return '␣';
|
|
||||||
} else if c == '\t' {
|
|
||||||
return '⭾';
|
|
||||||
} else {
|
|
||||||
return '<27>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rd_data(
|
|
||||||
data: &mut dyn DataSource,
|
|
||||||
buf: &mut [[u8; BYTES_PER_LINE]; 2],
|
|
||||||
alt_buf: &mut usize,
|
|
||||||
byte_counter: &mut usize,
|
|
||||||
config: &mut HeduConfig,
|
|
||||||
) -> Result<usize> {
|
|
||||||
match data.read(&mut buf[*alt_buf]) {
|
|
||||||
Ok(mut len) => {
|
|
||||||
*byte_counter += len; // FIXME: incremented too early! dump always starts at 0x10
|
|
||||||
if config.limit != 0 && *byte_counter >= config.limit {
|
|
||||||
trace!(
|
|
||||||
byte_counter,
|
|
||||||
limit = config.limit,
|
|
||||||
len,
|
|
||||||
nlen = (config.limit % BYTES_PER_LINE),
|
|
||||||
"byte counter is farther than limit"
|
|
||||||
);
|
|
||||||
len = config.limit % BYTES_PER_LINE;
|
|
||||||
config.stop = true;
|
|
||||||
}
|
|
||||||
return Ok(len);
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
error!("error while reading data: {err}");
|
|
||||||
bail!(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,8 +16,7 @@ categories.workspace = true
|
||||||
tracing = "0.1.37"
|
tracing = "0.1.37"
|
||||||
tracing-appender = "0.2.2"
|
tracing-appender = "0.2.2"
|
||||||
tracing-subscriber = "0.3.17"
|
tracing-subscriber = "0.3.17"
|
||||||
anyhow = { workspace = true }
|
pyo3 = {workspace = true}
|
||||||
thiserror = { workspace = true }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
gag = "1.0.0"
|
gag = "1.0.0"
|
||||||
|
|
|
@ -12,11 +12,12 @@
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
use anyhow;
|
use pyo3::{exceptions::PyException, PyErr};
|
||||||
use thiserror::Error;
|
|
||||||
use tracing::subscriber::SetGlobalDefaultError;
|
use tracing::subscriber::SetGlobalDefaultError;
|
||||||
|
|
||||||
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
//// TYPES /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// a quick alias for a result with a [`Error`]
|
||||||
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -26,16 +27,12 @@ use tracing::subscriber::SetGlobalDefaultError;
|
||||||
|
|
||||||
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// ## Errors for the [Logger](super::Logger)
|
/// ## Errors for the [Logger](super::Logger)
|
||||||
#[derive(Error)]
|
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Bad IO operation
|
/// Bad IO operation
|
||||||
#[error("Bad IO operation")]
|
|
||||||
IO(std::io::Error),
|
IO(std::io::Error),
|
||||||
/// Various errors raised when the messenger is used in a wrong way
|
/// Various errors raised when the messenger is used in a wrong way
|
||||||
#[error("Bad usage")]
|
|
||||||
Usage(String),
|
Usage(String),
|
||||||
/// Could not assign logger as the global default
|
/// Could not assign logger as the global default
|
||||||
#[error("Could not assign as global default")] // TODO: make this more clear
|
|
||||||
SetGlobalDefaultFail(SetGlobalDefaultError),
|
SetGlobalDefaultFail(SetGlobalDefaultError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +52,19 @@ impl From<SetGlobalDefaultError> for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
impl Into<PyErr> for Error {
|
||||||
|
fn into(self) -> PyErr {
|
||||||
|
match self {
|
||||||
|
Error::IO(err) => PyException::new_err(format!("LoggerError: IO {err:?}")),
|
||||||
|
Error::Usage(err) => PyException::new_err(format!("LoggerError: Usage {err}")),
|
||||||
|
Error::SetGlobalDefaultFail(err) => {
|
||||||
|
PyException::new_err(format!("LoggerError: SetGlobalDefaultFail {err}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
impl std::fmt::Debug for Error {
|
impl std::fmt::Debug for Error {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
@ -66,6 +76,18 @@ impl std::fmt::Debug for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
impl std::fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Error::IO(e) => write!(f, "IO Error {e}"),
|
||||||
|
Error::Usage(e) => write!(f, "Usage Error {e}"),
|
||||||
|
Error::SetGlobalDefaultFail(e) => write!(f, "SetGlobalDefaultFail {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
use std::{
|
use std::{
|
||||||
fmt,
|
fmt,
|
||||||
ops::Deref,
|
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
};
|
};
|
||||||
|
@ -28,20 +27,10 @@ pub mod error;
|
||||||
use error::*;
|
use error::*;
|
||||||
|
|
||||||
pub use tracing::{debug, error, info, trace, warn, Level};
|
pub use tracing::{debug, error, info, trace, warn, Level};
|
||||||
use tracing_appender::{
|
use tracing_appender;
|
||||||
self,
|
use tracing_subscriber::{prelude::*, fmt::format::FmtSpan};
|
||||||
non_blocking::{NonBlocking, WorkerGuard},
|
|
||||||
};
|
|
||||||
use tracing_subscriber::{
|
|
||||||
fmt::{
|
|
||||||
format::FmtSpan,
|
|
||||||
time::{self, FormatTime},
|
|
||||||
},
|
|
||||||
prelude::*,
|
|
||||||
};
|
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
|
||||||
|
|
||||||
|
use pyo3::prelude::*;
|
||||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// The log level used when none is specified
|
/// The log level used when none is specified
|
||||||
pub const DEFAULT_LOG_LEVEL: Level = Level::INFO;
|
pub const DEFAULT_LOG_LEVEL: Level = Level::INFO;
|
||||||
|
@ -58,7 +47,8 @@ static INITIALIZED: AtomicBool = AtomicBool::new(false);
|
||||||
///
|
///
|
||||||
/// 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.
|
||||||
pub struct Logger;
|
#[pyclass]
|
||||||
|
pub struct Logger {}
|
||||||
|
|
||||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
||||||
/// ## Main implementation
|
/// ## Main implementation
|
||||||
|
@ -87,33 +77,6 @@ impl Logger {
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ## initializes the logger
|
|
||||||
///
|
|
||||||
/// Will enable the logger to be used. This is a version that shows less information,
|
|
||||||
/// useful in cases with only one sender to the logging framework.
|
|
||||||
///
|
|
||||||
/// Assumes some defaults, use [`init_customized`](Self::init_customized) for more control
|
|
||||||
pub fn init_mini(max_level: Option<Level>) -> Result<()> {
|
|
||||||
Self::init_customized(
|
|
||||||
false,
|
|
||||||
PathBuf::from(DEFAULT_LOG_DIR),
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
max_level.unwrap_or(DEFAULT_LOG_LEVEL),
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,99 +94,58 @@ impl Logger {
|
||||||
display_thread_ids: bool,
|
display_thread_ids: bool,
|
||||||
display_thread_names: bool,
|
display_thread_names: bool,
|
||||||
display_line_number: bool,
|
display_line_number: bool,
|
||||||
pretty: bool,
|
|
||||||
show_time: bool,
|
|
||||||
uptime: bool, // uptime instead of system time
|
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// only init if no init has been performed yet
|
// only init if no init has been performed yet
|
||||||
if INITIALIZED.load(Ordering::Relaxed) {
|
if INITIALIZED.load(Ordering::Relaxed) {
|
||||||
warn!("trying to reinitialize the logger, ignoring");
|
warn!("trying to reinitialize the logger, ignoring");
|
||||||
bail!(Error::Usage(format!("logging is already initialized")));
|
return Err(Error::Usage(format!("logging is already initialized")));
|
||||||
}
|
} else {
|
||||||
let subscriber = tracing_subscriber::fmt::Subscriber::builder()
|
let filter = tracing_subscriber::filter::FilterFn::new(|_metadata| {
|
||||||
.with_level(display_level)
|
// let mut filter = false;
|
||||||
.with_max_level(max_level)
|
//
|
||||||
|
// // if it's this lib, continue
|
||||||
|
// filter |= metadata.target().contains(env!("CARGO_PKG_NAME"));
|
||||||
|
// filter |= metadata.target().contains("libpt");
|
||||||
|
//
|
||||||
|
// // if it's another crate, only show above debug
|
||||||
|
// filter |= metadata.level() > &Level::DEBUG;
|
||||||
|
//
|
||||||
|
// filter
|
||||||
|
// FIXME: Make the filter customizable with sane defaults. Don't block the
|
||||||
|
// executing crate.
|
||||||
|
true
|
||||||
|
});
|
||||||
|
|
||||||
|
let basic_subscriber = tracing_subscriber::fmt::Subscriber::builder()
|
||||||
|
// subscriber configuration
|
||||||
.with_ansi(ansi)
|
.with_ansi(ansi)
|
||||||
.with_target(display_target)
|
|
||||||
.with_file(display_filename)
|
.with_file(display_filename)
|
||||||
|
.with_level(display_level)
|
||||||
|
.with_target(display_target)
|
||||||
|
.with_max_level(max_level)
|
||||||
.with_thread_ids(display_thread_ids)
|
.with_thread_ids(display_thread_ids)
|
||||||
.with_line_number(display_line_number)
|
.with_line_number(display_line_number)
|
||||||
.with_thread_names(display_thread_names)
|
.with_thread_names(display_thread_names)
|
||||||
.with_span_events(FmtSpan::FULL);
|
.with_span_events(FmtSpan::FULL)
|
||||||
// I know this is hacky, but I couldn't get it any other way. I couldn't even find a
|
//.pretty // too verbose and over multiple lines, a bit like python tracebacks
|
||||||
// project that could do it any other way. You can't apply one after another, because the
|
.finish()
|
||||||
// type is changed every time. When using Box<dyn Whatever>, some methods complain about
|
// add layers
|
||||||
// not being in trait bounds.
|
.with(filter);
|
||||||
// TODO: somehow find a better solution for this
|
|
||||||
match (log_to_file, show_time, pretty, uptime) {
|
if log_to_file {
|
||||||
(true, true, true, true) => {
|
let file_appender = tracing_appender::rolling::daily(log_dir, "log");
|
||||||
let subscriber = subscriber
|
|
||||||
.with_writer(new_file_appender(log_dir))
|
|
||||||
.with_timer(time::uptime())
|
|
||||||
.pretty()
|
|
||||||
.finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(true, true, true, false) => {
|
|
||||||
let subscriber = subscriber
|
|
||||||
.with_writer(new_file_appender(log_dir))
|
|
||||||
.pretty()
|
|
||||||
.finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(true, false, true, _) => {
|
|
||||||
let subscriber = subscriber
|
|
||||||
.with_writer(new_file_appender(log_dir))
|
|
||||||
.without_time()
|
|
||||||
.pretty()
|
|
||||||
.finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(true, true, false, true) => {
|
|
||||||
let subscriber = subscriber
|
|
||||||
.with_writer(new_file_appender(log_dir))
|
|
||||||
.with_timer(time::uptime())
|
|
||||||
.finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(true, true, false, false) => {
|
|
||||||
let subscriber = subscriber.with_writer(new_file_appender(log_dir)).finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(true, false, false, _) => {
|
|
||||||
let file_appender = tracing_appender::rolling::daily(log_dir.clone(), "log");
|
|
||||||
let (file_writer, _guard) = tracing_appender::non_blocking(file_appender);
|
let (file_writer, _guard) = tracing_appender::non_blocking(file_appender);
|
||||||
let subscriber = subscriber.with_writer(file_writer).without_time().finish();
|
let layered_subscriber = basic_subscriber
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
.with(tracing_subscriber::fmt::Layer::default().with_writer(file_writer));
|
||||||
}
|
tracing::subscriber::set_global_default(layered_subscriber)?;
|
||||||
(false, true, true, true) => {
|
} else {
|
||||||
let subscriber = subscriber.pretty().with_timer(time::uptime()).finish();
|
tracing::subscriber::set_global_default(basic_subscriber)?;
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(false, true, true, false) => {
|
|
||||||
let subscriber = subscriber.pretty().with_timer(time::uptime()).finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(false, false, true, _) => {
|
|
||||||
let subscriber = subscriber.without_time().pretty().finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(false, true, false, true) => {
|
|
||||||
let subscriber = subscriber.with_timer(time::uptime()).finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(false, true, false, false) => {
|
|
||||||
let subscriber = subscriber.finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(false, false, false, _) => {
|
|
||||||
let subscriber = subscriber.without_time().finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INITIALIZED.store(true, Ordering::Relaxed);
|
INITIALIZED.store(true, Ordering::Relaxed);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// ## logging at [`Level::ERROR`]
|
/// ## logging at [`Level::ERROR`]
|
||||||
pub fn error<T>(&self, printable: T)
|
pub fn error<T>(&self, printable: T)
|
||||||
|
@ -262,6 +184,61 @@ impl Logger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// ## Implementation of the python interface
|
||||||
|
#[pymethods]
|
||||||
|
impl Logger {
|
||||||
|
/// ## Python version of [`new()`](Logger::new)
|
||||||
|
#[new]
|
||||||
|
pub fn py_new() -> PyResult<Self> {
|
||||||
|
Ok(Logger::new())
|
||||||
|
}
|
||||||
|
/// ## Python version of [`init()`](Logger::init)
|
||||||
|
#[pyo3(name = "init")]
|
||||||
|
#[staticmethod]
|
||||||
|
pub fn py_init(log_dir: Option<PathBuf>, max_level: Option<String>) -> Result<()> {
|
||||||
|
Self::init(
|
||||||
|
log_dir,
|
||||||
|
match max_level {
|
||||||
|
Some(s) => match s.to_uppercase().as_str() {
|
||||||
|
"TRACE" => Some(tracing::Level::TRACE),
|
||||||
|
"DEBUG" => Some(tracing::Level::DEBUG),
|
||||||
|
"INFO" => Some(tracing::Level::INFO),
|
||||||
|
"WARN" => Some(tracing::Level::WARN),
|
||||||
|
"ERROR" => Some(tracing::Level::ERROR),
|
||||||
|
_ => return Err(Error::Usage(format!("'{s}' is not a valid log level"))),
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/// ## Python version of [`error()`](Logger::error)
|
||||||
|
#[pyo3(name = "error")]
|
||||||
|
pub fn py_error(&self, printable: String) {
|
||||||
|
self.error(printable)
|
||||||
|
}
|
||||||
|
/// ## Python version of [`warn()`](Logger::warn)
|
||||||
|
#[pyo3(name = "warn")]
|
||||||
|
pub fn py_warn(&self, printable: String) {
|
||||||
|
self.warn(printable)
|
||||||
|
}
|
||||||
|
/// ## Python version of [`info()`](Logger::info)
|
||||||
|
#[pyo3(name = "info")]
|
||||||
|
pub fn py_info(&self, printable: String) {
|
||||||
|
self.info(printable)
|
||||||
|
}
|
||||||
|
/// ## Python version of [`debug()`](Logger::debug)
|
||||||
|
#[pyo3(name = "debug")]
|
||||||
|
pub fn py_debug(&self, printable: String) {
|
||||||
|
self.debug(printable)
|
||||||
|
}
|
||||||
|
/// ## Python version of [`trace()`](Logger::trace)
|
||||||
|
#[pyo3(name = "trace")]
|
||||||
|
pub fn py_trace(&self, printable: String) {
|
||||||
|
self.trace(printable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
impl fmt::Debug for Logger {
|
impl fmt::Debug for Logger {
|
||||||
/// ## DEBUG representation for [`Logger`]
|
/// ## DEBUG representation for [`Logger`]
|
||||||
|
@ -277,7 +254,4 @@ impl fmt::Debug for Logger {
|
||||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
||||||
fn new_file_appender(log_dir: PathBuf) -> NonBlocking {
|
|
||||||
let file_appender = tracing_appender::rolling::daily(log_dir.clone(), "log");
|
|
||||||
return tracing_appender::non_blocking(file_appender).0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,9 +16,9 @@ categories.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
humantime = "2.1.0"
|
humantime = "2.1.0"
|
||||||
libpt-core = { path = "../libpt-core" }
|
libpt-core = { version = "0.1.0", path = "../libpt-core" }
|
||||||
libpt-log = { path = "../libpt-log" }
|
libpt-log = { version = "0.1.0", path = "../libpt-log" }
|
||||||
libpt-math = { path = "../libpt-math" }
|
libpt-math = { version = "0.1.0", path = "../libpt-math" }
|
||||||
reqwest = { version = "0.11.20", features = ["blocking"] }
|
reqwest = { version = "0.11.20", features = ["blocking"] }
|
||||||
serde = { version = "1.0.188", features = ["serde_derive"] }
|
serde = { version = "1.0.188", features = ["serde_derive"] }
|
||||||
serde_json = "1.0.107"
|
serde_json = "1.0.107"
|
||||||
|
|
|
@ -10,9 +10,11 @@
|
||||||
// we want docs
|
// we want docs
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
#![warn(rustdoc::missing_crate_level_docs)]
|
#![warn(rustdoc::missing_crate_level_docs)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// we want Debug everywhere.
|
// we want Debug everywhere.
|
||||||
#![warn(missing_debug_implementations)]
|
#![warn(missing_debug_implementations)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// enable clippy's extra lints, the pedantic version
|
// enable clippy's extra lints, the pedantic version
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
|
@ -6,9 +6,11 @@
|
||||||
// we want docs
|
// we want docs
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
#![warn(rustdoc::missing_crate_level_docs)]
|
#![warn(rustdoc::missing_crate_level_docs)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// we want Debug everywhere.
|
// we want Debug everywhere.
|
||||||
#![warn(missing_debug_implementations)]
|
#![warn(missing_debug_implementations)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// enable clippy's extra lints, the pedantic version
|
// enable clippy's extra lints, the pedantic version
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
|
@ -188,11 +188,7 @@ pub fn continuous_uptime_monitor(
|
||||||
let mut last_was_up: bool = true;
|
let mut last_was_up: bool = true;
|
||||||
let mut last_ratio: u8 = status.success_ratio;
|
let mut last_ratio: u8 = status.success_ratio;
|
||||||
loop {
|
loop {
|
||||||
trace!(
|
trace!(?status, ?last_was_up, "loop iteration for continuous uptime monitor");
|
||||||
?status,
|
|
||||||
?last_was_up,
|
|
||||||
"loop iteration for continuous uptime monitor"
|
|
||||||
);
|
|
||||||
if !status.success {
|
if !status.success {
|
||||||
if last_was_up {
|
if last_was_up {
|
||||||
trace!("displaying status");
|
trace!("displaying status");
|
||||||
|
|
120
members/libpt-py/.github/workflows/CI.yml
vendored
Normal file
120
members/libpt-py/.github/workflows/CI.yml
vendored
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
# This file is autogenerated by maturin v1.1.0
|
||||||
|
# To update, run
|
||||||
|
#
|
||||||
|
# maturin generate-ci github
|
||||||
|
#
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- master
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
target: [x86_64, x86, aarch64, armv7, s390x, ppc64le]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.10'
|
||||||
|
- name: Build wheels
|
||||||
|
uses: PyO3/maturin-action@v1
|
||||||
|
with:
|
||||||
|
target: ${{ matrix.target }}
|
||||||
|
args: --release --out dist --find-interpreter
|
||||||
|
sccache: 'true'
|
||||||
|
manylinux: auto
|
||||||
|
- name: Upload wheels
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: wheels
|
||||||
|
path: dist
|
||||||
|
|
||||||
|
windows:
|
||||||
|
runs-on: windows-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
target: [x64, x86]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.10'
|
||||||
|
architecture: ${{ matrix.target }}
|
||||||
|
- name: Build wheels
|
||||||
|
uses: PyO3/maturin-action@v1
|
||||||
|
with:
|
||||||
|
target: ${{ matrix.target }}
|
||||||
|
args: --release --out dist --find-interpreter
|
||||||
|
sccache: 'true'
|
||||||
|
- name: Upload wheels
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: wheels
|
||||||
|
path: dist
|
||||||
|
|
||||||
|
macos:
|
||||||
|
runs-on: macos-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
target: [x86_64, aarch64]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.10'
|
||||||
|
- name: Build wheels
|
||||||
|
uses: PyO3/maturin-action@v1
|
||||||
|
with:
|
||||||
|
target: ${{ matrix.target }}
|
||||||
|
args: --release --out dist --find-interpreter
|
||||||
|
sccache: 'true'
|
||||||
|
- name: Upload wheels
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: wheels
|
||||||
|
path: dist
|
||||||
|
|
||||||
|
sdist:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Build sdist
|
||||||
|
uses: PyO3/maturin-action@v1
|
||||||
|
with:
|
||||||
|
command: sdist
|
||||||
|
args: --out dist
|
||||||
|
- name: Upload sdist
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: wheels
|
||||||
|
path: dist
|
||||||
|
|
||||||
|
release:
|
||||||
|
name: Release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: "startsWith(github.ref, 'refs/tags/')"
|
||||||
|
needs: [linux, windows, macos, sdist]
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: wheels
|
||||||
|
- name: Publish to PyPI
|
||||||
|
uses: PyO3/maturin-action@v1
|
||||||
|
env:
|
||||||
|
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
|
||||||
|
with:
|
||||||
|
command: upload
|
||||||
|
args: --skip-existing *
|
72
members/libpt-py/.gitignore
vendored
Normal file
72
members/libpt-py/.gitignore
vendored
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/target
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
.pytest_cache/
|
||||||
|
*.py[cod]
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
.venv/
|
||||||
|
env/
|
||||||
|
bin/
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
include/
|
||||||
|
man/
|
||||||
|
venv/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
pip-selfcheck.json
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.coverage
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
|
||||||
|
# Mr Developer
|
||||||
|
.mr.developer.cfg
|
||||||
|
.project
|
||||||
|
.pydevproject
|
||||||
|
|
||||||
|
# Rope
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# VSCode
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
# Pyenv
|
||||||
|
.python-version
|
22
members/libpt-py/Cargo.toml
Normal file
22
members/libpt-py/Cargo.toml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
[package]
|
||||||
|
name = "libpt-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 = "libpt_py"
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libpt = { version = "0.1.7", path = "../..", features = ["all"] }
|
||||||
|
pyo3 = { workspace = true }
|
21
members/libpt-py/LICENSE
Normal file
21
members/libpt-py/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 Christoph Johannes Scherr
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
76
members/libpt-py/README.md
Normal file
76
members/libpt-py/README.md
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
# pt / libpt
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
`pt` stands for either one of "personal tool", "plex tool", "pete" or something among those lines.
|
||||||
|
It is a collection of tools that i might or might not use. The intended purpose of this repo is that
|
||||||
|
I program whatever i feel is worth having in a personal thing into it, then use it as either a lib,
|
||||||
|
crate, python module or executable.
|
||||||
|
|
||||||
|
Let's see if I make it a bloated mess or stop committing after 30 hello worlds.
|
||||||
|
|
||||||
|
#### But the name `pt` / `libpt` already exists!
|
||||||
|
|
||||||
|
So what? I don't care. Besides, there is not enough names to name everything unique.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- See `cargo.toml`
|
||||||
|
- [openssl bindings for rust](https://docs.rs/openssl/latest/openssl/)
|
||||||
|
- [Python](https://www.python.org/)
|
||||||
|
- [`maturin`](https://maturin.rs) - `pip install maturin`
|
||||||
|
|
||||||
|
## Compiling & Installing from source
|
||||||
|
|
||||||
|
If you only want the rust library, you can simply build it with `cargo build`. Add it to your
|
||||||
|
project like any other local dependency.
|
||||||
|
|
||||||
|
If you want to use the python variant too, you need to compile with maturing.
|
||||||
|
|
||||||
|
- Install in `venv`: `maturin develop --release`
|
||||||
|
- Install in system: `maturin build --release && pip install target/wheels/libpt-x.x.x-*`
|
||||||
|
|
||||||
|
## Installing from [pypi](https://pypi.org)
|
||||||
|
|
||||||
|
`libpt` has been packaged for [pypi.org](https://pypi.org/project/libpt/).
|
||||||
|
|
||||||
|
You can install it with `pip install libpt`
|
||||||
|
|
||||||
|
## Installing from [crates.io](https://crates.io)
|
||||||
|
|
||||||
|
`libpt` has been packaged for [crates.io](https://crates.io/crates/libpt).
|
||||||
|
|
||||||
|
You can add the library to your project with `cargo add libpt`.
|
||||||
|
|
||||||
|
## Installing from my personal package registry
|
||||||
|
|
||||||
|
`libpt` has been packaged for [git.cscherr.de](https://git.cscherr.de).
|
||||||
|
|
||||||
|
You can add the registry to your `config.toml` and then `cargo add libpt`
|
||||||
|
|
||||||
|
[Package](https://git.cscherr.de/PlexSheep/-/packages/cargo/libpt/)
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Testing needs to be done separately for the rust and python parts:
|
||||||
|
|
||||||
|
- Rust testing with `cargo test`
|
||||||
|
- Python testing with `./scripts/pytests.sh` or `python -m unittest discover -fs tests/python`
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
The documentation can be automatically generated with `cargo doc --open`.
|
||||||
|
|
||||||
|
An up to date version of the Documentation can be found [here](https://docs.rs/libpt/)
|
||||||
|
|
||||||
|
## Mirrored
|
||||||
|
|
||||||
|
The origin of this repository is [git.cscherr.de](https://git.cscherr.de/PlexSheep/pt)
|
||||||
|
|
||||||
|
It is mirrored to:
|
||||||
|
- [Codeberg](https://codeberg.org/PlexSheep/pt)
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
**Pt is MIT Licensed**
|
25
members/libpt-py/pyproject.toml
Normal file
25
members/libpt-py/pyproject.toml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
[build-system]
|
||||||
|
requires = ["maturin>=0.14,<0.15"]
|
||||||
|
build-backend = "maturin"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "libpt"
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.7"
|
||||||
|
authors = [{ name = "Christoph J. Scherr", email = "software@cscherr.de" }]
|
||||||
|
license = { file = "LICENSE" }
|
||||||
|
keywords = ["pyo3"]
|
||||||
|
classifiers = [
|
||||||
|
"Programming Language :: Rust",
|
||||||
|
"Programming Language :: Python :: Implementation :: CPython",
|
||||||
|
"Programming Language :: Python :: Implementation :: PyPy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.urls]
|
||||||
|
Homepage = "https://git.cscherr.de/PlexSheep/libpt"
|
||||||
|
|
||||||
|
|
||||||
|
[tool.maturin]
|
||||||
|
features = ["pyo3/extension-module"]
|
||||||
|
python-source = "python"
|
||||||
|
module-name = "libpt._libpt"
|
1
members/libpt-py/python/libpt/__init__.py
Normal file
1
members/libpt-py/python/libpt/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
from ._libpt import *
|
14
members/libpt-py/python/libpt/__init__.pyi
Normal file
14
members/libpt-py/python/libpt/__init__.pyi
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
"""
|
||||||
|
# libpt python bindings
|
||||||
|
|
||||||
|
`libpt` is originally implemented in rust, but offers a python module too.
|
||||||
|
"""
|
||||||
|
from . import logger
|
||||||
|
from . import networking
|
||||||
|
from . import common
|
||||||
|
|
||||||
|
def is_loaded() -> bool:
|
||||||
|
"""
|
||||||
|
returns true if `libpt` has been loaded
|
||||||
|
"""
|
||||||
|
...
|
7
members/libpt-py/python/libpt/common/__init__.pyi
Normal file
7
members/libpt-py/python/libpt/common/__init__.pyi
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
"""
|
||||||
|
common functionalities
|
||||||
|
|
||||||
|
This module implements common functionality useful for many use cases, such as macros,
|
||||||
|
Formatting functions and more.
|
||||||
|
"""
|
||||||
|
from . import printing
|
14
members/libpt-py/python/libpt/common/printing.pyi
Normal file
14
members/libpt-py/python/libpt/common/printing.pyi
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
"""
|
||||||
|
tools that make printing stuff better
|
||||||
|
"""
|
||||||
|
def divider() -> str:
|
||||||
|
"""
|
||||||
|
Quickly get a one line visual divider
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def print_divider():
|
||||||
|
"""
|
||||||
|
Quickly print a one line visual divider
|
||||||
|
"""
|
||||||
|
...
|
65
members/libpt-py/python/libpt/logger.pyi
Normal file
65
members/libpt-py/python/libpt/logger.pyi
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
"""
|
||||||
|
# A specialized Logger for `libpt`
|
||||||
|
"""
|
||||||
|
|
||||||
|
""" the default log level """
|
||||||
|
DEFAULT_LOG_LEVEL = "INFO"
|
||||||
|
""" Set the value of this key as envar to set a loglevel """
|
||||||
|
LOGGER_ENV_KEY = "LIBPT_LOGLEVEL"
|
||||||
|
|
||||||
|
class Logger:
|
||||||
|
"""
|
||||||
|
`libpt` logger
|
||||||
|
|
||||||
|
Call `init` once before usage, else all logging attempts will be ignored.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
"""
|
||||||
|
get a new logger
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def init():
|
||||||
|
"""
|
||||||
|
initialize the logger before the first usage
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def init_specialized(color: bool):
|
||||||
|
"""
|
||||||
|
initialize the logger before the first usage, but with the ability to tweak things a bit
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def error(self, printable: str):
|
||||||
|
"""
|
||||||
|
log at level `error`
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def warn(self, printable: str):
|
||||||
|
"""
|
||||||
|
log at level `error`
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def info(self, printable: str):
|
||||||
|
"""
|
||||||
|
log at level `error`
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def debug(self, printable: str):
|
||||||
|
"""
|
||||||
|
log at level `error`
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def trace(self, printable: str):
|
||||||
|
"""
|
||||||
|
log at level `error`
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
7
members/libpt-py/python/libpt/networking/__init__.pyi
Normal file
7
members/libpt-py/python/libpt/networking/__init__.pyi
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
"""
|
||||||
|
# various networking tools
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
from . import monitoring
|
|
@ -0,0 +1,7 @@
|
||||||
|
"""
|
||||||
|
# monitor your network
|
||||||
|
|
||||||
|
This module offers functions to monitor your network.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from . import uptime
|
|
@ -0,0 +1,86 @@
|
||||||
|
"""
|
||||||
|
# monitor your network uptime
|
||||||
|
|
||||||
|
This method offers a way to monitor your networks/hosts uptime. This is achieved by making
|
||||||
|
HTTPS requests to a given list of
|
||||||
|
"""
|
||||||
|
|
||||||
|
class UptimeStatus:
|
||||||
|
"""
|
||||||
|
Describes an uptime status
|
||||||
|
|
||||||
|
UptimeStatus describes the result of an uptime check.
|
||||||
|
"""
|
||||||
|
""" true if the [`UptimeStatus`] is considered successful"""
|
||||||
|
success: bool
|
||||||
|
""" the percentage of reachable urls out of the total urls"""
|
||||||
|
success_ratio: int
|
||||||
|
""" 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.
|
||||||
|
"""
|
||||||
|
success_ratio_target: int
|
||||||
|
""" the number of reachable [`urls`](UptimeStatus::urls) """
|
||||||
|
reachable: int
|
||||||
|
""" set a timeout (in ms) """
|
||||||
|
timeout: int
|
||||||
|
"""URL list cant be ported to python, use UptimeStatus.urls()"""
|
||||||
|
__urls: ...
|
||||||
|
|
||||||
|
def __init__(self, success_ratio_target: int, url_strs: list[str], timeout: int) -> None:
|
||||||
|
"""
|
||||||
|
create a new UptimeStatus and check it
|
||||||
|
|
||||||
|
`success_ratio_target` should never be more than 100 (it represents a success percentage)
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def check(self) -> None:
|
||||||
|
"""
|
||||||
|
checks if the stored urls
|
||||||
|
|
||||||
|
Makes the actual https requests and updates fields accordingly.
|
||||||
|
|
||||||
|
This method can block some time, as the web requests are implemented as blocking and
|
||||||
|
executed by the shared library (not in python)
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def calc_success(self) -> None:
|
||||||
|
"""
|
||||||
|
calculate the success based on the `reachable` and `total`
|
||||||
|
|
||||||
|
Calculates the ratio of [reachable]/
|
||||||
|
(length of [__urls]).
|
||||||
|
|
||||||
|
Calculates a [`success_ratio`] from that, by multiplying with 100, then flooring.
|
||||||
|
|
||||||
|
If the [`success_ratio`] is greater than or equal to the [`success_ratio_target`],
|
||||||
|
the [`UptimeStatus`] will be considered a success.
|
||||||
|
|
||||||
|
In the special case that no URLs to check for have been provided, the check will be
|
||||||
|
considered a success, but the [`success_ratio`] will be `0`.
|
||||||
|
|
||||||
|
Note: does not check for networking, use [`check()`] for that.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def urls(self) -> list[str]:
|
||||||
|
"""
|
||||||
|
get urls for python
|
||||||
|
|
||||||
|
Since [`__urls`] has no python equivalent, return the urls as a `list[str]` in
|
||||||
|
Python.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def continuous_uptime_monitor(success_ratio_target: int, urls: list[str], interval: int, timeout: int) -> None:
|
||||||
|
"""
|
||||||
|
Uptime monitor
|
||||||
|
|
||||||
|
This function continuously monitors the uptime of your host/network.
|
||||||
|
|
||||||
|
On change of status, an update will be logged at INFO Level, containing
|
||||||
|
information on your current status, including timestamps of the last up/down time and durations
|
||||||
|
since.
|
||||||
|
"""
|
||||||
|
...
|
0
members/libpt-py/python/libpt/py.typed
Normal file
0
members/libpt-py/python/libpt/py.typed
Normal file
1
members/libpt-py/scripts/pytests.sh
Executable file
1
members/libpt-py/scripts/pytests.sh
Executable file
|
@ -0,0 +1 @@
|
||||||
|
python -m unittest discover -fs tests/python
|
101
members/libpt-py/src/lib.rs
Normal file
101
members/libpt-py/src/lib.rs
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
// FIXME: Using a local dependency does not work with maturin as it seems?
|
||||||
|
use libpt::{
|
||||||
|
log::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
|
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// ## Check if [`libpt`](crate) has been loaded
|
||||||
|
///
|
||||||
|
/// Always returns `true` if you can execute it.
|
||||||
|
#[pyfunction]
|
||||||
|
pub fn is_loaded() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// ## Python module: logger
|
||||||
|
#[pymodule]
|
||||||
|
fn py_logger(py: Python, parent: &PyModule) -> PyResult<()> {
|
||||||
|
let module = PyModule::new(py, "logger")?;
|
||||||
|
module.add_class::<Logger>()?;
|
||||||
|
|
||||||
|
parent.add_submodule(module)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// ////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// /// ## Python module: common
|
||||||
|
// #[pymodule]
|
||||||
|
// fn py_common(py: Python, parent: &PyModule) -> PyResult<()> {
|
||||||
|
// let module = PyModule::new(py, "common")?;
|
||||||
|
// py_common_printing(py, module)?;
|
||||||
|
//
|
||||||
|
// parent.add_submodule(module)?;
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// /// ## Python module: common.printing
|
||||||
|
// #[pymodule]
|
||||||
|
// fn py_common_printing(py: Python, parent: &PyModule) -> PyResult<()> {
|
||||||
|
// let module = PyModule::new(py, "printing")?;
|
||||||
|
// module.add_function(wrap_pyfunction!(common::printing::divider, module)?)?;
|
||||||
|
// module.add_function(wrap_pyfunction!(common::printing::print_divider, module)?)?;
|
||||||
|
//
|
||||||
|
// parent.add_submodule(module)?;
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// /// ## Python module: networking
|
||||||
|
// #[pymodule]
|
||||||
|
// fn py_networking(py: Python, parent: &PyModule) -> PyResult<()> {
|
||||||
|
// let module = PyModule::new(py, "networking")?;
|
||||||
|
// py_networking_monitoring(py, module)?;
|
||||||
|
//
|
||||||
|
// parent.add_submodule(module)?;
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// /// ## Python module: networking.monitoring
|
||||||
|
// #[pymodule]
|
||||||
|
// fn py_networking_monitoring(py: Python, parent: &PyModule) -> PyResult<()> {
|
||||||
|
// let module = PyModule::new(py, "monitoring")?;
|
||||||
|
// py_networking_monitoring_uptime(py, module)?;
|
||||||
|
//
|
||||||
|
// parent.add_submodule(module)?;
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// /// ## Python module: networking.monitoring.uptime
|
||||||
|
// #[pymodule]
|
||||||
|
// fn py_networking_monitoring_uptime(py: Python, parent: &PyModule) -> PyResult<()> {
|
||||||
|
// let module = PyModule::new(py, "uptime")?;
|
||||||
|
// module.add_class::<networking::monitoring::uptime::UptimeStatus>()?;
|
||||||
|
// module.add_function(wrap_pyfunction!(
|
||||||
|
// networking::monitoring::uptime::py_continuous_uptime_monitor,
|
||||||
|
// module
|
||||||
|
// )?)?;
|
||||||
|
//
|
||||||
|
// parent.add_submodule(module)?;
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// ## Python module: root
|
||||||
|
///
|
||||||
|
/// This function is the entry point of [`PyO3`](pyo3). This is where the main module is built.
|
||||||
|
#[pymodule]
|
||||||
|
fn _libpt(py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
|
m.add_function(wrap_pyfunction!(is_loaded, m)?)?;
|
||||||
|
|
||||||
|
// load sub modules
|
||||||
|
// py_common(py, m)?;
|
||||||
|
py_logger(py, m)?;
|
||||||
|
// py_networking(py, m)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,8 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
PKGs=(libpt-{core,math,log,net,bintols,ccc,hedu,bin,py} libpt)
|
|
||||||
for PKG in "${PKGs[@]}"; do
|
|
||||||
echo "Package: $PKG"
|
|
||||||
cargo publish --registry cscherr -p "$PKG"
|
|
||||||
cargo publish -p "$PKG"
|
|
||||||
done
|
|
|
@ -6,12 +6,10 @@
|
||||||
//! `pt` is a project consisting of multiple smaller crates, all bundled together in this
|
//! `pt` is a project consisting of multiple smaller crates, all bundled together in this
|
||||||
//! "main crate". Most crates will only show up if you activate their feature.
|
//! "main crate". Most crates will only show up if you activate their feature.
|
||||||
|
|
||||||
#[cfg(feature = "bintols")]
|
|
||||||
pub use libpt_bintols as bintols;
|
|
||||||
#[cfg(feature = "ccc")]
|
|
||||||
pub use libpt_ccc as ccc;
|
|
||||||
#[cfg(feature = "core")]
|
#[cfg(feature = "core")]
|
||||||
pub use libpt_core as core;
|
pub use libpt_core as core;
|
||||||
|
#[cfg(feature = "bintols")]
|
||||||
|
pub use libpt_bintols as bintols;
|
||||||
#[cfg(feature = "hedu")]
|
#[cfg(feature = "hedu")]
|
||||||
pub use libpt_hedu as hedu;
|
pub use libpt_hedu as hedu;
|
||||||
#[cfg(feature = "log")]
|
#[cfg(feature = "log")]
|
||||||
|
@ -20,3 +18,5 @@ pub use libpt_log as log;
|
||||||
pub use libpt_math as math;
|
pub use libpt_math as math;
|
||||||
#[cfg(feature = "net")]
|
#[cfg(feature = "net")]
|
||||||
pub use libpt_net as net;
|
pub use libpt_net as net;
|
||||||
|
#[cfg(feature = "ccc")]
|
||||||
|
pub use libpt_ccc as ccc;
|
||||||
|
|
Reference in a new issue