Move ladybug-python fully to lbug.h C-API, with no backend knob, while preserving public Python API behavior and stability.
- All heap memory returned by C-API result-reading calls is owned by the backend
QueryResultobject. - Memory is released when
result.close()is called (or when GC triggers close), matching Node-style lifetime semantics. - This includes:
char*returned through result paths (column names, string/uuid/decimal rendering, etc.)- blob buffers returned from result values
- Normal close order remains:
result.close()conn.close()db.close()
- Out-of-order close must never crash.
- We enforce safe parent/child close behavior in Python wrappers:
- Database tracks live connections; closes them before destroying DB handle.
- Connection tracks live query results; closes them before destroying connection handle.
- QueryResult methods detect closed parent DB/connection and raise Python exceptions, not segfault.
- Make C-API backend the only backend path.
- Add QueryResult-owned allocation tracking and deferred free-on-close.
- Add parent-child tracking across Database/Connection/QueryResult.
- Ensure out-of-order close behavior is idempotent and crash-safe.
- Add/adjust tests for:
- normal close ordering
- out-of-order close safety
- C-API smoke and parameter binding.
Use pybind only where C-API does not currently expose equivalent functionality.
- Keep C-API as default for duplicated core functionality (
Database,Connection,PreparedStatement,QueryResultlifecycle/query execution semantics). - Route to pybind for non-duplicated features:
- Python object scan replacement (
LOAD/COPY ... FROM df/tab) - Arrow memory-backed table APIs (
create_arrow_table,create_arrow_rel_table,drop_arrow_table) - UDF registration/removal (until C-API equivalent is available)
- Python object scan replacement (
- Track and reduce duplication over time by migrating pybind-only features to C-API upstream, then removing fallback paths.