Read Bsheet Inputs in a Model
Use BSheetReader when Python model code consumes cells from a committed
bsheet. It distinguishes a missing cell, a literal blank, a formula
without a cached value, a formula error, and numeric zero. Directly loading a
.bsheet.json or historical .btsheet.json file bypasses these checks and does not emit the canonical cell
identities used for lineage reconciliation.
Install the versioned helper
Section titled “Install the versioned helper”Download the immutable
bsheet_reader.py v1.5.0 source
from Bridge Town’s public GitHub release. Its SHA-256 digest is
c431799998019c63b7639aa09ba4d9e97a0461172664cce9655a0cea128f3e2b.
The release includes the complete
SHA256SUMS,
source at the immutable tag,
runnable example,
changelog, MIT license, and ownership record.
Verify the file outside the network-isolated model sandbox:
curl -fL -o bsheet_reader.py \ https://github.com/Bridge-Town/financial-modeling-mcp/releases/download/model-authoring-helpers-v1.5.0/bsheet_reader.pyprintf '%s %s\n' \ c431799998019c63b7639aa09ba4d9e97a0461172664cce9655a0cea128f3e2b \ bsheet_reader.py | sha256sum --checkCopy the verified file byte-for-byte into the model repository as
lib/bsheet_reader.py. For compatibility with existing imports, also copy the
release’s native_sheet_reader.py to lib/native_sheet_reader.py; it exposes
NativeSheetReader as an alias of BSheetReader. Both modules use only
Python’s standard library and make no network calls.
Read required values
Section titled “Read required values”Import the helper from a model file and use it as a context manager:
from lib.bsheet_reader import BSheetReader
with BSheetReader() as sheets: base_revenue = sheets.read_value("sht_inputs", "tab_drivers", "B2") growth_rate = sheets.read_value("sht_inputs", "tab_drivers", "B3")
result = { "next_period_revenue": round(float(base_revenue) * (1 + float(growth_rate)), 2)}Use the canonical sheet_id and tab_id returned by
get_bsheet. A tab’s
exact display name is also accepted, but telemetry always records its stable
tab_id. A1 references are normalized to uppercase.
After a successful with block, the helper writes
/outputs/native_sheet_read_set.json. It records bsheet_reader instrumentation
and contains only bounded
sheet_id/tab_id/cell_ref identities and read-status labels — never cell
values. Repeated reads are deduplicated, the default maximum is 1,000 entries,
and truncation is explicit.
Handle a meaningful blank
Section titled “Handle a meaningful blank”read_value is intentionally strict: a missing cell, literal blank, formula
without a cached value, or formula error raises a specific exception rather
than substituting zero. When a literal blank has business meaning, call
read_cell and branch on its status:
from lib.bsheet_reader import BSheetReader
with BSheetReader() as sheets: optional_bonus = sheets.read_cell("sht_inputs", "tab_drivers", "B4") bonus = 0.0 if optional_bonus.status == "literal_blank" else float(optional_bonus.value)Do not catch the base exception and continue with an invented value. Formula cache and error failures mean the sheet must be fixed and recalculated before the model runs.
Existing model code may keep using from lib.native_sheet_reader import NativeSheetReader when it installs both v1.5.0 files. Earlier immutable
releases remain available for historical models, but those reader versions
only understand .btsheet.json files.
Pair reads with output lineage
Section titled “Pair reads with output lineage”The read-set artifact says which canonical cells the model read. To explain
how an input drives an output, install the separately versioned
output_lineage.py helper and pass
the same sheet_id, tab_id, and cell_ref through InputSourceRef when
building the output trace.