Compare commits

...
This repository has been archived on 2024-10-16. You can view files and clone it, but cannot push or open issues or pull requests.

53 Commits

Author SHA1 Message Date
Christoph J. Scherr 11a2d7908e chore: just use github for ci and also add cd 2024-10-16 20:26:44 +02:00
Christoph J. Scherr 90e3442b50 chore: change ci message to fit conventional git commits 2024-10-16 13:49:50 +02:00
Christoph J. Scherr 30168c5523 chore: bump version
cargo devel CI / cargo CI (push) Successful in 1m49s Details
2024-09-08 01:34:28 +02:00
Christoph J. Scherr a7d0c18f52 chore: reset publish script
cargo devel CI / cargo CI (push) Has been cancelled Details
2024-09-08 01:27:27 +02:00
Christoph J. Scherr 54a694645f refactor(log): make logfile kinda behave like normal
cargo devel CI / cargo CI (push) Has been cancelled Details
2024-09-08 01:26:37 +02:00
Christoph J. Scherr 492e655d29 chore: bump versions
cargo devel CI / cargo CI (push) Successful in 1m50s Details
2024-09-08 01:14:35 +02:00
Christoph J. Scherr a9fbcf9518 fix(log): panic when trying to open alogfile in a dir that did not exist
cargo devel CI / cargo CI (push) Has been cancelled Details
2024-09-08 01:14:04 +02:00
Christoph J. Scherr 51e2c3029e chore: bump versions
cargo devel CI / cargo CI (push) Successful in 1m52s Details
2024-09-08 01:05:08 +02:00
Christoph J. Scherr 6197532bc7 refactor(log): refactor the build function
cargo devel CI / cargo CI (push) Has been cancelled Details
2024-09-08 00:35:19 +02:00
Christoph J. Scherr 3063f77798 Merge branch 'master' into devel
cargo devel CI / cargo CI (push) Successful in 1m50s Details
2024-09-07 23:51:36 +02:00
Christoph J. Scherr 05910ae3be docs: add backtics
cargo devel CI / cargo CI (push) Has been cancelled Details
2024-09-07 23:51:19 +02:00
PlexSheep 895b156e02 automatic cargo CI changes 2024-09-07 21:51:12 +00:00
Christoph J. Scherr 35ab3d9b28 chore: fix publish script
cargo devel CI / cargo CI (push) Successful in 2m1s Details
2024-09-07 23:49:15 +02:00
Christoph J. Scherr 917a68c8ab chore: bump versions
cargo devel CI / cargo CI (push) Has been cancelled Details
2024-09-07 23:48:22 +02:00
Christoph J. Scherr 5b0c82cf2b feat(log): specify span events + doc fixes 2024-09-07 23:47:06 +02:00
Christoph J. Scherr 3bf60f86b1 Merge branch 'devel'
cargo devel CI / cargo CI (push) Successful in 1m54s Details
2024-09-06 17:34:20 +02:00
Christoph J. Scherr 056c2d136c chore: bump version
cargo devel CI / cargo CI (push) Successful in 1m57s Details
2024-09-06 17:34:16 +02:00
Christoph J. Scherr 235a8bfb85 feat(cli): make VerbosityLevel serde compatible
cargo devel CI / cargo CI (push) Has been cancelled Details
2024-09-06 17:33:15 +02:00
Christoph J. Scherr 29beabdc29 docs: python not implemented notice #98
cargo devel CI / cargo CI (push) Successful in 1m50s Details
2024-08-30 18:06:46 +02:00
Christoph J. Scherr 17a235c1da chore: add docs.rs metadata #97
cargo devel CI / cargo CI (push) Successful in 1m55s Details
2024-08-30 17:49:40 +02:00
Christoph J. Scherr 4ff85b881c chore: full feature
cargo devel CI / cargo CI (push) Has been cancelled Details
2024-08-30 17:49:24 +02:00
Christoph J. Scherr 3a215390d6 chore: bump version and fix deptree of workspace
cargo devel CI / cargo CI (push) Successful in 1m57s Details
2024-08-30 17:39:53 +02:00
Christoph J. Scherr 442e17f9a8 fix: let logger use the crate name of the end-crate #91
cargo devel CI / cargo CI (push) Has been cancelled Details
2024-08-30 17:39:10 +02:00
cscherrNT 687fd94870 automatic cargo CI changes 2024-08-30 14:27:56 +00:00
Christoph J. Scherr 7eb7d95f94 docs: fix cli example deps
cargo devel CI / cargo CI (push) Successful in 2m11s Details
2024-08-30 16:25:48 +02:00
Christoph J. Scherr 43944b0e34 fix: features in main crate were bad
cargo devel CI / cargo CI (push) Failing after 1m42s Details
2024-08-30 16:02:11 +02:00
Christoph J. Scherr b8acb7300e chore: remove reexports for cli #93
cargo devel CI / cargo CI (push) Failing after 1m42s Details
2024-08-30 13:35:47 +02:00
cscherrNT d48b87dcfe Merge pull request 'idk why this isn't in master yet' (#94) from devel into master
cargo devel CI / cargo CI (push) Successful in 1m59s Details
Reviewed-on: #94
2024-07-22 13:30:20 +02:00
Christoph J. Scherr 6116d639b2 Merge branch 'devel' of https://git.cscherr.de/PlexSheep/pt into devel
cargo devel CI / cargo CI (push) Successful in 2m10s Details
2024-07-09 20:16:05 +02:00
Christoph J. Scherr 5c6e5b242e docs(cli): help template was missing something 2024-07-09 20:16:04 +02:00
PlexSheep ca3cabf6ca automatic cargo CI changes 2024-07-09 17:59:06 +00:00
Christoph J. Scherr 21444f1ffe chore: bump versions
cargo devel CI / cargo CI (push) Successful in 2m4s Details
2024-07-09 19:57:04 +02:00
Christoph J. Scherr 69ce80483d chore: clippy findings
cargo devel CI / cargo CI (push) Has been cancelled Details
2024-07-09 19:54:11 +02:00
Christoph J. Scherr 89c481fa2e fix: make the libpt log version correct 2024-07-09 19:53:50 +02:00
Christoph J. Scherr b1e6558a30 chore: bumps for log and cli
cargo devel CI / cargo CI (push) Failing after 1m14s Details
2024-07-09 19:52:09 +02:00
Christoph J. Scherr d052fb2b34 docs(cli): example was broken
cargo devel CI / cargo CI (push) Has been cancelled Details
2024-07-09 19:51:22 +02:00
Christoph J. Scherr 7db1833cbb feat(log): apperently, show time or not was also no option???
cargo devel CI / cargo CI (push) Has been cancelled Details
2024-07-09 19:50:12 +02:00
Christoph J. Scherr b96b2ac4f6 chore: bump libpt
cargo devel CI / cargo CI (push) Failing after 1m13s Details
2024-07-09 19:47:23 +02:00
Christoph J. Scherr c9f879b97f chore: bump libpt-cli
cargo devel CI / cargo CI (push) Has been cancelled Details
2024-07-09 19:46:27 +02:00
Christoph J. Scherr 914f17f359 chore: bump libpt-log
cargo devel CI / cargo CI (push) Has been cancelled Details
2024-07-09 19:45:21 +02:00
Christoph J. Scherr b06a821f29 docs(cli): add crate level documentation
cargo devel CI / cargo CI (push) Has been cancelled Details
but I'm lazy
2024-07-09 19:43:43 +02:00
Christoph J. Scherr 087e6dad8c refactor(py)!: remove libpt-py #87
cargo devel CI / cargo CI (push) Failing after 1m40s Details
2024-07-09 19:41:34 +02:00
Christoph J. Scherr 8226d74fb9 feat(log): apperently, it wasn't possible to set a min log level?
cargo devel CI / cargo CI (push) Failing after 1m44s Details
2024-07-09 19:39:33 +02:00
Christoph J. Scherr 729c4e3a4e fix(log): logfile works again #90 2024-07-09 19:37:56 +02:00
Christoph J. Scherr 1c92f95901 docs(log): add an example for using a logfile 2024-07-09 19:37:13 +02:00
Christoph J. Scherr 673eb691e9 fix(cli): clap count parser only works with u8, so revert the change to i8 back
cargo devel CI / cargo CI (push) Failing after 1m46s Details
2024-07-09 19:34:46 +02:00
Christoph J. Scherr b382b3e501 refactor(cli): cli example was weird 2024-07-09 19:29:20 +02:00
Christoph J. Scherr 87dc2871d7 refactor(log)!: rename ansiconst -> ansi
cargo devel CI / cargo CI (push) Failing after 1m46s Details
idk why it was called that, seems dumb, better break now than later in
case I actually get users
2024-07-09 18:33:31 +02:00
Christoph J. Scherr edb6342b0c docs(log): add defaults to builder methods #82
cargo devel CI / cargo CI (push) Failing after 1m45s Details
2024-07-09 18:31:30 +02:00
Christoph J. Scherr b2bf00db46 refactor(log): apply more clippy findings
cargo devel CI / cargo CI (push) Failing after 1m44s Details
2024-07-09 18:25:50 +02:00
Christoph J. Scherr 73f935d9b2 refactor(log): remove depereciated Logger::build()
cargo devel CI / cargo CI (push) Failing after 1m37s Details
2024-07-09 18:23:24 +02:00
Christoph J. Scherr 9b94c25234 refactor(log): apply clippy findings
cargo devel CI / cargo CI (push) Has been cancelled Details
2024-07-09 18:22:44 +02:00
Christoph J. Scherr 511fd69ab6 Merge pull request 'implement a cli module' (#85) from feat/cli into devel
cargo devel CI / cargo CI (push) Successful in 2m20s Details
Reviewed-on: #85
2024-07-09 18:12:24 +02:00
30 changed files with 329 additions and 715 deletions

View File

@ -21,8 +21,6 @@ jobs:
run: |
rustup component add rustfmt
rustup component add clippy
- name: install python
run: apt update && apt install libpython3-dev -y
- name: config custom registry
run: |
mkdir -p ~/.cargo/
@ -45,4 +43,4 @@ jobs:
with:
# Optional. Commit message for the created commit.
# Defaults to "Apply automatic changes"
commit_message: automatic cargo CI changes
commit_message: "ci: automatic cargo CI changes"

7
.github/dependabot.yaml vendored Normal file
View File

@ -0,0 +1,7 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
# Check for updates every Monday
schedule:
interval: "weekly"

View File

@ -1,10 +1,16 @@
name: cargo devel CI
name: Rust CI
on:
pull_request:
branches:
- '**'
push:
branches:
- '**'
# - '!master'
env:
CARGO_TERM_COLOR: always
jobs:
CI:
runs-on: ubuntu-latest
@ -42,10 +48,10 @@ jobs:
- name: cargo fmt
run: cargo fmt --all
- name: cargo test
run: cargo test --all-features --all-targets --workspace && cargo test --all-features --workspace --doc
run: cargo test --all-features --all-targets --workspace
- name: commit back to repository
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_message: "ci: automatic Rust CI changes"

54
.github/workflows/release.yaml vendored Normal file
View File

@ -0,0 +1,54 @@
name: Release-plz
permissions:
pull-requests: write
contents: write
on:
push:
branches:
- master
- main
jobs:
# Release unpublished packages.
release-plz-release:
name: Release-plz release
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Run release-plz
uses: MarcoIeni/release-plz-action@v0.5
with:
command: release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
# Create a PR with the new versions and changelog, preparing the next release.
release-plz-pr:
name: Release-plz PR
runs-on: ubuntu-latest
concurrency:
group: release-plz-${{ github.ref }}
cancel-in-progress: false
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Run release-plz
uses: MarcoIeni/release-plz-action@v0.5
with:
command: release-pr
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

View File

@ -1,17 +1,11 @@
[workspace]
resolver = "2"
members = [
".",
"members/libpt-core",
"members/libpt-log",
"members/libpt-py",
"members/libpt-cli",
]
members = [".", "members/libpt-core", "members/libpt-log", "members/libpt-cli"]
default-members = [".", "members/libpt-core"]
[workspace.package]
publish = true
version = "0.6.0-alpha.0"
version = "0.7.3-alpha.2"
edition = "2021"
authors = ["Christoph J. Scherr <software@cscherr.de>"]
license = "GPL-3.0-or-later"
@ -20,19 +14,15 @@ readme = "README.md"
homepage = "https://git.cscherr.de/PlexSheep/pt"
repository = "https://git.cscherr.de/PlexSheep/pt"
keywords = ["library"]
categories = [
"command-line-utilities",
"development-tools",
"development-tools::ffi",
]
categories = ["command-line-utilities", "development-tools"]
[workspace.dependencies]
anyhow = "1.0.79"
thiserror = "1.0.56"
libpt-core = { version = "0.4.0", path = "members/libpt-core" }
libpt-core = { version = "0.5.0", path = "members/libpt-core" }
libpt-bintols = { version = "0.5.1", path = "members/libpt-bintols" }
libpt-log = { version = "0.4.2", path = "members/libpt-log" }
libpt-cli = { version = "0.1.0", path = "members/libpt-cli" }
libpt-log = { version = "0.6.2-alpha.1", path = "members/libpt-log" }
libpt-cli = { version = "0.2.2-alpha.1", path = "members/libpt-cli" }
[package]
name = "libpt"
@ -51,11 +41,11 @@ categories.workspace = true
[features]
default = ["log", "core"]
core = []
full = ["default", "core", "log", "bintols"]
full = ["default", "core", "log", "bintols", "libpt-cli/full"]
log = ["dep:libpt-log"]
log-crate = ["libpt-cli/log"]
bintols = ["dep:libpt-bintols", "log"]
cli = ["dep:libpt-cli", "core", "log"]
# py = ["dep:libpt-py"]
[lib]
name = "libpt"
@ -69,4 +59,8 @@ crate-type = [
libpt-core = { workspace = true }
libpt-bintols = { workspace = true, optional = true }
libpt-log = { workspace = true, optional = true }
libpt-cli = { workspace = true, optional = true }
libpt-cli = { workspace = true, optional = true, features = ["log"] }
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

View File

@ -40,12 +40,19 @@ If you want to use the python variant too, you need to compile with maturing.
## Installing from [pypi](https://pypi.org)
`libpt` has been packaged for [pypi.org](https://pypi.org/project/libpt/).
The Python interface of `libpt` is currently not implemented, but it is planned
to eventually re add it. Meanwhile, you can use a much older version if you
really want.
You can install it with `pip install libpt`
> :warning: **This will install a very old version**
>
> `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`.

View File

@ -20,3 +20,7 @@ libpt-core = { workspace = true }
libpt-log = { workspace = true }
anyhow = { workspace = true }
thiserror = { workspace = true }
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

View File

@ -1,7 +1,7 @@
[package]
name = "libpt-cli"
publish.workspace = true
version = "0.1.0"
version = "0.2.2-alpha.2"
edition.workspace = true
authors.workspace = true
license.workspace = true
@ -12,11 +12,9 @@ repository.workspace = true
keywords.workspace = true
categories.workspace = true
[package.metadata.docs.rs]
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
[features]
default = []
full = ["log"]
log = ["dep:log"]
[dependencies]
@ -26,11 +24,14 @@ comfy-table = "7.1.1"
console = "0.15.8"
dialoguer = { version = "0.11.0", features = ["completion", "history"] }
embed-doc-image = "0.1.4"
exitcode = "1.1.2"
human-panic = "2.0.0"
indicatif = "0.17.8"
libpt-log = { workspace = true, optional = false }
log = { version = "0.4.21", optional = true }
serde = { version = "1.0.209", features = ["derive"] }
shlex = "1.3.0"
strum = { version = "0.26.3", features = ["derive"] }
thiserror.workspace = true
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

View File

@ -1,6 +1,6 @@
use clap::Parser;
use libpt_cli::args::VerbosityLevel;
use libpt_cli::{clap, printing};
use libpt_cli::printing;
use libpt_log::{debug, Logger};
/// This is the help
@ -23,10 +23,7 @@ struct Cli {
fn main() {
let cli = Cli::parse();
let _logger = Logger::builder()
.max_level(cli.verbosity.level())
.show_time(false)
.build();
let _logger = Logger::builder().set_level(cli.verbosity.level()).build();
debug!("logger initialized with level: {}", cli.verbosity.level());

View File

@ -1,7 +1,7 @@
use console::style;
use libpt_cli::printing;
use libpt_cli::repl::{DefaultRepl, Repl};
use libpt_cli::{clap, printing, strum};
use libpt_log::{debug, Level, Logger};
use libpt_log::{debug, Logger};
use clap::Subcommand;
use strum::EnumIter;
@ -31,10 +31,7 @@ enum ReplCommand {
fn main() -> anyhow::Result<()> {
// You would normally make a proper cli interface with clap before entering the repl. This is
// omitted here for brevity
let _logger = Logger::builder()
.show_time(false)
.max_level(Level::INFO)
.build()?;
let _logger = Logger::builder().display_time(false).build();
// the compiler can infer that we want to use the ReplCommand enum.
let mut repl = DefaultRepl::<ReplCommand>::default();
@ -76,7 +73,7 @@ fn main() -> anyhow::Result<()> {
if !fancy {
println!("{}", text.join(" "))
} else {
printing::blockprint(&text.join(" "), console::Color::Cyan)
printing::blockprint(text.join(" "), console::Color::Cyan)
}
}
}

View File

@ -4,6 +4,7 @@ use clap::Parser;
use libpt_log::Level;
#[cfg(feature = "log")]
use log;
use serde::{Deserialize, Serialize};
/// Custom help template for displaying command-line usage information
///
@ -18,7 +19,7 @@ use log;
/// # use libpt_cli::args::HELP_TEMPLATE;
/// use clap::Parser;
/// #[derive(Parser, Debug, Clone, PartialEq, Eq, Hash)]
/// #[command(help_template = HELP_TEMPLATE)]
/// #[command(help_template = HELP_TEMPLATE, author, version)]
/// pub struct MyArgs {
/// /// show more details
/// #[arg(short, long)]
@ -77,9 +78,9 @@ Author: {author-with-newline}
/// Get the loglevel like this:
///
/// ```no_run
/// # use libpt_cli::args::VerbosityLevel;
/// use libpt_cli::args::VerbosityLevel;
/// use libpt_log::Level;
/// # use clap::Parser;
/// use clap::Parser;
///
/// # #[derive(Parser, Debug)]
/// # pub struct Opts {
@ -95,18 +96,18 @@ Author: {author-with-newline}
/// let level: Level = opts.verbose.level();
/// }
/// ```
#[derive(Parser, Clone, PartialEq, Eq, Hash)]
#[derive(Parser, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub struct VerbosityLevel {
/// make the output more verbose
#[arg(
long,
short = 'v',
action = clap::ArgAction::Count,
action = clap::ArgAction::Count, // NOTE: this forces u8 type for some reason
global = true,
// help = L::verbose_help(),
// long_help = L::verbose_long_help(),
)]
verbose: i8,
verbose: u8,
/// make the output less verbose
///
@ -118,7 +119,7 @@ pub struct VerbosityLevel {
global = true,
conflicts_with = "verbose",
)]
quiet: i8,
quiet: u8,
}
impl VerbosityLevel {
@ -131,7 +132,7 @@ impl VerbosityLevel {
}
#[inline]
#[must_use]
fn value(&self) -> i8 {
fn value(&self) -> u8 {
Self::level_value(Level::INFO)
.saturating_sub((self.quiet).min(10))
.saturating_add((self.verbose).min(10))
@ -189,7 +190,7 @@ impl VerbosityLevel {
#[inline]
#[must_use]
const fn level_value(level: Level) -> i8 {
const fn level_value(level: Level) -> u8 {
match level {
Level::TRACE => 4,
Level::DEBUG => 3,

View File

@ -1,14 +1,6 @@
//! This module bundles a lot of good CLI tools, and adds some of it's own, to make development of
//! CLI apps easier and more ergonomic.
#![warn(clippy::pedantic, clippy::style, clippy::nursery)]
pub mod args;
pub mod printing;
pub mod repl;
pub use clap;
pub use comfy_table;
pub use console;
pub use dialoguer;
pub use exitcode;
pub use human_panic;
pub use indicatif;
pub use shlex;
pub use strum;

View File

@ -42,7 +42,7 @@ use console::{style, Color};
/// # Example
///
/// ```
/// use libpt_cli::console::Color;
/// use console::Color;
/// use libpt_cli::printing::blockprint;
/// # fn main() {
/// blockprint("Hello world!", Color::Blue);
@ -64,7 +64,7 @@ pub fn blockprint(content: impl ToString, color: Color) {
/// # Example
///
/// ```
/// use libpt_cli::console::Color;
/// use console::Color;
/// use libpt_cli::printing::blockfmt;
/// # fn main() {
/// let formatted_content = blockfmt("Hello world!", Color::Blue);
@ -93,8 +93,8 @@ pub fn blockfmt(content: impl ToString, color: Color) -> String {
///
/// # Example
/// ```
/// use libpt_cli::comfy_table::{presets, CellAlignment, ContentArrangement};
/// use libpt_cli::console::Color;
/// use comfy_table::{presets, CellAlignment, ContentArrangement};
/// use console::Color;
/// use libpt_cli::printing::blockfmt_advanced;
/// # fn main() {
/// println!(

View File

@ -27,8 +27,8 @@ use libpt_log::trace;
///
/// ```no_run
/// use libpt_cli::repl::{DefaultRepl, Repl};
/// use libpt_cli::clap::Subcommand;
/// use libpt_cli::strum::EnumIter;
/// use clap::Subcommand;
/// use strum::EnumIter;
///
/// #[derive(Subcommand, Debug, EnumIter, Clone)]
/// enum ReplCommand {

View File

@ -1,7 +1,7 @@
[package]
name = "libpt-core"
publish.workspace = true
version = "0.4.0"
version = "0.5.0"
edition.workspace = true
authors.workspace = true
license.workspace = true
@ -14,6 +14,9 @@ categories.workspace = true
[dependencies]
anyhow = "1.0.79"
libpt-log = { workspace = true }
[dev-dependencies]
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

View File

@ -8,3 +8,16 @@
/// macros to make things faster in your code
pub mod macros;
/// ## Get the name of the crate that uses your library
///
/// Let's say you're writing the library `foo` and need the name of the crate that uses `foo`. With
/// this function, you can get the name of the crate that uses `foo`.
///
/// Will return [None] if [`std::env::current_exe()`] errors or if conversion to [String] from [std::ffi::OsStr] fails.
pub fn get_crate_name() -> Option<String> {
if let Ok(exe) = std::env::current_exe() {
return Some(exe.file_stem()?.to_str()?.to_string());
}
None
}

View File

@ -1,7 +1,7 @@
[package]
name = "libpt-log"
publish.workspace = true
version = "0.4.3"
version = "0.6.2-alpha.2"
edition.workspace = true
authors.workspace = true
license.workspace = true
@ -13,11 +13,17 @@ keywords.workspace = true
categories.workspace = true
[dependencies]
tracing = "0.1.37"
tracing-appender = "0.2.2"
tracing-subscriber = "0.3.17"
tracing = "0.1.40"
tracing-appender = "0.2.3"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
anyhow = { workspace = true }
thiserror = { workspace = true }
libpt-core = { workspace = true, optional = false }
chrono = "0.4.38"
[dev-dependencies]
gag = "1.0.0"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

View File

@ -0,0 +1,11 @@
use libpt_log::Logger;
use tracing::info;
fn main() {
let _logger = Logger::builder()
.log_to_file(true)
.log_dir("/tmp/llll".into())
.build()
.unwrap();
info!("foo bar qux");
}

View File

@ -17,7 +17,9 @@ pub enum Error {
/// Could not assign logger as the global default
#[error("Could not assign logger as global default")]
SetGlobalDefaultFail(#[from] SetGlobalDefaultError),
/// any other error type, wrapped in [anyhow::Error](anyhow::Error)
/// any other error type, wrapped in [`anyhow::Error`]
#[error(transparent)]
Other(#[from] anyhow::Error),
#[error("Tried to open the logfile, but logging to file was not requested")]
LogfileButNoFilelog,
}

View File

@ -6,27 +6,34 @@
//! For the library version, only the basic [`tracing`] is used, so that it is possible for
//! the end user to use the [`tracing`] frontend they desire.
//!
//! I did however decide to create a [`Logger`] struct. This struct is mainly intended to be used
//! with the python module of [`pt`](../libpt/index.html), but is still just as usable in other contexts.
//! I did decide to create a [`Logger`] struct. This struct is mainly intended to be used with the
//! python module of [`pt`](../libpt/index.html), but is still just as usable in other contexts.
//! You can use this struct when use of the macros is not possible, but the macros should generally
//! be preferred.
//!
//! ## Technologies used for logging:
//! - [`tracing`]: base logging crate
//! - [`tracing_appender`]: Used to log to files
//! - [`tracing_subscriber`]: Used to do actual logging, formatting, to stdout
#![warn(clippy::pedantic, clippy::style, clippy::nursery)]
use std::{
fmt,
fmt::{self, Debug},
path::PathBuf,
sync::atomic::{AtomicBool, Ordering},
};
pub mod error;
use error::*;
use error::Error;
/// This is the magic dependency where the cool stuff happens
///
/// I'm just repackaging it a little to make it more ergonomic
pub use tracing;
pub use tracing::{debug, error, info, trace, warn, Level};
use tracing_appender::{self, non_blocking::NonBlocking};
use tracing_subscriber::fmt::{format::FmtSpan, time};
use tracing_subscriber::{
fmt::format::FmtSpan, layer::SubscriberExt as _, util::SubscriberInitExt, Layer,
};
use anyhow::{bail, Result};
/// The log level used when none is specified
@ -55,7 +62,9 @@ static INITIALIZED: AtomicBool = AtomicBool::new(false);
/// # }
///
/// ```
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
#[allow(clippy::struct_excessive_bools)] // it's just true/false values, not states, and I don't
// need to reinvent the wheel
pub struct LoggerBuilder {
/// create and log to logfiles
log_to_file: bool,
@ -86,6 +95,8 @@ pub struct LoggerBuilder {
show_time: bool,
/// show timestamps as uptime (duration since the logger was initialized)
uptime: bool,
/// log when span things happen
span_events: FmtSpan,
}
impl LoggerBuilder {
@ -120,110 +131,89 @@ impl LoggerBuilder {
/// This function will return an error if a global Logger was aready initialized. This module
/// uses the [tracing] crate for logging, so if a [tracing] logger is initialized elsewhere,
/// this method will error.
#[allow(clippy::missing_panics_doc)]
pub fn build(self) -> Result<Logger> {
// only init if no init has been performed yet
if INITIALIZED.load(Ordering::Relaxed) {
warn!("trying to reinitialize the logger, ignoring");
bail!(Error::Usage("logging is already initialized".to_string()));
}
let subscriber = tracing_subscriber::fmt::Subscriber::builder()
.with_level(self.display_level)
.with_max_level(self.max_level)
let layer = tracing_subscriber::fmt::layer()
.with_ansi(self.ansi)
.with_target(self.display_target)
.with_file(self.display_filename)
.with_thread_ids(self.display_thread_ids)
.with_line_number(self.display_line_number)
.with_thread_names(self.display_thread_names)
.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
// project that could do it any other way. You can't apply one after another, because the
// type is changed every time. When using `Box<dyn Whatever>`, some methods complain about
// not being in trait bounds.
// TODO: somehow find a better solution for this
match (self.log_to_file, self.show_time, self.pretty, self.uptime) {
(true, true, true, true) => {
let subscriber = subscriber
.with_writer(new_file_appender(self.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(self.log_dir))
.pretty()
.finish();
tracing::subscriber::set_global_default(subscriber)?;
}
(true, false, true, _) => {
let subscriber = subscriber
.with_writer(new_file_appender(self.log_dir))
.without_time()
.pretty()
.finish();
tracing::subscriber::set_global_default(subscriber)?;
}
(true, true, false, true) => {
let subscriber = subscriber
.with_writer(new_file_appender(self.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(self.log_dir))
.finish();
tracing::subscriber::set_global_default(subscriber)?;
}
(true, false, false, _) => {
let file_appender = tracing_appender::rolling::daily(self.log_dir.clone(), "log");
let (file_writer, _guard) = tracing_appender::non_blocking(file_appender);
let subscriber = subscriber.with_writer(file_writer).without_time().finish();
tracing::subscriber::set_global_default(subscriber)?;
}
(false, true, true, true) => {
let subscriber = subscriber.pretty().with_timer(time::uptime()).finish();
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)?;
}
.with_span_events(self.span_events.clone())
.with_filter(tracing::level_filters::LevelFilter::from_level(
self.max_level,
));
if self.log_to_file {
tracing_subscriber::registry()
.with(layer.and_then({
tracing_subscriber::fmt::layer()
.with_writer(
self.logfile()?
.expect("logging to file is requested but logfile returned None"),
)
.with_ansi(self.ansi)
.with_target(self.display_target)
.with_file(self.display_filename)
.with_thread_ids(self.display_thread_ids)
.with_line_number(self.display_line_number)
.with_thread_names(self.display_thread_names)
.with_span_events(self.span_events.clone())
.with_filter(tracing::level_filters::LevelFilter::from_level(
self.max_level,
))
}))
.init();
} else {
tracing_subscriber::registry().with(layer).init();
}
INITIALIZED.store(true, Ordering::Relaxed);
Ok(Logger {})
}
/// Opens a new file for logging to.
///
/// Format: `{log_dir}/{consumer_name}_2024-09-01.log`
///
/// Will be none if [`Self::log_to_file`] is [false].
fn logfile(&self) -> Result<Option<std::fs::File>> {
if !self.log_to_file {
return Err(Error::LogfileButNoFilelog.into());
}
let mut path = self.log_dir.clone();
std::fs::create_dir_all(&path)?;
path.push(format!(
"{}_{}.log",
libpt_core::get_crate_name().unwrap_or_else(|| "logfile".to_string()),
chrono::Local::now().date_naive()
));
let file = std::fs::File::create(path)?;
Ok(Some(file))
}
/// enable or disable logging to and creating of logfiles
pub fn log_to_file(mut self, log_to_file: bool) -> Self {
///
/// If you want to log to a file, don't forget to set [`Self::log_dir`]!
///
/// Default: false
#[must_use]
pub const fn log_to_file(mut self, log_to_file: bool) -> Self {
self.log_to_file = log_to_file;
self
}
/// set a directory where logfiles would be created in
///
/// Enable or disable creation and logging to logfiles with [log_to_file](Self::log_to_file).
/// Enable or disable creation and logging to logfiles with [`log_to_file`](Self::log_to_file).
///
/// The default logdir is [DEFAULT_LOG_DIR].
/// Default: [`DEFAULT_LOG_DIR`] (/dev/null)
#[must_use]
pub fn log_dir(mut self, log_dir: PathBuf) -> Self {
self.log_dir = log_dir;
self
@ -235,68 +225,110 @@ impl LoggerBuilder {
/// are displayed by a program that does not interpret them.
///
/// Keeping ANSI control sequences enabled has the disadvantage of added colors for the logs.
pub fn ansi(mut self, ansi: bool) -> Self {
///
/// Default: true
#[must_use]
pub const fn ansi(mut self, ansi: bool) -> Self {
self.ansi = ansi;
self
}
/// when making a log, display the source file in which a log was crated in
pub fn display_filename(mut self, display_filename: bool) -> Self {
///
/// Default: false
#[must_use]
pub const fn display_filename(mut self, display_filename: bool) -> Self {
self.display_filename = display_filename;
self
}
/// when making a log, display the time of the message
///
/// Default: true
#[must_use]
pub const fn display_time(mut self, show_time: bool) -> Self {
self.show_time = show_time;
self
}
/// when making a log, display the log level of the message
pub fn display_level(mut self, display_level: bool) -> Self {
///
/// Default: true
#[must_use]
pub const fn display_level(mut self, display_level: bool) -> Self {
self.display_level = display_level;
self
}
/// show target context
pub fn display_target(mut self, display_target: bool) -> Self {
///
/// Default: false
#[must_use]
pub const fn display_target(mut self, display_target: bool) -> Self {
self.display_target = display_target;
self
}
/// set the maximum verbosity level.
pub fn max_level(mut self, max_level: Level) -> Self {
self.max_level = max_level;
self
}
/// show the id of the thread that created this message
pub fn display_thread_ids(mut self, display_thread_ids: bool) -> Self {
///
/// Default: false
#[must_use]
pub const fn display_thread_ids(mut self, display_thread_ids: bool) -> Self {
self.display_thread_ids = display_thread_ids;
self
}
/// show the name of the thread that created this message
pub fn display_thread_names(mut self, display_thread_names: bool) -> Self {
///
/// Default: false
#[must_use]
pub const fn display_thread_names(mut self, display_thread_names: bool) -> Self {
self.display_thread_names = display_thread_names;
self
}
/// show which line in the source file produces a log
pub fn display_line_number(mut self, display_line_number: bool) -> Self {
///
/// Default: false
#[must_use]
pub const fn display_line_number(mut self, display_line_number: bool) -> Self {
self.display_line_number = display_line_number;
self
}
/// splits a log over multiple lines, looks like a python traceback
pub fn pretty(mut self, pretty: bool) -> Self {
///
/// Default: false
#[must_use]
pub const fn pretty(mut self, pretty: bool) -> Self {
self.pretty = pretty;
self
}
/// show a timestamp describing when the log was created
pub fn show_time(mut self, show_time: bool) -> Self {
self.show_time = show_time;
/// show timestamps as uptime (duration since the logger was initialized)
///
/// Default: false
#[must_use]
pub const fn uptime(mut self, uptime: bool) -> Self {
self.uptime = uptime;
self
}
/// show timestamps as uptime (duration since the logger was initialized)
pub fn uptime(mut self, uptime: bool) -> Self {
self.uptime = uptime;
/// set the lowest loglevel to be displayed
///
/// Default: [`Level::INFO`]
#[must_use]
pub const fn set_level(mut self, max_level: Level) -> Self {
self.max_level = max_level;
self
}
/// set how span events are handled
///
/// Default: [`FmtSpan::NONE`]
#[must_use]
pub const fn span_events(mut self, span_events: FmtSpan) -> Self {
self.span_events = span_events;
self
}
}
@ -317,11 +349,12 @@ impl Default for LoggerBuilder {
pretty: false,
show_time: true,
uptime: false,
span_events: FmtSpan::NONE,
}
}
}
/// ## Logger for [`pt`](libpt)
/// ## Logger for `libpt`
///
/// A logger is generally a functionality that let's you write information from your library or
/// application in a more structured manner than if you just wrote all information to `stdout` or
@ -333,19 +366,23 @@ impl Default for LoggerBuilder {
///
/// ## Levels
///
/// TODO: add levels desc and ascii art
/// * [ERROR](Level::ERROR) Something broke
/// * [WARN](Level::WARN) Something is bad
/// * [INFO](Level::INFO) Useful information for users
/// * [DEBUG](Level::DEBUG) Useful information for developers
/// * [TRACE](Level::TRACE) Very verbose information for developers (often for libraries)
///
/// ## Usage
///
/// You don't need to use the [Logger] struct, it's better to use the macros instead:
///
/// * `error!`
/// * `warn!`
/// * `info!`
/// * `debug!`
/// * `trace!`
/// * [`error!`]
/// * [`warn!`]
/// * [`info!`]
/// * [`debug!`]
/// * [`trace!`]
///
/// You can however use the [Logger] struct in cases where usage of a macro is bad or
/// You can however use the [Logger] struct in cases where usage of a macro is impossible or
/// you are somehow working with multiple loggers. The macros offer additional functionalities,
/// suck as full `format!` support and context, see [`tracing`], which we use as backend.
///
@ -365,206 +402,46 @@ pub struct Logger;
/// ## Main implementation
impl Logger {
/// Get a new [LoggerBuilder]
/// Get a new [`LoggerBuilder`]
#[must_use]
pub fn builder() -> LoggerBuilder {
LoggerBuilder::default()
}
/// ## initializes the logger
///
/// Will enable the logger to be used.
///
/// Assumes some defaults, use [`init_customized`](Self::init_customized) for more control
#[deprecated(since = "0.4.1", note = "use Logger::builder() instead")]
pub fn build(log_dir: Option<PathBuf>, max_level: Option<Level>, uptime: bool) -> Result<Self> {
#[allow(deprecated)]
Self::build_customized(
log_dir.is_some(),
log_dir.unwrap_or(PathBuf::from(DEFAULT_LOG_DIR)),
true,
false,
true,
false,
max_level.unwrap_or(DEFAULT_LOG_LEVEL),
false,
false,
false,
false,
true,
uptime,
)
}
/// ## 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
#[deprecated(since = "0.4.1", note = "use Logger::builder() instead")]
pub fn build_mini(max_level: Option<Level>) -> Result<Self> {
#[allow(deprecated)]
Self::build_customized(
false,
PathBuf::from(DEFAULT_LOG_DIR),
true,
false,
true,
false,
max_level.unwrap_or(DEFAULT_LOG_LEVEL),
false,
false,
false,
false,
false,
false,
)
}
/// ## initializes the logger
///
/// Will enable the logger to be used.
#[deprecated(since = "0.4.1", note = "use Logger::builder() instead")]
#[allow(clippy::too_many_arguments)]
pub fn build_customized(
log_to_file: bool,
log_dir: PathBuf,
ansi: bool,
display_filename: bool,
display_level: bool,
display_target: bool,
max_level: Level,
display_thread_ids: bool,
display_thread_names: bool,
display_line_number: bool,
pretty: bool,
show_time: bool,
uptime: bool, // uptime instead of system time
) -> Result<Self> {
// only init if no init has been performed yet
if INITIALIZED.load(Ordering::Relaxed) {
warn!("trying to reinitialize the logger, ignoring");
bail!(Error::Usage("logging is already initialized".to_string()));
}
let subscriber = tracing_subscriber::fmt::Subscriber::builder()
.with_level(display_level)
.with_max_level(max_level)
.with_ansi(ansi)
.with_target(display_target)
.with_file(display_filename)
.with_thread_ids(display_thread_ids)
.with_line_number(display_line_number)
.with_thread_names(display_thread_names)
.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
// project that could do it any other way. You can't apply one after another, because the
// type is changed every time. When using Box<dyn Whatever>, some methods complain about
// not being in trait bounds.
// TODO: somehow find a better solution for this
match (log_to_file, show_time, pretty, uptime) {
(true, true, true, true) => {
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 subscriber = subscriber.with_writer(file_writer).without_time().finish();
tracing::subscriber::set_global_default(subscriber)?;
}
(false, true, true, true) => {
let subscriber = subscriber.pretty().with_timer(time::uptime()).finish();
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);
Ok(Logger {})
}
/// ## logging at [`Level::ERROR`]
pub fn error<T>(&self, printable: T)
where
T: fmt::Display,
{
error!("{}", printable)
error!("{}", printable);
}
/// ## logging at [`Level::WARN`]
pub fn warn<T>(&self, printable: T)
where
T: fmt::Display,
{
warn!("{}", printable)
warn!("{}", printable);
}
/// ## logging at [`Level::INFO`]
pub fn info<T>(&self, printable: T)
where
T: fmt::Display,
{
info!("{}", printable)
info!("{}", printable);
}
/// ## logging at [`Level::DEBUG`]
pub fn debug<T>(&self, printable: T)
where
T: fmt::Display,
{
debug!("{}", printable)
debug!("{}", printable);
}
/// ## logging at [`Level::TRACE`]
pub fn trace<T>(&self, printable: T)
where
T: fmt::Display,
{
trace!("{}", printable)
trace!("{}", printable);
}
}
@ -586,8 +463,3 @@ impl Default for Logger {
.expect("building a Logger failed")
}
}
fn new_file_appender(log_dir: PathBuf) -> NonBlocking {
let file_appender = tracing_appender::rolling::daily(log_dir.clone(), "log");
tracing_appender::non_blocking(file_appender).0
}

View File

@ -1,72 +0,0 @@
/target
# Byte-compiled / optimized / DLL files
__pycache__/
.pytest_cache/
*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
.venv/
env/
bin/
build/
develop-eggs/
dist/
eggs/
lib/
lib64/
parts/
sdist/
var/
include/
man/
venv/
*.egg-info/
.installed.cfg
*.egg
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
pip-selfcheck.json
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Rope
.ropeproject
# Django stuff:
*.log
*.pot
.DS_Store
# Sphinx documentation
docs/_build/
# PyCharm
.idea/
# VSCode
.vscode/
# Pyenv
.python-version

View File

@ -1,31 +0,0 @@
[package]
name = "libpt-py"
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
[package.metadata.maturin]
name = "libpt"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
libpt = { version = "0.5.0"}
pyo3 = { version = "0.19.0", features = ["full"] }
anyhow.workspace = true
[features]
default = ["log", "core", "full"]
core = []
full = ["default", "core", "log", "bintols"]
log = ["libpt/log"]
bintols = ["libpt/bintols", "log"]

View File

@ -1,16 +0,0 @@
[build-system]
requires = ["maturin>=1.4,<2.0"]
build-backend = "maturin"
[project]
name = "libpt"
requires-python = ">=3.8"
classifiers = [
"Programming Language :: Rust",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]
dynamic = ["version"]
[tool.maturin]
features = ["pyo3/extension-module"]

View File

@ -1,76 +0,0 @@
use pyo3::prelude::*;
use libpt::bintols as origin;
mod split {
use libpt::bintols::split as origin;
use pyo3::prelude::*;
#[pyfunction]
pub fn split_int(data: u128) -> Vec<u8> {
origin::unsigned_to_vec(data)
}
/// implement a python module in Rust
pub fn submodule(py: Python, parent: &PyModule) -> PyResult<()> {
let module = PyModule::new(py, "split")?;
module.add_function(wrap_pyfunction!(split_int, module)?)?;
parent.add_submodule(module)?;
Ok(())
}
}
mod display {
use libpt::bintols::display as origin;
use pyo3::prelude::*;
#[pyfunction]
pub fn bytes_to_bin(data: &[u8]) -> String {
origin::bytes_to_bin(data)
}
#[pyfunction]
pub fn byte_bit_display(data: usize) -> String {
origin::byte_bit_display(data)
}
#[pyfunction]
pub fn humanbytes(total: u128) -> String {
origin::humanbytes(total)
}
/// implement a python module in Rust
pub fn submodule(py: Python, parent: &PyModule) -> PyResult<()> {
let module = PyModule::new(py, "display")?;
module.add_function(wrap_pyfunction!(bytes_to_bin, module)?)?;
module.add_function(wrap_pyfunction!(byte_bit_display, module)?)?;
module.add_function(wrap_pyfunction!(humanbytes, module)?)?;
parent.add_submodule(module)?;
Ok(())
}
}
/// implement a python module in Rust
pub fn submodule(py: Python, parent: &PyModule) -> PyResult<()> {
let module = PyModule::new(py, "bintols")?;
// binary constants
module.add("KIBI", origin::KIBI)?;
module.add("MEBI", origin::MEBI)?;
module.add("GIBI", origin::GIBI)?;
module.add("TEBI", origin::TEBI)?;
module.add("PEBI", origin::PEBI)?;
module.add("EXBI", origin::EXBI)?;
module.add("ZEBI", origin::ZEBI)?;
module.add("YOBI", origin::YOBI)?;
display::submodule(py, module)?;
split::submodule(py, module)?;
parent.add_submodule(module)?;
Ok(())
}

View File

@ -1,11 +0,0 @@
use pyo3::prelude::*;
mod printing;
/// implement a python module in Rust
pub fn submodule(py: Python, parent: &PyModule) -> PyResult<()> {
let module = PyModule::new(py, "core")?;
printing::submodule(py, module)?;
parent.add_submodule(module)?;
Ok(())
}

View File

@ -1,24 +0,0 @@
use pyo3::prelude::*;
use libpt::core::printing as origin;
/// Quickly get a one line visual divider
#[pyfunction]
pub fn divider() -> String {
origin::divider()
}
/// Quickly print a one line visual divider
#[pyfunction]
pub fn print_divider() {
origin::print_divider()
}
/// implement a python module in Rust
pub fn submodule(py: Python, parent: &PyModule) -> PyResult<()> {
let module = PyModule::new(py, "printing")?;
module.add_function(wrap_pyfunction!(divider, module)?)?;
module.add_function(wrap_pyfunction!(print_divider, module)?)?;
parent.add_submodule(module)?;
Ok(())
}

View File

@ -1,30 +0,0 @@
//! Python bindings for [`libpt`]
#[cfg(feature = "bintols")]
mod bintols;
#[cfg(feature = "core")]
mod core;
#[cfg(feature = "log")]
mod log;
use pyo3::prelude::*;
/// return the version of libpt
#[pyfunction]
fn version() -> String {
env!("CARGO_PKG_VERSION").to_string()
}
/// implement a python module in Rust
#[pymodule]
#[pyo3(name = "libpt")]
fn libpt_py(py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(version, m)?)?;
#[cfg(feature = "core")]
core::submodule(py, m)?;
#[cfg(feature = "log")]
log::submodule(py, m)?;
#[cfg(feature = "bintols")]
bintols::submodule(py, m)?;
Ok(())
}

View File

@ -1,91 +0,0 @@
use std::path::PathBuf;
use pyo3::prelude::*;
use libpt::log as origin;
#[derive(Clone)]
#[pyclass]
pub enum Level {
Error,
Warn,
Info,
Debug,
Trace,
}
impl From<Level> for origin::Level {
fn from(value: Level) -> Self {
match value {
Level::Error => origin::Level::ERROR,
Level::Warn => origin::Level::WARN,
Level::Info => origin::Level::INFO,
Level::Debug => origin::Level::DEBUG,
Level::Trace => origin::Level::TRACE,
}
}
}
#[pyclass]
pub struct Logger {
inner: origin::Logger,
}
impl From<origin::Logger> for Logger {
fn from(inner: origin::Logger) -> Self {
Self { inner }
}
}
#[pymethods]
impl Logger {
#[new]
pub fn build(
log_dir: Option<PathBuf>,
max_level: Option<Level>,
uptime: Option<bool>,
) -> anyhow::Result<Self> {
// concert our wrapper type
let max_level = max_level.map(origin::Level::from);
let mut builder = origin::Logger::builder();
if log_dir.is_some() {
builder = builder.log_dir(log_dir.unwrap());
}
if max_level.is_some() {
builder = builder.max_level(max_level.unwrap());
}
if uptime.is_some() {
builder = builder.uptime(uptime.unwrap());
}
Ok(builder.build()?.into())
}
/// ## logging at [`Level::ERROR`]
pub fn error(&self, printable: String) {
self.inner.error(printable)
}
/// ## logging at [`Level::WARN`]
pub fn warn(&self, printable: String) {
self.inner.warn(printable)
}
/// ## logging at [`Level::INFO`]
pub fn info(&self, printable: String) {
self.inner.info(printable)
}
/// ## logging at [`Level::DEBUG`]
pub fn debug(&self, printable: String) {
self.inner.debug(printable)
}
/// ## logging at [`Level::StringRACE`]
pub fn trace(&self, printable: String) {
self.inner.trace(printable)
}
}
/// implement a python module in Rust
pub fn submodule(py: Python, parent: &PyModule) -> PyResult<()> {
let module = PyModule::new(py, "log")?;
module.add_class::<Logger>()?;
parent.add_submodule(module)?;
Ok(())
}

View File

@ -1,6 +1,6 @@
#!/bin/bash
set -e
cargo check --all-features
cargo check --all-features --workspace
echo ">>>>>>>> SELECT A NEW VERSION"
cargo ws version
NEW_VERSION=$(cat Cargo.toml | rg '^\s*version\s*=\s*"([^"]*)"\s*$' -or '$1')