Skip to content

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.

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:

Terminal window
curl -fL -o bsheet_reader.py \
https://github.com/Bridge-Town/financial-modeling-mcp/releases/download/model-authoring-helpers-v1.5.0/bsheet_reader.py
printf '%s %s\n' \
c431799998019c63b7639aa09ba4d9e97a0461172664cce9655a0cea128f3e2b \
bsheet_reader.py | sha256sum --check

Copy 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.

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.

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.

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.