Skip to main content

Minimal ObjectBox LMDB reader toolkit

Project description

ob-dump-reader

GitHub License PyPI Version

Minimal ObjectBox LMDB reader toolkit for Python. Its core job: walk a data.mdb file and hand you each stored object's raw FlatBuffers table bytes, plus its entity id and object id — no per-field FlatBuffers or schema knowledge for that part, just lmdb (the py-lmdb bindings). It also covers the handful of things flatc --python output can't: ToMany relations (a separate LMDB structure, not a table field) and Flex/ ExternalPropertyType fields (flatc only knows the base FlatBuffers type, not ObjectBox's semantic annotation on top) — see "Beyond flatc" below.

Decoding those raw bytes into typed objects is left to the official flatc --python compiler — not this package, and not ob-dump's own C++ core either. This is a deliberate toolkit split, not a missing feature: see the parent project's docs/BACKLOG.md for the reasoning.

Workflow

# 1. Generate a schema JSON (entityId -> table name/shape) and a .fbs from
#    your ObjectBox model, using the ob_dump CLI (see ../README.md):
ob_dump --schema objectbox-model.json -o schema.json
ob_dump --fbs    objectbox-model.json -o schema.fbs

# 2. Generate typed Python classes with the *official* FlatBuffers compiler.
flatc --python -o models/ schema.fbs
import ob_dump_reader as ob
from models.Ammo import Ammo  # from flatc --python, see step 2 above

AMMO_ENTITY_ID = 1  # from schema.json


def on_record(record: ob.ObRecord) -> None:
    if record.entity_id == AMMO_ENTITY_ID:
        ammo = Ammo.GetRootAs(record.data)  # flatc-generated class decodes the bytes
        print(f"{ammo.Name()}: {ammo.BcG1()}")
        # ... insert into whatever your new database is.


ob.read_objectbox_records("/path/to/objectbox/dir", on_record)

Async

ob_dump_reader.aio mirrors the same API as async/await coroutines (built on py-lmdb's own lmdb.aio executor-based wrapper — LMDB itself has no native async I/O, so this dispatches the same blocking calls to a thread executor rather than avoiding them):

import ob_dump_reader.aio as ob


async def on_record(record: ob.ObRecord) -> None:
    ...


await ob.read_objectbox_records("/path/to/objectbox/dir", on_record)

Reads are in place, no copy

read_objectbox_records/read_objectbox_to_many_targets read data.mdb/lock.mdb directly, with no temporary copy step — they open the LMDB environment itself readonly=True (matching ob-dump's own C++ LmdbReader), so they never need a write-capable handle. This is exactly what LMDB's MVCC design is for: any number of readers can safely run alongside one concurrent writer, in any process, with zero risk to the original data — even while a live ObjectBox process has the same store open.

Beyond flatc: ToMany relations and Flex/ExternalPropertyType fields

ob_dump --schema lists each property's externalType and each entity's relations (id, name, target entity) when present — use that to know which of your fields need one of these:

import ob_dump_reader as ob
from ob_dump_reader.decode_helpers import (
    decode_flex,
    bytes_to_hex,
    bytes_to_uuid_string,
    try_parse_json_string,
)

# ToMany: not part of the FlatBuffers table at all, so flatc has no
# accessor for it — relation_id/source_object_id come from `ob_dump --schema`
# and the record you're looking at (record.object_id).
author_ids = ob.read_objectbox_to_many_targets(db_dir, relation_id, record.object_id)

# Flex: flatc gives you the raw bytes (a bytes/bytearray field) —
# decode with decode_flex.
value = decode_flex(ammo.SomeFlexField())

# ExternalPropertyType: flatc gives you the base type's plain value
# (a byte blob for Uuid/Int128/Decimal128/Bson, a string for
# Json/JavaScript/JsonToNative) — decode with the matching helper.
uuid = bytes_to_uuid_string(ammo.SomeUuidField())
blob = bytes_to_hex(ammo.SomeBsonField())
parsed = try_parse_json_string(ammo.SomeJsonField())

Every one of these mirrors ob-dump's own C++ decode (src/fb_decode.cpp) exactly — same hex/UUID formatting, same JSON-parse-with-string-fallback for JavaScript, same forward-only relation direction (see docs/BACKLOG.md "ToMany relations" for why: the backward direction is an auto-maintained index for ObjectBox's own query engine, not needed for a one-directional dump).

Why this shape

The alternative — an FFI wrapper around ob-dump's C++ core — would mean building/vendoring native C++ from a PyPI package for every platform. Not needed here: py-lmdb already gives a mature, actively-maintained Python binding to LMDB, and flatc --python already gives an officially generated, correct decoder. This package is only the small piece connecting the two — LMDB traversal and the ObjectBox key format (docs/BACKLOG.md in the parent project) — and stays that small on purpose.

Integrity & Licensing

ob-dump was developed as an independent implementation for reading data stored in the ObjectBox format. It adheres to a "Clean Room Design" approach regarding binary software:

  • Purpose-Limited: Built solely to support data recovery and migration to another database, for projects whose own license is incompatible with objectbox-c's (a closed-source binary — see "Why this exists" in the parent project's docs/BACKLOG.md). Not intended as, and not pursued as, a competing product to ObjectBox itself — no write support, no query engine, no ongoing-database use case, strictly a one-time read-only export path out of an existing store.
  • No Reverse Engineering: We have performed no decompilation, disassembly, or any other analysis of the closed-source objectbox-c binary.
  • Open Specification: Data parsing is based exclusively on public formats (LMDB and FlatBuffers) and the open-source code of the official schema generator (objectbox_generator, licensed under Apache 2.0).
  • Model-Driven: The decoding process is driven by the user-provided objectbox-model.json file, which is an open, user-accessible schema definition.

This approach ensures full licensing integrity: ob-dump is an independent software project that contains no proprietary or misappropriated code, making it suitable for integration into projects with any licensing requirements.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ob_dump_reader-0.0.0.dev0.tar.gz (29.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ob_dump_reader-0.0.0.dev0-py3-none-any.whl (13.6 kB view details)

Uploaded Python 3

File details

Details for the file ob_dump_reader-0.0.0.dev0.tar.gz.

File metadata

  • Download URL: ob_dump_reader-0.0.0.dev0.tar.gz
  • Upload date:
  • Size: 29.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for ob_dump_reader-0.0.0.dev0.tar.gz
Algorithm Hash digest
SHA256 720d0207700fb4d0ef71fd7fde966d9df135f441ddba5d052dee5c3a39ce0f92
MD5 60c1d8f7c9409dd8b23d153966d19caa
BLAKE2b-256 9b5d3c011b8fabf47a831d05b20bb97cf65e8c7aece857cc2ba3c5487271e9b1

See more details on using hashes here.

File details

Details for the file ob_dump_reader-0.0.0.dev0-py3-none-any.whl.

File metadata

  • Download URL: ob_dump_reader-0.0.0.dev0-py3-none-any.whl
  • Upload date:
  • Size: 13.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for ob_dump_reader-0.0.0.dev0-py3-none-any.whl
Algorithm Hash digest
SHA256 8b65d537cea0f8c4f47719301eb810c86370a7d9f2c3345a00911b8eef5700d0
MD5 4d187b92489504d76df7ec8fbe8b00d5
BLAKE2b-256 8b7698d73a4fc54b2085ee8bb579f87ae1dafc594ab6a539e348641730cb7e0f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page