v0.1.12-alpha
🎉 v0.1.12 – “Edge-Case Exterminator” 🎉
Your most battle-tested release yet! v0.1.12 shores up every remaining corner case so that nothing—not malformed DBCs, weird BLF messages, or unexpected enum types—can slip through or crash your pipeline.
✨ What’s New in v0.1.12
🛠 Bullet-Proof Decoding
Drop-summary logging
iter_blf_chunks() now reports decoded vs dropped frame counts (Decoded 980/1000 messages (20 dropped)), so you know exactly what didn’t make it through.
Signal-filter resilience
Unhashable or non-stringable filter keys are silently skipped rather than throwing errors.
🔍 Strict Type Safety
Immediate dtype validation
load_blf() now pre-validates every entry in dtype_map, ensuring invalid numpy/pandas dtypes are caught up-front with clear ValueError.
Reserved-name protection
Never accidentally overwrite your timing columns: 'timestamp' and 'raw_timestamp' are disallowed as signal names and reserved from injection.
🔄 Comprehensive Signal Injection
Interpolation fallback
Missing signals in the log can be linearly interpolated if requested (interpolate_missing=True), otherwise integer signals get zero-filled and float signals get NaNs.
Collision-tolerant prefixing
Signals are always prefixed uniquely—checking frame_id, then arbitration_id, then sequence index—so no two signals ever collide, with zero warnings or errors.
🎨 Robust Enum Handling
NameSignalValue-proof mapping
Enum values (including NameSignalValue objects) and raw integers are safely converted to labels; unknown values are passed through, never dropped or cast to NaN.
📂 Streamlined Exports
Auto-mkdir & side-car metadata
Both to_csv() and to_parquet() auto-create parent directories and export df.attrs["signal_attributes"] to JSON alongside your data.
Graceful failures
Parquet write errors are caught and rethrown as ValueError, so you’ll always get a Python exception rather than a stack-trace deep in pyarrow.
🔧 Quickstart
pip install canml==0.1.12from canml.canmlio import load_blf, to_csv, CanmlConfig
# Full-file decode with edge-case safety
cfg = CanmlConfig(
chunk_size=5000,
force_uniform_timing=True,
interpolate_missing=True,
dtype_map={"Speed": "float32"}
)
df = load_blf(
blf_path="drive.blf",
db="vehicle.dbc",
config=cfg,
message_ids={0x100, 0x200},
expected_signals=["Speed", "RPM"]
)
print(df.attrs["signal_attributes"]) # All custom DBC attributes
to_csv(df, "out.csv", metadata_path="out_meta.json")Huge thanks to everyone for helping us squash every corner-case bug—canml is now truly unstoppable! 🎉