[](https://gist.github.com/cheerfulstoic/d107229326a01ff0f333a1d3476e068d)
[](https://github.com/Adalfarus/aplustools/actions)
[](https://github.com/Adalfarus/aplustools/blob/main/LICENSE)
[](https://pepy.tech/projects/aplustools)

# aplustools2
aplustools2 is a simple, user-friendly Python library for performing amazing tasks. It simplifies complex processes, allowing you to achieve more with less code. Developed with a focus on ease of use and efficiency, aplustools is the go-to solution for Python developers looking to enhance their projects.
## Compatibility
๐ฉ (Works perfectly); ๐จ (Untested); ๐ง (Some Issues); ๐ฅ (Unusable)
| OS | UX & README instructions | Tests | More Complex Functionalities |
|--------------------------|--------------------------|-------|------------------------------|
| Windows | ๐ฉ | ๐ฉ | ๐ฉ |
| MacOS | ๐จ | ๐ฉ | ๐จ |
| Linux (Ubuntu 22.04 LTS) | ๐ฉ | ๐ฉ | ๐จ |
## Features
- Easy to use for beginners, but not lacking for experts
- Pretty efficient
- Supports the three main platforms
- Regular updates and support
- Comprehensive documentation
## Installation
You can install aplustools2 via pip:
```sh
pip install aplustools[all] --pre --upgrade
```
Or clone the repository and install manually:
```sh
git clone https://github.com/Adalfarus/aplustools.git
cd aplustools
python -m build
```
(If you have problems with the package please use `py -m pip install aplustools[all] --pre --upgrade --user`)
(The standard shortform for aplustools is aps, so please use ```import aplustools as aps``` for consistency)
## ๐ฆ Usage
Here are a few quick examples of how to use `aplustools`.
---
### ๐ `auto_repr`: Auto-generate clean `__repr__`
```python
from aplustools.io.env import auto_repr
@auto_repr
class Person:
def __init__(self, name: str, age: int, email: str):
self.name = name
self.age = age
self.email = email
self._internal = "should be hidden"
p = Person("Alice", 30, "alice@example.com")
print(p) # Person(name=Alice, age=30, email=alice@example.com)
```
---
### ๐ `auto_repr_with_privates`: Show private fields too
```python
from aplustools.io.env import auto_repr_with_privates
class Person:
def __init__(self, name: str, age: int):
self.name = name
self._age = age # Will be shown in __repr__
auto_repr_with_privates(Person, use_repr=True)
print(Person("Bob", 42)) # Person(name='Bob', _age=42)
```
---
## ๐ File Locking (Cross-Platform)
### โ
Manual file locking via `get_system()`
```python
from aplustools.io.env import get_system
fd = get_system().lock_file("test.lock", blocking=True)
print(get_system().is_file_locked("test.lock")) # True
get_system().unlock_file(fd)
```
---
### โ
Context-managed locking via `OSFileLock`
```python
from aplustools.io.fileio import OSFileLock
with OSFileLock("test.lock") as fd:
print(f"Locked with fd={fd}")
# Lock is automatically released here
```
---
### โ
Pythonic locking with `os_open` (like `open()`)
```python
from aplustools.io.fileio import os_open
with os_open("example.txt", "w") as file:
file.write("Hello, safely locked world!\n")
```
> Internally uses `OSFileLock` for safe, exclusive access across platforms (Unix/Windows).
---
## ๐ข Binary Encoding Utilities (`aplustools.data.bintools`)
Efficient tools for working with binary formats and structured bytes.
---
### ๐ Measure bit and byte length
```python
from aplustools.data.bintools import bit_length, bytes_length
print(bit_length(42)) # 6
print(bytes_length(1000)) # 2
```
---
### ๐ Encode/Decode integers
```python
from aplustools.data.bintools import encode_integer, decode_integer
encoded = encode_integer(123456)
print(encoded) # b'\x01\xe2@'
decoded = decode_integer(encoded)
print(decoded) # 123456
```
---
### ๐ Encode/Decode floats
```python
from aplustools.data.bintools import encode_float, decode_float
f_bytes = encode_float(3.14159, precision="single")
print(decode_float(f_bytes, precision="single")) # ~3.14159
```
---
### ๐ฆ Variable-length integer encoding
```python
from aplustools.data.bintools import to_varint_length, read_varint_length
import io
data = to_varint_length(300)
length = read_varint_length(io.BytesIO(data))
print(length) # 300
```
---
### ๐ Human-readable size formatting
```python
from aplustools.data.bintools import bytes_to_human_readable_binary_iec
print(bytes_to_human_readable_binary_iec(1024)) # 1.0 KiB
print(bytes_to_human_readable_binary_iec(1048576)) # 1.0 MiB
```
---
## ๐ Secure Password Generation (`aplustools.security.passwords`)
Create readable, secure, and crack-resistant passwords.
---
### ๐ Generate secure passwords easily
```python
from aplustools.security.passwords import SecurePasswordGenerator
generator = SecurePasswordGenerator(security="super_strong")
pw_data = generator.passphrase()
print(pw_data["password"]) # Actual password
print(pw_data["extra_info"]) # Generation method metadata
```
---
### ๐ง Available styles
```python
generator.sentence() # Readable sentence
generator.pattern() # Format like Aa99##
generator.complex_pattern() # Pattern + random word mix
generator.complex() # High entropy, mixed format
generator.mnemonic() # Easy to remember
```
---
### ๐ง Estimate worst-case crack time
```python
pw_data = generator.generate_secure_password(return_worst_case=True)
print(pw_data["worst_case"]) # e.g., "centuries"
```
---
## โฑ Basic Timing (`aplustools.package.chronokit`)
Measure elapsed time with nanosecond resolution.
---
### โฒ Use `BasicTimer` for simple measurements
```python
from aplustools.package.chronokit import BasicTimer
import time
timer = BasicTimer(auto_start=True)
time.sleep(0.123)
timer.stop()
print(timer.get()) # timedelta
print(timer.get_readable()) # Human-readable
```
---
### ๐ Create precise deltas
```python
from aplustools.package.chronokit import PreciseTimeDelta
delta = PreciseTimeDelta(seconds=1.5, microseconds=250)
print(str(delta)) # 0:00:01.500250
print(delta.to_readable()) # "1.500s"
```
---
## โฑ Flexible Timing with `FlexTimer`
Advanced control for performance tracking, interval measurements, and benchmarking.
---
### ๐งช Measure CPU-only time (ignores sleep)
```python
from aplustools.package.chronokit import CPUFTimer
with CPUFTimer():
sum(i * i for i in range(100_000))
```
> Ideal for benchmarking with minimal system interference.
---
### ๐ Manual start/stop and waiting
```python
from aplustools.package.chronokit import FlexTimer
t = FlexTimer(start_now=False)
t.start(start_at=1.2)
t.wait(0.8)
t.stop()
print(t.get().to_clock_string()) # e.g., 00:00:02.00
```
---
### โฑ Record laps (interval checkpoints)
```python
t = FlexTimer()
# ... task 1 ...
t.lap()
# ... task 2 ...
t.lap()
print(t.show_laps()) # List of lap durations
```
---
### ๐ช Time entire functions with a decorator
```python
@FlexTimer().time()
def compute():
return [x**2 for x in range(1_000_000)]
compute() # Prints execution time
```
---
### ๐ Schedule callbacks after a delay
```python
def on_done():
print("Finished!")
FlexTimer().after(2, on_done)
```
---
### ๐งต Run functions at intervals
```python
def tick():
print("Tick!")
FlexTimer().interval(1, count=5, callback=tick)
```
---
### ๐ Estimate time complexity of a function
```python
def fn(n):
return [i ** 2 for i in range(n)]
def gen_inputs():
for i in range(1000, 50000, 1000):
yield ((i,), {})
from aplustools.package.chronokit import FlexTimer
print(FlexTimer.complexity(fn, gen_inputs())) # e.g., "O(N)"
```
---
## โ๏ธ Concurrency and Shared Memory (`aplustools.io.concurrency`)
Smart thread pools and safe process-shared memory.
---
### ๐งต Dynamic thread pool with auto-scaling
```python
from aplustools.io.concurrency import LazyDynamicThreadPoolExecutor
import time
def task(i):
time.sleep(0.5)
return f"Task {i}"
with LazyDynamicThreadPoolExecutor(min_workers=2, max_workers=10) as pool:
results = [f.result() for f in [pool.submit(task, i) for i in range(5)]]
print(results)
```
---
### ๐ง Share memory across processes with `SharedStruct`
```python
from aplustools.io.concurrency import SharedStruct
from multiprocessing import Process
def increment(ref, count):
shared = ref.dereference()
for _ in range(count):
with shared:
val = shared.get_field(0)
shared.set_field(0, val + 1)
shared.close()
if __name__ == "__main__":
counter = SharedStruct("i", create=True)
counter.set_field(0, 0)
p1 = Process(target=increment, args=(counter.reference(), 1000))
p2 = Process(target=increment, args=(counter.reference(), 1000))
p1.start(); p2.start(); p1.join(); p2.join()
print("Final:", counter.get_field(0)) # 2000
counter.close()
counter.unlink()
```
---
### ๐ Struct format reference
* `"i"` โ one 4-byte integer
* `"if"` โ integer + float
* `"i10s"` โ integer + 10-byte string
```python
with SharedStruct("if", create=True) as stats:
stats.set_data(42, 3.14)
print(stats.get_data()) # (42, 3.14)
```
---
## ๐ Web Requests (`aplustools.web.request`)
Make web requests in sync or async mode โ single or batch.
---
### ๐น Quick HTTPS fetch
```python
from aplustools.web.request import fetch
data = fetch("https://httpbin.org/get")
print(data.decode())
```
---
### ๐ธ Threaded batch requests with `BatchRequestHandler`
```python
from aplustools.web.request import BatchRequestHandler
handler = BatchRequestHandler(min_workers=2, max_workers=10)
# Single request
print(handler.request("https://httpbin.org/get").decode())
# Multiple (sync)
urls = ["https://httpbin.org/get"] * 5
print(len(handler.request_many(urls)))
# Multiple (async)
result = handler.request_many(urls, async_mode=True)
print(len(result.no_into().no_into_results))
handler.shutdown()
```
๐ก The thread pool can be reused via `handler.pool`.
---
### โก High-performance async requests with `AioHttpRequestHandler`
```python
from aplustools.web.request import AioHttpRequestHandler
aio = AioHttpRequestHandler()
print(aio.request("https://httpbin.org/get").decode())
print(len(aio.request_many(["https://httpbin.org/get"] * 5)))
aio.shutdown()
```
> Sync interface, but internally async. Great for sync environments that want async speed.
## ๐ `aplustools.security.crypto`
This section demonstrates the flexible, backend-agnostic cryptography interface provided by `aplustools`. The section includes standard hashing, key derivation, and post-quantum encryption/signing using modern algorithms.
### ๐ฆ Setup and Imports
```python
from aplustools.security.crypto.algos import (
Sym,
Asym,
HashAlgorithm,
KeyDerivationFunction,
)
from aplustools.security.crypto.exceptions import NotSupportedError
from aplustools.security.crypto import set_backend, Backend
import os
```
Set the std lib cryptography backend (you can later switch to advanced libraries like `cryptography`, `argon2-cffi`, etc.):
```python
set_backend() # Uses Backend.std_lib
```
### ๐ Hashing with Standard Algorithms
Most `HashAlgorithm` variants support `.hash()`, `.verify()`, and `.std_verify()`.
```python
# MD5
h = HashAlgorithm.MD5.hash(b"hello world")
print("MD5:", h.hex())
print("Verify:", HashAlgorithm.MD5.verify(b"hello world", h))
print("Std-Verify:", HashAlgorithm.std_verify(b"hello world", h))
# SHA1
h = HashAlgorithm.SHA1.hash(b"hello world")
print("SHA1:", h.hex())
print("Verify:", HashAlgorithm.SHA1.verify(b"hello world", h))
print("Std-Verify:", HashAlgorithm.std_verify(b"hello world", h))
# SHA256
h = HashAlgorithm.SHA2.SHA256.hash(b"hello world")
print("SHA256:", h.hex())
print("Verify:", HashAlgorithm.SHA2.SHA256.verify(b"hello world", h))
print("Std-Verify:", HashAlgorithm.std_verify(b"hello world", h))
# SHA3-256
h = HashAlgorithm.SHA3.SHA256.hash(b"hello world")
print("SHA3-256:", h.hex())
print("Verify:", HashAlgorithm.SHA3.SHA256.verify(b"hello world", h))
print("Std-Verify:", HashAlgorithm.std_verify(b"hello world", h))
```
### โ๏ธ Hashing with Variable-Length and Specialized Algorithms
Some algorithms require an output length (e.g., SHAKE128, BLAKE2s):
```python
# SHAKE128 (8 bytes)
h = HashAlgorithm.SHA3.SHAKE128.hash(b"hello", 8)
print("SHAKE128:", h.hex())
print("Verify:", HashAlgorithm.SHA3.SHAKE128.verify(b"hello", h))
print("Std-Verify:", HashAlgorithm.std_verify(b"hello", h))
# BLAKE2s (8 bytes)
h = HashAlgorithm.BLAKE2.BLAKE2s.hash(b"hello", 8)
print("BLAKE2s:", h.hex())
print("Verify:", HashAlgorithm.BLAKE2.BLAKE2s.verify(b"hello", h))
print("Std-Verify:", HashAlgorithm.std_verify(b"hello", h))
```
Some algorithms are optional in std lib:
```python
# RIPEMD160
try:
h = HashAlgorithm.RIPEMD160.hash(b"hello")
print("RIPEMD160:", h.hex())
print("Verify:", HashAlgorithm.RIPEMD160.verify(b"hello", h))
print("Std-Verify:", HashAlgorithm.std_verify(b"hello", h))
except Exception as e:
print("RIPEMD160 unsupported in std_lib:", e)
```
### ๐ Key Derivation Functions (KDFs)
All KDFs support `.derive(password, salt, ...)` and produce fixed-length binary output:
```python
password = b"my-password"
salt = os.urandom(16)
print("PBKDF2HMAC:", KeyDerivationFunction.PBKDF2HMAC.derive(password, salt=salt).hex())
print("PBKDF1 :", KeyDerivationFunction.PBKDF1.derive(password, salt=salt, length=16).hex())
print("Scrypt :", KeyDerivationFunction.Scrypt.derive(password, salt=salt, length=16).hex())
print("HKDF :", KeyDerivationFunction.HKDF.derive(password, salt=salt).hex())
print("ConcatKDF :", KeyDerivationFunction.ConcatKDF.derive(password, otherinfo=b"my-info").hex())
```
### ๐ Switch to Advanced Backends
Enable advanced features like post-quantum crypto and better hashing support:
```python
set_backend(
[
Backend.cryptography_alpha, # Currently only supports hashes like SHA3
Backend.quantcrypt, # To enable post-quantum cryptography
Backend.argon2_cffi, # Required for Argon2
Backend.bcrypt, # Required for BCrypt
Backend.std_lib, # Fallback
]
)
```
### ๐ง Argon2 Hashing and Verification
```python
# Hash a password/message using Argon2
hashed = HashAlgorithm.ARGON2.hash(b"Ha", os.urandom(16))
print("\nArgon2 Hash:", hashed.decode())
# Verify the hash
is_valid = HashAlgorithm.ARGON2.verify(b"Ha", hashed)
print("Argon2 Valid:", is_valid)
try:
print(
"Std-Verify",
HashAlgorithm.std_verify(
b"Ha", hashed, fallback_algorithm="argon2", text_ids=False
),
) # Std-Verify can't decode special algos like argon2 or bcrypt
except NotSupportedError:
print("Std-Verify failed")
```
### ๐ BCrypt Hashing and Verification
```python
# Hash a password with BCrypt
bcrypt_hash = HashAlgorithm.BCRYPT.hash(b"my-secret-password")
print("BCrypt Hash:", bcrypt_hash.decode())
# Verify the password against the hash
is_valid = HashAlgorithm.BCRYPT.verify(b"my-secret-password", bcrypt_hash)
print("BCrypt Valid:", is_valid)
```
### ๐ Argon2 / BCrypt for Secure Key Derivation
```python
# Derive a key using Argon2 KDF
derived_key = KeyDerivationFunction.ARGON2.derive(b"my-password", salt=os.urandom(16))
print("Argon2 Derived Key:", derived_key.hex())
# Derive a key using BCrypt KDF
bcrypt_key = KeyDerivationFunction.BCRYPT.derive(b"my-password", salt=os.urandom(16))
print("BCrypt Derived Key:", bcrypt_key.hex())
```
## ๐ Asymmetric Encryption: Kyber (Post-Quantum KEM)
This demonstrates a Kyber key exchange using encapsulation (sender) and decapsulation (recipient):
```python
# Recipient generates a keypair
recipient_key = Asym.Cipher.KYBER.keypair.new("kyber1024")
# Extract public key from recipient and share it with the sender
pub_key_bytes = recipient_key.encode_public_key()
# Keys can't be regenerated and try: except: takes more space;
# This can only happen if you do not pass one of the keys when using .decode( ... )
if pub_key_bytes is None:
raise ValueError("recipient_key has no public key")
# Sender receives the public key and creates a key object with only the public key
sender_key = Asym.Cipher.KYBER.keypair.decode("kyber1024", public_key=pub_key_bytes)
# Sender encapsulates a shared secret for the recipient
ciphertext, shared_secret_sender = sender_key.encapsulate()
# Recipient decapsulates to recover the shared secret
shared_secret_recipient = recipient_key.decapsulate(ciphertext)
print("\n=== Kyber KEM Flow ===")
print(f"Ciphertext : {ciphertext.hex()}")
print(f"Sender Shared Secret : {shared_secret_sender.hex()}")
print(f"Recipient Shared Secret: {shared_secret_recipient.hex()}")
assert shared_secret_sender == shared_secret_recipient, "Shared secrets do not match!"
```
## โ๏ธ Asymmetric Signing: Dilithium (Post-Quantum Signature)
This demonstrates secure message signing and verification using the Dilithium signature algorithm:
```python
# Generate the signing keypair (private + public)
sign_key = Asym.Cipher.DILITHIUM.keypair.new("dilithium5")
# Sign a message using the private key
message = b"Hello World"
signature = sign_key.sign(message)
# Extract and share only the public key
pub_key_bytes = sign_key.encode_public_key()
# Keys can't be regenerated and try: except: takes more space;
# This can only happen if you do not pass one of the keys when using .decode( ... )
if pub_key_bytes is None:
raise ValueError("sign_key has no public key")
# Create a new key object with only the public key for verification
verify_key = Asym.Cipher.DILITHIUM.keypair.decode(
"dilithium5", public_key=pub_key_bytes
)
# Verify the signature using the public key
is_valid = verify_key.sign_verify(message, signature)
print("\n=== Dilithium Signature Flow ===")
print(f"Signature : {signature.hex()}")
print(f"Signature Valid? {is_valid}")
assert is_valid, "Signature verification failed!"
```
### aps cli
Can currently run tests with ```aps tests run tests/ -minimal``` and show a basic help using ```aps help```.
For more detailed usage and examples, check out our [documentation](https://github.com/adalfarus/aplustools/wiki).
## Naming convention, dependencies and library information
[PEP 8 -- Style Guide for Python Code](https://peps.python.org/pep-0008/#naming-conventions)
For modules I use 'lowercase', classes are 'CapitalizedWords' and functions and methods are 'lower_case_with_underscores'.
### Information
- Additional information will be added in the full release.
## Contributing
We welcome contributions! Please see our [contributing guidelines](https://github.com/adalfarus/aplustools/blob/main/CONTRIBUTING.md) for more details on how you can contribute to aplustools.
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the branch (`git push origin feature/AmazingFeature`)
5. Open a pull request
### Aps Build master
You can use the aps_build_master script for your os to make your like a lot easier.
It supports running tests, installing, building and much more as well as chaining together as many commands as you like.
This example runs test, build the project and then installs it
````commandline
call .\aps_build_master.bat 234
````
````shell
sudo apt install python3-pip
sudo apt install python3-venv
chmod +x ./aps_build_master.sh
./aps_build_master.sh 234
````
## License
aplustools is licensed under the LGPL-2.1 License - see the [LICENSE](https://github.com/adalfarus/aplustools/blob/main/LICENSE) file for details.
Raw data
{
"_id": null,
"home_page": null,
"name": "aplustools",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": "Cariel Becker <cariel.becker@gmx.de>",
"keywords": "general, tools, app tools, production, apt",
"author": null,
"author_email": "Cariel Becker <cariel.becker@gmx.de>",
"download_url": "https://files.pythonhosted.org/packages/f2/75/fc19868098bd4f1e7281174fec75e2126804cf71e431f5f41fbb7065d147/aplustools-2.0.0.2.tar.gz",
"platform": null,
"description": "[](https://gist.github.com/cheerfulstoic/d107229326a01ff0f333a1d3476e068d)\n[](https://github.com/Adalfarus/aplustools/actions)\n[](https://github.com/Adalfarus/aplustools/blob/main/LICENSE)\n[](https://pepy.tech/projects/aplustools)\n\n\n# aplustools2\n\naplustools2 is a simple, user-friendly Python library for performing amazing tasks. It simplifies complex processes, allowing you to achieve more with less code. Developed with a focus on ease of use and efficiency, aplustools is the go-to solution for Python developers looking to enhance their projects.\n\n## Compatibility\n\ud83d\udfe9 (Works perfectly); \ud83d\udfe8 (Untested); \ud83d\udfe7 (Some Issues); \ud83d\udfe5 (Unusable)\n\n| OS | UX & README instructions | Tests | More Complex Functionalities |\n|--------------------------|--------------------------|-------|------------------------------|\n| Windows | \ud83d\udfe9 | \ud83d\udfe9 | \ud83d\udfe9 |\n| MacOS | \ud83d\udfe8 | \ud83d\udfe9 | \ud83d\udfe8 |\n| Linux (Ubuntu 22.04 LTS) | \ud83d\udfe9 | \ud83d\udfe9 | \ud83d\udfe8 |\n\n## Features\n\n- Easy to use for beginners, but not lacking for experts\n- Pretty efficient\n- Supports the three main platforms\n- Regular updates and support\n- Comprehensive documentation\n\n## Installation\n\nYou can install aplustools2 via pip:\n\n```sh\npip install aplustools[all] --pre --upgrade\n```\n\nOr clone the repository and install manually:\n\n```sh\ngit clone https://github.com/Adalfarus/aplustools.git\ncd aplustools\npython -m build\n```\n\n(If you have problems with the package please use `py -m pip install aplustools[all] --pre --upgrade --user`)\n(The standard shortform for aplustools is aps, so please use ```import aplustools as aps``` for consistency)\n\n## \ud83d\udce6 Usage\n\nHere are a few quick examples of how to use `aplustools`.\n\n---\n\n### \ud83d\udd01 `auto_repr`: Auto-generate clean `__repr__`\n\n```python\nfrom aplustools.io.env import auto_repr\n\n@auto_repr\nclass Person:\n def __init__(self, name: str, age: int, email: str):\n self.name = name\n self.age = age\n self.email = email\n self._internal = \"should be hidden\"\n\np = Person(\"Alice\", 30, \"alice@example.com\")\nprint(p) # Person(name=Alice, age=30, email=alice@example.com)\n```\n\n---\n\n### \ud83d\udd01 `auto_repr_with_privates`: Show private fields too\n\n```python\nfrom aplustools.io.env import auto_repr_with_privates\n\nclass Person:\n def __init__(self, name: str, age: int):\n self.name = name\n self._age = age # Will be shown in __repr__\n\nauto_repr_with_privates(Person, use_repr=True)\nprint(Person(\"Bob\", 42)) # Person(name='Bob', _age=42)\n```\n\n---\n\n## \ud83d\udd10 File Locking (Cross-Platform)\n\n### \u2705 Manual file locking via `get_system()`\n\n```python\nfrom aplustools.io.env import get_system\n\nfd = get_system().lock_file(\"test.lock\", blocking=True)\nprint(get_system().is_file_locked(\"test.lock\")) # True\nget_system().unlock_file(fd)\n```\n\n---\n\n### \u2705 Context-managed locking via `OSFileLock`\n\n```python\nfrom aplustools.io.fileio import OSFileLock\n\nwith OSFileLock(\"test.lock\") as fd:\n print(f\"Locked with fd={fd}\")\n# Lock is automatically released here\n```\n\n---\n\n### \u2705 Pythonic locking with `os_open` (like `open()`)\n\n```python\nfrom aplustools.io.fileio import os_open\n\nwith os_open(\"example.txt\", \"w\") as file:\n file.write(\"Hello, safely locked world!\\n\")\n```\n\n> Internally uses `OSFileLock` for safe, exclusive access across platforms (Unix/Windows).\n\n---\n\n## \ud83d\udd22 Binary Encoding Utilities (`aplustools.data.bintools`)\n\nEfficient tools for working with binary formats and structured bytes.\n\n---\n\n### \ud83d\udccf Measure bit and byte length\n\n```python\nfrom aplustools.data.bintools import bit_length, bytes_length\n\nprint(bit_length(42)) # 6\nprint(bytes_length(1000)) # 2\n```\n\n---\n\n### \ud83d\udd01 Encode/Decode integers\n\n```python\nfrom aplustools.data.bintools import encode_integer, decode_integer\n\nencoded = encode_integer(123456)\nprint(encoded) # b'\\x01\\xe2@'\n\ndecoded = decode_integer(encoded)\nprint(decoded) # 123456\n```\n\n---\n\n### \ud83d\udd01 Encode/Decode floats\n\n```python\nfrom aplustools.data.bintools import encode_float, decode_float\n\nf_bytes = encode_float(3.14159, precision=\"single\")\nprint(decode_float(f_bytes, precision=\"single\")) # ~3.14159\n```\n\n---\n\n### \ud83d\udce6 Variable-length integer encoding\n\n```python\nfrom aplustools.data.bintools import to_varint_length, read_varint_length\nimport io\n\ndata = to_varint_length(300)\nlength = read_varint_length(io.BytesIO(data))\nprint(length) # 300\n```\n\n---\n\n### \ud83d\udccf Human-readable size formatting\n\n```python\nfrom aplustools.data.bintools import bytes_to_human_readable_binary_iec\n\nprint(bytes_to_human_readable_binary_iec(1024)) # 1.0 KiB\nprint(bytes_to_human_readable_binary_iec(1048576)) # 1.0 MiB\n```\n\n---\n\n## \ud83d\udd10 Secure Password Generation (`aplustools.security.passwords`)\n\nCreate readable, secure, and crack-resistant passwords.\n\n---\n\n### \ud83d\udd11 Generate secure passwords easily\n\n```python\nfrom aplustools.security.passwords import SecurePasswordGenerator\n\ngenerator = SecurePasswordGenerator(security=\"super_strong\")\npw_data = generator.passphrase()\n\nprint(pw_data[\"password\"]) # Actual password\nprint(pw_data[\"extra_info\"]) # Generation method metadata\n```\n\n---\n\n### \ud83d\udd27 Available styles\n\n```python\ngenerator.sentence() # Readable sentence\ngenerator.pattern() # Format like Aa99##\ngenerator.complex_pattern() # Pattern + random word mix\ngenerator.complex() # High entropy, mixed format\ngenerator.mnemonic() # Easy to remember\n```\n\n---\n\n### \ud83e\udde0 Estimate worst-case crack time\n\n```python\npw_data = generator.generate_secure_password(return_worst_case=True)\nprint(pw_data[\"worst_case\"]) # e.g., \"centuries\"\n```\n\n---\n\n## \u23f1 Basic Timing (`aplustools.package.chronokit`)\n\nMeasure elapsed time with nanosecond resolution.\n\n---\n\n### \u23f2 Use `BasicTimer` for simple measurements\n\n```python\nfrom aplustools.package.chronokit import BasicTimer\nimport time\n\ntimer = BasicTimer(auto_start=True)\ntime.sleep(0.123)\ntimer.stop()\n\nprint(timer.get()) # timedelta\nprint(timer.get_readable()) # Human-readable\n```\n\n---\n\n### \ud83d\udccf Create precise deltas\n\n```python\nfrom aplustools.package.chronokit import PreciseTimeDelta\n\ndelta = PreciseTimeDelta(seconds=1.5, microseconds=250)\nprint(str(delta)) # 0:00:01.500250\nprint(delta.to_readable()) # \"1.500s\"\n```\n\n---\n\n## \u23f1 Flexible Timing with `FlexTimer`\n\nAdvanced control for performance tracking, interval measurements, and benchmarking.\n\n---\n\n### \ud83e\uddea Measure CPU-only time (ignores sleep)\n\n```python\nfrom aplustools.package.chronokit import CPUFTimer\n\nwith CPUFTimer():\n sum(i * i for i in range(100_000))\n```\n\n> Ideal for benchmarking with minimal system interference.\n\n---\n\n### \ud83d\udd04 Manual start/stop and waiting\n\n```python\nfrom aplustools.package.chronokit import FlexTimer\n\nt = FlexTimer(start_now=False)\nt.start(start_at=1.2)\nt.wait(0.8)\nt.stop()\n\nprint(t.get().to_clock_string()) # e.g., 00:00:02.00\n```\n\n---\n\n### \u23f1 Record laps (interval checkpoints)\n\n```python\nt = FlexTimer()\n# ... task 1 ...\nt.lap()\n# ... task 2 ...\nt.lap()\n\nprint(t.show_laps()) # List of lap durations\n```\n\n---\n\n### \ud83e\ude84 Time entire functions with a decorator\n\n```python\n@FlexTimer().time()\ndef compute():\n return [x**2 for x in range(1_000_000)]\n\ncompute() # Prints execution time\n```\n\n---\n\n### \ud83d\udd52 Schedule callbacks after a delay\n\n```python\ndef on_done():\n print(\"Finished!\")\n\nFlexTimer().after(2, on_done)\n```\n\n---\n\n### \ud83e\uddf5 Run functions at intervals\n\n```python\ndef tick():\n print(\"Tick!\")\n\nFlexTimer().interval(1, count=5, callback=tick)\n```\n\n---\n\n### \ud83d\udcc8 Estimate time complexity of a function\n\n```python\ndef fn(n):\n return [i ** 2 for i in range(n)]\n\ndef gen_inputs():\n for i in range(1000, 50000, 1000):\n yield ((i,), {})\n\nfrom aplustools.package.chronokit import FlexTimer\nprint(FlexTimer.complexity(fn, gen_inputs())) # e.g., \"O(N)\"\n```\n\n---\n\n## \u2699\ufe0f Concurrency and Shared Memory (`aplustools.io.concurrency`)\n\nSmart thread pools and safe process-shared memory.\n\n---\n\n### \ud83e\uddf5 Dynamic thread pool with auto-scaling\n\n```python\nfrom aplustools.io.concurrency import LazyDynamicThreadPoolExecutor\nimport time\n\ndef task(i):\n time.sleep(0.5)\n return f\"Task {i}\"\n\nwith LazyDynamicThreadPoolExecutor(min_workers=2, max_workers=10) as pool:\n results = [f.result() for f in [pool.submit(task, i) for i in range(5)]]\n\nprint(results)\n```\n\n---\n\n### \ud83e\udde0 Share memory across processes with `SharedStruct`\n\n```python\nfrom aplustools.io.concurrency import SharedStruct\nfrom multiprocessing import Process\n\ndef increment(ref, count):\n shared = ref.dereference()\n for _ in range(count):\n with shared:\n val = shared.get_field(0)\n shared.set_field(0, val + 1)\n shared.close()\n\nif __name__ == \"__main__\":\n counter = SharedStruct(\"i\", create=True)\n counter.set_field(0, 0)\n\n p1 = Process(target=increment, args=(counter.reference(), 1000))\n p2 = Process(target=increment, args=(counter.reference(), 1000))\n p1.start(); p2.start(); p1.join(); p2.join()\n\n print(\"Final:\", counter.get_field(0)) # 2000\n counter.close()\n counter.unlink()\n```\n\n---\n\n### \ud83d\udcce Struct format reference\n\n* `\"i\"` \u2014 one 4-byte integer\n* `\"if\"` \u2014 integer + float\n* `\"i10s\"` \u2014 integer + 10-byte string\n\n```python\nwith SharedStruct(\"if\", create=True) as stats:\n stats.set_data(42, 3.14)\n print(stats.get_data()) # (42, 3.14)\n```\n\n---\n\n## \ud83c\udf10 Web Requests (`aplustools.web.request`)\n\nMake web requests in sync or async mode \u2014 single or batch.\n\n---\n\n### \ud83d\udd39 Quick HTTPS fetch\n\n```python\nfrom aplustools.web.request import fetch\n\ndata = fetch(\"https://httpbin.org/get\")\nprint(data.decode())\n```\n\n---\n\n### \ud83d\udd38 Threaded batch requests with `BatchRequestHandler`\n\n```python\nfrom aplustools.web.request import BatchRequestHandler\n\nhandler = BatchRequestHandler(min_workers=2, max_workers=10)\n\n# Single request\nprint(handler.request(\"https://httpbin.org/get\").decode())\n\n# Multiple (sync)\nurls = [\"https://httpbin.org/get\"] * 5\nprint(len(handler.request_many(urls)))\n\n# Multiple (async)\nresult = handler.request_many(urls, async_mode=True)\nprint(len(result.no_into().no_into_results))\n\nhandler.shutdown()\n```\n\n\ud83d\udca1 The thread pool can be reused via `handler.pool`.\n\n---\n\n### \u26a1 High-performance async requests with `AioHttpRequestHandler`\n\n```python\nfrom aplustools.web.request import AioHttpRequestHandler\n\naio = AioHttpRequestHandler()\n\nprint(aio.request(\"https://httpbin.org/get\").decode())\nprint(len(aio.request_many([\"https://httpbin.org/get\"] * 5)))\n\naio.shutdown()\n```\n\n> Sync interface, but internally async. Great for sync environments that want async speed.\n\n## \ud83d\udd10 `aplustools.security.crypto`\n\nThis section demonstrates the flexible, backend-agnostic cryptography interface provided by `aplustools`. The section includes standard hashing, key derivation, and post-quantum encryption/signing using modern algorithms.\n\n### \ud83d\udce6 Setup and Imports\n\n```python\nfrom aplustools.security.crypto.algos import (\n Sym,\n Asym,\n HashAlgorithm,\n KeyDerivationFunction,\n)\nfrom aplustools.security.crypto.exceptions import NotSupportedError\nfrom aplustools.security.crypto import set_backend, Backend\nimport os\n```\n\nSet the std lib cryptography backend (you can later switch to advanced libraries like `cryptography`, `argon2-cffi`, etc.):\n\n```python\nset_backend() # Uses Backend.std_lib\n```\n\n### \ud83d\udd0d Hashing with Standard Algorithms\n\nMost `HashAlgorithm` variants support `.hash()`, `.verify()`, and `.std_verify()`.\n\n```python\n# MD5\nh = HashAlgorithm.MD5.hash(b\"hello world\")\nprint(\"MD5:\", h.hex())\nprint(\"Verify:\", HashAlgorithm.MD5.verify(b\"hello world\", h))\nprint(\"Std-Verify:\", HashAlgorithm.std_verify(b\"hello world\", h))\n\n# SHA1\nh = HashAlgorithm.SHA1.hash(b\"hello world\")\nprint(\"SHA1:\", h.hex())\nprint(\"Verify:\", HashAlgorithm.SHA1.verify(b\"hello world\", h))\nprint(\"Std-Verify:\", HashAlgorithm.std_verify(b\"hello world\", h))\n\n# SHA256\nh = HashAlgorithm.SHA2.SHA256.hash(b\"hello world\")\nprint(\"SHA256:\", h.hex())\nprint(\"Verify:\", HashAlgorithm.SHA2.SHA256.verify(b\"hello world\", h))\nprint(\"Std-Verify:\", HashAlgorithm.std_verify(b\"hello world\", h))\n\n# SHA3-256\nh = HashAlgorithm.SHA3.SHA256.hash(b\"hello world\")\nprint(\"SHA3-256:\", h.hex())\nprint(\"Verify:\", HashAlgorithm.SHA3.SHA256.verify(b\"hello world\", h))\nprint(\"Std-Verify:\", HashAlgorithm.std_verify(b\"hello world\", h))\n```\n\n### \u2696\ufe0f Hashing with Variable-Length and Specialized Algorithms\n\nSome algorithms require an output length (e.g., SHAKE128, BLAKE2s):\n\n```python\n# SHAKE128 (8 bytes)\nh = HashAlgorithm.SHA3.SHAKE128.hash(b\"hello\", 8)\nprint(\"SHAKE128:\", h.hex())\nprint(\"Verify:\", HashAlgorithm.SHA3.SHAKE128.verify(b\"hello\", h))\nprint(\"Std-Verify:\", HashAlgorithm.std_verify(b\"hello\", h))\n\n# BLAKE2s (8 bytes)\nh = HashAlgorithm.BLAKE2.BLAKE2s.hash(b\"hello\", 8)\nprint(\"BLAKE2s:\", h.hex())\nprint(\"Verify:\", HashAlgorithm.BLAKE2.BLAKE2s.verify(b\"hello\", h))\nprint(\"Std-Verify:\", HashAlgorithm.std_verify(b\"hello\", h))\n```\n\nSome algorithms are optional in std lib:\n\n```python\n# RIPEMD160\ntry:\n h = HashAlgorithm.RIPEMD160.hash(b\"hello\")\n print(\"RIPEMD160:\", h.hex())\n print(\"Verify:\", HashAlgorithm.RIPEMD160.verify(b\"hello\", h))\n print(\"Std-Verify:\", HashAlgorithm.std_verify(b\"hello\", h))\nexcept Exception as e:\n print(\"RIPEMD160 unsupported in std_lib:\", e)\n```\n\n### \ud83d\udd11 Key Derivation Functions (KDFs)\n\nAll KDFs support `.derive(password, salt, ...)` and produce fixed-length binary output:\n\n```python\npassword = b\"my-password\"\nsalt = os.urandom(16)\n\nprint(\"PBKDF2HMAC:\", KeyDerivationFunction.PBKDF2HMAC.derive(password, salt=salt).hex())\nprint(\"PBKDF1 :\", KeyDerivationFunction.PBKDF1.derive(password, salt=salt, length=16).hex())\nprint(\"Scrypt :\", KeyDerivationFunction.Scrypt.derive(password, salt=salt, length=16).hex())\nprint(\"HKDF :\", KeyDerivationFunction.HKDF.derive(password, salt=salt).hex())\nprint(\"ConcatKDF :\", KeyDerivationFunction.ConcatKDF.derive(password, otherinfo=b\"my-info\").hex())\n```\n\n### \ud83d\udee0 Switch to Advanced Backends\n\nEnable advanced features like post-quantum crypto and better hashing support:\n\n```python\nset_backend(\n [\n Backend.cryptography_alpha, # Currently only supports hashes like SHA3\n Backend.quantcrypt, # To enable post-quantum cryptography\n Backend.argon2_cffi, # Required for Argon2\n Backend.bcrypt, # Required for BCrypt\n Backend.std_lib, # Fallback\n ]\n)\n```\n\n### \ud83e\uddc2 Argon2 Hashing and Verification\n\n```python\n# Hash a password/message using Argon2\nhashed = HashAlgorithm.ARGON2.hash(b\"Ha\", os.urandom(16))\nprint(\"\\nArgon2 Hash:\", hashed.decode())\n\n# Verify the hash\nis_valid = HashAlgorithm.ARGON2.verify(b\"Ha\", hashed)\nprint(\"Argon2 Valid:\", is_valid)\n\ntry:\n print(\n \"Std-Verify\",\n HashAlgorithm.std_verify(\n b\"Ha\", hashed, fallback_algorithm=\"argon2\", text_ids=False\n ),\n ) # Std-Verify can't decode special algos like argon2 or bcrypt\nexcept NotSupportedError:\n print(\"Std-Verify failed\")\n```\n\n### \ud83d\udd10 BCrypt Hashing and Verification\n\n```python\n# Hash a password with BCrypt\nbcrypt_hash = HashAlgorithm.BCRYPT.hash(b\"my-secret-password\")\nprint(\"BCrypt Hash:\", bcrypt_hash.decode())\n\n# Verify the password against the hash\nis_valid = HashAlgorithm.BCRYPT.verify(b\"my-secret-password\", bcrypt_hash)\nprint(\"BCrypt Valid:\", is_valid)\n```\n\n### \ud83d\udd11 Argon2 / BCrypt for Secure Key Derivation\n\n```python\n# Derive a key using Argon2 KDF\nderived_key = KeyDerivationFunction.ARGON2.derive(b\"my-password\", salt=os.urandom(16))\nprint(\"Argon2 Derived Key:\", derived_key.hex())\n\n# Derive a key using BCrypt KDF\nbcrypt_key = KeyDerivationFunction.BCRYPT.derive(b\"my-password\", salt=os.urandom(16))\nprint(\"BCrypt Derived Key:\", bcrypt_key.hex())\n```\n\n## \ud83d\udd10 Asymmetric Encryption: Kyber (Post-Quantum KEM)\n\nThis demonstrates a Kyber key exchange using encapsulation (sender) and decapsulation (recipient):\n\n```python\n# Recipient generates a keypair\nrecipient_key = Asym.Cipher.KYBER.keypair.new(\"kyber1024\")\n\n# Extract public key from recipient and share it with the sender\npub_key_bytes = recipient_key.encode_public_key()\n# Keys can't be regenerated and try: except: takes more space; \n# This can only happen if you do not pass one of the keys when using .decode( ... )\nif pub_key_bytes is None:\n raise ValueError(\"recipient_key has no public key\")\n\n# Sender receives the public key and creates a key object with only the public key\nsender_key = Asym.Cipher.KYBER.keypair.decode(\"kyber1024\", public_key=pub_key_bytes)\n# Sender encapsulates a shared secret for the recipient\nciphertext, shared_secret_sender = sender_key.encapsulate()\n\n# Recipient decapsulates to recover the shared secret\nshared_secret_recipient = recipient_key.decapsulate(ciphertext)\n\nprint(\"\\n=== Kyber KEM Flow ===\")\nprint(f\"Ciphertext : {ciphertext.hex()}\")\nprint(f\"Sender Shared Secret : {shared_secret_sender.hex()}\")\nprint(f\"Recipient Shared Secret: {shared_secret_recipient.hex()}\")\nassert shared_secret_sender == shared_secret_recipient, \"Shared secrets do not match!\"\n```\n\n## \u270d\ufe0f Asymmetric Signing: Dilithium (Post-Quantum Signature)\n\nThis demonstrates secure message signing and verification using the Dilithium signature algorithm:\n\n```python\n# Generate the signing keypair (private + public)\nsign_key = Asym.Cipher.DILITHIUM.keypair.new(\"dilithium5\")\n\n# Sign a message using the private key\nmessage = b\"Hello World\"\nsignature = sign_key.sign(message)\n\n# Extract and share only the public key\npub_key_bytes = sign_key.encode_public_key()\n# Keys can't be regenerated and try: except: takes more space; \n# This can only happen if you do not pass one of the keys when using .decode( ... )\nif pub_key_bytes is None:\n raise ValueError(\"sign_key has no public key\")\n\n# Create a new key object with only the public key for verification\nverify_key = Asym.Cipher.DILITHIUM.keypair.decode(\n \"dilithium5\", public_key=pub_key_bytes\n)\n# Verify the signature using the public key\nis_valid = verify_key.sign_verify(message, signature)\n\nprint(\"\\n=== Dilithium Signature Flow ===\")\nprint(f\"Signature : {signature.hex()}\")\nprint(f\"Signature Valid? {is_valid}\")\nassert is_valid, \"Signature verification failed!\"\n```\n\n### aps cli\nCan currently run tests with ```aps tests run tests/ -minimal``` and show a basic help using ```aps help```.\n\nFor more detailed usage and examples, check out our [documentation](https://github.com/adalfarus/aplustools/wiki).\n\n## Naming convention, dependencies and library information\n[PEP 8 -- Style Guide for Python Code](https://peps.python.org/pep-0008/#naming-conventions)\n\nFor modules I use 'lowercase', classes are 'CapitalizedWords' and functions and methods are 'lower_case_with_underscores'.\n\n### Information\n- Additional information will be added in the full release.\n\n## Contributing\n\nWe welcome contributions! Please see our [contributing guidelines](https://github.com/adalfarus/aplustools/blob/main/CONTRIBUTING.md) for more details on how you can contribute to aplustools.\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a pull request\n\n### Aps Build master\n\nYou can use the aps_build_master script for your os to make your like a lot easier.\nIt supports running tests, installing, building and much more as well as chaining together as many commands as you like.\n\nThis example runs test, build the project and then installs it\n````commandline\ncall .\\aps_build_master.bat 234\n````\n\n````shell\nsudo apt install python3-pip\nsudo apt install python3-venv\nchmod +x ./aps_build_master.sh\n./aps_build_master.sh 234\n````\n\n## License\n\naplustools is licensed under the LGPL-2.1 License - see the [LICENSE](https://github.com/adalfarus/aplustools/blob/main/LICENSE) file for details.\n",
"bugtrack_url": null,
"license": null,
"summary": "A collection of helpful tools",
"version": "2.0.0.2",
"project_urls": {
"Documentation": "https://github.com/adalfarus/aplustools/wiki",
"Home": "https://pypi.org/project/aplustools/",
"Issue tracker": "https://github.com/adalfarus/aplustools/issues",
"Repository": "https://github.com/adalfarus/aplustools"
},
"split_keywords": [
"general",
" tools",
" app tools",
" production",
" apt"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "59d9522c3dbec83f3c91f81520df128651203226d0ff3fe8a4ea48cb9fbf4ac0",
"md5": "8354b747f958846ce19bf3646c5d1117",
"sha256": "bf4f36b65dd71669aff3d89c7463d72c3db56f7bfc3e1955c96403633d2be7c3"
},
"downloads": -1,
"filename": "aplustools-2.0.0.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "8354b747f958846ce19bf3646c5d1117",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 5438983,
"upload_time": "2025-07-26T16:02:44",
"upload_time_iso_8601": "2025-07-26T16:02:44.608642Z",
"url": "https://files.pythonhosted.org/packages/59/d9/522c3dbec83f3c91f81520df128651203226d0ff3fe8a4ea48cb9fbf4ac0/aplustools-2.0.0.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "f275fc19868098bd4f1e7281174fec75e2126804cf71e431f5f41fbb7065d147",
"md5": "04ecb4ee148cac88cdbcc5b5f32dd4b4",
"sha256": "9b7dfd9bd21f9dcb5f7019cc40a7f1c9f4976fb8f03b5d52f5bd81c359bb9433"
},
"downloads": -1,
"filename": "aplustools-2.0.0.2.tar.gz",
"has_sig": false,
"md5_digest": "04ecb4ee148cac88cdbcc5b5f32dd4b4",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 5433067,
"upload_time": "2025-07-26T16:02:46",
"upload_time_iso_8601": "2025-07-26T16:02:46.392644Z",
"url": "https://files.pythonhosted.org/packages/f2/75/fc19868098bd4f1e7281174fec75e2126804cf71e431f5f41fbb7065d147/aplustools-2.0.0.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-26 16:02:46",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "adalfarus",
"github_project": "aplustools",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"lcname": "aplustools"
}