Xaeian
Python utilities. Zero dependencies for core. Optional extras for time, serial, media, database and more...
Philosophy
Xaeian wraps stdlib boilerplate into intent-level APIs. You read what code does, not how. In real projects this cuts ~35% of code volume.
This follows the Zen of Python:
- Beautiful over ugly:
Time() + "15m"vsdatetime.now(tz=...) + timedelta(minutes=15) - Simple over complex:
db.find_one("users", id=42)vs acquire/try/finally/dict/close - Flat over nested:
DIR.zip(src, out)vsos.walk+zipfile+os.path.relpathloop - Readability counts: code reads like intentions, not implementation
- One obvious way to do it:
crc16_modbus.encode(frame),JSON.load(path),Time(ts).to("iso") - Errors should never pass silently:
DatabaseErrorwraps driver exceptions with context - Namespaces are one honking great idea:
FILE,DIR,PATH,CSV,JSONas static classes
Trade-offs:
- Explicit over implicit:
PATH.resolveauto-joins with CWD,db.insertauto-serializes dicts to JSON. Convenient in 95% of cases, surprising in the rest. Deliberate, and switchable where it gets in the way (auto_resolve=False). - Performance: an extra abstraction layer costs. Path resolution, auto-serialization and placeholder conversion run on every call. Negligible for APIs and tools, not for tight loops over millions of rows.
Type safety comes from Pydantic models and type hints on the application layer. Xaeian is the plumbing underneath. Each layer does one thing and stays out of the way. It fits best when you own the stack end-to-end and value compact code over configurability.
Install
pip install xaeian # core
pip install xaeian[time] # + pytz, tzlocal
pip install xaeian[serial] # + pyserial
pip install xaeian[plot] # + matplotlib
pip install xaeian[dsp] # + scipy
pip install xaeian[db] # + pymysql, psycopg2
pip install xaeian[db-async] # + aiomysql, asyncpg, aiosqlite
pip install xaeian[media] # + pypdf, PyMuPDF, Pillow
pip install xaeian[eda] # + sexpdata, pypdf, PyMuPDF
pip install xaeian[sftp] # + paramiko
pip install xaeian[all] # everything
Examples
from xaeian import FILE, JSON, CSV, Time, logger, split_str, generate_password
from xaeian.crc import crc16_modbus
from xaeian.db import Database
# Files: auto extension, context-based paths
JSON.save("config", {"debug": True, "port": 8080})
CSV.save("users", [{"name": "Jan", "age": 30}, {"name": "Anna", "age": 25}])
# Time: parse anything, arithmetic with strings
t = Time("2025-03-01T00:00:00+01:00") + "2w 3d"
t.round("w") # Monday 00:00
t.to("iso") # "2025-03-18T00:00:00+01:00", the offset you gave is the offset you get
# CRC: encode/decode with Modbus, ISO, custom
frame = crc16_modbus.encode(b"\x01\x03\x00\x00\x00\x0A")
assert crc16_modbus.decode(frame) is not None
# String tools
split_str('a,"b,c",d', sep=",") # ['a', '"b,c"', 'd']
generate_password(16) # 'aB3$xY9!mN2@pQ7&'
# Database: sqlite/mysql/postgres, sync/async
db = Database("sqlite", "app.db")
db.insert("users", {"name": "Jan", "settings": {"theme": "dark"}})
db.find("users", order="name", limit=10)
with db.transaction():
db.update("users", {"verified": True}, "id = ?", 42) # `?` on every backend
# Serial recorders: threaded read, latest value via .value
from xaeian.serial import Recorder
recs = [Recorder(p, name=n, regex=Recorder.SCI_NORM)
for n, p in {"U1": "COM7", "I1": "COM8"}.items()]
for r in recs: r.start() # background reader threads
... # app-side reap loop snapshots r.value (CSV, DB, MQTT)
for r in recs: r.stop()
# Plot: fluent, stacked panels, auto datetime
from xaeian.plot import Plot
(Plot(theme="dark")
.line(t, temp, "Temperature [°C]")
.panel()
.line(t, hum, "Humidity [%]")
.title("Sensors")
.save("dashboard.png"))
# DSP: immutable signals, filters, FFT, vibration metrics
from xaeian.dsp import Signal
sig = Signal.from_accel(raw_x, fs=6666, bits=16, g_range=2)
clean = sig.highpass(10).lowpass(500)
print(f"RMS:{clean.rms:.4f} peak_freq:{clean.fft().peak_freq:.0f}Hz")
# Binary structs: C-like encoding with CRC, bitfields, scale/offset
from xaeian.cstruct import Struct, Field, Bitfield, Type, Endian
from xaeian.crc import crc32_iso
pkt = Struct(endian=Endian.little, crc=crc32_iso)
pkt.add(
Field(Type.uint32, "timestamp", "s"),
Bitfield("flags", [("enabled", 1), ("error", 1), ("mode", 6)]),
Field(Type.float, "temperature", "°C"),
)
flags = {"enabled": 1, "error": 0, "mode": 5}
raw = pkt.encode({"timestamp": 1234567890, "flags": flags, "temperature": 23.5})
pkt.decode(raw) # {"timestamp": 1234567890, "flags": {...}, "temperature": 23.5}
# Media: compress, strip metadata
from xaeian.media.min import compress
compress("report.pdf") # → report-min.pdf
compress("photos/", max_px=1280) # → photos-min/ (recursive)
# Logging: colored, rotating
log = logger("app", file="app.log")
log.inf("started") # 2025-03-01 14:32:01 INF started
CLI
xn tree . # directory tree
xn dupes photos/ # find duplicates
xn wifi # saved Wi-Fi passwords
xn fonts web/fonts/ # rename to {family}-{weight}
xn host 10.0.0.1 --drop # drop a pinned SSH host key
xn min report.pdf # compress PDF
xn min photo.jpg -f avif # convert to AVIF
xn min photos/ --max-px 1280 # batch resize
xn meta photo.jpg -i # strip EXIF in-place
xn ico logo.png -o favicon.ico # multi-size .ico
Modules
| Module | Description | Docs |
|---|---|---|
files |
FILE, DIR, PATH, JSON, CSV, INI, YAML, async | xaeian/files/readme.md |
table |
Lightweight tabular ops on list[dict] |
xaeian/readme.md |
xstring |
Split, replace, strip comments, passwords | xaeian/readme.md |
xtime |
Datetime parsing, arithmetic, rounding | xaeian/readme.md |
colors |
ANSI 256-color terminal codes | xaeian/readme.md |
log |
Colored logging with file rotation | xaeian/readme.md |
crc |
CRC-8/16/32 with predefined variants | xaeian/readme.md |
cstruct |
Binary struct serialization (C-like) | xaeian/readme.md |
cmd |
Shell command helpers | xaeian/readme.md |
serial |
Port, recorders with CSV logging, embedded shell client | xaeian/serial/readme.md |
plot |
Fluent matplotlib wrapper with stacked panels | xaeian/readme.md |
dsp |
Signal processing, SOS filters, FFT, vibration | xaeian/readme.md |
db |
Database abstraction (SQLite, MySQL, PostgreSQL) | xaeian/db/readme.md |
media |
Compress, convert, strip metadata (PDF & images) | xaeian/media/readme.md |
eda |
E-series, KiCad export, ngspice runner | xaeian/eda/readme.md |
net |
Network clients (SFTP, FTP, S3) | xaeian/net/readme.md |
cli |
Command-line utilities behind xn |
xaeian/cli/readme.md |
cli |
tree, dupes, wifi, fonts, host, min, meta, ico, plot | xaeian/cli/readme.md |
Metadata
Release files for xaeian 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| xaeian-1.0.1.tar.gz | 257.3 kB | With provenance | Details for xaeian-1.0.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| xaeian-1.0.1-py3-none-any.whl | Python 3 | none | any | Details for xaeian-1.0.1-py3-none-any.whl |
Total release size: 473.2 kB
Release files / xaeian-1.0.1.tar.gz
| Download URL | xaeian-1.0.1.tar.gz |
|---|---|
| Size | 257.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
66a27d9ca7f566cd919283a08130f468e594e59b22e3fdba87f1ff348d7512e5
|
|
BLAKE2b-256 checksum How to use checksums |
1c805a3d2b9277fd8e6efa2c1ba8a2e987433407ea288b6ae3ebd1265e6a1f5d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / xaeian-1.0.1-py3-none-any.whl
| Download URL | xaeian-1.0.1-py3-none-any.whl |
|---|---|
| Size | 215.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9658ea5c8b5ac02c3b3fb6c961ebf7d480df12e71e73270a820e47339489c0f4
|
|
BLAKE2b-256 checksum How to use checksums |
a8a5a8db6477cfa7f5329fc2105ec92a44b05cbb4256e0d1c8435b7456c27bed
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logSecurity for xaeian 1.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for xaeian-1.0.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.