Python ctypes binding for the TSEdge embedded time-series storage library.
Project description
TSEdge Python Binding
tsedge is a Python ctypes binding for the TSEdge embedded C time-series
storage library. Python code calls the public C API from include/tsedge.h;
the native TSEdge core still owns WAL, segment files, compressed blocks, block
indexes and recovery.
Starting with 0.1.1, locally built wheels can bundle the native TSEdge shared
library inside the package. If the bundled library is present, TSEDGE_LIBRARY
is not required. TSEDGE_LIBRARY and explicit lib_path arguments still take
priority, so applications can override the bundled library.
Prebuilt bundled wheels are currently prepared for macOS arm64. Linux, Windows and macOS x86_64 wheels are planned for a later release.
No runtime Python dependencies are required.
Installation
For local development from the repository:
cd python
python3 -m pip install .
For a built bundled wheel:
python3 -m pip install python/dist/*.whl
When installing from TestPyPI after publishing:
python3 -m pip install \
--index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
tsedge
Building the Native Library
Build the C library first:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
The Python loader searches in this order:
lib_pathpassed toTSEdge.open(..., lib_path=...);TSEDGE_LIBRARY;- bundled
tsedge/native/libtsedge.dylib,libtsedge.soortsedge.dll; - common CMake build directories;
- the system dynamic-library search path.
Manual override on Linux:
export TSEDGE_LIBRARY=$PWD/build/libtsedge.so
Manual override on macOS:
export TSEDGE_LIBRARY=$PWD/build/libtsedge.dylib
You can also pass a path explicitly:
db = TSEdge.open("sensor_db", lib_path="/path/to/libtsedge.dylib")
Bundled Native Library Wheel
Local macOS bundled wheel build:
rm -rf build
MACOSX_DEPLOYMENT_TARGET=11.0 cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0
cmake --build build
ctest --test-dir build --output-on-failure
cd python
MACOSX_DEPLOYMENT_TARGET=11.0 python3 scripts/prepare_native.py
MACOSX_DEPLOYMENT_TARGET=11.0 python3 -m build --wheel
python3 -m twine check dist/*
scripts/prepare_native.py copies the compiled native library into:
python/src/tsedge/native/libtsedge.dylib
You can override the source library path:
TSEDGE_NATIVE_LIBRARY=/path/to/libtsedge.dylib python3 scripts/prepare_native.py
Check that the wheel is platform-specific and contains the native library:
ls dist/
python3 -m zipfile -l dist/*.whl | grep tsedge/native
Expected local Apple Silicon wheel tag:
tsedge-0.1.1-py3-none-macosx_11_0_arm64.whl
The bundled wheel should not be tagged py3-none-any and should not use a
CPython ABI tag such as cp314-cp314.
Runtime check without TSEDGE_LIBRARY:
python3 -m venv /tmp/tsedge-bundled-test
source /tmp/tsedge-bundled-test/bin/activate
python3 -m pip install python/dist/*.whl
unset TSEDGE_LIBRARY
cd /tmp
python3 -c "from tsedge import TSEdge; db = TSEdge.open('/tmp/tsedge_bundled_db'); db.close(); print('OK')"
deactivate
Linux, Windows and macOS x86_64 bundled wheels are intentionally left for a
later cibuildwheel step.
Basic Usage
from tsedge import Aggregate, Durability, TSEdge
with TSEdge.open("sensor_db") as db:
db.create_series("air.temperature")
db.set_durability(Durability.BALANCED)
db.append_batch("air.temperature", [
(1, 23.1),
(2, 23.4),
(3, 23.2),
])
avg = db.aggregate("air.temperature", 1, 3, Aggregate.AVG)
print(avg)
Batch Writes
points = [(i, 20.0 + (i % 100) * 0.01) for i in range(100_000)]
db.append_batch("air.temperature", points)
db.flush_all()
The binding accepts (timestamp, value) tuples or Point dataclass instances.
It builds a temporary ctypes array and calls tsedge_append_batch.
Range Reads
read_range wraps the C callback API and returns copied Point objects:
points = db.read_range("air.temperature", 0, 10_000)
The C point pointer is valid only during the callback, so values are copied immediately.
Aggregates
avg = db.aggregate("air.temperature", 0, 10_000, "avg")
min_value = db.aggregate("air.temperature", 0, 10_000, "min")
max_value = db.aggregate("air.temperature", 0, 10_000, "max")
count = db.aggregate("air.temperature", 0, 10_000, "count")
Aggregate names are case-insensitive. You can also use the Aggregate enum.
Window Aggregation
windows = db.aggregate_windowed(
"air.temperature",
start_time=0,
end_time=1_000_000,
window_size=1000,
)
The binding calls tsedge_aggregate_windowed, copies the returned C array into
Python WindowAggregate objects and releases the C memory with
tsedge_free_window_aggregates.
Series Metadata
stats = db.get_series_stats("air.temperature")
print(stats.block_count, stats.compression_ratio)
for series in db.list_series():
print(series.name, series.total_points)
list_series copies the C array into Python objects and frees it with
tsedge_free_series_list.
Verify
report = db.verify()
print(report.error_count)
report = TSEdge.verify_path("sensor_db")
Database corruption reported by tsedge_verify is returned in VerifyReport.
Set raise_on_error=True if you want a TSEdgeError instead.
CSV Export
db.export_csv("air.temperature", 0, 10_000, "temperature.csv")
Disk Quota, If Available
If the loaded C library provides the quota API, the binding exposes it:
db.set_disk_quota(100 * 1024 * 1024)
print(db.get_disk_quota())
db.enforce_disk_quota()
If an older native library does not export quota symbols, these methods raise
TSEdgeError with a clear message.
Sensor Simulation Example
python/examples/sensor_simulation.py is a realistic edge-device workflow. It
generates deterministic sensor-like telemetry in Python and writes it to TSEdge
in batches. The data is stored by the C core through WAL, segment files and
compressed blocks; Python acts only as the application layer.
The example creates:
air.temperatureair.humiditymotor.vibrationmotor.current
Run it from the repository with the source tree:
PYTHONPATH=python/src TSEDGE_LIBRARY=$PWD/build/libtsedge.dylib \
python3 python/examples/sensor_simulation.py --points 10000 --batch-size 1000
After installing a bundled wheel, neither PYTHONPATH nor TSEDGE_LIBRARY is
needed:
python3 python/examples/sensor_simulation.py --points 10000 --batch-size 1000
Options:
--db
--csv
--points
--batch-size
The script prints per-series statistics, min/max/avg/count aggregates, a 60-second window aggregation summary, a small range read, a CSV export path and a verification report.
Run Examples From Source
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
export TSEDGE_LIBRARY=$PWD/build/libtsedge.dylib
PYTHONPATH=python/src python3 python/examples/basic_usage.py
PYTHONPATH=python/src python3 python/examples/batch_write.py
PYTHONPATH=python/src python3 python/examples/read_and_aggregate.py
PYTHONPATH=python/src python3 python/examples/window_aggregate.py
PYTHONPATH=python/src python3 python/examples/sensor_simulation.py --points 10000 --batch-size 1000
PYTHONPATH=python/src python3 python/smoke_test.py
Use libtsedge.so in TSEDGE_LIBRARY on Linux.
Build and Check the Package
cd python
python3 -m pip install --upgrade build twine
MACOSX_DEPLOYMENT_TARGET=11.0 python3 scripts/prepare_native.py
MACOSX_DEPLOYMENT_TARGET=11.0 python3 -m build --wheel
python3 -m twine check dist/*
This creates a platform wheel in python/dist/.
Test a Wheel Locally
python3 -m venv /tmp/tsedge-pkg-test
source /tmp/tsedge-pkg-test/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install python/dist/*.whl
unset TSEDGE_LIBRARY
python3 -c "from tsedge import TSEdge; print(TSEdge)"
python3 python/examples/basic_usage.py
python3 python/examples/sensor_simulation.py --points 1000 --batch-size 100
deactivate
TestPyPI
Do not upload to the main PyPI until the TestPyPI flow has been checked.
Upload to TestPyPI only when credentials are configured:
cd python
python3 -m twine upload --repository testpypi dist/*
Install back from TestPyPI in a clean environment:
python3 -m venv /tmp/tsedge-testpypi
source /tmp/tsedge-testpypi/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install \
--index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
tsedge
python3 -c "from tsedge import TSEdge; print(TSEdge)"
deactivate
Limitations
- Local bundled wheel verification currently targets macOS.
- Linux and Windows wheels will be a separate
cibuildwheelstep. read_rangereturns a Python list, not a lazy iterator.- NumPy arrays are not supported in the first version.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tsedge-0.1.1-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: tsedge-0.1.1-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 42.5 kB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
241334642456dc5f4bf43f8b176328affe547a75411162a08b6c260bb74abbe7
|
|
| MD5 |
1d44ee6e9acc40edc931983ddb95ead4
|
|
| BLAKE2b-256 |
4394b1e60191e72214d2ebe0996f039ad7b2af9224c708ae102e4831e911c76b
|
File details
Details for the file tsedge-0.1.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.
File metadata
- Download URL: tsedge-0.1.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- Upload date:
- Size: 44.0 kB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19a31adda592a36ce096c317fe2f6918891b85f0c0865afff7de2ec09fdf11ea
|
|
| MD5 |
20e91dbb2fab160d1a999c76cccc7c4a
|
|
| BLAKE2b-256 |
d501f7eff029ab59bc883bd13a1d74749ad2295a712474c5f49be6e36f320645
|
File details
Details for the file tsedge-0.1.1-py3-none-macosx_11_0_x86_64.whl.
File metadata
- Download URL: tsedge-0.1.1-py3-none-macosx_11_0_x86_64.whl
- Upload date:
- Size: 35.9 kB
- Tags: Python 3, macOS 11.0+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d5f63fe94f3e4db3567a293873ed436cf20af6544c436b82844c60eca4a59d3
|
|
| MD5 |
b4529c6ef53bd90ab58443307c6b9e9d
|
|
| BLAKE2b-256 |
1de5f78888c4f6b3a5e73476d29bd38b3a138fc445efd9fbfd88769a4316644f
|
File details
Details for the file tsedge-0.1.1-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: tsedge-0.1.1-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 34.2 kB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ed6add3cfa3b76a6803ea9bf13b1e3332c2a6649928ab52f3273a1bd5e1699f1
|
|
| MD5 |
bae0a00655776b59f20c5c7676745098
|
|
| BLAKE2b-256 |
c7f881c4ca899b8409d5ea0a03f7c69fe2749c4e55bf73ce1a3aa2b356c0ff32
|