🤖 AI generated content
Follow-up to the Locator migration (#59) and to the reader interface added in #112. Two generations of "get me the object" API now coexist; the older one should go, in a PR of its own.
Older interface (takes fetch_data: DataFetcher = Callable[[int, int], ReadBuffer] and does the read inside the object):
ROOTFile.get_TFile, ROOTFile.get_StreamerInfo (src/rootfilespec/bootstrap/TFile.py:185, :204) — duplicated by tfile_locator / streamerinfo_locator, including the validation logic, which has already drifted between the two copies
TFile.get_KeyList (TFile.py:263), TDirectory.get_KeyList (src/rootfilespec/bootstrap/TDirectory.py:109) — duplicated by keylist_locator
TKey.read_object(fetch_data, objtype=...) (src/rootfilespec/bootstrap/TKey.py:98-143) — still the implementation behind TKey.read_from / TypedTKey.read_from, which call it with a lambda returning the buffer; invert that so read_from(buffer) is the implementation
- the
DataFetcher alias itself (src/rootfilespec/serializable.py:353)
Middle generation (takes Callable[[Locator], ReadBuffer]): ROOT3a3aRNTuple.get_header / get_footer, FooterEnvelope.get_pagelists, PageListEnvelope.get_pages, RPageDescription.get_page, REnvelopeLink and RNTuple.from_anchor. These fetch eagerly inside library code, which is at odds with docs/design.md ("objects describe where data is; callers decide when and how to fetch it"). rootfilespec.reader.Fetcher.buffer has the matching shape today so they keep working; decide whether RNTuple.from_anchor stays as a convenience (then probably taking a Fetcher) or moves next to FileReader.
To do:
Related: #112, #59, #46, #81 (comparing the key image at the front of a record with the key-list copy — the natural place is the new read_from).
Assisted-by: claude-code:claude-fable-5-1
Follow-up to the Locator migration (#59) and to the reader interface added in #112. Two generations of "get me the object" API now coexist; the older one should go, in a PR of its own.
Older interface (takes
fetch_data: DataFetcher = Callable[[int, int], ReadBuffer]and does the read inside the object):ROOTFile.get_TFile,ROOTFile.get_StreamerInfo(src/rootfilespec/bootstrap/TFile.py:185,:204) — duplicated bytfile_locator/streamerinfo_locator, including the validation logic, which has already drifted between the two copiesTFile.get_KeyList(TFile.py:263),TDirectory.get_KeyList(src/rootfilespec/bootstrap/TDirectory.py:109) — duplicated bykeylist_locatorTKey.read_object(fetch_data, objtype=...)(src/rootfilespec/bootstrap/TKey.py:98-143) — still the implementation behindTKey.read_from/TypedTKey.read_from, which call it with a lambda returning the buffer; invert that soread_from(buffer)is the implementationDataFetcheralias itself (src/rootfilespec/serializable.py:353)Middle generation (takes
Callable[[Locator], ReadBuffer]):ROOT3a3aRNTuple.get_header/get_footer,FooterEnvelope.get_pagelists,PageListEnvelope.get_pages,RPageDescription.get_page,REnvelopeLinkandRNTuple.from_anchor. These fetch eagerly inside library code, which is at odds withdocs/design.md("objects describe where data is; callers decide when and how to fetch it").rootfilespec.reader.Fetcher.bufferhas the matching shape today so they keep working; decide whetherRNTuple.from_anchorstays as a convenience (then probably taking aFetcher) or moves next toFileReader.To do:
read_from(buffer)the primary implementation onTKeytests/test_rntuple_hardcoded.py::test_read_multiple_rntuples, the last test on the old interface (kept that way in Vendor root-io-spec and fix the first three quick wins from the bootstrap review #112 so these methods stay covered until they are removed)docs/design.mdRelated: #112, #59, #46, #81 (comparing the key image at the front of a record with the key-list copy — the natural place is the new
read_from).Assisted-by: claude-code:claude-fable-5-1