Skip to content

Commit a51fdd2

Browse files
kurodo3[bot]claude
andcommitted
docs: add include_metadata docstrings and README section (PLT-1734)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 8e5db7b commit a51fdd2

2 files changed

Lines changed: 43 additions & 3 deletions

File tree

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,31 @@ for batch in batches:
3636
digest = digester.finalize()
3737
```
3838

39+
## Metadata hashing
40+
41+
By default, Arrow schema- and field-level metadata are excluded from the hash,
42+
preserving hash format 0.0.1 stability. Pass `include_metadata=True` to any
43+
entry point to include them:
44+
45+
```python
46+
# One-shot
47+
digest = ArrowDigester.hash_table(table, include_metadata=True)
48+
49+
# Streaming
50+
digester = ArrowDigester(schema, include_metadata=True)
51+
for batch in batches:
52+
digester.update(batch)
53+
digest = digester.finalize()
54+
```
55+
56+
When `include_metadata=True`, adding or changing any metadata key or value on
57+
any field (including nested struct children and list element fields) produces a
58+
different hash. Metadata key ordering is deterministic — the hash is stable
59+
regardless of insertion order.
60+
61+
A schema with no metadata produces the same hash regardless of `include_metadata`
62+
(empty-metadata invariant).
63+
3964
## License
4065

4166
MIT OR Apache-2.0

src/starfix/arrow_digester.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,14 @@ def _finalize_digest(final_digest, entry: tuple) -> None:
743743
class ArrowDigester:
744744
"""Pure-Python equivalent of the Rust ``ArrowDigester``.
745745
746-
Produces identical SHA-256 hashes with a 3-byte version prefix.
746+
Produces identical SHA-256 hashes with a 3-byte version prefix
747+
(hash format version 0.0.1, independent of the package version).
748+
749+
By default, Arrow schema- and field-level metadata are excluded from
750+
the hash. Pass ``include_metadata=True`` to any entry point to include
751+
them — see the ``include_metadata`` parameter on each method.
752+
A schema with no metadata produces the same hash regardless of that
753+
flag (empty-metadata invariant).
747754
"""
748755

749756
def __init__(self, schema: pa.Schema, *, include_metadata: bool = False) -> None:
@@ -816,7 +823,9 @@ def hash_record_batch(record_batch: pa.RecordBatch, *, include_metadata: bool =
816823
record_batch: The record batch to hash.
817824
include_metadata: When True, schema-level and per-field Arrow
818825
metadata are included in the hash. Default is False,
819-
preserving hash format 0.0.1 stability.
826+
preserving hash format 0.0.1 stability. A schema with no
827+
metadata produces the same hash regardless of this flag
828+
(empty-metadata invariant).
820829
"""
821830
d = ArrowDigester(record_batch.schema, include_metadata=include_metadata)
822831
d.update(record_batch)
@@ -830,7 +839,9 @@ def hash_table(table: pa.Table, *, include_metadata: bool = False) -> bytes:
830839
table: The table to hash.
831840
include_metadata: When True, schema-level and per-field Arrow
832841
metadata are included in the hash. Default is False,
833-
preserving hash format 0.0.1 stability.
842+
preserving hash format 0.0.1 stability. A schema with no
843+
metadata produces the same hash regardless of this flag
844+
(empty-metadata invariant).
834845
"""
835846
d = ArrowDigester(table.schema, include_metadata=include_metadata)
836847
for batch in table.to_batches():
@@ -842,6 +853,10 @@ def hash_array(array: pa.Array) -> bytes:
842853
"""Hash a single array (spec Section 6).
843854
844855
Uses the same recursive BTreeMap decomposition as the record-batch path.
856+
857+
Note:
858+
``include_metadata`` is intentionally absent here — standalone arrays
859+
carry no schema or field metadata. This matches the Rust ``starfix`` API.
845860
"""
846861
import pyarrow as pa
847862

0 commit comments

Comments
 (0)